Make a better menu

Im working on a project, where i need a menu for settings, which should work like this:

  • “Hold” - Rotary Encoder Button
  • Main-Menu opens
  • Turn encoder to cycle menu-items
  • “doubleclick” - Encoder to enter Menu-Item
  • Turn encoder to cycle menu item parameters
  • Hold to save, or leave alone for 5000ms to time out

I have attached my code below, the 3 functions that are interesting. The menu works actually, but i don’t really like how i made it, because if i have mor and more items, it will be very complex.

Here i try to give an idea what has to happen:

Main Menu

  • If the encoder is held, the menu should be activated. The encoder is a library where i can attach a function that will handle
  • If the menu comes active, a timer has to start for 5s, for the timeout
  • If any rotary encoder movement or clicking is made, the function “menuEvent();” needs to be called, to reset the timeout (or anything else that does the same)
  • When the menu will activate, the function formatOutput(value, 00, 00, 0, 0); needs to be called, the value variable will be the current position of the menu in decimal format (00 to 16). After that, this function needs to be called for displaying the value setOutputs(register_output_1, register_output_2);
  • In case of a doubleclick the selected menu-item should be called

Menu Items

  • Same as the Main menu, each rotary encoder movement has to reset the timeout
  • the function formatOutput(menu_item, 255, encValueItem, 0, 0); needs to be called, and after that setOutputs(register_output_1, register_output_2); “menu_item” is the value of the Main-Menu, 255 is blank, and encValueItem is the current position
  • it would be nice, if the current setting would be the selected, could be done by this:
    readEEPROM(STORAGE_ADDRESS, someHexAdress), 1);
  • when the encoder is double clicked, a save function should be called, in case of the 5s timeout, a function for restoring the original values must be called

Attached here are the code i already have:

Encoder

void checkEncoder() {
  ClickEncoder::Button b = encoder->getButton();
  switch (b) {
    case ClickEncoder::Held:
      if (menu_true == 0) {
        menu_true = 1;
        menuEvent();
        display_time_true = 0;
        formatOutput(value, 00, 00, 0, 0);
        setOutputs(register_output_1, register_output_2);
      }
      if (menu_true == 1 && menu_item_active == 1 && p_once == 0) {
        p_save = 1;
        p_once = 1;

      }
      break;
    case ClickEncoder::DoubleClicked:
      menu_item_active = 1;
      menu_item = encValueMenu;
      menuEvent();
      encMovement = 0;
      formatOutput(menu_item, 255, 00, 0, 0);
      setOutputs(register_output_1, register_output_2);

      break;
  }
}

Main Menu:

void menuHandler() {

  if  (menu_true == 1 && millis() - last_menu > menu_timeout) {
    menu_true = 0;
    display_time_true = 1;
    menu_item_active = 0;
    initColor(0);
    p_once = 0;
    p_save = 0;
    encValueMenu = 0;
    encValueItem = 0;
      }

  if (menu_true == 1 && menu_item_active == 0) {
    
    encMovement += encoder->getValue();
    encValueMenu = encMovement;
    
    
    if (encValueMenu <0 ) encValueMenu = 0;
    if (encValueMenu >menuItems ) encValueMenu = menuItems; 
    
    if ( encValueMenu != lastMenu && encValueMenu > 0) {
      menuEvent();
      lastMenu = encValueMenu;
      formatOutput(encValueMenu, 00, 00, 0, 0);
      setOutputs(register_output_1, register_output_2);
    }   
  }

  if (menu_item_active == 1 && p_save == 0) {

    
    switch (menu_item) {
      case 2:
        menuColor();
        break;
      default:
        break;
    }
  }

Menu item, all will looks similiar, some of them will just set a value, other will instant change something, like the led in the example

void menuColor() {
  if (p_save == 0) {
    
    encMovement += encoder->getValue();
    encValueItem = encMovement;
  } 

    if (encValueItem != lastItem && encValueItem >= 0 && encValueItem <= 16) {
      menuEvent();
      lastItem = encValueItem;
      formatOutput(menu_item, 255, encValueItem, 0, 0);
      setOutputs(register_output_1, register_output_2);
      setLedColor(encValueItem, 0);
    }
  
  else {
    writeEEPROM(STORAGE_ADDRESS, EEPROM_LED,value);
    setLedColor(value,1);
    p_save = 0;
    p_once = 0;
  }
}

Menu-Event

void menuEvent() {
  
  //if any menu event occurs, the timeout for displaying the menu will be reset. 
  
  last_menu = millis();
}

What do you think of my solution, maybe it is not bad as i think? Or are there any better ways to do this. I need around 16 Main Menu entries, and each entry has about 0-6 items, some of them 16 (like the Color).

Any help would be great, and sorry for the long post.