Change Menu Buttons

I'm working on a simple menu & sub menu using 3 buttons (up/down/select)

up/down controls main menu unless I press select, then it controls the sub menu instead,

I can't seem to figure out how to make the select button take me back to controlling the main menu, any ideas?

https://www.youtube.com/watch?v=0M3XRUYQLEg



#include <SPI.h>
#include <ST7789_t3.h> // Hardware-specific library

// pin definition for teensy 4.0 + ST7739
#define TFT_CS    10
#define TFT_MOSI  11
#define TFT_MISO  12
#define TFT_SCK   13
#define TFT_RST   14
#define TFT_DC    15

// For 1.9" TFT with ST7789
ST7789_t3 tft = ST7789_t3(TFT_CS, TFT_DC, TFT_RST);

volatile byte menuPage = 0; // stores the current page position.
volatile byte oldMenuPage = 0; // stores the last page position.

volatile byte subPage = 0;  // stores the current preset position.
volatile byte oldsubPage = 0; // stores the last preset position.

// Button reading, including debounce without delay function declarations
const byte upButton = 23; // Up Button
const byte downButton = 22; // Down Button
const byte selectButton = 21; // Select Button

byte oldButtonState1 = HIGH;  // assume switch open because of pull-down resistor
byte oldButtonState2 = HIGH;  // assume switch open because of pull-down resistor
byte oldButtonState3 = HIGH;  // assume switch open because of pull-down resistor

const unsigned long debounceTime = 100;  // milliseconds
unsigned long buttonPressTime;  // when the switch last changed state
boolean buttonPressed = 0; // a flag variable

volatile boolean mainMenu = true;
//volatile boolean subMenu = false;


//******************************************************************************************



void setup() {

  // button section of setup
  pinMode (upButton, INPUT_PULLUP);    // setup the button pins
  pinMode (downButton, INPUT_PULLUP);
  pinMode (selectButton, INPUT_PULLUP);


  tft.init(172, 320);   // initialize a ST7789 chip, 172x320 pixels
  tft.setRotation(1);
  tft.fillScreen(ST7735_BLACK);
  tft.setTextColor(ST7735_WHITE);
  tft.setTextSize(3);
  // tft.setFont(&TypoHoopRegular20pt7b);
  tft.setCursor(5, 146);
  tft.print("<");
  tft.setCursor(302, 146);
  tft.print(">");
  tft.setCursor(130, 5);
  tft.print("PAGE 1");

}



//******************************************************************************************




void loop() {

  menuList();
  subPageList();
  readSelectButton();
  readUpButton();
  readDownButton();
  // **** to do **** if select button pressed, flip-flop between presetList() and menuList()
  // **** to do **** if mainMenu active, up/down buttons control mainMenu only
  // **** to do **** if subMenu active, up/down buttons control subMenu only

} // end of loop



//******************************************************************************************



void readUpButton() {

  // UP BUTTON
  byte buttonState2 = digitalRead (upButton);
  if (buttonState2 != oldButtonState2) {
    if (millis () - buttonPressTime >= debounceTime) { // debounce
      buttonPressTime = millis ();  // when we closed the switch
      oldButtonState2 =  buttonState2;  // remember for next time

      if (buttonState2 == LOW && mainMenu == true) {   // if button up pressed & main menu is active

        menuPage ++; //increment the current menu page's position count
        if (menuPage > 2) {
          menuPage = 0;  //0-2 (3 menu pages)
        }
      }
      else if (buttonState2 == LOW && mainMenu == false) {   // if button up pressed & sub menu is active
        subPage ++;
                if (subPage > 5) {
          subPage = 0;  ///0-5 (6 sub menu pages)
        }
      } // end of else if
    }  // end if debounce time up
  } // end of state change
} // end of function



void readDownButton() {

  // Down Button
  byte buttonState1 = digitalRead (downButton);
  if (buttonState1 != oldButtonState1) {
    if (millis () - buttonPressTime >= debounceTime) { // debounce
      buttonPressTime = millis ();  // when we closed the switch
      oldButtonState1 =  buttonState1;  // remember for next time

      if (buttonState1 == LOW && mainMenu == true) { // if button down pressed & main menu is active
        // "Button Pressed"

        menuPage --; //decrement the current menu page's position count
        if (menuPage > 200) {
          menuPage = 2;  ///0-2 (3 menu pages)
        }
      }
       else if (buttonState1 == LOW && mainMenu == false) {   // if button up pressed & sub menu is active
        subPage --;
        if (subPage > 200) {
          subPage = 5;  ///0-5 (6 sub menu pages)
        }
      } // end of else if
    }  // end if debounce time up
  } // end of state change
} // end of function


void readSelectButton() {

  // Select Button
  byte buttonState3 = digitalRead (selectButton);
  if (buttonState3 != oldButtonState3) {
    if (millis () - buttonPressTime >= debounceTime) { // debounce
      buttonPressTime = millis ();  // when we closed the switch
      oldButtonState3 =  buttonState3;  // remember for next time

      if (buttonState3 == LOW) {
        // "Button Pressed"
        mainMenu = false;  // if pressed again make true
        //subMenu = true;
      }
    }  // end if debounce time up
  } // end of state change
} // end of function


void menuList() {

  if (oldMenuPage != menuPage) {
    oldMenuPage = menuPage;

    // 3 menu pages
    switch (menuPage) {
      case 0:    // Page 1
        tft.fillScreen(ST7735_BLACK);
        tft.setCursor(5, 146);
        tft.print("<");
        tft.setCursor(302, 146);
        tft.print(">");
        tft.setCursor(130, 5);
        tft.print("PAGE 1");

        // load subPage() if selected<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
        break;

      case 1:    // Page 2
        tft.fillScreen(ST7735_BLACK);
        tft.setCursor(5, 146);
        tft.print("<");
        tft.setCursor(302, 146);
        tft.print(">");
        tft.setCursor(130, 5);
        tft.print("PAGE 2");

        // load subPage() if selected<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
        break;

      case 2:    // Page 3
        tft.fillScreen(ST7735_BLACK);
        tft.setCursor(5, 146);
        tft.print("<");
        tft.setCursor(302, 146);
        tft.print(">");
        tft.setCursor(130, 5);
        tft.print("PAGE 3");

        // load subPage() if selected<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
        break;
    }
  }
}


void subPageList() {

  if (oldsubPage != subPage) {
    oldsubPage = subPage;

    // Program List:
    switch (subPage) {
      case 0:    // Preset  0
        //delete old number
        tft.fillScreen(ST7735_BLACK);
        //print new text
        tft.setCursor(150, 136);
        tft.print("1");
        break;

      case 1:    // Preset  1
        //delete old number
        tft.fillScreen(ST7735_BLACK);
        //print new text
        tft.setCursor(150, 136);
        tft.print("2");
        break;

      case 2:    // Preset  2
        //delete old text
        tft.fillScreen(ST7735_BLACK);
        //print new text
        tft.setCursor(150, 136);
        tft.print("3");
        break;

      case 3:    // Preset  3
        //delete old text
        tft.fillScreen(ST7735_BLACK);
        //print new text
        tft.setCursor(150, 136);
        tft.print("4");
        break;

      case 4:    // Preset  4
        //delete old text
        tft.fillScreen(ST7735_BLACK);
        //print new text
        tft.setCursor(150, 136);
        tft.print("5");
        break;

      case 5:    // Preset  5
        //delete old text
        tft.fillScreen(ST7735_BLACK);
        //print new text
        tft.setCursor(150, 136);
        tft.print("6");
        break;
    }
  }
}

you should use a button library to make the code much easier to handle

1 Like

What @J-M-L says. I recommend the following one.

1 Like

You can make all that code, but not get it to return to main menu? That's quite amazing.. In readSelectButton() try to change mainMenu = false; to mainMenu = !mainMenu; - that will toggle between main menu and sub menu.

1 Like

fantastic, thank you!

i suggest handling menu items as data, not logic and button presses as actions that advance thru tables of menus.

menu items can either be sub-menus or actions (function pointers)

lacking a 4th button, i only see having a menu item to exit from a particular menu. more advanced approaches are possible

of course this code looks daunting, but it is only 162 lines vs 213 (52 for tft) for the posted code and additional menu items and sub menus can easily be added.

(why not have a sub-function to display one or more lines of text on your tft)?

consider

// check multiple buttons and toggle LEDs

enum { Off = HIGH, On = LOW };

byte pinsLed [] = { 10, 11, 12 };
byte pinsBut [] = { A1, A2, A3 };
#define N_BUT   sizeof(pinsBut)

// -----------------------------------------------------------------------------
#define NO_BUT  -1
byte butState [N_BUT];

int
butChk ()
{
    for (unsigned n = 0; n < sizeof(pinsBut); n++)  {
        byte but = digitalRead (pinsBut [n]);

        if (butState [n] != but)  {
            butState [n] = but;

            delay (10);     // debounce

            if (On == but)
                return n;
        }
    }
    return NO_BUT;
}

// ---------------------------------------------------------
void
butInit (void)
{
    for (unsigned n = 0; n < sizeof(pinsBut); n++)  {
        pinMode (pinsBut [n], INPUT_PULLUP);
        butState [n] = digitalRead (pinsBut [n]);
    }
}

// -----------------------------------------------------------------------------
enum { B_Sel,  B_Adv,  B_Back };
enum { T_Menu, T_Func, T_Back, T_Last };

struct MenuItem {
    int         type;
    MenuItem   *p;
    const char *text;
};

typedef MenuItem*       M;
typedef void (*F) (void);

struct MenuStk {
    MenuItem    menu;
    int         idx;
};
int   stkIdx;

// ---------------------------------------------------------
void back   (void) { Serial.println (__func__); }

void func1  (void) {
    Serial.println (__func__);

    for (unsigned n = 0; n < sizeof(pinsLed); n++)
        digitalWrite (pinsLed [n], ! digitalRead (pinsLed [n]));
}    

void func11 (void) { Serial.println (__func__); digitalWrite (pinsLed [0], On); }
void func12 (void) { Serial.println (__func__); digitalWrite (pinsLed [1], On); }
void func13 (void) { Serial.println (__func__); digitalWrite (pinsLed [2], On); }

void func21 (void) { Serial.println (__func__); digitalWrite (pinsLed [0], Off); }
void func22 (void) { Serial.println (__func__); digitalWrite (pinsLed [1], Off); }
void func23 (void) { Serial.println (__func__); digitalWrite (pinsLed [2], Off); }

// ---------------------------------------------------------
MenuItem sub1 [] = {
    { T_Func, (M)func11,  "Func-11" },
    { T_Func, (M)func12,  "Func-12" },
    { T_Func, (M)func13,  "Func-13" },
    { T_Back, 0,          "back"    },
    { T_Last, 0,       0        },
};

MenuItem sub2 [] = {
    { T_Func, (M)func21,  "Func-21" },
    { T_Func, (M)func22,  "Func-22" },
    { T_Func, (M)func23,  "Func-23" },
    { T_Back, 0,          "back"    },
    { T_Last, 0,       0        },
};

MenuItem top [] = {
    { T_Menu, sub1,    "Sub-1" },
    { T_Menu, sub2,    "Sub-2" },
    { T_Func, (M)func1,  "Func-1" },
    { T_Back, 0,         "back"   },
    { T_Last, 0,       0        },
};

MenuItem *menu   = top;
int       idx    = 0;

// -----------------------------------------------------------------------------
void
loop ()
{
    void (*f) (void);

    switch (butChk ())  {
    case NO_BUT:
        return;

    case B_Adv:
        if (T_Last == menu [++idx].type)
            idx = 0;
        break;

    case B_Back:
        if (0 < idx)
            idx--;
        break;

    case B_Sel:
        switch (menu [idx].type)  {
        case T_Func:
            f = (F) menu [idx].p;
            f ();
            // drop thru

        case T_Back:
            menu = top;
            idx  = 0;
            break;

        case T_Menu:
            menu = menu [idx].p;
            idx  = 0;
            break;
        }
    }

    Serial.println (menu [idx].text);
}

// -----------------------------------------------------------------------------
void
setup ()
{
    Serial.begin (9600);

    butInit ();

    for (unsigned n = 0; n < sizeof(pinsLed); n++)  {
        digitalWrite (pinsLed [n], Off);
        pinMode      (pinsLed [n], OUTPUT);
    }

    Serial.println (menu [idx].text);
}
1 Like

I will study that thank you

Then encapsulate the data and actions into class to make it all nice and OOP.

i developed a much more sophisticated menu system that supports editing strings, ints as well as booleans. (menu items could define custom button actions). (not a class, but OO)

i don't think every menu system needs such sophistication and the overhead it would require to use.

i think it's worth understanding various menu mechanisms and choosing only what is necessary to make the code as simple and maintainable as possible

some enhancements to what i posted are

  • including a ptr argument for actions (would minimize # of functions)

  • optionally displaying the value of the argument when scrolling thru the menu (avoid the need for a function)

  • having a stack keeping track of the menu and menu item rather than starting at the top menu (minimize button presses)

  • have a 4th button instead requiring a back menu item

hey guys, how do i add this if else statement?
it will be used to overwrite the old sub menu number,
not sure if it should be in the loop or in my sub menu

void loop() {

  menuList();
  subPageList();
  readSelectButton();
  readUpButton();
  readDownButton();

  if (menuPage == 0) {
    fillColor = yellow;
    
  } else if (menuPage = 1) {
    fillColor = ltBlue;
    
  } else if (menuPage = 2) {
    fillColor = dkGrey;
    
  } else (menuPage = 3) {
    fillColor = dkBlue;
  }
} // end of loop
void subPageList() {

  if (menuPage == 0) {
    fillColor = yellow;
    
  } else if (menuPage = 1) {
    fillColor = ltBlue;
    
  } else if (menuPage = 2) {
    fillColor = dkGrey;
    
  } else (menuPage = 3) {
    fillColor = dkBlue;
  }

  
  if (oldsubPage != subPage) {
    oldsubPage = subPage;

    // Program List:
    switch (subPage) {
      case 0:    // Preset  1

        //delete old number
        tft.fillScreen(ST7735_BLACK);
        //print new text
        tft.setCursor(150, 136);
        tft.print("1");
        MIDI.sendProgramChange (1, 1); // preset, channel
        break;

      case 1:    // Preset  2
        //delete old number
        tft.fillScreen(ST7735_BLACK);
        //print new text
        tft.setCursor(150, 136);
        tft.print("2");
        MIDI.sendProgramChange (2, 1); // preset, channel
        break;

      case 2:    // Preset  3
        //delete old text
        tft.fillScreen(ST7735_BLACK);
        //print new text
        tft.setCursor(150, 136);
        tft.print("3");
        MIDI.sendProgramChange (3, 1); // preset, channel
        break;

      case 3:    // Preset  4
        //delete old text
        tft.fillScreen(ST7735_BLACK);
        //print new text
        tft.setCursor(150, 136);
        tft.print("4");
        MIDI.sendProgramChange (4, 1); // preset, channel
        break;

      case 4:    // Preset  5
        //delete old text
        tft.fillScreen(ST7735_BLACK);
        //print new text
        tft.setCursor(150, 136);
        tft.print("5");
        MIDI.sendProgramChange (5, 1); // preset, channel
        break;
}
}
}

why not use a switch statement?

Nested switch statements we’re giving me the same errors as the if else ones

but they would make the code easier to understand

i figured it out, added fillColor= to each main menu item
then added fillScreen(fillColor) to every sub menu item

when using this to switch between the main and sub menu

      if (buttonState3 == LOW) {
        // "Button Pressed"
        mainMenu = !mainMenu;  // flip flop mainMenu true or false

It doesn't load the main menu or sub page until I press the up/down buttons,
how can i make it immediate when pressing the select button?

current sketch



#include <SPI.h>
#include <ST7789_t3.h> // Hardware-specific library
#include <MIDI.h>

#include "TimeLineLogo.h"
#include "BigSkyLogo.h"
#include "MobiusLogo.h"
#include "TrinityLogo.h"

// This is required to set up the MIDI library.
// The default MIDI setup uses the built-in serial port pin 1
MIDI_CREATE_DEFAULT_INSTANCE();

// pin definition for teensy 4.0 + ST7789
#define TFT_CS    10
#define TFT_MOSI  11
#define TFT_MISO  12
#define TFT_SCK   13
#define TFT_RST   14
#define TFT_DC    15

// For 1.9" TFT with ST7789
ST7789_t3 tft = ST7789_t3(TFT_CS, TFT_DC, TFT_RST);

#define yellow    0xE4A0
#define ltBlue    0x55FB
#define dkGrey    0x6B4D
#define dkBlue    0x0B35

volatile byte menuPage = 0; // stores the current page position.
volatile byte oldMenuPage = 0; // stores the last page position.

volatile byte subPage = 0;  // stores the current sub page position.
volatile byte oldsubPage = 0; // stores the last sub page position.

// Button reading, including debounce without delay function declarations
const byte upButton = 23; // Up Button
const byte downButton = 22; // Down Button
const byte selectButton = 21; // Select Button

byte oldButtonState1 = HIGH;  // assume switch open because of pull-down resistor
byte oldButtonState2 = HIGH;  // assume switch open because of pull-down resistor
byte oldButtonState3 = HIGH;  // assume switch open because of pull-down resistor

const unsigned long debounceTime = 100;  // milliseconds
unsigned long buttonPressTime;  // when the switch last changed state
boolean buttonPressed = 0; // a flag variable

volatile boolean mainMenu = true;

uint16_t fillColor = yellow;

//******************************************************************************************



void setup() {

  MIDI.begin(MIDI_CHANNEL_OFF);

  // button section of setup
  pinMode (upButton, INPUT_PULLUP);    // setup the button pins
  pinMode (downButton, INPUT_PULLUP);
  pinMode (selectButton, INPUT_PULLUP);


  tft.init(172, 320);   // initialize a ST7789 chip, 172x320 pixels
  tft.setRotation(1);
  tft.fillScreen(yellow);
  //tft.fillScreen(ST7735_BLACK);
  tft.setTextColor(ST7735_WHITE);
  tft.setTextSize(2);
  // tft.setFont(&TypoHoopRegular20pt7b);
  tft.setCursor(5, 146);
  tft.print("<");
  tft.setCursor(302, 146);
  tft.print(">");
  tft.setCursor(130, 5);
  tft.print("Select");
  tft.drawBitmap(10, 40, Trinity, 301, 85, ST7735_WHITE);
}



//******************************************************************************************




void loop() {

  menuList();
  subPageList();
  readSelectButton();
  readUpButton();
  readDownButton();

} // end of loop



//******************************************************************************************



void readUpButton() {

  // UP BUTTON
  byte buttonState2 = digitalRead (upButton);
  if (buttonState2 != oldButtonState2) {
    if (millis () - buttonPressTime >= debounceTime) { // debounce
      buttonPressTime = millis ();  // when we closed the switch
      oldButtonState2 =  buttonState2;  // remember for next time

      if (buttonState2 == LOW && mainMenu == true) {   // if button up pressed & main menu is active

        menuPage ++; //increment the current menu page's position count
        if (menuPage > 3) {
          menuPage = 0;  //0-3 (4 menu pages)
        }
      }
      else if (buttonState2 == LOW && mainMenu == false) {   // if button up pressed & sub menu is active
        subPage ++;
        if (subPage > 19) {
          subPage = 0;  ///0-19 (20 sub menu pages)
        }
      } // end of else if
    }  // end if debounce time up
  } // end of state change
} // end of function



void readDownButton() {

  // Down Button
  byte buttonState1 = digitalRead (downButton);
  if (buttonState1 != oldButtonState1) {
    if (millis () - buttonPressTime >= debounceTime) { // debounce
      buttonPressTime = millis ();  // when we closed the switch
      oldButtonState1 =  buttonState1;  // remember for next time

      if (buttonState1 == LOW && mainMenu == true) { // if button down pressed & main menu is active
        // "Button Pressed"

        menuPage --; //decrement the current menu page's position count
        if (menuPage > 200) {
          menuPage = 3;  ///0-3 (4 menu pages)
        }
      }
      else if (buttonState1 == LOW && mainMenu == false) {   // if button up pressed & sub menu is active
        subPage --;
        if (subPage > 200) {
          subPage = 19;  ///0-19 (20 sub menu pages)
        }
      } // end of else if
    }  // end if debounce time up
  } // end of state change
} // end of function


void readSelectButton() {

  // Select Button
  byte buttonState3 = digitalRead (selectButton);
  if (buttonState3 != oldButtonState3) {
    if (millis () - buttonPressTime >= debounceTime) { // debounce
      buttonPressTime = millis ();  // when we closed the switch
      oldButtonState3 =  buttonState3;  // remember for next time

      if (buttonState3 == LOW) {
        // "Button Pressed"
        mainMenu = !mainMenu;  // flip flop mainMenu true or false

        // if mainMenu = true load mainMenu
        // if mainMenu = false load subMenu

      }
    }  // end if debounce time up
  } // end of state change
} // end of function


void menuList() {

  if (oldMenuPage != menuPage) {
    oldMenuPage = menuPage;

    // 4 menu pages
    switch (menuPage) {
      case 0:    // Page 1
        tft.fillScreen(yellow);
        tft.setTextSize(2);
        tft.setCursor(5, 146);
        tft.print("<");
        tft.setCursor(302, 146);
        tft.print(">");
        tft.setCursor(130, 5);
        tft.print("Select");
        tft.drawBitmap(10, 40, Trinity, 301, 85, ST7735_WHITE);
        fillColor = yellow;
        break;

      case 1:    // Page 2
        tft.fillScreen(ltBlue);
        tft.setTextSize(2);
        tft.setCursor(5, 146);
        tft.print("<");
        tft.setCursor(302, 146);
        tft.print(">");
        tft.setCursor(130, 5);
        tft.print("Select");
        tft.drawBitmap(10, 10, BigSky, 300, 150, ST7735_WHITE);
        fillColor = ltBlue;
        break;

      case 2:    // Page 3
        tft.fillScreen(dkGrey);
        tft.setTextSize(2);
        tft.setCursor(5, 146);
        tft.print("<");
        tft.setCursor(302, 146);
        tft.print(">");
        tft.setCursor(130, 5);
        tft.print("Select");
        tft.drawBitmap(10, 55, TimeLine, 301, 53, ST7735_WHITE);
        fillColor = dkGrey;
        break;

      case 3:    // Page 4
        tft.fillScreen(dkBlue);
        tft.setTextSize(2);
        tft.setCursor(5, 146);
        tft.print("<");
        tft.setCursor(302, 146);
        tft.print(">");
        tft.setCursor(130, 5);
        tft.print("Select");
        tft.drawBitmap(10, 40, Mobius, 301, 85, ST7735_WHITE);
        fillColor = dkBlue;
        break;

    }
  }
}


void subPageList() {

  if (oldsubPage != subPage) {
    oldsubPage = subPage;

    // Program List:
    switch (subPage) {
      case 0:    // Preset  1

        //delete old number
        tft.fillScreen(fillColor);
        tft.setTextSize(2);
        tft.setCursor(5, 146);
        tft.print("<");
        tft.setCursor(302, 146);
        tft.print(">");
        tft.setCursor(145, 5);
        tft.print("Back");
        //print new text
        tft.setCursor(60, 55);
        tft.setTextSize(10);
        tft.print("P 1");
        MIDI.sendProgramChange (1, 1); // preset, channel
        break;

      case 1:    // Preset  2
        //delete old number
        tft.fillScreen(fillColor);
        tft.setTextSize(2);
        tft.setCursor(5, 146);
        tft.print("<");
        tft.setCursor(302, 146);
        tft.print(">");
        tft.setCursor(145, 5);
        tft.print("Back");
        //print new text
        tft.setCursor(60, 55);
        tft.setTextSize(10);
        tft.print("P 2");
        MIDI.sendProgramChange (2, 1); // preset, channel
        break;

      case 2:    // Preset  3
        //delete old number
        tft.fillScreen(fillColor);
        tft.setTextSize(2);
        tft.setCursor(5, 146);
        tft.print("<");
        tft.setCursor(302, 146);
        tft.print(">");
        tft.setCursor(145, 5);
        tft.print("Back");
        //print new text
        tft.setCursor(60, 55);
        tft.setTextSize(10);
        tft.print("P 3");
        MIDI.sendProgramChange (3, 1); // preset, channel
        break;

      case 3:    // Preset  4
        //delete old number
        tft.fillScreen(fillColor);
        tft.setTextSize(2);
        tft.setCursor(5, 146);
        tft.print("<");
        tft.setCursor(302, 146);
        tft.print(">");
        tft.setCursor(145, 5);
        tft.print("Back");
        //print new text
        tft.setCursor(60, 55);
        tft.setTextSize(10);
        tft.print("P 4");
        MIDI.sendProgramChange (4, 1); // preset, channel
        break;

      case 4:    // Preset  5
        //delete old text
        tft.fillScreen(fillColor);
        tft.setTextSize(2);
        tft.setCursor(5, 146);
        tft.print("<");
        tft.setCursor(302, 146);
        tft.print(">");
        tft.setCursor(145, 5);
        tft.print("Back");
        //print new text
        tft.setCursor(60, 55);
        tft.setTextSize(10);
        tft.print("P 5");
        MIDI.sendProgramChange (5, 1); // preset, channel
        break;

      case 5:    // Preset  6
        //delete old text
        tft.fillScreen(fillColor);
        tft.setTextSize(2);
        tft.setCursor(5, 146);
        tft.print("<");
        tft.setCursor(302, 146);
        tft.print(">");
        tft.setCursor(145, 5);
        tft.print("Back");
        //print new text
        tft.setCursor(60, 55);
        tft.setTextSize(10);
        tft.print("P 6");
        MIDI.sendProgramChange (6, 1); // preset, channel
        break;

      case 6:    // Preset  7
        //delete old number
        tft.fillScreen(fillColor);
        tft.setTextSize(2);
        tft.setCursor(5, 146);
        tft.print("<");
        tft.setCursor(302, 146);
        tft.print(">");
        tft.setCursor(145, 5);
        tft.print("Back");
        //print new text
        tft.setCursor(60, 55);
        tft.setTextSize(10);
        tft.print("P 7");
        MIDI.sendProgramChange (7, 1); // preset, channel
        break;

      case 7:    // Preset  8
        //delete old number
        tft.fillScreen(fillColor);
        tft.setTextSize(2);
        tft.setCursor(5, 146);
        tft.print("<");
        tft.setCursor(302, 146);
        tft.print(">");
        tft.setCursor(145, 5);
        tft.print("Back");
        //print new text
        tft.setCursor(60, 55);
        tft.setTextSize(10);
        tft.print("P 8");
        MIDI.sendProgramChange (8, 1); // preset, channel
        break;

      case 8:    // Preset  9
        //delete old text
        tft.fillScreen(fillColor);
        tft.setTextSize(2);
        tft.setCursor(5, 146);
        tft.print("<");
        tft.setCursor(302, 146);
        tft.print(">");
        tft.setCursor(145, 5);
        tft.print("Back");
        //print new text
        tft.setCursor(60, 55);
        tft.setTextSize(10);
        tft.print("P 9");
        MIDI.sendProgramChange (9, 1); // preset, channel
        break;

      case 9:    // Preset  10
        //delete old text
        tft.fillScreen(fillColor);
        tft.setTextSize(2);
        tft.setCursor(5, 146);
        tft.print("<");
        tft.setCursor(302, 146);
        tft.print(">");
        tft.setCursor(145, 5);
        tft.print("Back");
        //print new text
        tft.setCursor(60, 55);
        tft.setTextSize(10);
        tft.print("P 10");
        MIDI.sendProgramChange (10, 1); // preset, channel
        break;

      case 10:    // Preset  11
        //delete old text
        tft.fillScreen(fillColor);
        tft.setTextSize(2);
        tft.setCursor(5, 146);
        tft.print("<");
        tft.setCursor(302, 146);
        tft.print(">");
        tft.setCursor(145, 5);
        tft.print("Back");
        //print new text
        tft.setCursor(60, 55);
        tft.setTextSize(10);
        tft.print("P 11");
        MIDI.sendProgramChange (11, 1); // preset, channel
        break;

      case 11:    // Preset  12
        //delete old text
        tft.fillScreen(fillColor);
        tft.setTextSize(2);
        tft.setCursor(5, 146);
        tft.print("<");
        tft.setCursor(302, 146);
        tft.print(">");
        tft.setCursor(145, 5);
        tft.print("Back");
        //print new text
        tft.setCursor(60, 55);
        tft.setTextSize(10);
        tft.print("P 12");
        MIDI.sendProgramChange (12, 1); // preset, channel
        break;

      case 12:    // Preset  13
        //delete old number
        tft.fillScreen(fillColor);
        tft.setTextSize(2);
        tft.setCursor(5, 146);
        tft.print("<");
        tft.setCursor(302, 146);
        tft.print(">");
        tft.setCursor(145, 5);
        tft.print("Back");
        //print new text
        tft.setCursor(60, 55);
        tft.setTextSize(10);
        tft.print("P 13");
        MIDI.sendProgramChange (13, 1); // preset, channel
        break;

      case 13:    // Preset  14
        //delete old number
        tft.fillScreen(fillColor);
        tft.setTextSize(2);
        tft.setCursor(5, 146);
        tft.print("<");
        tft.setCursor(302, 146);
        tft.print(">");
        tft.setCursor(145, 5);
        tft.print("Back");
        //print new text
        tft.setCursor(60, 55);
        tft.setTextSize(10);
        tft.print("P 14");
        MIDI.sendProgramChange (14, 1); // preset, channel
        break;

      case 14:    // Preset  15
        //delete old text
        tft.fillScreen(fillColor);
        tft.setTextSize(2);
        tft.setCursor(5, 146);
        tft.print("<");
        tft.setCursor(302, 146);
        tft.print(">");
        tft.setCursor(145, 5);
        tft.print("Back");
        //print new text
        tft.setCursor(60, 55);
        tft.setTextSize(10);
        tft.print("P 15");
        MIDI.sendProgramChange (15, 1); // preset, channel
        break;

      case 15:    // Preset  16
        //delete old text
        tft.fillScreen(fillColor);
        tft.setTextSize(2);
        tft.setCursor(5, 146);
        tft.print("<");
        tft.setCursor(302, 146);
        tft.print(">");
        tft.setCursor(145, 5);
        tft.print("Back");
        //print new text
        tft.setCursor(60, 55);
        tft.setTextSize(10);
        tft.print("P 16");
        MIDI.sendProgramChange (16, 1); // preset, channel
        break;

      case 16:    // Preset  17
        //delete old text
        tft.fillScreen(fillColor);
        tft.setTextSize(2);
        tft.setCursor(5, 146);
        tft.print("<");
        tft.setCursor(302, 146);
        tft.print(">");
        tft.setCursor(145, 5);
        tft.print("Back");
        //print new text
        tft.setCursor(60, 55);
        tft.setTextSize(10);
        tft.print("P 17");
        MIDI.sendProgramChange (17, 1); // preset, channel
        break;

      case 17:    // Preset  18
        //delete old text
        tft.fillScreen(fillColor);
        tft.setTextSize(2);
        tft.setCursor(5, 146);
        tft.print("<");
        tft.setCursor(302, 146);
        tft.print(">");
        tft.setCursor(145, 5);
        tft.print("Back");
        //print new text
        tft.setCursor(60, 55);
        tft.setTextSize(10);
        tft.print("P 18");
        MIDI.sendProgramChange (18, 1); // preset, channel
        break;

      case 18:    // Preset  19
        //delete old number
        tft.fillScreen(fillColor);
        tft.setTextSize(2);
        tft.setCursor(5, 146);
        tft.print("<");
        tft.setCursor(302, 146);
        tft.print(">");
        tft.setCursor(145, 5);
        tft.print("Back");
        //print new text
        tft.setCursor(60, 55);
        tft.setTextSize(10);
        tft.print("P 19");
        MIDI.sendProgramChange (19, 1); // preset, channel
        break;

      case 19:    // Preset  20
        //delete old number
        tft.fillScreen(fillColor);
        tft.setTextSize(2);
        tft.setCursor(5, 146);
        tft.print("<");
        tft.setCursor(302, 146);
        tft.print(">");
        tft.setCursor(145, 5);
        tft.print("Back");
        //print new text
        tft.setCursor(60, 55);
        tft.setTextSize(10);
        tft.print("P 20");
        MIDI.sendProgramChange (20, 1); // preset, channel
        break;

    }
  }
}

void loadSub() {

  tft.fillScreen(fillColor);
  tft.setTextSize(2);
  tft.setCursor(5, 146);
  tft.print("<");
  tft.setCursor(302, 146);
  tft.print(">");
  tft.setCursor(145, 5);
  tft.print("Back");
  //print new text
  tft.setCursor(60, 55);
  tft.setTextSize(10);
  tft.print("P 1");
  MIDI.sendProgramChange (1, 1); // preset, channel
}


void loadMenu() {

  tft.fillScreen(yellow);
  tft.setTextSize(2);
  tft.setCursor(5, 146);
  tft.print("<");
  tft.setCursor(302, 146);
  tft.print(">");
  tft.setCursor(130, 5);
  tft.print("Select");
}

I cant make any sense of that, i've got no idea where i am in the menu or what each of the 3 buttons do, leds dont work, output is: Sub-1 Func-11 Func-11 Func-11 Func-11 Func-11 Func-11 func11 Sub-1 Func-11 Func-11 Func-11 Func-11 Func-11 Func-11 func11 Sub-1 Sub-1 Sub-1 Sub-1 Sub-1 Sub-1 Sub-1 Func-11 Func-11 Func-11 Func-11 Func-11 Func-11 Func-11 Func-11 Func-11 func11 Sub-1 Sub-1 Sub-1 Sub-1 Sub-1 Sub-1 Sub-2 Sub-1 Sub-1 Sub-1 Sub-1 Sub-2 Func-21 Func-22 func22 Sub-1 Sub-2 Func-1 func1 Sub-1 Func-11 func11 Sub-1 Func-11 Func-11 Func-11 Func-11 Func-11 Func-11 Func-11 func11 Sub-1 Func-11 Func-12 Func-13 back Func-11

each menu

each menu item has a label that is printed when that menu item is scrolled to. those labels are Capitalized.

selecting a menu item that is an action causes the associated function to be executed and those functions print their names (i.e. __func__) which are lower case

the button pins are for my hardware, defined near the top

byte pinsBut [] = { A1, A2, A3 };

an enum associates a label with the indices of the button pins array (the 1st button is Sel)

enum { B_Sel,  B_Adv,  B_Back };s

i don't understand why menu labels repeat. did you define a 4th button?

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.