Some good findings and some stuff to fix..
get started with a minimal sketch. Try to compile this which is based on your code:
typedef boolean (*Menu_Function)(unsigned int);
boolean SetPowerLevel(unsigned int PowerPtr);
boolean SetBrightness(unsigned int Level = 0);
boolean SetContrast(unsigned int Level = 0);
struct t_MenuItem
{
char Caption[16];
char Data[80];
bool Type;
Menu_Function Function;
};
static const t_MenuItem Menu[] PROGMEM =
{
{"Set Voltage 1", "[Value,0]", 1, SetBrightness},
{"Set Voltage 2", "[Value,1]", 1, SetPowerLevel},
{"Power level 1", "[Min,2],[Max,3]", 0, SetPowerLevel},
{"Power level 2", "[On:Hour,4],[On:Minute,5],[Off:Hour,6],[Off:Minute,7],[Level,8]", 0, SetPowerLevel},
{"Dev 1: Alarm MON", "[On:Hour,9],[On:Minute,10],[Off:Hour,11],[Off:Minute,12],[Level,13]", 0, SetPowerLevel},
{"Dev 1: Alarm TUE", "[On:Hour,14],[On:Minute,15],[Off:Hour,16],[Off:Minute,17],[Level,18]", 0, SetPowerLevel},
{"Dev 1: Alarm WED", "[On:Hour,19],[On:Minute,20],[Off:Hour,21],[Off:Minute,22],[Level,23]", 0, SetPowerLevel},
{"Dev 1: Alarm THU", "[On:Hour,24],[On:Minute,25],[Off:Hour,26],[Off:Minute,27],[Level,28]", 0, SetPowerLevel},
{"Dev 1: Alarm SAT", "[On:Hour,29],[On:Minute,30],[Off:Hour,31],[Off:Minute,32],[Level,33]", 0, SetPowerLevel},
{"Dev 1: Alarm SUN", "[On:Hour,34],[On:Minute,35],[Off:Hour,36],[Off:Minute,37],[Level,38]", 0, SetPowerLevel},
{"Dev 2: Alarm MON", "[On:Hour,39],[On:Minute,40],[Off:Hour,41],[Off:Minute,42],[Level,43]", 0, SetPowerLevel},
{"Dev 2: Alarm TUE", "[On:Hour,44],[On:Minute,45],[Off:Hour,46],[Off:Minute,47],[Level,48]", 0, SetPowerLevel},
{"Dev 2: Alarm WED", "[On:Hour,49],[On:Minute,50],[Off:Hour,51],[Off:Minute,52],[Level,53]", 0, SetPowerLevel},
{"Dev 2: Alarm THU", "[On:Hour,54],[On:Minute,55],[Off:Hour,56],[Off:Minute,57],[Level,58]", 0, SetPowerLevel},
{"Dev 2: Alarm SAT", "[On:Hour,59],[On:Minute,60],[Off:Hour,61],[Off:Minute,62],[Level,63]", 0, SetPowerLevel},
{"Dev 2: Alarm SUN", "[On:Hour,64],[On:Minute,65],[Off:Hour,66],[Off:Minute,67],[Level,68]", 0, SetPowerLevel},
{"Set Date", "[Day,69],[Month,70],[Year,71]", 0, SetPowerLevel},
{"Set Time", "[Hour,72],[Minute,73]", 0, SetPowerLevel},
{"Contrast", "[Value,74]", 0, SetContrast},
{"Brightness", "[Value,75]", 1, SetBrightness},
{"Time out", "[Value,76]", 0, SetPowerLevel},
{"Sleep", "[Value,77]", 0, SetPowerLevel},
};
const size_t MenuElementsCount = sizeof Menu / sizeof Menu[0];
boolean SetPowerLevel(unsigned int PowerPtr) {
Serial.println(PowerPtr);
return true;
}
boolean SetBrightness(unsigned int Level) {
Serial.println(Level);
return true;
}
boolean SetContrast(unsigned int Level) {
Serial.println(Level);
return true;
}
void setup() {
Serial.begin(115200);
}
void loop() {}
(I fixed the typedef for the function pointer as you forgot to mention there was an unsigned int parameter expected in the callback.)
You'll see the compiler complaining
[color=orange]
.../sketch_nov17b.ino:39:1: warning: initializer-string for array of chars is too long [-fpermissive]
};
^
.../sketch_nov17b.ino:39:1: warning: initializer-string for array of chars is too long [-fpermissive]
.../sketch_nov17b.ino:39:1: warning: initializer-string for array of chars is too long [-fpermissive]
.../sketch_nov17b.ino:39:1: warning: initializer-string for array of chars is too long [-fpermissive]
.../sketch_nov17b.ino:39:1: warning: initializer-string for array of chars is too long [-fpermissive]
.../sketch_nov17b.ino:39:1: warning: initializer-string for array of chars is too long [-fpermissive]
.../sketch_nov17b.ino:39:1: warning: initializer-string for array of chars is too long [-fpermissive]
.../sketch_nov17b.ino:39:1: warning: initializer-string for array of chars is too long [-fpermissive]
.../sketch_nov17b.ino:39:1: warning: initializer-string for array of chars is too long [-fpermissive]
.../sketch_nov17b.ino:39:1: warning: initializer-string for array of chars is too long [-fpermissive]
.../sketch_nov17b.ino:39:1: warning: initializer-string for array of chars is too long [-fpermissive]
.../sketch_nov17b.ino:39:1: warning: initializer-string for array of chars is too long [-fpermissive]
[/color]
that's because 16 is not enough for many of your Captions because you miss space for the trailing null char.
Change 16 into 17 will remove the warnings
struct t_MenuItem
{
char Caption[17]; // <<==== HERE USE 17
char Data[80];
bool Type;
Menu_Function Function;
};
other note: you don't need to pre-declare the number of elements in your menu array. Let the compiler do the work for you. The array is statically defined, so the compiler can guess the number of elements you want and to get that number, use const size_t MenuElementsCount = sizeof Menu / sizeof Menu[0];
Now the good findings: it seems that the definition with static and PROGMEM does put everything into Flash memory.
try to compile this:
typedef boolean (*Menu_Function)(unsigned int);
boolean SetPowerLevel(unsigned int PowerPtr);
boolean SetBrightness(unsigned int Level = 0);
boolean SetContrast(unsigned int Level = 0);
struct t_MenuItem
{
char Caption[17];
char Data[80];
bool Type;
Menu_Function Function;
};
static const t_MenuItem Menu[] PROGMEM =
{
{"Set Voltage 1", "[Value,0]", 1, SetBrightness},
{"Set Voltage 2", "[Value,1]", 1, SetPowerLevel},
{"Power level 1", "[Min,2],[Max,3]", 0, SetPowerLevel},
{"Power level 2", "[On:Hour,4],[On:Minute,5],[Off:Hour,6],[Off:Minute,7],[Level,8]", 0, SetPowerLevel},
{"Dev 1: Alarm MON", "[On:Hour,9],[On:Minute,10],[Off:Hour,11],[Off:Minute,12],[Level,13]", 0, SetPowerLevel},
{"Dev 1: Alarm TUE", "[On:Hour,14],[On:Minute,15],[Off:Hour,16],[Off:Minute,17],[Level,18]", 0, SetPowerLevel},
{"Dev 1: Alarm WED", "[On:Hour,19],[On:Minute,20],[Off:Hour,21],[Off:Minute,22],[Level,23]", 0, SetPowerLevel},
{"Dev 1: Alarm THU", "[On:Hour,24],[On:Minute,25],[Off:Hour,26],[Off:Minute,27],[Level,28]", 0, SetPowerLevel},
{"Dev 1: Alarm SAT", "[On:Hour,29],[On:Minute,30],[Off:Hour,31],[Off:Minute,32],[Level,33]", 0, SetPowerLevel},
{"Dev 1: Alarm SUN", "[On:Hour,34],[On:Minute,35],[Off:Hour,36],[Off:Minute,37],[Level,38]", 0, SetPowerLevel},
{"Dev 2: Alarm MON", "[On:Hour,39],[On:Minute,40],[Off:Hour,41],[Off:Minute,42],[Level,43]", 0, SetPowerLevel},
{"Dev 2: Alarm TUE", "[On:Hour,44],[On:Minute,45],[Off:Hour,46],[Off:Minute,47],[Level,48]", 0, SetPowerLevel},
{"Dev 2: Alarm WED", "[On:Hour,49],[On:Minute,50],[Off:Hour,51],[Off:Minute,52],[Level,53]", 0, SetPowerLevel},
{"Dev 2: Alarm THU", "[On:Hour,54],[On:Minute,55],[Off:Hour,56],[Off:Minute,57],[Level,58]", 0, SetPowerLevel},
{"Dev 2: Alarm SAT", "[On:Hour,59],[On:Minute,60],[Off:Hour,61],[Off:Minute,62],[Level,63]", 0, SetPowerLevel},
{"Dev 2: Alarm SUN", "[On:Hour,64],[On:Minute,65],[Off:Hour,66],[Off:Minute,67],[Level,68]", 0, SetPowerLevel},
{"Set Date", "[Day,69],[Month,70],[Year,71]", 0, SetPowerLevel},
{"Set Time", "[Hour,72],[Minute,73]", 0, SetPowerLevel},
{"Contrast", "[Value,74]", 0, SetContrast},
{"Brightness", "[Value,75]", 1, SetBrightness},
{"Time out", "[Value,76]", 0, SetPowerLevel},
{"Sleep", "[Value,77]", 0, SetPowerLevel},
};
const size_t MenuElementsCount = sizeof Menu / sizeof Menu[0];
boolean SetPowerLevel(unsigned int PowerPtr) {
Serial.println(PowerPtr);
return true;
}
boolean SetBrightness(unsigned int Level) {
Serial.println(Level);
return true;
}
boolean SetContrast(unsigned int Level) {
Serial.println(Level);
return true;
}
void setup() {
Serial.begin(115200);
Serial.print(F("The menu holds ")); Serial.print(MenuElementsCount); Serial.println(F(" elements"));
for (size_t i = 0; i < MenuElementsCount; i++) {
Serial.print("Menu #"); Serial.println(i);
Serial.write('\t'); Serial.println((__FlashStringHelper*) Menu[i].Caption);
Serial.write('\t'); Serial.println((__FlashStringHelper*) Menu[i].Data);
Serial.write('\t'); Serial.println(pgm_read_byte(&Menu[i].Type) ? F("TRUE") : F("FALSE"));
}
}
void loop() {}
the serial monitor at 115200 bauds will show you all your menu entries and RAM seems to be not impacted by the size of the menu. (something might have changed in the way PROGMEM is handled)