PROGMEM

I was running low on variable memory, which I have now successfully recovered by some major tweaks to the code, but one attempt to recover this was to move a font table into PROGMEM.

The sketch compiled OK, but the results were completely wrong.....

Illustrated by the two attached pictures, declaring the font table into PROGMEM, which is the ONLY change I made, stops it working correctly.

I'm still on the low-slopes of the learning curve, but I wouldn't have thought it made any difference where the table was stored, but it did.....

Any thoughts anyone ??

2016-10-31_004508.jpg

2016-10-31_004537.jpg

Read and follow the documentation in AVRLibcReferenceManual / pgmspace.

which is the ONLY change I made,

In the words of a wise man:

"Well there's your problem!"

After declaring variables to be in program memory, you need to use special functions to read them from program memory, just like you need to use functions to read from EEPROM.

http://www.nongnu.org/avr-libc/user-manual/group__avr__pgmspace.html

Yes, Whandall, I think I found the answer.....

After further investigation, I now find that reading the characters from PROGMEM requires a different method to retrieve it....

"/* Using the ... table in program memory requires the use of special functions to retrieve the data"

I find that slightly bizarre, after having told the compiler where the data is stored, why do you have to tell it where to get it from ???

after having told the compiler where the data is stored, why do you have to tell it where to get it from

Because of the AVR architecture, progmem is not just at a different location, but it an entirely different "address space." The compiler essentially simulates this by treating it as separate addresses, but it doesn't actually understand how to access a different address space.

Question answered, thanks for the links Whandall and Jiggy-Ninja.

It is academic now, as I have re-structured the application code and I managed to recover tons of variable space - I can put my font definition table in data-memory. That's also a bonus because I need to add more code, and program memory may become an issue. I'm currently at 93%, but re-writing parts of the sketch is reducing this considerably .....

similar thanks to westfw for your explanation

daba:
I find that slightly bizarre, after having told the compiler where the data is stored, why do you have to tell it where to get it from ???

Blame Harvard architecture.

Harvard architecture uses different memory spaces for different kinds of memory. You cannot just say "grab the data at address 100", you have to specify whether to get it from the EEPROM space, the RAM space, or the flash space. The AVR instruction set has a different sets of commands that are necessary to read and write to these different address spaces.

C and C++ has no native support for multiple memory spaces like that, so it treats all variables as being accessed from RAM by default. Special functions are made that use the other assembly instructions to load or read from the other memory spaces.

The other way of doing things, that AVR does not use, is Von Neumann architecture. There is only one address space, and it is segmented into different parts representing the different kinds of memory. Addresses 0x0000 - 0x4FFF might be reserved for flash memory, 0x5000 - 0x9FFF for RAM, and 0xA000 - 0xAFFF for EEPROM. These will be easier to work with in a higher-level language, because the different ways of accessing the different memory spaces becomes more transparent, because if you have a pointer to location 0xA100, the chip knows unambiguously that that location is EEPROM.