olikraus / u8g2

U8glib library for monochrome displays, version 2
Other
5.03k stars 1.04k forks source link

Timing Problem with KS0108 #493

Closed roberto314 closed 6 years ago

roberto314 commented 6 years ago

This is not really a library problem - more an enhancement: I measured the E - cycle time on a KS0108 display i have and i needed 2.8us! The datasheet says 450ns and in u8g2 the delay nano takes an 8-bit parameter (which is actually 200). Can't you change that to DELAY_100NANO so the parameter can be changed from 5 (which would be 500ns) up to 255 (which would be 25,5 us)? Also i made a functonal framework to get u8g2 working with ChibiOS, could be interesting for the porting guide. See: http://www.chibios.com/forum/viewtopic.php?f=8&t=4459

olikraus commented 6 years ago

You mean, I should change the meaning of this value from ns to 100ns:

I measured the E - cycle time on a KS0108 display i have and i needed 2.8us!

What does this mean? On your setup you measured this value? Or you figured out, that smaller values do not work?

You mean this value: https://github.com/olikraus/u8g2/blob/master/csrc/u8x8_d_ks0108.c#L121 and your request is to modify the call here: https://github.com/olikraus/u8g2/blob/master/csrc/u8x8_byte.c#L169

hmmm difficult... a lot of other displays are affected...

olikraus commented 6 years ago

Actually I agree to the discussion on chibios.com, that nano seconds are useless. At least I should use a U8X8_MSG_DELAY_10NANO msg instead. Maybe I should change the message from U8X8_MSG_DELAY_NANO to U8X8_MSG_DELAY_10NANO and modify the values for all displays.

roberto314 commented 6 years ago

I had a setup with a Nucleo F401 @ 84MHz ARM and made accurate timings with chibios and a hardware timer. Checked with oscilloscope. After a lot of fiddling i figured out the 2.8us. In your previous post you mentioned the exact positions i would change too, but i think only KS0108 Displays are affected? With 10ns i one could only get a max. of 2.55us - too short for my KS0108 (maybe mine is extra slow?) but i could wait two times this value (just duplicate the call) which would be fine.

olikraus commented 6 years ago

the problem is, that the code is reused across many displays. I can not simply extend the range.

roberto314 commented 6 years ago

You can make a #define EXTENDED_RANGE for example. Set it to default = FALSE and if TRUE you can youse 10NANO instead of 1NANO. I also would suggest to extend even further to 2*10NANO.

olikraus commented 6 years ago

I see the following values at the moment:

u8x8_d_a2printer.c:  /* write_pulse_width_ns = */ 40,
u8x8_d_il3820_296x128.c:  /* write_pulse_width_ns = */ 150, 
u8x8_d_ist3020.c:  /* write_pulse_width_ns = */ 60, /* IST3020 datasheet, page 54 */
u8x8_d_ks0108.c:  /* write_pulse_width_ns = */ 200, /* KS0108: actially 450 ns */
u8x8_d_lc7981.c:  /* write_pulse_width_ns = */ 20,  
u8x8_d_lc7981.c:  /* write_pulse_width_ns = */ 20,  
u8x8_d_lc7981.c:  /* write_pulse_width_ns = */ 20,  
u8x8_d_ld7032_60x32.c:  /* write_pulse_width_ns = */ 40,    
u8x8_d_ls013b7dh03.c:  /* write_pulse_width_ns = */ 100,
u8x8_d_max7219.c:  /* write_pulse_width_ns = */ 150,    
u8x8_d_pcd8544_84x48.c:  /* write_pulse_width_ns = */ 40,
u8x8_d_pcf8812.c:  /* write_pulse_width_ns = */ 150,    
u8x8_d_sbn1661.c:  /* write_pulse_width_ns = */ 200,    /*  */
u8x8_d_sed1330.c:  /* write_pulse_width_ns = */ 220,        /* G242CX Datasheet p5 */
u8x8_d_sed1330.c:  /* write_pulse_width_ns = */ 220,        /* G242CX Datasheet p5 */
u8x8_d_sh1107.c:  /* write_pulse_width_ns = */ 150, /* sh1107: cycle time is 300ns, so use 300/2 = 150 */
u8x8_d_sh1107.c:  /* write_pulse_width_ns = */ 150, /* sh1107: cycle time is 300ns, so use 300/2 = 150 */
u8x8_d_ssd1305.c:  /* write_pulse_width_ns = */ 150,    /* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
u8x8_d_ssd1306_128x32.c:  /* write_pulse_width_ns = */ 150, /* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
u8x8_d_ssd1306_128x64_noname.c:  /* write_pulse_width_ns = */ 150,  /* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
u8x8_d_ssd1306_128x64_noname.c:  /* write_pulse_width_ns = */ 150,  /* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
u8x8_d_ssd1306_64x32.c:  /* write_pulse_width_ns = */ 150,  /* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
u8x8_d_ssd1306_64x48.c:  /* write_pulse_width_ns = */ 150,  /* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
u8x8_d_ssd1306_96x16.c:  /* write_pulse_width_ns = */ 150,  /* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
u8x8_d_ssd1309.c:  /* write_pulse_width_ns = */ 150,    /* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
u8x8_d_ssd1309.c:  /* write_pulse_width_ns = */ 150,    /* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
u8x8_d_ssd1322.c:  /* write_pulse_width_ns = */ 150,    /* SSD1322: cycle time is 300ns, so use 300/2 = 150 */
u8x8_d_ssd1322.c:  /* write_pulse_width_ns = */ 150,    /* SSD1322: cycle time is 300ns, so use 300/2 = 150 */
u8x8_d_ssd1325.c:  /* write_pulse_width_ns = */ 60, /* SSD1325 */
u8x8_d_ssd1326.c:  /* write_pulse_width_ns = */ 60, /* ssd1326 */
u8x8_d_ssd1327.c:  /* write_pulse_width_ns = */ 60, 
u8x8_d_ssd1327.c:  /* write_pulse_width_ns = */ 60, 
u8x8_d_ssd1329.c:  /* write_pulse_width_ns = */ 60, /* ssd1329 */
u8x8_d_ssd1606_172x72.c:  /* write_pulse_width_ns = */ 150, 
u8x8_d_ssd1607_200x200.c:  /* write_pulse_width_ns = */ 150,    
u8x8_d_st75256.c:  /* write_pulse_width_ns = */ 70, 
u8x8_d_st75256.c:  /* write_pulse_width_ns = */ 70, 
u8x8_d_st75256.c:  /* write_pulse_width_ns = */ 70, 
u8x8_d_st7565.c:  /* write_pulse_width_ns = */ 80,  /* st7565 datasheet, table 24, tcclw */
u8x8_d_st7565.c:  /* write_pulse_width_ns = */ 80,  /* st7565 datasheet, table 24, tcclw */
u8x8_d_st7565.c:  /* write_pulse_width_ns = */ 80,  /* st7565 datasheet, table 24, tcclw */
u8x8_d_st7565.c:  /* write_pulse_width_ns = */ 80,  /* st7565 datasheet, table 24, tcclw */
u8x8_d_st7565.c:  /* write_pulse_width_ns = */ 80,  /* st7565 datasheet, table 24, tcclw */
u8x8_d_st7565.c:  /* write_pulse_width_ns = */ 80,  /* st7565 datasheet, table 24, tcclw */
u8x8_d_st7565.c:  /* write_pulse_width_ns = */ 80,  /* st7565 datasheet, table 24, tcclw */
u8x8_d_st7567.c:  /* write_pulse_width_ns = */ 80,  /* */
u8x8_d_st7567.c:  /* write_pulse_width_ns = */ 80,  /* */
u8x8_d_st7588.c:  /* write_pulse_width_ns = */ 50,  
u8x8_d_st7920.c:  /* write_pulse_width_ns = */ 40,
u8x8_d_st7920.c:  /* write_pulse_width_ns = */ 40,
u8x8_d_t6963.c:  /* write_pulse_width_ns = */ 80,
u8x8_d_t6963.c:  /* write_pulse_width_ns = */ 80,
u8x8_d_t6963.c:  /* write_pulse_width_ns = */ 80,
u8x8_d_t6963.c:  /* write_pulse_width_ns = */ 80,
u8x8_d_uc1601.c:  /* write_pulse_width_ns = */ 80,  /* uc1601 datasheet, page 43 */
u8x8_d_uc1604.c:  /* write_pulse_width_ns = */ 35,  
u8x8_d_uc1608.c:  /* write_pulse_width_ns = */ 35,  /* uc1608 datasheet, page 39 */
u8x8_d_uc1608.c:  /* write_pulse_width_ns = */ 35,  /* uc1608 datasheet, page 39 */
u8x8_d_uc1608.c:  /* write_pulse_width_ns = */ 35,  /* uc1608 datasheet, page 39 */
u8x8_d_uc1610.c:  /* write_pulse_width_ns = */ 40,
u8x8_d_uc1611.c:  /* write_pulse_width_ns = */ 80,  /* uc1611 datasheet, page 60 */
u8x8_d_uc1611.c:  /* write_pulse_width_ns = */ 80,  /* uc1611 datasheet, page 60 */
u8x8_d_uc1611.c:  /* write_pulse_width_ns = */ 80,  /* uc1611 datasheet, page 60 */
u8x8_d_uc1617.c:  /* write_pulse_width_ns = */ 65,  /* uc1617 datasheet, page 52 */
u8x8_d_uc1638.c:  /* write_pulse_width_ns = */ 35,  /*  */
u8x8_d_uc1701_dogs102.c:  /* write_pulse_width_ns = */ 40,
u8x8_d_uc1701_mini12864.c:  /* write_pulse_width_ns = */ 40,
olikraus commented 6 years ago

one more question: Will a delay of 512ns be sufficient?

roberto314 commented 6 years ago

I thought ONLY change the KS0108 driver to 2*10NANO and leave the others alone. A delay of 512ns won't be sufficent as i need 2.8us!

olikraus commented 6 years ago

I thought ONLY change the KS0108 driver to 2*10NANO and leave the others alone. A delay of 512ns won't be sufficent as i need 2.8us!

But how? The value for the delay is stored in a data structure which is common to all displays. This structure (u8x8_display_info_t) has a 8 bit value for the nano-delay. So, 255ns is max for all displays.

If I change the meaning of the 8bit, I have top update all displays (see list above). If I extend this to 16 bit i have many more things to change.

The question is, what is how can I introduce larger delay without affecting other displays, without increasing the size of the code and data.

olikraus commented 6 years ago

currently I think about a none-linear function like this:

#include <stdio.h>
#include <stdint.h>

uint16_t fn(uint8_t x)
{
    if ( (x & 128) == 0  )
      return x;
    return 128 + ((x&127)<<5);

}

void main(void)
{
  uint16_t i;
  uint16_t r;
  for( i = 0; i < 256; i+=10 )
  {
    r = fn(i);
    printf("%d --> %d\n", (int)i, (int)r);
  }
}

result is:

0 --> 0 10 --> 10 20 --> 20 30 --> 30 40 --> 40 50 --> 50 60 --> 60 70 --> 70 80 --> 80 90 --> 90 100 --> 100 110 --> 110 120 --> 120 130 --> 192 140 --> 512 150 --> 832 160 --> 1152 170 --> 1472 180 --> 1792 190 --> 2112 200 --> 2432 210 --> 2752 220 --> 3072 230 --> 3392 240 --> 3712 250 --> 4032

You probably want to put 212, which will result a delay of 2816 = 128+ (212-128) x 32 = 128+84 x 32

olikraus commented 6 years ago

I could add a scaling function (inverse function of the above):

#define RFN(x) (((x)<128)?(x):((((x)-128+31) >> 5)+128))

So for 2800ns you just write RFN(2800) and the result will be 212

olikraus commented 6 years ago

One more thing: 450ns is the official value. I will include this value into the lib. So I guess you need to patch u8g2 for your specific display anyway.

roberto314 commented 6 years ago

That sounds like a plan. So you discarded the idea of 10_NANO instead of 1_NANO delay functions? The implementations will have to change anyway (because 150ns of the ssd1309 is no longer 150ns but 832ns). IMO it would make sense to do both.

olikraus commented 6 years ago

oh, i just realized, that i have an extra function for ks0108: uint8_t u8x8_byte_ks0108(u8x8_t u8x8, uint8_t msg, uint8_t arg_int, void arg_ptr) I can two calls (double the range): https://github.com/olikraus/u8g2/blob/master/csrc/u8x8_byte.c#L344

Then 450ns would have the value 225 in the config struct

olikraus commented 6 years ago

So you discarded the idea of 10_NANO instead of 1_NANO delay functions?

Well, yes, almost. The problem is, changing this will break all existing HAL implementations for u8g2.

The implementations will have to change anyway (because 150ns of the ssd1309 is no longer 150ns but 832ns). IMO it would make sense to do both.

ok, I do not understand the SSD1309 remark, but yes, all calls dispalys have to be changed. But it would be more like adding a macro around the existing values.

Nevertheless, I think I prefer a specific solution for the KS0108.

roberto314 commented 6 years ago

I meant the function which implements the actual delay has to be changed. It would only work as before for values below 128.

olikraus commented 6 years ago

I would probably change only the meaning of the delay field...

roberto314 commented 6 years ago

But in the delay implementation the meaning would be interpreted wrong! For example: Let's stay with the SSD1309 implementation, we need 150ns so, to use your macro RFN(150) which equals to something like 129 (i haven't calculated it, just a guess). Th NANO Delay function gets 129 and interprets it as 129ns NOT 128+ (129-128) x 32 = 128+32 = 160ns which would likely cause the display to malfunction. I don't know, maybe i am wrong in general, but in my specific application that would be a problem.

olikraus commented 6 years ago

The meaning of the delay field would be changed only for the ks0108. So other devices are not touched.

roberto314 commented 6 years ago

Yes, i get that. I meant the delay implementation would also be different, so switching between displays won't be easily possible. It would be better to implement a new delay function just for the ks0108. Von meinem Huawei-Mobiltelefon gesendet-------- Originalnachricht --------Betreff: Re: [olikraus/u8g2] Timing Problem with KS0108 (#493)Von: olikraus An: olikraus/u8g2 Cc: roberto314 100prozentoffner@gmail.com,Author The meaning of the delay field would be changed only for the ks0108. So other devices are not touched.

—You are receiving this because you authored the thread.Reply to this email directly, view it on GitHub, or mute the thread.

{"api_version":"1.0","publisher":{"api_key":"05dde50f1d1a384dd78767c55493e4bb","name":"GitHub"},"entity":{"external_key":"github/olikraus/u8g2","title":"olikraus/u8g2","subtitle":"GitHub repository","main_image_url":"https://cloud.githubusercontent.com/assets/143418/17495839/a5054eac-5d88-11e6-95fc-7290892c7bb5.png","avatar_image_url":"https://cloud.githubusercontent.com/assets/143418/15842166/7c72db34-2c0b-11e6-9aed-b52498112777.png","action":{"name":"Open in GitHub","url":"https://github.com/olikraus/u8g2"}},"updates":{"snippets":[{"icon":"PERSON","message":"@olikraus in #493: The meaning of the delay field would be changed only for the ks0108. So other devices are not touched.\r\n"}],"action":{"name":"View Issue","url":"https://github.com/olikraus/u8g2/issues/493#issuecomment-361408351"}}}

olikraus commented 6 years ago

ok, not a perfect solution, but at least it fixed the problem (hopefully)

olikraus commented 6 years ago

closing for now...