TFT 2.4 font problem Atmega2560 - Page 1
Forum section: electronics / general

author: dan3460
author_rank: Frequent Contributor
timestamp: May 09, 2017, 02:30:05 am
content: I have the same screen that a previous poster but my problem is a little different. I'm using an Arduino 2560 but programing from Atmel Studio. Several months ago a got the display, came with an Arduino uno (atmega328p). I took from the web a library and made the screen work. Because it was a test I only pasted the code and not the information about the author. Several months after I'm working on the project for which I have purchased the screen. I made modifications to the pins that I'm using and after a few changes I got the screen to work, but doesn't print characters. I know that connections are correct, as I can send commands to the screen, draw lines, circles, change colors. etc. When I try to print a character it prints a square where the character should be. If I print a word, it will position it where I wanted it, but prints the same number of squares as the number of letters of the word. I'm not new to C++, but I have never gotten very deep into memory management. For what I understand, there is header with the definitions of the font, here the first few lines:Code:static const unsigned char font[] PROGMEM = {0x00, 0x00, 0x00, 0x00, 0x00,0x3E, 0x5B, 0x4F, 0x5B, 0x3E,0x3E, 0x6B, 0x4F, 0x6B, 0x3E,0x1C, 0x3E, 0x7C, 0x3E, 0x1C,0x18, 0x3C, 0x7E, 0x3C, 0x18,I think this is putting the definition of each character in the same region of flash memory where the program resides.Then is this piece of code, that I think gets the codes from the table above and prints the character:Code:c -= pgm_read_byte(&gfxFont->first);GFXglyph *glyph = &(((GFXglyph *)pgm_read_pointer(&gfxFont->glyph)));uint8_t *bitmap = (uint8_t *)pgm_read_pointer(&gfxFont->bitmap);uint16_t bo = pgm_read_word(&glyph->bitmapOffset);uint8_t w = pgm_read_byte(&glyph->width),h = pgm_read_byte(&glyph->height),xa = pgm_read_byte(&glyph->xAdvance);int8_t xo = pgm_read_byte(&glyph->xOffset),yo = pgm_read_byte(&glyph->yOffset);uint8_t xx, yy, bits, bit = 0;int16_t xo16, yo16;if(size > 1) {xo16 = xo;yo16 = yo;}// Todo: Add character clipping here// NOTE: THERE IS NO 'BACKGROUND' COLOR OPTION ON CUSTOM FONTS.// THIS IS ON PURPOSE AND BY DESIGN. The background color feature// has typically been used with the 'classic' font to overwrite old// screen contents with new data. This ONLY works because the// characters are a uniform size; it's not a sensible thing to do with// proportionally-spaced fonts with glyphs of varying sizes (and that// may overlap). To replace previously-drawn text when using a custom// font, use the getTextBounds() function to determine the smallest// rectangle encompassing a string, erase the area with fillRect(),// then draw new text. This WILL infortunately 'blink' the text, but// is unavoidable. Drawing 'background' pixels will NOT fix this,// only creates a new set of problems. Have an idea to work around// this (a canvas object type for MCUs that can afford the RAM and// displays supporting setAddrWindow() and pushColors()), but haven't// implemented this yet.for(yy=0; yy<h; yy++) {for(xx=0; xx<w; xx++) {if(!(bit++ & 7)) {bits = pgm_read_byte(&bitmap[bo++]);}if(bits & 0x80) {if(size == 1) {drawPixel(x+xo+xx, y+yo+yy, color);} else {fillRect(x+(xo16+xx)*size, y+(yo16+yy)*size, size, size, color);}}bits <<= 1;}}I think what is happening is that the program is reading a blank area of the memory and not where the font resides, therefore just fills the space with the color of the font.Can anyone explain how the memory is read by the program?If necessary I can post the full library, just let me know.Thanks.

author: Nusa
author_rank: Super Contributor
timestamp: May 09, 2017, 06:30:01 am
content: PROGMEM says to put this const data in flash memory, which is usually in far greater supply than SRAM on AVR's (256K vs 8K in the case of the 2560). You then use pgmspace functions to access it.Partial code fragments from library functions without the context of the function header or the invoking code are the devil, you know. You're lucky I recognize the library.The code fragment you provided is only used for custom fonts, where YOU provide the address to the font data via a setFont(&myFontTable) call. To default to the built-in font table that pointer should be NULL, which causes it to execute the code above your fragment instead.You might find the library documetation useful:https://cdn-learn.adafruit.com/downloads/pdf/adafruit-gfx-graphics-library.pdf

author: dan3460
author_rank: Frequent Contributor
timestamp: May 09, 2017, 12:32:07 pm
content: Thanks for the reply. What you said is what I though, that by default the program would use the table called "font" to create the letter. I set the setFont() function to NULL but it did not made a difference. If I understand correctly in the function definition for setFont()Code:void setFont(const GFXfont *f = NULL);is being assign to NULL by default. So, as you said, the upper portion of the drawChar() should be working and it is (I instruxcted to turn the LED on);Code:if(!gfxFont) { // 'Classic' built-in fontif((x >= LCD_W) || // Clip right(y >= LCD_H) || // Clip bottom((x + 6 * size - 1) < 0) || // Clip left((y + 8 * size - 1) < 0)) // Clip topreturn;if(!_cp437 && (c >= 176)) c++; // Handle 'classic' charset behaviorPORTB |= (1<<PB7); //*************************************************************************for(int8_t i=0; i<6; i++ ) {uint8_t line;if(i < 5) line = pgm_read_byte(font+(c*5)+i);else line = 0x0;//for(int8_t j=0; j<8; j++, line >>= 1) {for(int8_t j=8; j>0; j--, line >>= 1) {if(line & 0x1) {if(size == 1) drawPixel(x+i, y+j, color);else fillRect(x+(i*size), y+(j*size), size, size, color);} else if(bg != color) {if(size == 1) drawPixel(x+i, y+j, bg);else fillRect(x+i*size, y+j*size, size, size, bg);}}}My understanding of the code is that for a particular character goes and fetch from the table "font" the codes to draw the character. Then by shifting it examines each bit and depending on the size will put a pixel or draw a square if the bit is 1.So here clearly the program is fetching 0xFF as is making a rectangle of the color of the font. That tells me that is fetching from unwritten memory.I think is clear that I deleted something between my initial tests and this implementation, that is preventing the pgm_read_byte() to fetch from the right memory spot.

author: dan3460
author_rank: Frequent Contributor
timestamp: May 09, 2017, 04:52:45 pm
content: I kept on experimenting, I set up PORTA so I can dump the contents of the variable "line" and check the value. As I concluded in my previous post, the pgm_read_byte() is reading from an empty space of memory. Is it possible that the way that pgmspace.h functions differently between the Atmega328 and 2560?I'm lost as to how to solve this problem.

author: dan3460
author_rank: Frequent Contributor
timestamp: May 09, 2017, 07:51:35 pm
content: I have continued experimenting. I created a minimal program for testing:Code:#include <avr/io.h>#include <avr/pgmspace.h>static const unsigned char font[] PROGMEM = {0x00, 0x00, 0x00, 0x00, 0x00,0x3E, 0x5B, 0x4F, 0x5B, 0x3E,0x3E, 0x6B, 0x4F, 0x6B, 0x3E,0x1C, 0x3E, 0x7C, 0x3E, 0x1C,0x18, 0x3C, 0x7E, 0x3C, 0x18,0x1C, 0x57, 0x7D, 0x57, 0x1C,0x1C, 0x5E, 0x7F, 0x5E, 0x1C,0x00, 0x18, 0x3C, 0x18, 0x00,0xFF, 0xE7, 0xC3, 0xE7, 0xFF,0x00, 0x18, 0x24, 0x18, 0x00,0xFF, 0xE7, 0xDB, 0xE7, 0xFF,0x30, 0x48, 0x3A, 0x06, 0x0E};int main(void){DDRB |= (1<<PB7);DDRA = 0xFF;for (uint8_t i = 0; i < 6; i++){PORTB |= (1<<PB7);uint8_t line = pgm_read_byte(font+11+i);PORTA = line;PORTB &= ~(1<<PB7);}/* Replace with your application code */while (1){}}If I use the simulator provided with Atmel Studio, I can see in PORB the codes starting at the 11th position on the table. If I load this on the Arduino 2560 I get 0xFF.I tested making PORTA = I and when loaded on the Arduino I get the correct sequence on PORTA, this was to make sure that the program was working.Ideas?

author: Nusa
author_rank: Super Contributor
timestamp: May 10, 2017, 12:58:49 am
content: I haven't played with Atmel Studio, so can't comment much on that.One thought: Try replacing "pgm_read_byte(" with "pgm_read_byte_far(" as an experiment.

author: dan3460
author_rank: Frequent Contributor
timestamp: May 10, 2017, 03:00:57 am
content: I simplified the problem even further, this code works on the simulator but not on the chip:Code:int main(void){uint8_t numeros={1,2,3,4,5,6};DDRB |= (1<<PB7);DDRA = 0xFF;for (uint8_t i = 0; i < 6; i++){PORTB |= (1<<PB7);//unsigned char line = pgm_read_byte(&font[10+i]);PORTA = numeros; //<<<<----------------- Variable push to Register APORTB &= ~(1<<PB7);}/* Replace with your application code */while (1){}}This one, with only the change indicated works in both simulator and the chip.Code:int main(void){uint8_t numeros={1,2,3,4,5,6};DDRB |= (1<<PB7);DDRA = 0xFF;for (uint8_t i = 0; i < 6; i++){PORTB |= (1<<PB7);//unsigned char line = pgm_read_byte(&font[10+i]);PORTA = i; //<<<<----------------- Variable push to Register A - only changePORTB &= ~(1<<PB7);}/* Replace with your application code */while (1){}}There is a problem in reading from memory. Tomorrow I pull an Arduino 1 and I will try the same program. Maybe atmel forgot to include a library for managing memory?I will try to experiment before I go to bed. ThanksPD- No luck on test.

author: dan3460
author_rank: Frequent Contributor
timestamp: May 10, 2017, 01:36:42 pm
content: I have done the test on an Arduino Uno and it works, I can store and read from flash memory.Thinking that the chip on the 2560 may be defective, I pulled another 2560 that I was saving for another project and I have the same behavior, I cannot read from memory.My next test is to use the Arduino environment to program the 2560. I'll post my findings.

author: dan3460
author_rank: Frequent Contributor
timestamp: May 11, 2017, 12:01:20 am
content: I just wanted to update the thread, it sees that the USBASP is having trouble managing the memory in the 2560. I updated the firmware on the USBASP but did not change anything. I have another post on AVR Freaks and the thought there is what I described.Any ideas will be appreciated.

author: dan3460
author_rank: Frequent Contributor
timestamp: May 11, 2017, 01:01:21 am
content: About to throw the boards out the window. I made an Arduino Uno a programmer and used it to program the 2560 and I got the same error. I think is something in Atmel Studio.I can't believe i'm the only one with this problem.

author: dan3460
author_rank: Frequent Contributor
timestamp: May 11, 2017, 01:37:53 am
content: In case anyone is interested I solve the problem. The version that I was using of arvdude as an external tool to load the program I think was not up to date. It occurred to me to try to load the program directly from the command line, I used arvdudess. I looked for the hex file and wrote in the 2560 and works with no problem. Uploaded the same file from the Atmel Studio didn't work.Thanks again for the help.