TL;DR: I want some syntax sugar, to make the code shorter and more beautiful.
Pelude:
I'm writing a library for Arduino, that should help store configuration in EEPROM (power-independend flash memory).
To use it, person should do something like:
#include "myEeprom.h"
//Instantiate global configuration object
myeeprom config;
//Define constants for convinient use, values are indexes of config fields
const int CONF_BTN_ACTIVE = 0;
const int CONF_DEFAULT_LEVEL = 1;
const int CONF_USER_NAME = 2;
//Function, that defines configuration of config fields, that would be stored
//it sould be called inside of setup() function
void init_config_fields()
{
//Set first field (see how constants are used as indexed)
//each field is a struct { int type, char* name, int bytes_size }
config.fields[CONF_BTN_ACTIVE] = {
myeeprom::TYPE_BOOL,
"CONF_BTN_ACTIVE",
1
};
// next one
config.fields[CONF_DEFAULT_LEVEL] = {
myeeprom::TYPE_INT,
"CONF_BTN_ACTIVE",
4
};
// next one
config.fields[CONF_USER_NAME] = {
myeeprom::TYPE_STR,
"CONF_USER_NAME",
16 // size in bytes is actually only used if type is TYPE_STR
}
// make myeeprom know, how much field does stored in it.
config.fields_count = 3;
// make myeeprom calculate all addresses of config fields,
// read it's values, and do other useful stuff.
config.init();
}
...
// Somewhere in code:
// read data:
bool is_btn_active;
config.read(CONF_BTN_ACTIVE, &is_btn_active);
// write data
config.write(CONF_DEFAULT_LEVEL, 175);
// read data by string key (for example we got it from Serial):
config.read("CONF_BTN_ACTIVE", &is_btn_active);
// display all config to Serial with debugging function:
for (int i=0; i < config.fields_count; i++)
{
Serial.print("config field ");
config.debug_print(i, &Serial);
Serial.print("\n");
}
Now, the question!
I want to have a macro, that could solve this tasks:
Allow me to write strings like "CONF_BTN_ACTIVE" just once, not repeating whem. They are used twise, first as a constant, for convinience when writing programm, and, second, for debugging convinience in runtime. But if there are alot of such fields, the code is getting ugly :(
Allow me not to write full amount of fields (like config.fields_count = 3).
So, the code whould look like:
#include "myEeprom.h"
//Instantiate global configuration object
myeeprom config;
//Function, that defines configuration of config fields, that would be stored
//it sould be called inside of setup() function
void init_config_fields()
{
//Create fields config and constants with use of macro
add_config_magic_macro(config, CONF_BTN_ACTIVE, myeeprom::TYPE_BOOL, 1)
// next one
add_config_magic_macro(config, CONF_DEFAULT_LEVEL, myeeprom::TYPE_INT, 4)
// next one
add_config_magic_macro(config, CONF_USER_NAME, myeeprom::TYPE_STR, 16);
// make myeeprom calculate all addresses of config fields,
// read it's values, and do other useful stuff.
config.init();
}
As i've discovered, I cannot create statically incrementing constant macros without boost preprocessor, so, it shouldn't be it.
I can use some non-constant variable and increment it in add_config_magic_macro, but, I don't now how to create global constants when I call such a macro inside a function, and I cant run this code outside of a function.
Ideally this should be compile-time non-dynamic initialization of a fields configuration array, because of arduino's little amount of runtime memory.
Answer to the question How to use Macro argument as string literal? doesn't help, because I need macro to create global const and, at the same time local, in-function structure with the string.