1

I am currently working on a display library. The font should be stored in PROGMEM. The code looks something like this:

unsigned int i = 0;
Serial.println(pgm_read_byte(&font[1]),HEX);
unsigned char width = pgm_read_byte(&font[0]);
unsigned char height = pgm_read_byte(&font[1]); 
unsigned char spacing = pgm_read_byte(&font[2]);

The strange thing is that the code breaks (Serial spits out random characters, OLED displays only noise or nothing) when I remove the

Serial.println(pgm_read_byte(&font[1]),HEX);

If I replace it with something like

Serial.println("Hello World!");

the code breaks as well, but in a different way. I think pgm_read_byte() returns different things with different Strings in the Serial.println() function.

Is there something going on with the compiler? Are there some optimization options that I should change? Or am I doing it completely wrong?

Here is the whole function:

/**
 * 
 * Displays text using a predefined sprite in PROGMEM
 * Only fonts with a uniform letter spacing are supported
 * The font must have the following format
 * Byte   Description
 *  0.    X width of one letter in pixel
 *  1.    Y height of one letter in bytes (8 pixel)
 *  2.    letter spacing in pixels
 *  3.    data
 *  .      .
 *  .      .
 *  .      .
 *  N.    data
 * 
 * The data is arranged like this
 *    | 0 | 1 | 2 | 3 | 4 | ... |126|127
 *     b0  b1  b2
 *     b3  b4  b5
 *    LSB D0
 * In each byte the data is displayed like this
 *    .
 *    .
 *    .
 *    MSB D7
 * 
 * A font starts with the symbol "!" (ASCII 33) and ends with the symbol "~" (ASCII 126).
 * Each symbol in between has to be present. The letters have to be arranged like this
 * Letter     A       B       C     
 * Bytes    b0 b1   b2 b3   b4 b5
 *          b6 b7   b8 b9  b10 b11
 * 
 * @param unsigned char disp[]          the display buffer where the text should be shown
 * @param const unsigned char font[]    the font in PROGMEM
 * @param const char *string            the string to display
 * @param unsigned char X               x location
 * @param unsigned char Y               y location
 * @param int mode                      blend mode
 */
void gfx::text(unsigned char disp[], unsigned char *font, const char *string, unsigned char X, unsigned char Y, int mode){
  unsigned int i = 0;
  Serial.println(pgm_read_byte(&font[1]),HEX);
  unsigned char width = pgm_read_byte(&font[0]);
  unsigned char height = pgm_read_byte(&font[1]); 
  unsigned char spacing = pgm_read_byte(&font[2]);
  while(string[i])
  {
    if(string[i] > 32 && string[i] < 127){  //only display valid characters, otherwise leave a blank spot
      unsigned char s[width*height];
      unsigned char c = string[i] - 33;
      //transfer pixel with and height to the sprite
      s[0] = width;
      s[1] = height;
      //copy the other bytes
      for(int y = 0; y < height; y++){
        for(int x = 0; x < width; x++){
          unsigned int sprite_pointer = 2 + width*y + x;
          unsigned int font_pointer = 3 + c*width + x + y*width*93;
          s[sprite_pointer] = pgm_read_byte(&font[font_pointer]);
        }
      }
      sprite(disp,s,X+i*(width + spacing),Y,mode); 
    }  
    i++;
  }
}
  • I am also having issues with PROGMEM. I can't use forloops to iterate through and print a PROGMEM'd array, it just spits out garbage. I have to go character by character using constants. – qaxf6auux May 31 '18 at 7:46
  • 1
    The problem is probably not in the code you show, but in some weird interaction with other parts of your program. Please, post a Minimal, Complete, and Verifiable example isolating the problem. – Edgar Bonet May 31 '18 at 9:03
  • Why compute unsigned int sprite_pointer = 2 + width*y + x;? The array s only has width*height entries, when the for loop goes at the maximum values of x and y, this index will be out-of-bounds. You need 2 bytes more in the s array. What's the size of the font you're passing it? – Maximilian Gerhardt May 31 '18 at 10:24
  • If this is code from a 3rd party library I would find another library. If its your code, you need to look at simplifying the function so you can see why it doesn't work. If anything goes wrong in the code you program will splat stuff everywhere, If its internet connected you could start a world war :) What does 93 mean? – Code Gorilla May 31 '18 at 12:01
  • Maximilian Gerhardt was right. The array had only (witdh*height) but I wrote (width*height+2) in it. So something else got overwritten and nothing worked. Thanks a lot! – w7sbc May 31 '18 at 13:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.