Multiple switch case issue

Hello!
I have made a menu using switch case so when the user presses the select button a function is carried out.

Issue:
One of the functions contains another switch case that also uses buttons but when I click the buttons again only the menu is controlled and not the function i.e. it will load the function and the first case but when a button is clicked nothing happens.

What I want to happen:
I want the buttons to stop controlling the menu and control the switch in the other function. The buttons should only control the menu when the menu function is called (and the same for the other respective functions).

I'm not sure how to tackle this and don't know what the problem is.

n.b. please do not suggest any additional libraries other than the ones i have used, also the function works fine by itself when outside the menu so I know it works. I am also new to programming in C and using the arduino.

n.b. I have also tried using a nested switch case to no avail :frowning: (although I may have been going about this in a bad way). I am open to using if statements (or anything else appropriate) as well (as a last resort) however I would much prefer to use switch cases.

I greatly appreciate any help as I am at my wits end :confused:

#include <Wire.h>
#include <Adafruit_RGBLCDShield.h>
#include <utility/Adafruit_MCP23017.h>
#include <EEPROM.h>

Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield();


//variables to decide which buttons are being used when
bool choosing;
bool playing;

//variables to select the users choices, 3 and 2 and the starting numbers displayed
int size_S=4;
int size_M=2;

uint8_t choice=1;
uint8_t oldButtons=0;

char buffer [12];

//function displaying the menu options
void SelectDisplay(int size_S, int size_M){ 
  lcd.setCursor(0,0);
  sprintf(buffer, "S:%02d M:%02d", size_S, size_M);
  lcd.print(buffer); 
  lcd.setCursor (0,1);
  lcd.print((choice==1?"Choose S":"Choose M"));
}

//variables to store user's choice
int choice_S;
int choice_M;

//!!THIS IS THE FUNCTION THAT DOESN'T WORK INSIDE THE MENU
//function for user to select options S and M
int Select(int choice_S, int choice_M){
  
  uint8_t buttons, changes;

  buttons = lcd.readButtons ();
  changes = oldButtons & (~buttons);

  if (playing==true){
        
    //calling the menu disply function
    SelectDisplay (size_S,size_M);
    
      switch (choice){
        case 1: //case S
          if (changes & BUTTON_UP){
            size_S = (size_S == 10 ? 4:size_S+1);
          }else if (changes & BUTTON_DOWN){
            size_S = (size_S == 4 ? 10:size_S-1);
          }else if (changes & BUTTON_RIGHT){
            choice= 2;
          }
          break;
        case 2: //case M
          if (changes & BUTTON_UP){
            size_M = (size_M == 4 ? 2:size_M+1);
          }else if (changes & BUTTON_DOWN){
            size_M = (size_M == 2 ? 4:size_M-1);
          }else if (changes & BUTTON_LEFT){
            choice = 1;
          }
          break;
      }
      
     if (changes & BUTTON_SELECT){
        choice_S=size_S;
        choice_M=size_M;  
      }
      
  }
    oldButtons=buttons;  
}

//variable to change the menu page and options
int menu=1;
//function displaying what the menu options
void displayMenu(){
  
    switch(menu){
      case 0:
        menu=1;
        break;
      case 1: 
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print(">Play");
        lcd.setCursor(0,1);
        lcd.print(" Characters");
        break;
      case 2: 
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print(" Play");
        lcd.setCursor(0,1);
        lcd.print(">Characters");
        break;
      case 3: 
        break;
        //etc..
    }
}

//function for carrying out the user's menu selection
void menuAction (){
  
    switch (menu){
      case 1://play
        Select(choice_S, choice_M); //!!HERE IS WHERE THE FUNCTION I WANT TO WORK IS CALLED
        break;
      case 2:       
        break;
      case 3:
        break;
      //etc..
    }  
}

//function for navigating the menu
void mainMenu(){
  int navigate = lcd.readButtons ();

  if (playing==true){
    choosing=false;
  }else{
    choosing=true;
  }

  if(choosing==true){

    //if statement to navigate the menu 
    if (BUTTON_DOWN & navigate){
      menu++;
      displayMenu();
      delay(200);
    }
    if (BUTTON_UP & navigate){
      menu--;
      displayMenu();
      delay(200);
    }
    if (BUTTON_SELECT & navigate){
      playing=true;
      menuAction();
      delay(200);
    } 
  }
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  lcd.begin(16,2);
  displayMenu();
  choice=1;
  choosing=true;
}

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

i suggest you use the serial monitor and add serial.println s to each function to verify the flow of your code. you want to see which function is being invoke when buttons are pressed.

furthermore you want to print arguments to those function and any state information (e.g. menu)

Thanks for you suggestion, I have done that already (i just removed them for the sake of the forum to make it easier to read) so i know it goes to the first case of the choice switch but when the buttons are clicked it doesn't do whatever is in the if statement.

e.g.

if (changes & BUTTON_UP){
            size_S = (size_S == 10 ? 4:size_S+1);

For example the above won't change when the buttons are clicked when this function is called from the menu.

talinwan:
Thanks for you suggestion, I have done that already (i just removed them for the sake of the forum to make it easier to read)

In other words you posted a program different to the one you tested? That risks creating more bugs and
confusing things.

What are you expecting this to do:

  changes = oldButtons & (~buttons);
  changes = oldButtons & (~buttons);

Are you trying to bitwise detect a changed bit? You would normally use an exclusive or for that:

  changes = oldButtons ^ (~buttons);

MarkT:
In other words you posted a program different to the one you tested? That risks creating more bugs and
confusing things.

What are you expecting this to do:

  changes = oldButtons & (~buttons);

I removed the serial.println since i only added it to try and see where the error was, it was not part of my original code. Everything else is exactly the same as the code i tested.

The changes variable was to detect a change in the button although not sure if I need it or not

aarg:
Are you trying to bitwise detect a changed bit? You would normally use an exclusive or for that:

  changes = oldButtons ^ (~buttons);

Thank you, I have added your suggestion. However, I am still not able to get the second switch case to work when called in the menu.