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++;
}
}
unsigned int sprite_pointer = 2 + width*y + x;
? The arrays
only haswidth*height
entries, when thefor
loop goes at the maximum values ofx
andy
, this index will be out-of-bounds. You need 2 bytes more in thes
array. What's the size of thefont
you're passing it?witdh*height
) but I wrote (width*height+2
) in it. So something else got overwritten and nothing worked. Thanks a lot!