Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/The-Young-Maker/OpenMenuOS/llms.txt

Use this file to discover all available pages before exploring further.

OpenMenuOS abstracts hardware input so the rest of the menu system does not need to know whether the user is pressing discrete buttons or spinning a rotary encoder. You configure pins and voltage levels once during setup(), and the library translates raw GPIO signals into navigation events — scroll up, scroll down, select — for whichever screen is currently active.

The three logical buttons

Every navigation action maps to one of three logical inputs:
Logical inputPurpose
UpMove selection to the previous item
DownMove selection to the next item
SelectConfirm the current item / enter a sub-screen
Each button maps to a physical GPIO pin. Setting a pin to -1 disables that input entirely, which is useful when using an encoder for up/down and only a single button for select.
// All three buttons
OpenMenuOS menu(19, 5, 2);  // btn_up, btn_down, btn_sel

// Only select button; up/down handled by encoder
OpenMenuOS menu(-1, -1, 19);

// No pins at construction — assign them later
OpenMenuOS menu;

Pin configuration methods

You can assign or reassign pins after construction using the individual setter methods. This is handy when the encoder provides up/down and a separate GPIO provides select.
menu.setUpPin(19);      // Up button GPIO
menu.setDownPin(5);     // Down button GPIO
menu.setSelectPin(2);   // Select button GPIO

Button voltage mode

By default the library expects buttons to pull the pin low when pressed. If your circuit pulls pins high on press (e.g., external pull-down resistors or active-high logic), set the mode to "High":
menu.setButtonsMode("low");   // Pin reads LOW when pressed (default)
menu.setButtonsMode("High");  // Pin reads HIGH when pressed
The argument is case-insensitive in practice, but the canonical values shown in the source and examples are "low" and "High".

Rotary encoder support

A rotary encoder replaces the Up and Down buttons with a single rotating knob. Connect the encoder’s CLK and DT pins, then configure them with setEncoderPin(). The encoder button (SW pin) acts as the Select input and is configured with setSelectPin().
// From the simple example sketch:
menu.setEncoderPin(5, 2);  // CLK pin, DT pin
menu.setSelectPin(19);     // Encoder push-button
Encoder support is enabled automatically as soon as setEncoderPin() is called. The encoder also works for navigating popup buttons — rotate to move between OK/Cancel, press to confirm.
When using an encoder, you do not need to call setUpPin() or setDownPin(). The CLK/DT pair replaces both directional buttons.

Input method comparison

Three separate momentary push-buttons wired to individual GPIOs. Suitable for simple, low-cost hardware.
OpenMenuOS menu(19, 5, 2);      // up, down, select
menu.setButtonsMode("low");     // active-low wiring
menu.begin(&mainMenu);

Debouncing and long-press detection

The library handles debouncing internally for all button inputs. Raw GPIO reads are filtered so that a single physical press registers as exactly one navigation event, even on noisy hardware. Long-press detection is tracked per-screen using the pressedTime, releasedTime, and isLongDetected state variables on SettingsScreen. A long press on the Select button while inside a settings item triggers a special edit-lock release, letting the user commit a range value or exit a setting modification.
// These are managed internally — no setup required:
unsigned long pressedTime;
unsigned long releasedTime;
bool isPressing;
bool isLongDetected;
You do not need to implement debouncing or long-press timers in your own code. The library handles both transparently inside handleInput().

Reading raw button states

The OpenMenuOS class exposes getter methods that return the configured pin numbers. These are informational — the library reads the GPIO states itself inside loop().
int upPin  = menu.UpButton();     // configured up button pin
int dnPin  = menu.DownButton();   // configured down button pin
int selPin = menu.SelectButton(); // configured select button pin

Full encoder setup example

This is the encoder configuration taken directly from the library’s simple example sketch:
#include "OpenMenuOS.h"

OpenMenuOS menu;

MenuScreen mainMenu("Main Menu");
SettingsScreen settingsScreen("Settings");

void setup() {
    settingsScreen.addBooleanSetting("Animations", true);
    settingsScreen.addRangeSetting("Brightness", 0, 100, 75, "%");

    mainMenu.addItem("Settings", &settingsScreen);

    // Encoder: CLK on pin 5, DT on pin 2
    menu.setEncoderPin(5, 2);
    // Select button on pin 19 (encoder push-button)
    menu.setSelectPin(19);
    // Buttons wire active-low
    menu.setButtonsMode("low");

    menu.useStylePreset("Rabbit_R1");
    menu.begin(&mainMenu);
}

void loop() {
    menu.loop();
}

Build docs developers (and LLMs) love