5

In this code for heating monitor, there appears to be macros called FLASH_ARRAY and FLASH_TABLE. I can't find any reference to them either in this code, Arduino, or on the Internet. What do they do?

FLASH_ARRAY(byte, VARIABLE_DEVICE_TABLE,
    DEVICE_LADDNING_RETUR,
    DEVICE_LADDNING_UT,
    DEVICE_TANK1,
    DEVICE_TANK2,
    ...
    VARIABLE_ID_LOAD,
    VARIABLE_ID_TIME_EMPTY);

and

FLASH_TABLE(byte, NUMBER_TEMP_TABLE, 7,
  {DEVICE_LADDNING_RETUR, 99,  5, 10,  7, MAIN_TYPE_TEXT_CELCIUS, 2},
  {DEVICE_LADDNING_UT,    99, 43, 10,  7, MAIN_TYPE_TEXT_CELCIUS, 2},
  ...
  {DEVICE_UTE,             0, 55, 15,  7, MAIN_TYPE_TEXT_CELCIUS_WITH_NEGATIVE, 103},
  {VARIABLE_ID_EFFECT,   114, 29, 10,  7, MAIN_TYPE_TEXT_VARIABLE, 2});

2 Answers 2

5

After further digging, this appears to be from Mikal Hart's Flash library.

The reason this library was developed is:

Storing static program data in flash/PROGMEM is a tricky part of Arduino programming. To save precious RAM, a novice user already at odds with unfamiliar C++ syntax must digest such daunting concepts as prog_char, PSTR(), PROGMEM, pgm_read_word(), etc. Even seasoned users get tripped up by the indirection and typecasting that are required to retrieve valid PROGMEM data. Add to that a couple of apparent bugs in the implementation, and it’s clear that PROGMEM is a complicated mess.

I have written a new library, Flash, which abstracts away most of this complexity. It provides new String, Array, Table, and String Array types that make ROM-based data collections as easy to use as “normal” types. Each overrides the C++ [] operator, so to extract individual elements one uses familiar array access syntax:

Specifically, these are macros and a simple helper class to make it easier to create arrays and tables of values in program memory.

The two macros are declared as so:

// Example: FLASH_ARRAY(float, temperatures, 98.1, 98.5, 99.1, 102.1);
#define FLASH_ARRAY(type, name, values...) \
  static const type name##_flash[] PROGMEM = { values }; \
  _FLASH_ARRAY<type> name(name##_flash, sizeof(name##_flash) / sizeof(type));

// Example: FLASH_TABLE(uint8_t, fonts, 7, {ON, OFF, ON, ON, OFF, ON, OFF}, {OFF, ON, OFF, ON, OFF, ON, OFF});
#define FLASH_TABLE(type, name, cols, values...) \
  static const type name##_flash[][cols] PROGMEM = { values }; \
  _FLASH_TABLE<type> name((const PROGMEM type *)name##_flash, sizeof(name##_flash) / sizeof(name##_flash[0]), cols);

The helper functions include size and override the operator [] so that they can easily be accessed like so

FLASH_ARRAY[0]

I disagree with zmo - this is more than boilerplate. The area of PROGMEM causes a lot of questions from Arduino users, and it is very easy to do things wrong when creating arrays in PROGMEM.

2
  • 1
    Could you add an explanation of the macros within the answer? This answer contains only a link and won't be of much use, if the link goes offline.
    – asheeshr
    Mar 5, 2014 at 1:24
  • Cybergibbons, this is nice, handy and useful, but this adds definitely a non trivial overhead: it's encapsulating an object within a full instance. When you only got 2k of RAM, every byte is precious.
    – zmo
    Mar 5, 2014 at 16:39
4

The flash array is from Mikal Hart's flash library as you show, and what it does is that they declare an array or a matrix (table) object in the PROGMEM memory:

#define FLASH_ARRAY(type, name, values...) \
static const type name##_flash[] PROGMEM = { values }; \
_FLASH_ARRAY<type> name(name##_flash, sizeof(name##_flash) / sizeof(type));

which is an instance of the _FLASH_ARRAY class defined in that same file, which is a facility to access PROGMEM/Flash memory.

Basically, it's a lot of boilerplate for what already does the PSTR() macro amongst other from pgmspace.h. I personally would avoid using that and prefer to use the original macros along with my own index and pointers.

BTW, except for some Arduono IDE magic, I don't think that can compile, as the Flash.h is not included.

EDIT:

To make another point against the FLASH_TABLE/FLASH_ARRAY boilerplate/overhead, since avc-gcc 4.8 has been introduced the __flash qualifier which is a replacement for the PROGMEM macro, simplifying the whole stuff:

// to use string literals without having to cast
#define FSTR(X) ((const __flash char[]) { X })

// create string pstr in the .progmem.data address space
const __flash char* pstr = FSTR ("foo"); 

and no more use of the pgm_read_*() functions, you can now access the content of the flash memory using *pstr, as shown is this thread. In case you want to keep a code compatible with older version of avr-gcc, here's a post that offers macros to deal with both systems.

Your Answer

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

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