Durante il tempo libero ho cercato varie soluzioni per realizzare una collezione di dati non omogenea, ho provato quasi di tutto e solo una soluzione mi ha colpito, si per vari motivi ma uno in particolare mi porta ancora a pensare alle possibili applicazioni.
Io ho usato un array di struct:
int16_t setpoint_pb0 = 3000;
int16_t setpoint_pb0_max_value = 32767;
int8_t setpoint_pb0_min_value = -50;
uint8_t diff_pb0 = 2;
struct data_type_t {
uint8_t type;
void *ptr_data;
};
struct data_type_t data_types[] PROGMEM = {
{INT16 | VIEW_AS_DOUBLE , &setpoint_pb0},
{INT16 | VIEW_AS_DOUBLE , &setpoint_pb0_max_value},
{INT8 , &setpoint_pb0_min_value},
{UINT8 , &diff_pb0}
.....
INT16, INT8 VIEW_AS_DOUBLE sono macro utili per assegnare un valore a data_type.type, VIEW_AS_DOUBLE indica che il dato
anche se è un int16 deve essere visualizzato sul display 7x3 segment con il punto decimale.
La cosa interessante è che data_type.ptr_data contiene un puntatore o meglio un indirizzo di memoria RAM, grazie a &setpoint_pb0. Questo è possibile perché le variabili sono globali e il loro indirizzo viene risolto prima di creare il contenuto in flash. Altra cosa interessante è la possibilita per ptr_data di prendere un puntatore a funzione.
Se al posto di usare la flash usiamo la EEprom possiamo anche cambiare ptr_data per farlo puntare altrove, cioè se in eeprom ci salviamo l'indirizzo di setup() e in type ci salviamo un bit code identificativo possiamo castare a qualunque cosa prevista.
if (data_type.type = FNC_SETUP)
(setup)(*data_type.ptr_data)(); // sempre che il cast sia giusto
La cosa bella sarebbe non avere la necessità di castare, ma purtroppo non vedo soluzione.
Per gestire i double ho evitato del tutto di usare questo tipo, anche per temperatura che viene ricavate in centesimi di grado e salvata in un int16_t e quando deve essere visualizzata accendo solo il punto decimale del display nel posto giusto.
Che ne pensate di sta cosa, quale possibile applicazione pratica ci può essere nel salvare puntatori in flash o EEprom?
Ciao.