### 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("