Passing a menu structure to a function

How do I pass a pointer to my menu structure to a function?

The menu structure is:

const prog_char M0[] PROGMEM = "Exit            /                ";
const prog_char M1[] PROGMEM = "Run Spherical   / panorama       ";
const prog_char M7[] PROGMEM = "Center motors   /                ";
const prog_char M2[] PROGMEM = "Setup           / field of view  ";
const prog_char M3[] PROGMEM = "Setup           / tilt limits    ";
const prog_char M4[] PROGMEM = "Picture order   / (Up/Dn, L/R)   ";
const prog_char M5[] PROGMEM = "Advanced options/                ";
const prog_char M6[] PROGMEM = "Program info    /                ";
const prog_char *menuList[] PROGMEM = {M0,M1,M7,M2,M3,M4,M5,M6};

I'm trying to use a common routine to scroll through the menu and future submenus. I enter the menu with this code.

void MenuSelect() {
  int menuItem;
  menuItem = MenuLoop(*menuList);
  switch (menuItem)
  {
...

and loop through the menu options with the code below.

int MenuLoop(prog_char *menu[])
{
  int menuItem = 1;
  strcpy_P(line1, (char*)pgm_read_word(&(menu[menuItem])));
  LCDWrite(line1);
...

Except I can't get the parameter syntax correct. What is the proper way to pass the pointer to the structure and be able to access it with the PROGMEM functions?

Except I can't get the parameter syntax correct.

Show us what you have tried, and the error message(s) that you see.

You have an array of pointers that you seem to be trying (incorrectly) to reference as though it was a single object.

Here is a shortened version of the code.

#include <avr/pgmspace.h>

//menu items
//                              0123456789012345/0123456789012345
const prog_char M0[] PROGMEM = "Exit            /                ";
const prog_char M1[] PROGMEM = "Run Spherical   / panorama       ";
const prog_char M7[] PROGMEM = "Center motors   /                ";
const prog_char M2[] PROGMEM = "Setup           / field of view  ";
const prog_char M3[] PROGMEM = "Setup           / tilt limits    ";
const prog_char M5[] PROGMEM = "Advanced options/                ";
const prog_char M6[] PROGMEM = "Program info    /                ";
const prog_char *menuList[] PROGMEM = {M0,M1,M7,M2,M3,M5,M6};
const int menuCount = 7;      //number of menu items

char line1[34];

void setup() 
{ 
  Serial.begin(9600);
  menuSelect();
} 
  
void loop() 
{
}

int MenuLoop(prog_char menu)
{
  boolean exitMenu = false;
  int menuItem = 1;
  for (menuItem = 1; menuItem < 3; menuItem++)
  {
    strcpy_P(line1, (char*)pgm_read_word(&(menu[menuItem])));
    Serial.println(line1);
  }
  return menuItem;
}


void MenuSelect() {
  int menuItem;
  menuItem = MenuLoop(*menuList);
  Serial.println(menuItem);
}

Run with calling the function MenuLoop(prog_char menu) with the command MenuLoop(menuList) I get the errors
Menu_array_test.cpp: In function ‘int MenuLoop(prog_char)’:
Menu_array_test:33: error: invalid types ‘prog_char[int]’ for array subscript
Menu_array_test.cpp: In function ‘void MenuSelect()’:
Menu_array_test:42: error: invalid conversion from 'const prog_char
’ to ‘prog_char’
Menu_array_test:42: error: initializing argument 1 of ‘int MenuLoop(prog_char)’

So i’m not doing either command correctly.

The problem is I’m not sure what I’m trying to do. I think I’m trying to pass a pointer to the array to the function so that I can use it in the PROGMEM strcpy_P call. This way I can use the same menu display looping function for all menus and submenus.

If I change to

int MenuLoop(const prog_char *menu)

then it compiles but crashes when it gets to the strcpy_P call (it restarts the program).

I think I'm trying to pass a pointer to the array to the function

menuList is an array of pointers. If you are going to pass it to a function, and I really can't see the need to pass a global variable to a function, the function argument needs to match the variable type you are trying to pass it.

int MenuLoop(prog_char menu)

says nothing about the argument being either a pointer or an array.

I have to tell the MenuLoop function which array to use; main menu menuList or advanced menu advancedList. What is the best way to do that so I don’t have to write a looping function for each menu?

Since the variable that you want to pass to the function is defined like: const prog_char *menuList[], I'd define the function to take that type of variable as an argument.

When I change the function argument to:

int MenuLoop(const prog_char *menu[])

I get the error cannot convert 'const prog_char*' to 'const prog_char**'

When I change the function argument to:

int MenuLoop(const prog_char *menu)

it crashes at

strcpy_P(line1, (char*)pgm_read_word(&(menu[menuItem])));

Is this not the right data type for the strcpy_P function?

When I change the function argument to:

You know what the argument type needs to be. Make it that and quit trying to make the compiler happy by changing it.

The compiler is not complaining about the function. It is complaining about how you are trying to call the function.

With the function defined as

int MenuLoop(const prog_char *menu[])

you should be able to call it

MenuLoop(menuList);

since the arguments then match.

When I change the function argument to: it crashes at

Not surprising, as what you passed it was not correct.

Got it!

#include <avr/pgmspace.h>

//menu items
//                              0123456789012345/0123456789012345
const prog_char M0[] PROGMEM = "Exit            /                ";
const prog_char M1[] PROGMEM = "Run Spherical   / panorama       ";
const prog_char M7[] PROGMEM = "Center motors   /                ";
const prog_char M2[] PROGMEM = "Setup           / field of view  ";
const prog_char M3[] PROGMEM = "Setup           / tilt limits    ";
const prog_char M5[] PROGMEM = "Advanced options/                ";
const prog_char M6[] PROGMEM = "Program info    /                ";
const prog_char *menuList[] PROGMEM = {M0,M1,M7,M2,M3,M5,M6};
const int menuCount = 7;      //number of menu items

char line1[34];

void setup() 
{ 
  Serial.begin(9600);
  MenuSelect();
} 
  
void loop() 
{
}

int MenuLoop(const prog_char *menu[])
{
  Serial.println("MenuLoop");
  boolean exitMenu = false;
  int menuItem = 1;
  for (menuItem = 1; menuItem < 3; menuItem++)
  {
    Serial.println("FOR loop");
    strcpy_P(line1, (char*)pgm_read_word(&(menu[menuItem])));
    Serial.println(line1);
    delay(400);
  }
  return menuItem;
}


void MenuSelect() {
  int menuItem;
  menuItem = MenuLoop(menuList);
  Serial.println(menuItem);
}

Thanks for your help.
And thanks for other posts that helped me figure out my memory issues. This is turning out to be a cool project and a lot of fun and learning.