0

I've got some working code with a definition that looks like this:

const unsigned char DynTextPositions[10][4][4] = {
    ...
};

Which is defined / referenced via a header:

#include <avr/pgmspace.h>
#ifndef DYNTEXTPOS_H
#define DYNTEXTPOS_H

extern const unsigned char DynTextPositions[10][4][4];

#endif

This data is being fed into a rendering function which draws lines based on the given positions. The data is read as follows:

float deltas[4][4];
// ...
deltas[n][k] = float(DynTextPositions[c+1][n][k] - DynTextPositions[c][n][k]) / 32.0;

As-is, this works just fine, as long as I've got my other scenes commented out. When I uncomment them, the combined data size seems to overflow the data segment. This is expected, because there's a fair bit of data, so I'm trying to move the DynTextPositions data into PROGMEM.

I've got PROGMEM working with some bitmaps, but it doesn't seem to work here. An example definition for a working bitmap is as follows:

PROGMEM const unsigned char ArduinoLogo[] = { ... };

However, as soon as I apply the PROGMEM attribute to DynTextPositions the rendering code seems to freak out - the positions appear to be all off-screen and completely wrong.

The only thing I can think of is that, for some reason, the data is either being considered signed rather than unsigned, or is getting corrupted along the way. Either that or the nested array is somehow being treated as a set of pointers.

Any idea why this might be?

7
  • Did you remember to change your code to read it from flash? Commented Mar 30, 2015 at 0:39
  • @IgnacioVazquez-Abrams I wasn't aware that I had to - I thought it was just memory-mapped elsewhere and the compiler took care of it. This may be the reason!
    – Polynomial
    Commented Mar 30, 2015 at 0:41
  • Not with PROGMEM. With __flash sure, but that isn't usable from C++. Commented Mar 30, 2015 at 0:42
  • 1
    I tried the solution pgm_read_byte(&DynTextPositions[c,l,k]) but still seem to be getting garbage values. Am I missing something?
    – Polynomial
    Commented Mar 30, 2015 at 0:44
  • Commas are almost certainly not what you want to use there. Commented Mar 30, 2015 at 0:44

1 Answer 1

3

Including <avr/pgmspace.h> and using the PROGMEM qualifier macro are only two of the steps required in order to get this to work. Since the data will no longer be available via the data bus you will need to use the various pgm_read_*() macros or *_P*() functions defined in avr/pgmspace.h. These work by using the appropriate assembly code instructions to access data stored in program space, i.e. flash, on the MCU.

Under GCC 4.7 or higher when writing C code, the __flash named address space is available. Variables declared within this namespace do not require any additional steps to access them. Note that the Arduino IDE compiles as C++, and hence does not make this (or any of the others) available.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.