Noob help with strings and arrays.

I am trying to build a menu using a matrix-like array. I am noob to this so please excuse my stupidity.

Say i wanted to make an array of titles/names for a menu like this (syntax/structure/understanding may be out of whack so bear with me)

char Menu [][][] =
{
{"Title1","Title2","Title3"},
{"Item1","Item2","Item3"},
{"Item1","Item2","Item3"},
{"Item1","Item2","Item3"}
}

And then do some switch cases that result in 2 variables
uint8_t MODE, ITEM;

Where i would like to pass that data on like so:

// inside u8g picture loop
u8g.setpos (64-u8g.getstrwidth(Menu [ITEM][MODE])/2);
U8g.print (Menu [ITEM][MODE);

My questions are as follows:

  1. How do i initialize that array give 20 colums and 8 rows with a maximum text length of 18 characters

  2. How do i exclusively store that array in progmem wirhout using sram

  3. How do i call it back and pass it on to u8glib functions. I am especially having trouble with getstrwidth.

Any help is greatly appreciated.

Ps. Full code is huge so i tried to make a snippet just as an idea as opposed to posting that hulk of a monstrosity on here.

So you want to add another monstrosity? Go ahead. I hope you have enough RAM.

char Menu [8][20][19] = {
  {"Title1", "Title2", "Title3", "Title4", "Title5", "Title6", "Title7", "Title8", "Title9", "Title10", "Title11", "Title12", "Title13", "Title14", "Title15", "Title16", "Title17", "Title18", "Title19", "Title20"},
  {"L1-Item1", "L1-Item2", "L1-Item3", "L1-Item4", "L1-Item5", "L1-Item6", "L1-Item7", "L1-Item8", "L1-Item9", "L1-Item10", "L1-Item11", "L1-Item12", "L1-Item13", "L1-Item14", "L1-Item15", "L1-Item16", "L1-Item17", "L1-Item18", "L1-Item19", "L1-Item20"},
  {"L2-Item1", "L2-Item2", "L2-Item3", "L2-Item4", "L2-Item5", "L2-Item6", "L2-Item7", "L2-Item8", "L2-Item9", "L2-Item10", "L2-Item11", "L2-Item12", "L2-Item13", "L2-Item14", "L2-Item15", "L2-Item16", "L2-Item17", "L2-Item18", "L2-Item19", "L2-Item20"},
  {"L3-Item1", "L3-Item2", "L3-Item3", "L3-Item4", "L3-Item5", "L3-Item6", "L3-Item7", "L3-Item8", "L3-Item9", "L3-Item10", "L3-Item11", "L3-Item12", "L3-Item13", "L3-Item14", "L3-Item15", "L3-Item16", "L3-Item17", "L3-Item18", "L3-Item19", "L3-Item20"},
  {"L4-Item1", "L4-Item2", "L4-Item3", "L4-Item4", "L4-Item5", "L4-Item6", "L4-Item7", "L4-Item8", "L4-Item9", "L4-Item10", "L4-Item11", "L4-Item12", "L4-Item13", "L4-Item14", "L4-Item15", "L4-Item16", "L4-Item17", "L4-Item18", "L4-Item19", "L4-Item20"},
  {"L5-Item1", "L5-Item2", "L5-Item3", "L5-Item4", "L5-Item5", "L5-Item6", "L5-Item7", "L5-Item8", "L5-Item9", "L5-Item10", "L5-Item11", "L5-Item12", "L5-Item13", "L5-Item14", "L5-Item15", "L5-Item16", "L5-Item17", "L5-Item18", "L5-Item19", "L5-Item20"},
  {"L6-Item1", "L6-Item2", "L6-Item3", "L6-Item4", "L6-Item5", "L6-Item6", "L6-Item7", "L6-Item8", "L6-Item9", "L6-Item10", "L6-Item11", "L6-Item12", "L6-Item13", "L6-Item14", "L6-Item15", "L6-Item16", "L6-Item17", "L6-Item18", "L6-Item19", "L6-Item20"},
  {"L7-Item1", "L7-Item2", "L7-Item3", "L7-Item4", "L7-Item5", "L7-Item6", "L7-Item7", "L7-Item8", "L7-Item9", "L7-Item10", "L7-Item11", "L7-Item12", "L7-Item13", "L7-Item14", "L7-Item15", "L7-Item16", "L7-Item17", "L7-Item18", "L7-Item19", "L7-Item20"},
};

void setup() {
  Serial.begin(250000);
  Serial.print(F("The size of array Menu is "));
  Serial.print(sizeof(Menu));
  Serial.println(F(" bytes."));
  Serial.println(Menu[1][4]);
}

void loop() {}
The size of array Menu is 3040 bytes.
L1-Item5

You could include all the text items in a linear (one dimension) array in Progmem and use your program to retrieve them in any order or grouping that you need.

...R

On some Arduinos you could move the strings to PROGMEM,
but I don't know whether ug8 lib supports that directly.

const char Menu [8][20][19] PROGMEM = {
  {"Title1", "Title2", "Title3", "Title4", "Title5", "Title6", "Title7", "Title8", "Title9", "Title10", "Title11", "Title12", "Title13", "Title14", "Title15", "Title16", "Title17", "Title18", "Title19", "Title20"},
  {"L1-Item1", "L1-Item2", "L1-Item3", "L1-Item4", "L1-Item5", "L1-Item6", "L1-Item7", "L1-Item8", "L1-Item9", "L1-Item10", "L1-Item11", "L1-Item12", "L1-Item13", "L1-Item14", "L1-Item15", "L1-Item16", "L1-Item17", "L1-Item18", "L1-Item19", "L1-Item20"},
  {"L2-Item1", "L2-Item2", "L2-Item3", "L2-Item4", "L2-Item5", "L2-Item6", "L2-Item7", "L2-Item8", "L2-Item9", "L2-Item10", "L2-Item11", "L2-Item12", "L2-Item13", "L2-Item14", "L2-Item15", "L2-Item16", "L2-Item17", "L2-Item18", "L2-Item19", "L2-Item20"},
  {"L3-Item1", "L3-Item2", "L3-Item3", "L3-Item4", "L3-Item5", "L3-Item6", "L3-Item7", "L3-Item8", "L3-Item9", "L3-Item10", "L3-Item11", "L3-Item12", "L3-Item13", "L3-Item14", "L3-Item15", "L3-Item16", "L3-Item17", "L3-Item18", "L3-Item19", "L3-Item20"},
  {"L4-Item1", "L4-Item2", "L4-Item3", "L4-Item4", "L4-Item5", "L4-Item6", "L4-Item7", "L4-Item8", "L4-Item9", "L4-Item10", "L4-Item11", "L4-Item12", "L4-Item13", "L4-Item14", "L4-Item15", "L4-Item16", "L4-Item17", "L4-Item18", "L4-Item19", "L4-Item20"},
  {"L5-Item1", "L5-Item2", "L5-Item3", "L5-Item4", "L5-Item5", "L5-Item6", "L5-Item7", "L5-Item8", "L5-Item9", "L5-Item10", "L5-Item11", "L5-Item12", "L5-Item13", "L5-Item14", "L5-Item15", "L5-Item16", "L5-Item17", "L5-Item18", "L5-Item19", "L5-Item20"},
  {"L6-Item1", "L6-Item2", "L6-Item3", "L6-Item4", "L6-Item5", "L6-Item6", "L6-Item7", "L6-Item8", "L6-Item9", "L6-Item10", "L6-Item11", "L6-Item12", "L6-Item13", "L6-Item14", "L6-Item15", "L6-Item16", "L6-Item17", "L6-Item18", "L6-Item19", "L6-Item20"},
  {"L7-Item1", "L7-Item2", "L7-Item3", "L7-Item4", "L7-Item5", "L7-Item6", "L7-Item7", "L7-Item8", "L7-Item9", "L7-Item10", "L7-Item11", "L7-Item12", "L7-Item13", "L7-Item14", "L7-Item15", "L7-Item16", "L7-Item17", "L7-Item18", "L7-Item19", "L7-Item20"},
};

void setup() {
  Serial.begin(250000);
  Serial.print(F("The size of array Menu is "));
  Serial.print(sizeof(Menu));
  Serial.println(F(" bytes."));
  Serial.println((__FlashStringHelper*)Menu[1][4]);
}

void loop() {}
The size of array Menu is 3040 bytes.
L1-Item5

But now the array resides in PROGMEM, not RAM.

Thank you so much. Sorry for the stupidity but I am just trying to understand why you consider this such a monstrosity compared to a bunch of single dimension declarations? How would you approach it in order to save resources. Like i said im noobish so please be gentle lol.

Are the entries in the array the real data for the menus or just dummies to experiment with ?

The_silver1:
Thank you so much. Sorry for the stupidity but I am just trying to understand why you consider this such a monstrosity compared to a bunch of single dimension declarations? How would you approach it in order to save resources. Like i said im noobish so please be gentle lol.

Forget all that monstrosity talk..., if your program intent is to move through menu options then you need to define the text, there is no way around that (even harsh commentary won't solve the issue for you :wink: ).

If you can do it programmatically, you can save a lot of space, e.g.

{"Sensor1", "Sensor2", ... "SensorN"}

would be something that you can just store the word Sensor and then select the number from where it is in an array.

Ukhelibob.
The entries are just (sub)menu titles and titles of menu items within that (sub)menu.

Bulldoglowell

Yes the intent is to have a list of menu items and menu titles. This so that i can use a for loop to print the items based on the "mode" and progress thru menu using switch cases for ascertaining the selections and menu modes. Is there a better way of approaching this? I am all ears. Im not quite sure i understand what you meant by doing it "programmatically". If you mean doing it using an array, thats what im trying to do. The only reason i chose multidimensional is just for ease of organization and adjustment as needed.

Also in whandal's code he uses __FlashStringHelper which im not sure if its a standard arduino function or if it calls to some library that is not included. Additionaly what do f() and the * do in that situation? I tried googling (albeit quickly) in order to grasp whats going on but it was of no help lol

The_silver1:
Ukhelibob.
The entries are just (sub)menu titles and titles of menu items within that (sub)menu.

Bulldoglowell

Yes the intent is to have a list of menu items and menu titles. This so that i can use a for loop to print the items based on the "mode" and progress thru menu using switch cases for ascertaining the selections and menu modes. Is there a better way of approaching this? I am all ears

programmatically constructing the strings is a better way, if possible.

if you have many discreet menu topics/names then you have to get clever about how to efficiently store them.

the design/definition of the progression of menu output would influence how to store all that.

what do your menus look like (in real life)?

Is there a better way of approaching this?

That is why I asked whether the data in the array was real or just a test. If it were real then as BL pointed out above you don't need an array as you could create the required text on the fly based on the menu level and entry number. Depending on what you want to print that may still be possible.

Guys plese excuse me, i am stupid when it comes to this... its a little outside of my skill level but i am trying to learn. I think i have come a long way without bothering any gurus here however i have hit a wall i cant climb on my own. Also my response time is slow since im typing on phome and am new user so am limited with how many posts i can write within a given time. (Really sucks for edits lol)

Sorry ukhelibob, i didnt understand what you meant by real vs test. I assumed real meant variable data.

Bulldoglowell

Menu structure:

Not really code but gives the idea.
Main menu  -> submenu 
                                 -items
                                 -items
                                 -items
                                 -items  -> item4submenu 
                                                         -Items -> user input menu
                   ->submenu 2

Basic structure is as above obv its just a sample. Its a little more complex bc im checking button state for hold, dbl click or single click.

How im handling it:

uint8_t MODE, SELECTED;
#define main_menu 0

If (btn != held && btn != dbl_click){
Switch (MODE) // mode is yhe colum of array
{
 case main_menu: 
    Switch (selected) //selected is row of array
      {
        case 1: // start from 1 since position 0 in array is title
        MODE = 4; // (call menu 4 based on selection 1 of mode 0)
        break;
      // other cases
      }
     break;
   //cases for other menu modes
 }
Disp_draw () // draws display using u8g picture loop
}

partial menu handling code

void BTN_STATE_CHANGE()
{
  switch (MENU_MODE)
  {
    case 0: // home screen
      MENU_MODE = 1;
      SELECTED_ITEM = 1;
      break;
    case 1: // MAIN MENU
      switch (SELECTED_ITEM)
      {
        case 1://INPUT
          MENU_MODE = 2;
          if ( bitRead(CURRENT_CONFIG, 0) == 1) {
            SELECTED_ITEM = 1;
          }
          else if ( bitRead(CURRENT_CONFIG, 1) == 1) {
            SELECTED_ITEM = 2;
          }
          else if ( bitRead(CURRENT_CONFIG, 2) == 1) {
            SELECTED_ITEM = 4;
          }
          else if ( bitRead(CURRENT_CONFIG, 3) == 1) {
            SELECTED_ITEM = 3;
          }
          else
          {
            SELECTED_ITEM = 1;
          }
          break;
        case 2://SETTINGS
          MENU_MODE = 3;
          SELECTED_ITEM = 1;
          break;
        case 3: // POWER
          MENU_MODE = 12;
          SELECTED_ITEM = 1;
          break;
      }
      break;
    case 2:// SELECT INPUT
      switch (SELECTED_ITEM)
      {
        case 1: // BLUETOOTH
          if ( bitRead(CURRENT_CONFIG, 4) == 1) {
            CURRENT_CONFIG = BT + QC;
          }
          if ( bitRead(CURRENT_CONFIG, 4) == 0) {
            CURRENT_CONFIG = BT;
          }
          break;
        case 2: // CHROMECAST
          if ( bitRead(CURRENT_CONFIG, 4) == 1) {
            CURRENT_CONFIG = CC + QC;
          }
          if ( bitRead(CURRENT_CONFIG, 4) == 0) {
            CURRENT_CONFIG = CC;
          }
        case 3:// RADIO
          if ( bitRead(CURRENT_CONFIG, 4) == 1) {
            CURRENT_CONFIG = RF + QC;
          }
          if ( bitRead(CURRENT_CONFIG, 4) == 0) {
            CURRENT_CONFIG = RF;
          }
          break;
        case 4: // AUX
          if ( bitRead(CURRENT_CONFIG, 4) == 1) {
            CURRENT_CONFIG = AUX + QC;
          }
          if ( bitRead(CURRENT_CONFIG, 4) == 0) {
            CURRENT_CONFIG = AUX;
          }
          break;
      }
      SET_INPUTS(CURRENT_CONFIG);
      MENU_MODE = 0;
      SELECTED_ITEM = 1;
      break;

lol, my newb timelimit screwed up the timing of my posting that edit so I'm reposting it so its noticed lol.

Bulldoglowel,

The_silver1:
... I am all ears. I'm not quite sure I understand what you meant by doing it "programmatically". If you mean doing it using an array, that's what I'm trying to do. The only reason I chose a multidimensional array is just for ease of organization and adjustment as needed.

Also in whandal's code, he uses __FlashStringHelper which I'm not sure if its a standard Arduino function or if it calls to some library that is not included. Additionally, what do f() and the * do in that situation? I tried googling (albeit quickly) in order to grasp whats going on but it was of no help lol

ukhelibob that's awesome -> "May all of your blinks be without delay()"

p.p.s in all fairness I don't think Whandal was being too harsh. I initially called my full code a hulk of a monstrosity and he was referring to making it more monstrous I guess lol?

Not really code but gives the idea.
Main menu  -> submenu 
                                 -items
                                 -items
                                 -items
                                 -items  -> item4submenu 
                                                         -Items -> user input menu
                   ->submenu 2

that's a real example?

BulldogLowell:
that's a real example?

I'm not sure I understand your question. if you're being sarcastic then no sir it's not a real example. I was just trying to (poorly) illustrate the idea. if I misread and no sarcasm implied then yes that's the basic structure. Will go a few levels deeper though. I think the deepest level is 5 levels deep.

sry, but does this make more sense?:

MAIN MENU
{
  ITEM1 //submenu 1
  ITEM2 //submenu 2
  ITEM3 //submenu 3
}


SUBMENU1 
{
  ITEM1 //sub- submenu 1
  ITEM2 //sub- submenu 2
  ITEM3 //sub- submenu 3
}


sub- SUBMENU1 
{
  ITEM1 //sub -sub- submenu 1
  ITEM2 //user input menu
  ITEM3 //sub -sub- submenu 3
}

etc....

So if we are in the main menu the text on the screen says
ITEM1
ITEM2
ITEM3

In submenu 1 the text on the screen says
ITEM1
ITEM2
ITEM3

Is that right ?
It seems unlikely, but only you know

UKHeliBob:
Is that right ?
It seems unlikely, but only you know

I was only using ITEM# as a place holder

keep in mind that SELECTED is cycled using rotary encoder ++ or --

so it would look like

const char MENU_ARRAY [8][20][19] PROGMEM  = {"HOME", "Main Menu", "Input Menu", "settings menu", "charge menu", "battery menu", "filters menu".......},
                    {"","input menu", "ble", "charge","full charge","Max Cell V", "lpf".........},
                    {"","settings menu","aux", "qc only","storage charge","Min Cell V", "lpf level"......},
                    {"","power menu", "cc" , "screen","","Storage V", "bpf".......},
                    {"","", "rf", "filters","","","bpf level".......},
                    {"","", "", "levels","","".......},
                    {"","", "","battery","","".......},
                    {"","","","","","".......},
int items[]     =  {0,3, 4,6,2,3,4.......};

/*
main menu
title = "Main Menu"
MENU_MODE = 1; //arbitrarynumber to keep track of what menu we are in
ITEM1 = "INPUT MENU"
ITEM2 = "SETTINGS MENU"
ITEM3 = "POWER MENU"
SELECTED >=1 && SELECTED <=3
*/

/*
INPUT MENU
title = "input Menu"
MENU_MODE = 2;  //arbitrarynumber to keep track of what menu we are in
ITEM1 = "BLE"
ITEM2 = "AUX"
ITEM3 = "CC"
ITEM4 = "RF"
SELECTED >=1 && SELECTED <=4
*/

/*
settings MENU
title = "settings Menu"
MENU_MODE = 3; //arbitrarynumber to keep track of what menu we are in
ITEM1 = "Charge"
ITEM2 = "QC ONLY"
ITEM3 = "Screen"
ITEM4 = "Filters"
ITEM5 = "Levels"
ITEM6 = "Battery"
SELECTED >=1 && SELECTED <=6
*/

/*
CHARGE MENU
title = "Charge Menu"
MENU_MODE = 4; //arbitrarynumber to keep track of what menu we are in
ITEM1 = "Full Charge"
ITEM2 = "Storage Charge"
SELECTED >=1 && SELECTED <=2
*/

/*
BATTERY MENU
title = "Battery Menu"
MENU_MODE = 5; //arbitrarynumber to keep track of what menu we are in
ITEM1 = "Max Cell V"
ITEM2 = "Min Cell V"
ITEM3 = "Storage V"
SELECTED >=1 && SELECTED <=3
*/

/*
FILTERS MENU
title = "Filters Menu"
MENU_MODE = 6; //arbitrarynumber to keep track of what menu we are in
ITEM1 = "LPF"
ITEM2 = "LPF LEVEL"
ITEM3 = "BPF"
ITEM4 = "BPF LEVEL"
SELECTED >=1 && SELECTED <=4
*/

/*

MORE MENUS HERE

*/


// this is how i would like to draw display

u8g.firstPage();
  do {
    if (MENU_MODE >= 1 && MENU_MODE <= 14) // IF IN A MENU DRAW THAT MENU
    {
      //DRAW TITLE
      u8g.setFont(CURRENT_FONT);
      u8g.setColorIndex(1);
      u8g.drawBox(0, 0, 127, 12);
      u8g.setPrintPos((int(64 - (u8g.getStrWidth((__FlashStringHelper*)MENU_ARRAY[0][MENU_MODE]) / 2))), 10);
      u8g.setColorIndex(0);
      u8g.print((__FlashStringHelper*)MENU_ARRAY[0][MENU_MODE]);
      u8g.setColorIndex(1);
      u8g.drawLine(0, 13, 127, 13);
      //DRAW ITEMS
      for (uint8_t i = 1; i < ITEMS[MENU_MODE]; i++)
      {
        u8g.setPrintPos(10, (3 + 10 * (i + 1)));
        u8g.print((__FlashStringHelper*)MENU_ARRAY[i][MENU_MODE]);
      }
      u8g.setPrintPos(0, (3 + 10 * (SELECTED_ITEM + 1)));
      u8g.print("->");
    }
// BETWEEN MENU_MODE 14 TO 19 DRAW APPROPRIATE USER INPUT SCREENS (BAR GRAPH, VOLTAGE, PERCENT,)
}while u8g.nextpage}; //THE SYNTAX HERE IS NOT CORRECT



// THIS IS HOW I HANDLE MENU SELECTION.... I USE INTERRUPTS TO CALL THIS FUNCTION
// button pressed handling

void BTN_STATE_CHANGE()
{
  switch (MENU_MODE)
  {
    case 0: // home screen
      MENU_MODE = 1;
      SELECTED_ITEM = 1;
      break;
    case 1: // MAIN MENU
      switch (SELECTED_ITEM)
      {
        case 1://INPUT
          MENU_MODE = 2;
          if ( bitRead(CURRENT_CONFIG, 0) == 1) {
            SELECTED_ITEM = 1;
          }
          else if ( bitRead(CURRENT_CONFIG, 1) == 1) {
            SELECTED_ITEM = 2;
          }
          else if ( bitRead(CURRENT_CONFIG, 2) == 1) {
            SELECTED_ITEM = 4;
          }
          else if ( bitRead(CURRENT_CONFIG, 3) == 1) {
            SELECTED_ITEM = 3;
          }
          else
          {
            SELECTED_ITEM = 1;
          }
          break;
        case 2://SETTINGS
          MENU_MODE = 3;
          SELECTED_ITEM = 1;
          break;
        case 3: // POWER
          MENU_MODE = 12;
          SELECTED_ITEM = 1;
          break;
      }
      break;
    case 2:// SELECT INPUT
      switch (SELECTED_ITEM)
      {
        case 1: // BLUETOOTH
          if ( bitRead(CURRENT_CONFIG, 4) == 1) {
            CURRENT_CONFIG = BT + QC;
          }
          if ( bitRead(CURRENT_CONFIG, 4) == 0) {
            CURRENT_CONFIG = BT;
          }
          break;
        case 2: // CHROMECAST
          if ( bitRead(CURRENT_CONFIG, 4) == 1) {
            CURRENT_CONFIG = CC + QC;
          }
          if ( bitRead(CURRENT_CONFIG, 4) == 0) {
            CURRENT_CONFIG = CC;
          }
        case 3:// RADIO
          if ( bitRead(CURRENT_CONFIG, 4) == 1) {
            CURRENT_CONFIG = RF + QC;
          }
          if ( bitRead(CURRENT_CONFIG, 4) == 0) {
            CURRENT_CONFIG = RF;
          }
          break;
        case 4: // AUX
          if ( bitRead(CURRENT_CONFIG, 4) == 1) {
            CURRENT_CONFIG = AUX + QC;
          }
          if ( bitRead(CURRENT_CONFIG, 4) == 0) {
            CURRENT_CONFIG = AUX;
          }
          break;
      }
      SET_INPUTS(CURRENT_CONFIG);
      MENU_MODE = 0;
      SELECTED_ITEM = 1;
      break;

...
}

I was only using ITEM# as a place holder

Hooray, we finally got there.

As expected the entries in the array are not the real ones.

MENU_ARRAY[][][] =

You are still messing up the syntax, why?

UKHeliBob:
As expected the entries in the array are not the real ones.

lolllllll now you lost me completely. "real" ones? please, sir, excuse my stupidity and explain if you could

Whandall:
You are still messing up the syntax, why?

wasn't doing it intentionally. a lot of syntax errors there. was only using that to illustrate my point. my apologies, sorry sir(if anyone is not a sir i am sorry, no harm meant)

EDIT: fixed best as could for demo code. demo code does not have entire array or entire menu/button/draw handling code.

whandall. did i use (__FlashStringHelper*) right in u8g.print?

as in:

u8g.setPrintPos((int(64 - (u8g.getStrWidth((__FlashStringHelper*)MENU_ARRAY[0][MENU_MODE]) / 2))), 10); // find width of title to center the string
      u8g.setColorIndex(0);
      u8g.print((__FlashStringHelper*)MENU_ARRAY[0][MENU_MODE]); // print title

lolllllll now you lost me completely. "real" ones? please, sir, excuse my stupidity and explain if you could

The original array had entries like this

{"Title1", "Title2", "Title3", "Title4", "Title5", "Title6", "Title7", "Title8", "Title9", "Title10", "Title11", "Title12", "Title13", "Title14", "Title15", "Title16", "Title17", "Title18", "Title19", "Title20"},
  {"L1-Item1", "L1-Item2", "L1-Item3", "L1-Item4", "L1-Item5", "L1-Item6", "L1-Item7", "L1-Item8", "L1-Item9", "L1-Item10", "L1-Item11", "L1-Item12", "L1-Item13", "L1-Item14", "L1-Item15", "L1-Item16", "L1-Item17", "L1-Item18", "L1-Item19", "L1-Item20"},

The names could have been created in the program without the use of an array by adding a number to some text

Now we know that the entries are really

{"HOME", "Main Menu", "Input Menu", "settings menu", "charge menu", "battery menu", "filters menu".......},
                    {"","input menu", "ble", "charge","full charge","Max Cell V", "lpf".........},

They can't be created by the program by adding a number to some text