Initalising complex structures and unions

Hi,

Trying to initialise a structure containing structures and unions, also containing structures.

BUT

Get an error StructTest:177: error: too many initializers for 'const Menu'

};

^

This s probably something really stupid but I can't see it, tearing my hair out for a day now, and I didn't have that much to start with!

Cut down version provided for simplification but it still gives the same error

Any help welcomed!

StructTest.ino (11.4 KB)

You have a 2D array of initializers to populate a 1D array. Not in THIS universe...

I thought the menuDefs[] was supposed to define an array, the actual length of which was determined by the initialisation?

But why do you say I am initialising in 2 dimensions, the reasoning could be helpful.

It would be helpful if you were to chop down the code to be small enough to post here (in Code Tags) yet still demonstrate the problem. Not everyone is inclined to download attachments.

I thought the menuDefs[] was supposed to define an array, the actual length of which was determined by the initialisation?

That is true.

But why do you say I am initialising in 2 dimensions, the reasoning could be helpful.

const struct Menu PROGMEM menuDefs[] = 
{
  { // <-- This is the start of the 0th element in an array (of arrays)
    { // <-- This is the start of the 0th element in that array
      menuSelectFromList, "MODE", &currentSettings.runMode,
      { .setListValue = { 5, (char*)&modeList }}
    }
  },
  
  { // <-- This is the start of 1st element in the array (of arrays)
    {// <-- This is the start of the 0th element in that array
      menuSetActive, "BUZZER", &currentSettings.signalBuzzerOn
    }
  }
};

Don't put comments AFTER entries in the arrays. That makes it too hard to read the code.

Is this easier,

Sorry but I still don't see the error, struct Menu is an array of 4 structures of MenuItem,

StructTest1.ino (9.98 KB)

GrahamB:
Is this easier,

No, posting it here with Code Tags would be easier. Like this:

void setup() {
  // put your setup code here, to run once:

}

void loop() {
  // put your main code here, to run repeatedly:

}

These are global variables,defined before setup. Scroll down and you will see setup and loop are both present, but empty as I don't think they have nothing to with this problem.

Sorry, new to this forum so I didn't understand your meaning, took a bit of searching to find it.

struct settings
{
  // The physical
  bool          signalBuzzerOn;             // TRUE if the buzzer is on
  byte          signalTone;                 // frequency of the buzzer tone 0-9 Adjusted to Hz by toneFreq = ((MaxFreq - minFreq)/10)*signalTone + minFreq) 
  bool          signalLedOn;                // TRUE if the signal LED is on
  // Output settings
  byte          speedStandard;              // The speed standard in use, PARIS or CODEX
                                            // NOTE: 2 speeds maintained for the FARNSWORTH method, if farnsworth is not used then these will be the same
  byte          charWPM;                    // the transmit/receive speed for character signals in WPM
  byte          textWPM;                    // the transmit/receive speed for overall text in WPM
  byte          outputFile;                 // 01-99 the suffix for the output file outputxx.txt and outputxx.sig (00 is select the next unused file)
  // Input settings
  byte          keyDebounceMs;              // debounce time for the morse key in ms
  byte          EOMTimeout;                 // end of message timeout in 1/10 seconds, 0 is no timeout
  byte          signalTolerancePct;         // The tolerance to be applied to standard signals recognised by receive as a percentage
                                            // if a Dit is 50ms and this is 50 then a Dit should be recognised as 25-75ms
                                            // NOTE MUST STOP OVERLAPS
  byte          promptType;                 // None | Saved | Codegroup | File Type of prompt to be displayed See promptOptions enum
  byte          promptSavedIndex;           // Index to saved Prompts array to use 0-?
  byte          promptCodeGroupLen;         // Length of each code group 1-16
  bool          promptCodeGroupPunctuation; // true if punctuation allowed in codegroups
  byte          promptFile;                 // 00-99 the suffix for the prompt file promptxx.txt
  // Koch Trainer - Recieve
  byte          krLessonNo;                 // Koch receive Lesson Number
  int           krDuration;                 // lesson duration in characters 50-500 
  // Koch Trainer - Transmit
  byte          ktLessonNo;                 // Koch transmit Lesson Number
  int           ktDuration;                 // lesson duration in characters 50-500 
  // The current Run Mode
  byte          runMode;                    // current run mode - see enum runMode
};

enum speedStandard                          // 2 standards
{
  PARIS,
  CODEX
};

enum runMode                                // mode in which to run
{
  KEY,
  TX,
  RX,
  KOCH,
  KOCHKEY
};

enum promptOptions                          // options for the prompt on transmit
{
  PNONE,
  PSAVED,
  PCODEGROUP,
  PFILE
};


struct settings currentSettings = {true, 2, true, PARIS, 15, 5, 0, 5, 30, 50, PSAVED, 0, 8, false, 0, 1, 100, 1, 100, KEY};

//-------------------------------------------------------------------------------------------------------------------------------------------
// setup values to define and control the menus
//-------------------------------------------------------------------------------------------------------------------------------------------

enum menuActions               // action to take on menu item selection, index to define the selectAction union member 
{
  menuCallMenu,                // Menu Item on select goes to another menu, if selectedMenu is 99 call exit menu then exit
  menuSetActive,               // Menu Item Sets the active selects an item, set the *active value from valueSelect or valueUnSelect 
  menuSetValue,                // set a value defined by the min-max parms can set a byte or a char[2]
  menuSelectFromList,          // select a value from a character list and save the index value
  menuRunFunction,             // Menu Item when selected calls the function
  menuBlank                    // used for a blank entry, not selectable, not highlightable, used for a Title, seperator or comment
};

// FOLLOWING ARE PARAMETER STRUCTURES FOR EACH ACTION TYPE
struct SetValue        // selectType = menuSetValue  - details of value to set with what to change on selection
{
  bool  valType;               // value type, true if a byte, false if a char[2]
  byte  minValue;              // minimum value that can be set
  byte  maxValue;              // maximum value that can be set
}; 

struct SetFromList     // selectType = menuSelectFromList  - details of a list of values, array of strings
{
  byte  listEntryCount;        // count of entries in the list, used as the list may not have 6 entries
                               // NOTE Each entry is limited to 7 characters + a null
                               // This is a pointer to the array to avoid using the memory for each menu entry.
  char  *listPtr;//[][8];      // pointer to the list, 2 dimensional array or array of null terminated strings
}; 

union itemParms        // entry identified by menuActions
{
  void *selectFunction;        // selectType = menuRunFunction - pointer to a function to run when the menu item is selected
  byte menu;                   // selectType = menuCallMenu    - menu number (index) of the menu to display on selection (99 = exit Menus)
                               // selectType = menuSetActive   - Settings value is true/false, no parameters needed
  struct SetValue     setItemValue;   // selectType = menuSetValue    - details of value to set type (byte or char[2] and min/max
  struct SetFromList  setListValue;   // selectType = menuSetValue    - details of value to set settings value to change (char[2]) and min/max
                               // selectType = menuBlank       - does not require any values
};

struct MenuItem        // define a Menu Item
{
  byte  selectType;            // indicates the action on select from menuActions, could be another menu, run, toggle the item setting an external bool
                               // call a function to set parameter values? etc.
  char  itemText[18];          // Menu item text i.e. "Setup" Max length of 17 chars Plus the null string terminator
                               // strings are aligned when displayed so leading and trailing spaces should not be used
                               // NOTE: can trim this down to the longest item, Make sure to allow a null at te end,
  void  *settingsValue;        // pointer to the settngs value to set (defined as void, as the type may vary 
  union itemParms parameters;  // the parameters for each action (Some have none)
};


// define a menu
struct Menu
{
  MenuItem  item[4];           // array of 4 menu items in each menu 
};

// function prototypes for functions called from menus
void settingsMenu(void);

char  modeList[5][8] = {"Key", "Tx", "Rx", "Koch", "Koch Tx"};

// Now define the menu structure, and save in progmem as it is all constants
const struct Menu PROGMEM menuDefs[] = 
{
  {             // first entry in menuDefs
    { menuSelectFromList, "MODE", &currentSettings.runMode, { .setListValue = { 5, (char*)&modeList }}},  // first entry in menuDefs.item
    { menuCallMenu, "RUN", NULL, { .menu = 99}},                                                          // second entry in menuDefs.item
    { menuRunFunction, "SETTINGS", NULL,{.selectFunction = &settingsMenu}},                               // third entry in menuDefs.item
    { menuCallMenu, "LIGHT & SOUND", NULL, {.menu = 1}}                                                   // fourth entry in menuDefs.item
  },
  {             // second entry in menuDefs
    { menuSetActive, "BUZZER", &currentSettings.signalBuzzerOn },                                         //....
    { menuSetValue, "BUZZER TONE", &currentSettings.signalTone, {.menu = 99}},
    { menuRunFunction, "SETTINGS", NULL, {.selectFunction = &settingsMenu}},
    { menuCallMenu, "LIGHT & SOUND", NULL, {.menu = 1}}
  }
};

Starting with the low-hanging fruit. This:

void *selectFunction;        // selectType = menuRunFunction - pointer to a function to run when the menu item is selected

Does not declare a pointer to a function as claimed in the comment.

This does:

void (*selectFunction)();

The same error occurs in at least one other place.

Thank you,
I would have got to that eventually, perhaps?

But correcting that just leaves me with the same StructTest1:153: error: too many initializers for 'const Menu'

If it were my project, I’d start over and rebuild the structures and initializations from the ground up by adding one element at a time. Adding things until you break it seems easier than trying to unravel what’s going on here. YMMV.

I Like your response,

But I was hoping that someone would say something like "Why is there an extra comma on line 145?"

I know when I find it I will feel stupid!!!

Try changing this:

const struct Menu PROGMEM menuDefs[] = 
{
  {             // first entry in menuDefs
    { menuSelectFromList, "MODE", &currentSettings.runMode, { .setListValue = { 5, (char*)&modeList }}},  // first entry in menuDefs.item
    { menuCallMenu, "RUN", NULL, { .menu = 99}},                                                          // second entry in menuDefs.item
    { menuRunFunction, "SETTINGS", NULL,{.selectFunction = &settingsMenu}},                               // third entry in menuDefs.item
    { menuCallMenu, "LIGHT & SOUND", NULL, {.menu = 1}}                                                   // fourth entry in menuDefs.item
  },
  {             // second entry in menuDefs
    { menuSetActive, "BUZZER", &currentSettings.signalBuzzerOn },                                         //....
    { menuSetValue, "BUZZER TONE", &currentSettings.signalTone, {.menu = 99}},
    { menuRunFunction, "SETTINGS", NULL, {.selectFunction = &settingsMenu}},
    { menuCallMenu, "LIGHT & SOUND", NULL, {.menu = 1}}
  }
};

to this:

const struct Menu PROGMEM menuDefs[] = 
{
  {             // first entry in menuDefs
    {
      { menuSelectFromList, "MODE", &currentSettings.runMode, { .setListValue = { 5, (char*)&modeList }}},  // first entry in menuDefs.item
      { menuCallMenu, "RUN", NULL, { .menu = 99}},                                                          // second entry in menuDefs.item
      { menuRunFunction, "SETTINGS", NULL,{.selectFunction = &settingsMenu}},                               // third entry in menuDefs.item
      { menuCallMenu, "LIGHT & SOUND", NULL, {.menu = 1}}                                                   // fourth entry in menuDefs.item
    }
  },
  {             // second entry in menuDefs
    {
      { menuSetActive, "BUZZER", &currentSettings.signalBuzzerOn },                                         //....
      { menuSetValue, "BUZZER TONE", &currentSettings.signalTone, {.menu = 99}},
      { menuRunFunction, "SETTINGS", NULL, {.selectFunction = &settingsMenu}},
      { menuCallMenu, "LIGHT & SOUND", NULL, {.menu = 1}}
    }
  }
};

Note the additional level of braces.

Thank you christop.

And DOH!

I knew that but just couldn't see it.

And thanks to everyone else as well.