### Arduino Menu 4 Simple Example Source: https://github.com/neu-rah/arduinomenu/blob/master/README.md This example demonstrates a basic menu structure for controlling an LED blink pattern. It includes setup for serial communication, input, and output, and defines adjustable 'On' and 'Off' times for the blink using fields. ```c++ #include #include #include #include using namespace Menu; #define LEDPIN LED_BUILTIN #define MAX_DEPTH 1 unsigned int timeOn=10; unsigned int timeOff=90; MENU(mainMenu, "Blink menu", Menu::doNothing, Menu::noEvent, Menu::wrapStyle ,FIELD(timeOn,"On","ms",0,1000,10,1, Menu::doNothing, Menu::noEvent, Menu::noStyle) ,FIELD(timeOff,"Off","ms",0,10000,10,1,Menu::doNothing, Menu::noEvent, Menu::noStyle) ,EXIT(" encoder;//simple quad encoder driver encoderInStream encStream(encoder,4);// simple quad encoder fake Stream //a keyboard with only one key as the encoder button keyMap encBtn_map[]={{-encBtn,options->getCmdChar(enterCmd)}};//negative pin numbers use internal pull-up, on = low keyIn<1> encButton(encBtn_map);//1 is the number of keys serialIn serial(Serial); //input from the encoder + encoder button + serial menuIn* inputsList[]={&encStream,&encButton,&serial}; chainStream<3> in(inputsList);//3 is the number of inputs ``` -------------------------------- ### Define Compiler Flag Example Source: https://github.com/neu-rah/arduinomenu/wiki/Compile-options Use -D flags to activate compiler options. This example shows how to define MENU_IDLE_BKGND. ```c -DMENU_IDLE_BKGND ``` -------------------------------- ### Start Menu in Idle State Source: https://github.com/neu-rah/arduinomenu/wiki/FAQ Initializes the menu to start in an idle state, requiring user interaction (e.g., pressing 'select') to enter the menu. The menu resumes when select is pressed. ```c++ nav.idleOn(user_function); ``` -------------------------------- ### Menu Prompt Example Source: https://github.com/neu-rah/arduinomenu/wiki/WebMenu Represents a common menu item, such as an action or a simple prompt. Key properties include the item's index, enabled status, and the text prompt displayed to the user. ```json {"idx":"1","enabled":"1","selStart":" ","prompt":"Action A"} ``` -------------------------------- ### Handle idle state with doInput/doOutput Source: https://github.com/neu-rah/arduinomenu/wiki/Idling Manage input and output manually when the menu is in an idle state. This example shows how to display a 'suspended' message and handle menu output when not idle. ```c++ //... //on u8g2 or other devices that uses doInpu/doOutput instead of poll nav.doInput() if (nav.sleepTask) { u8g2.firstPage(); do { u8g2.setCursor(0, 15); u8g2.print("suspended"); } while ( u8g2.nextPage() ); } else { if (nav.changed(0)) { u8g2.firstPage(); do nav.doOutput(); while(u8g2.nextPage()); } } //... ``` -------------------------------- ### ESP8266 Web Menu Interface Source: https://context7.com/neu-rah/arduinomenu/llms.txt This snippet demonstrates the setup for serving an ArduinoMenu interface over a web page on ESP8266/ESP32. It includes necessary includes and comments on accessing the HTML+XSLT and JSON state endpoints. Requires SPIFFS image with static web files. ```cpp #include #include #include #include // ESP8266 web output driver using namespace Menu; // JSON response structure for root menu: // { // "output": "", // "menu": { // "title": {"prompt": "Main menu"}, // "path": "", "sel": "0", // "items": [ // {"idx":"0","enabled":"1","selStart":">","prompt":"Led: ", // "value":"Off","options":["On","Off"]}, // {"idx":"1","enabled":"1","selStart":" ","prompt":"Brightness", // "field":"50","range":{"low":"0","high":"100","step":"10","tune":"1"},"unit":"%"} // ] // } // } // WebSocket path commands: // "/" -> root menu // "/0" -> activate item 0 (enter submenu or execute action) // "/0/1" -> set toggle/select item 0 to value index 1 // "/1/value" -> set numeric field to value // #define MAX_DEPTH 2 // int ledCtrl = LOW; // int brightness = 50; // TOGGLE(ledCtrl, ledMenu, "Led: ", doNothing, noEvent, noStyle // ,VALUE("On", HIGH, doNothing, noEvent) // ,VALUE("Off", LOW, doNothing, noEvent) // ); // MENU(mainMenu, "Main menu", doNothing, noEvent, wrapStyle // ,SUBMENU(ledMenu) // ,FIELD(brightness, "Brightness", "%", 0, 100, 10, 1, doNothing, noEvent, wrapStyle) // ); // ... ESP8266 server setup omitted for brevity; see examples/lolin32 for full sketch ``` -------------------------------- ### NAVROOT Macro for Menu Navigation Source: https://context7.com/neu-rah/arduinomenu/llms.txt The NAVROOT macro instantiates the navRoot object, connecting the menu tree, input, and output streams. It requires 'menu.h' and 'menuIO/serialOut.h'. The example shows runtime configuration options like enabling/disabling menu items and controlling input/output polling. ```cpp #include #include #include using namespace Menu; #define MAX_DEPTH 3 MENU(mainMenu, "Root", doNothing, noEvent, wrapStyle ,OP("Item A", doNothing, noEvent) ,OP("Item B", doNothing, noEvent) ,EXIT("","prompt":"Led: ","value":"Off","options":["On","Off"]}, {"idx":"1","enabled":"1","selStart":" ","prompt":"Action A"}, {"idx":"2","enabled":"1","selStart":" ","prompt":"Action B"}, {"idx":"3","enabled":"1","selStart":" ","prompt":"On" ,"field":"50","range": {"low":"0","high":"100","step":"10","tune":"1"},"unit":"ms"}, {"idx":"4","enabled":"1","selStart":" ","prompt":"Select" ,"select":"Zero","options":["Zero","One","Two"]}, {"idx":"5","enabled":"1","selStart":" ","prompt":"Choose" ,"choose":"Last","options": ["First","Second","Third","Last"] ] } } ``` -------------------------------- ### Get Selected Option Prompt Source: https://github.com/neu-rah/arduinomenu/wiki/FAQ Returns the prompt object for the currently selected option. This object represents the selected menu item. ```c++ nav.selected() ``` -------------------------------- ### Text Field Example Source: https://github.com/neu-rah/arduinomenu/wiki/WebMenu Represents a menu item that is a text field. It includes common prompt information and specific properties for text input, such as the current text value. ```json {"idx":"1","enabled":"1","selStart":" ","prompt":"Key","editCursor":" ","text":"XXXXXX"} ``` -------------------------------- ### Field Item Example Source: https://github.com/neu-rah/arduinomenu/wiki/WebMenu Represents a menu item that is a field, allowing users to view and potentially edit values. It includes common prompt information along with field-specific details like current value, range, and unit. ```json { "idx":"1", "enabled":"1", "cursor":" ", "prompt":"", "field":"0.00", "range":{ "low":"0.00", "high":"100.00", "step":"10.00", "tune":"1.00" }, "unit":"%" } ``` -------------------------------- ### Implement Idle/Suspend Mode with Screensaver Source: https://context7.com/neu-rah/arduinomenu/llms.txt Use `idleOn()` and `idleOff()` to suspend menu I/O and execute a custom function, such as a screensaver. The `idleFunc` receives idle events and can be used to display dynamic content or perform background tasks. Set `nav.idleTask` in `setup()` for automatic invocation when the menu exits the root. ```cpp #include #include #include using namespace Menu; #define MAX_DEPTH 1 // idleFunc signature: result fn(menuOut& o, idleEvent e) result screenSaver(menuOut& o, idleEvent e) { switch (e) { case idleStart: o.clear(); Serial.println("=== SCREENSAVER ON ==="); break; case idling: // called every poll while idle — draw dynamic content here o.setCursor(0, 0); o.print("Uptime: "); o.print(millis() / 1000); o.print("s "); nav.idleChanged = true; // signal: keep calling idling every poll break; case idleEnd: Serial.println("=== MENU RESUMED ==="); break; } return proceed; } MENU(mainMenu, "Demo", doNothing, noEvent, wrapStyle ,OP("Sleep now", [](){ nav.idleOn(screenSaver); return proceed; }, enterEvent) ,OP("Item B", doNothing, noEvent) ,EXIT("'; char disabledCursor;//='-'; bool invertFieldKeys;//=false; bool nav2D;//=false;// N/A should be false const navCodesDef &navCodes;//=defaultNavCodes; bool useUpdateEvent;//=false, if false, when field value is changed use enterEvent instead. bool canExit;//=true, if false do not exit from main menu inline char getCmdChar(navCmds cmd) const {return navCodes[cmd].ch;} }; ``` -------------------------------- ### Create List of Menu Output Devices Source: https://github.com/neu-rah/arduinomenu/wiki/Initialization Define a static array of menuOut pointers and initialize an outputsList controller with this array and its size. ```c++ Menu::menuOut* const outputs[] MEMMODE={&outSerial,&outLCD};//list of output devices Menu::outputsList out(outputs,2);//outputs list controller ``` -------------------------------- ### Initialize Prompt (Non-AVR) Source: https://github.com/neu-rah/arduinomenu/wiki/Menu-structure-objects Initializes a prompt option without using PROGMEM, suitable for non-AVR devices. Requires a callback function and an event handler. ```c++ //define "Op 1" void op1Func(); promptShadow op1Info("Op 1",(callback)op1Func,enterEvent); prompt op1(op1Info); ``` -------------------------------- ### Get Selected Option Index Source: https://github.com/neu-rah/arduinomenu/wiki/FAQ Returns the index of the currently selected option within the current navigation level. ```c++ nav.node().sel ``` -------------------------------- ### Customizing Options in V3.x Source: https://github.com/neu-rah/arduinomenu/wiki/Options Shows how to instantiate and assign a custom configuration object to the global options pointer in V3.x, allowing for detailed customization of menu behavior. ```c++ config myOptions( '>',//character used as cursor on enabled options '-',//character used as cursor on disabled options false,//invert up/down keys between nav and field edit false,//2D Nav - not implemented yet defaultNavCodes,//use default navigation characters '[+] [-] [\*] [/]' true,//use updateEvent true//can exit from main menu ); ... options=&myOptions; ``` -------------------------------- ### Initialize Empty Outputs List Source: https://github.com/neu-rah/arduinomenu/wiki/Initialization Create an outputsList named 'out' with a length of zero when no outputs are required. ```c++ Menu::outputsList out(NULL,0); ``` -------------------------------- ### Initialize Prompt (AVR with PROGMEM) Source: https://github.com/neu-rah/arduinomenu/wiki/Menu-structure-objects Initializes a prompt option using PROGMEM for AVR microcontrollers. This method stores strings and structures in flash memory to save RAM. ```c++ //define "Op 1" void op1Func(); const char op1Text[] PROGMEM="Op 1"; const promptShadowRaw op1InfoRaw PROGMEM={(callback)op1Func,\_noStyle,op1Text,enterEvent,noStyle}; const promptShadow& op1Info=*(promptShadow*)&op1InfoRaw; prompt op1(op1Info); ``` -------------------------------- ### Prevent Menu Exit Source: https://github.com/neu-rah/arduinomenu/wiki/FAQ Configures the menu system to prevent users from exiting the current menu. This is typically set during the setup phase. ```c++ options->canExit=false; ``` -------------------------------- ### Get Current Navigation Level Controller Source: https://github.com/neu-rah/arduinomenu/wiki/FAQ Retrieves the navigation level controller object for the current menu. This object provides access to navigation-specific functions. ```c++ nav.node() ``` -------------------------------- ### Automating Input Chain Construction with MENU_INPUTS Source: https://github.com/neu-rah/arduinomenu/wiki/Input The MENU_INPUTS macro simplifies the creation of input chains. Provide the desired stream name followed by a list of input streams to be concatenated. ```c++ MENU_INPUTS(name[,&menuIn]); ``` ```c++ MENU_INPUTS(in,&encStream,&encButton,&serial); ``` -------------------------------- ### Panel Structure Definition Source: https://github.com/neu-rah/arduinomenu/wiki/Output Defines a rectangular area on an output device with position (x, y) and dimensions (w, h). Use `maxX()` and `maxY()` to get the maximum coordinates. ```c++ struct panel { idx_t x,y,w,h; inline idx_t maxX() const {return x+w;} inline idx_t maxY() const {return y+h;} }; ``` -------------------------------- ### Custom Menu Item Rendering with Class Extension Source: https://context7.com/neu-rah/arduinomenu/llms.txt Extend `prompt` or use `altFIELD` to customize how menu items are displayed. `fancyPrompt` overrides `printTo` for custom rendering, while `altFIELD` with `decPlaces` formats floating-point values to a specified decimal precision. ```cpp #include #include #include using namespace Menu; #define MAX_DEPTH 2 // Custom prompt that renders with a border class fancyPrompt : public prompt { public: fancyPrompt(constMEM promptShadow& p) : prompt(p) {} Used printTo(navRoot& root, bool sel, menuOut& out, idx_t idx, idx_t len, idx_t panelNr) override { out.print(sel ? F("[*] ") : F("[ ] ")); return out.printRaw(F("Custom Item"), len); } }; double temperature = 23.456; // altFIELD with 2 decimal places using built-in decPlaces template // altFIELD(FieldClass, var, label, unit, min, max, step, tune, action, eventMask, style) MENU(mainMenu, "Custom Items", doNothing, noEvent, wrapStyle ,altOP(fancyPrompt, "Special", doNothing, noEvent) ,altFIELD(decPlaces<2>::menuField, temperature, "Temp", "C", -40.0, 85.0, 1.0, 0.01, doNothing, noEvent, noStyle) ,EXIT(" #include #include #include #include #include using namespace Menu; #define MAX_DEPTH 2 #define ENC_A 2 #define ENC_B 3 #define BTN_OK 4 // Quadrature encoder (uses PCINT or polling) encoderIn encoder; encoderInStream encStream(encoder, 4); // Single button mapped to 'enter' command character keyMap btnMap[] = {{-BTN_OK, options->getCmdChar(enterCmd)}}; // negative = INPUT_PULLUP keyIn<1> btnInput(btnMap); // Serial fallback input serialIn serial(Serial); // Combine all three into one stream // MENU_INPUTS(name, &stream1, &stream2, ...) MENU_INPUTS(in, &encStream, &btnInput, &serial); // equivalent to: // menuIn* inputList[] = {&encStream, &btnInput, &serial}; // chainStream<3> in(inputList); MENU(mainMenu, "Encoder Demo", doNothing, noEvent, wrapStyle ,OP("Start", doNothing, enterEvent) ,OP("Stop", doNothing, enterEvent) ,EXIT(" #include #include #include #include using namespace Menu; #define MAX_DEPTH 2 LiquidCrystal lcd(8, 9, 4, 5, 6, 7); // standard wiring MENU(mainMenu, "Dual Output", doNothing, noEvent, wrapStyle ,OP("Option 1", doNothing, noEvent) ,OP("Option 2", doNothing, noEvent) ,EXIT(" #include #include using namespace Menu; #define MAX_DEPTH 2 MENU(mainMenu, "Prog Nav", doNothing, noEvent, wrapStyle ,OP("Item 0", doNothing, enterEvent) ,OP("Item 1", doNothing, enterEvent) ,OP("Item 2", doNothing, enterEvent) ,EXIT("` enumerated field, click to select value as a sub-menu ``` -------------------------------- ### Default Menu Handlers Source: https://github.com/neu-rah/arduinomenu/wiki/Utils Provides default implementations for menu actions and idle events. `inaction` is the default idle handler, `doNothing` is a callback that does nothing, and `doExit` provides the default action for exiting a menu. ```cpp result Menu::inaction(menuOut& o,idleEvent) {return proceed;} ``` ```cpp result Menu::doNothing() {return proceed;} ``` ```cpp result Menu::doExit() {return quit;} ``` -------------------------------- ### SELECT Macro for Submenu Choices Source: https://context7.com/neu-rah/arduinomenu/llms.txt Use the SELECT macro to present choices as a submenu. It reflects external changes to the variable and requires the 'menu.h' and 'menuIO/serialOut.h' headers. The 'onColorChange' function demonstrates how to react to value changes. ```cpp #include #include #include using namespace Menu; #define MAX_DEPTH 2 int colorMode = 0; // 0=Off, 1=Red, 2=Green, 3=Blue result onColorChange(eventMask e, prompt& p) { // colorMode is already updated when this fires Serial.print("Color: "); Serial.println(colorMode); return proceed; } // SELECT(var, id, label, action, eventMask, style, VALUE(...), ...) SELECT(colorMode, colorSel, "Color", onColorChange, enterEvent, noStyle ,VALUE("Off", 0, doNothing, noEvent) ,VALUE("Red", 1, doNothing, noEvent) ,VALUE("Green", 2, doNothing, noEvent) ,VALUE("Blue", 3, doNothing, noEvent) ); MENU(mainMenu, "LED Control", doNothing, noEvent, wrapStyle ,SUBMENU(colorSel) ,EXIT(" #include #include using namespace Menu; #define MAX_DEPTH 1 bool adminMode = false; result toggleAdmin() { adminMode = !adminMode; // enable/disable items at runtime mainMenu[2].enabled = adminMode ? enabledStatus : disabledStatus; return proceed; } MENU(mainMenu, "System", doNothing, noEvent, wrapStyle ,OP("Status", doNothing, noEvent) ,OP("Toggle Admin", toggleAdmin, enterEvent) ,OP("Factory Reset",doNothing, enterEvent) // starts disabled ,EXIT("'; selected option text cursor char disabledCursor;//='-'; disabled option text cursor const navCodesDef &navCodes;//=defaultNavCodes; reference to existing navigation chars/commands table bool invertFieldKeys;//global fields keys inversion flag (for code driven single input) ``` ```c++ bool nav2D=false;//not used bool canExit=true;//v4.0 moved from global options bool useUpdateEvent=false;//if false, use enterEvent when field value is changed. idx_t inputBurst=1;//limit of inputs that can be processed before output ``` -------------------------------- ### Handle Menu Output Source: https://github.com/neu-rah/arduinomenu/wiki/Home This function verifies the need for output and satisfies it. It also checks for user value changes and redraws them accordingly. It is an inline function. ```c++ inline void doOutput(); ``` -------------------------------- ### Define Central Navigation Object using Macro Source: https://github.com/neu-rah/arduinomenu/wiki/Initialization Use the NAVROOT macro as a shorthand to initialize the central navigation object, specifying the navigation object name, menu definition, max depth, input stream, and output list. ```c++ NAVROOT(nav,main_menu,MAX_DEPTH,in,out); ``` -------------------------------- ### navNode Constructor Source: https://github.com/neu-rah/arduinomenu/wiki/Navigation Initializes a navNode object, which controls a single navigation depth layer targeting a menu or multi-choice option. ```APIDOC ## class navNode ### Description This object controls a single navigation depth layer, targeting a menu or multi-choice option. The `navRoot` object uses an array of these objects with a size equal to `maxDepth`. ### Public Data Members - **idx_t sel=0**: The current selection index. - **menuNode* target**: The focused menu node. - **static navRoot* root**: The navigation root object (experimental). This might change to non-static to allow multiple navigation root objects. ``` -------------------------------- ### Padded Options Group Configuration Source: https://github.com/neu-rah/arduinomenu/wiki/WebMenu Groups multiple options or fields together as a single selectable item. Each item in the 'pad' array defines a sub-menu or field with its own configuration, including range and units. ```json { "idx":"0", "enabled":"1", "selStart": ">", "prompt":"", "pad":[ {"idx":"0","enabled":"1","cursor":" ","prompt":"" ,"field":"1","range": {"low":"1","high":"31","step":"1","tune":"0"},"unit":"/"}, {"idx":"1","enabled":"1","cursor":" ","prompt":"" ,"field":"1","range": {"low":"1","high":"12","step":"1","tune":"0"},"unit":"/"}, {"idx":"2","enabled":"1","cursor":" ","prompt":"" ,"field":"2000","range": {"low":"2000","high":"2100","step":"10","tune":"1"},"unit":""} ] } ``` -------------------------------- ### Customize Navigation Key Mappings Source: https://context7.com/neu-rah/arduinomenu/llms.txt Remap physical key inputs to navigation commands by defining a custom `navCodesDef` table and applying it via the global `options` pointer. This allows using custom key layouts, such as WASD for navigation. ```cpp #include #include #include using namespace Menu; #define MAX_DEPTH 1 // Custom navigation key table — remap to WASD + Space/Esc const navCodesDef myNavCodes = { {noCmd, 0}, {escCmd, 'q'}, // 'q' = escape/back {enterCmd, ' '}, // space = enter/select {upCmd, 'w'}, // 'w' = up {downCmd, 's'}, // 's' = down {leftCmd, 'a'}, {rightCmd, 'd'}, {idxCmd, '?'}, {scrlUpCmd, 0x35}, {scrlDownCmd, 0x36} }; // Custom config: cursor char, disabled char, nav codes, invertFieldKeys config myOptions('*', '-', myNavCodes, false); MENU(mainMenu, "Custom Keys", doNothing, noEvent, wrapStyle ,OP("Option A", doNothing, noEvent) ,OP("Option B", doNothing, noEvent) ,EXIT("