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
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.
-
1Could 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– asheeshr2014年03月05日 01:24:57 +00:00Commented 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– zmo2014年03月05日 16:39:55 +00:00Commented Mar 5, 2014 at 16:39
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.