olikraus / u8glib

Arduino Monochrom Graphics Library for LCDs and OLEDs
https://github.com/olikraus/u8glib/wiki
Other
1.24k stars 313 forks source link

impact on timer interrupts.. #478

Closed adriangeisow closed 6 years ago

adriangeisow commented 6 years ago

I'm using a custom set of timer interrupts for a PWM application, and the length of the 'on' pulse changes when using u8glib - I guess because u8glib blocks interrupts during SPI transfers, see details below.

Any suggestions as to how I might mitigate this? Is u8g2 likely to behave any differently? (I'm extensively using the ...P routines for PROGMEM text display, so a bit reluctant to change if there's not likely to be any benefit). I might be expecting too much from the hardware of course...

Details: I'm using a 3d printer kit - atmega2560+RAMPS1.4+ST7920_128X64 LCD, which seems to assign the hardware SPI to an SD card (which I'm not currently using). Writing to the display works fine using either U8GLIB_ST7920_128X64_1X or _4X sw initialisers. I have timer3 ISRs on overflow and compare match to turn on/off two separate PWM signals, running at 0.5mS (8k counts at 16MHz clock). The pulse length modulates as expected if I'm not calling u8glib routines; but when I do, the pulse length dithers by 5-10us or so.

The main loop which refreshes the delay takes roughly 80ms. The main timer3_overflow ISR takes about 15us, but sometimes 20us - perhaps because of nested interrupts - I've turned these on in the non-critical bits of the ISR as I also need to track a quadrature encoder on a pin change interrupt. The compare match ISRs are very short - ~0.5us - timings all from scope traces on tracer pins. I'm not using any of the other timers (& turned off timer0 to be sure, and not using servo or other timer based libraries that I'm aware of...)

olikraus commented 6 years ago

I think in u8g2 I have not (yet) stopped the IRQ during SPI sent.

adriangeisow commented 6 years ago

OK thank you! I will try an upgrade to u8g2 to see if that helps - will need to do something about all the e.g. drawStrP routines as I have all my text in indexed arrays of PROGMEM strings. I guess I should be able to copy and edit the u8glib versions to call the u8g2 routines..?

Many thanks for your prompt response :)

olikraus commented 6 years ago

ok, drawStrP is not yet there, but you can use u8g2.print() if you pass the PROGMEM string as "class __FlashStringHelper *" (well, not yet tested).

the porting guide from u8glib to u8g2 is here: https://github.com/olikraus/u8g2/wiki/u8gvsu8g2

olikraus commented 6 years ago

ok, i can confirm, that this works:

const char s[] PROGMEM  = "ABC" ;
...
u8g2.print((class __FlashStringHelper *)s);
adriangeisow commented 6 years ago

OK, that's great! - will try it out (when I get back to the hardware next week).

olikraus commented 6 years ago

here is a more complex example:

void setup(void) {
  u8g2.begin();
}

const char s[] PROGMEM = "Progmem";
const char s1[] PROGMEM  = "ABC" ;
const char s2[] PROGMEM  = "DEF" ;
const char s3[] PROGMEM  = "GHI" ;
const char s4[] PROGMEM  = "JKL" ;

const char *a[] = { s1, s2, s3, s4 };

int i = 0;

void loop(void) {
  u8g2.setFont(u8g2_font_ncenB14_tr);
  u8g2.firstPage();
  do {
    u8g2.setCursor(0, 20);
    u8g2.print((class __FlashStringHelper *)s);   // print a sting, located in PROGMEM

    u8g2.setCursor(0, 40);
    u8g2.print((class __FlashStringHelper *)a[i]);  // print a sting (PROGMEM) via RAM array.
  } while ( u8g2.nextPage() );
  delay(1000);
  i++;
  if ( i >= 4 )
    i = 0;
}
adriangeisow commented 6 years ago

Those calls work for me, but I also call getStrWidthP(s); replacing that with getStrWidth((class __FlashStringHelper *) s) doesn't seem to work... Looks like the u8g2 string width routines are a bit more complex..

adriangeisow commented 6 years ago

I have it working - by strcpy_P to a buffer first - as I need the returned length from drawStrP as well as from getStrWidthP. Not the most elegant solution I'm sure, but OK for now. Many thanks for your help. I'll close the issue shortly unless you have other suggestions.

olikraus commented 6 years ago

I have it working - by strcpy_P to a buffer first

Yes indeed, i think this is a proper solution.