OpenMoCo AVR Libraries
Motion Control and MoCoBus Libraries for the AVR Platform
OMMenuMgr Class Reference

The OpenMoCo Menu Manager provides a nearly complete automation of a menuing system. This class is designed to allow for rapid development of menuing systems on Arduino devices, using five input controls (buttons), and character displays of at least two rows. More...

#include <OMMenuMgr.h>

List of all members.

Public Member Functions

 OMMenuMgr (OMMenuItem *c_first, uint8_t c_type=MENU_ANALOG)
void setAnalogButtonPin (uint8_t p_pin, const int p_values[5][2], int p_thresh)
void setDigitalButtonPins (const int p_pins[5][2])
uint8_t checkInput ()
void enable (bool p_en)
bool enable ()
void setDrawHandler (void(*p_func)(char *, int, int, int))
void setExitHandler (void(*p_func)())
void setRoot (OMMenuItem *p_root)
bool shown ()
unsigned int holdModifier ()

Detailed Description

The OpenMoCo Menu Manager provides a nearly complete automation of a menuing system. This class is designed to allow for rapid development of menuing systems on Arduino devices, using five input controls (buttons), and character displays of at least two rows.

OpenMoCo Menu Manager Class

Designed to make it easy to implement menu systems, the Menu Manager requires the developer to do little more than specify the structure of the menu, and how to draw on the display.

Key features:

  • Menu structures automatically and easily stored in program memory instead of SRAM
  • Automatic handling of either analog or digital button inputs
  • Automatic management of user inputs for numeric and select list types
    • In-place editing with ability for user to abort
    • Write-back on user save to original variables
    • Specify lists of display values for users to select between
    • Control over user input precision in floats, and more
  • Ability to trigger code actions from menu items
  • One-method polling automatically handles and executes menu as-needed
  • Streamlined setup for complex and even recursive menus
  • Support for any width screen
  • Reduced memory footprint
  • No fixed limitations on menu depths, have as many sub-menus as you require
  • Flexible drawing methodology allows the user of any character-based (or even graphic) display
Author:
C. A. Church Dynamic Perception LLC

See http://www.dynamicperception.com for more information

(c) 2008-2012 C.A. Church / Dynamic Perception LLC

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Overview

The Menu Manager displays a character-based menu when triggered by the user. Five user inputs are used (although only four are required): Enter, Up, Down, Back, and Forward. Forward is optional. These inputs may either be buttons tied to digital pins, or up to five buttons tied to a single analog pin using a series of resistors to present different analog values when a button is pressed.

The menu is triggered by hitting the Enter key by the user when the menu is enabled. When it is displayed, the user is presented with all available options at the current menu level, one per row, with a cursor indicating the currently selected item. The up and down keys scroll the list through all available items at the current menu level. If the user presses enter, or forward on the current item, the item will be presented as either a value edit, a new menu, or an action will be executed as defined by the user based on the type of the menu entry. The back button will cancel out of the current input, go back one menu level, or exit the menu entirely if the user is at the root menu level.

When a value is being edited, the user may adjust the value within the range specified by the developer non-destructively using the up and down buttons. The user may cancel the edit of the value by using the back button, or may save the value using either of enter or forward. When the user saves the value, it is written directly to the variable specified by the developer. All numeric types are supported; individual bit flags, and special select lists are supported as well. For select lists, the user is presented with strings defined by the developer for the numeric values stored in the target variable, providing the ability to give the user a more complete and obvious solution.

Menu items may also be sub-menus. You can even re-use the same sub-menus under different menus with minimal impact to flash size and SRAM usage, letting you use the same menus under different contexts.

Menu items may be actions - you may wish to draw special screens and allow for use-case driven inputs. In this manner, you can trigger callbacks when menu items are triggered and disable the menu easily while interacting with the user, and then seamlessly place the user back into the menu where they left off when they are done.

Finally, the Menu Manager can be used to easily poll the user inputs without drawing the menu as needed by the developer.

The Basics of Menu Items

To create menu items, you'll need to specify their contents and create them using special datatypes which will keep them in program memory until needed. The basic item is defined via the MENU_ITEM data type, and specifies the label to give to the item, the type of item it is, the length (for certain types), and the target of the item. For example:

// LABEL TYPE LENGTH TARGET
MENU_ITEM item_foo = { {"Foo Edit"}, ITEM_VALUE, 0, MENU_TARGET(&value_foo) };

There are three cores types of items:

  • ITEM_VALUE
    • A value to be edited, which will either be a numeric type or a select list
  • ITEM_ACTION
    • An action to be executed when the user hits enter or forward on the item
  • ITEM_MENU
    • A sub-menu to be displayed when the user hits enter or forward on the item

To create a value item, we must also create a special variables which tells the menu system how to process the item. This special variable will be constructed again from a new type, with several parameters:

byte foo = 0;
// Data Type Max Min Target
MENU_VALUE value_foo = { TYPE_BYTE, 100, 0, MENU_TARGET(&foo) };
// LABEL TYPE LENGTH TARGET
MENU_ITEM item_foo = { {"Foo Edit"}, ITEM_VALUE, 0, MENU_TARGET(&value_foo) };

Here, we see that we can specify the type of data the item points to, a maximum value, a minimum value, and the target variable (by address) to be edited. Minimum and Maximum values are limited to the range of a signed long, no matter the data type, and are not used for select lists.

The following Data Type values are allowed:

  • TYPE_BYTE
  • TYPE_INT
  • TYPE_UINT
  • TYPE_LONG
  • TYPE_ULONG
  • TYPE_FLOAT
    • Whole integer changes, zero decimal precision per change
  • TYPE_FLOAT_10
    • Change by tenths
  • TYPE_FLOAT_100
    • Change by hundredths
  • TYPE_FLOAT_1000
    • Change by thousandths
  • TYPE_SELECT
  • TYPE_BFLAG

The Basics of Creating Menus

Of course, items on their own are of little use - we wouldn't typically go through all of this work to just have a single input! To create a menu, we need to create a list of items in that menu, and then create the item which represents the menu. For this, again, we have a special data type that allows us to easily create them and store in program space:

MENU_LIST root_list[] = { &item_foo, &item_bar };
MENU_ITEM menu_root = { {"Root Menu"}, ITEM_MENU, MENU_SIZE(root_list), MENU_TARGET(&root_list) };

We may, of course, create multiple lists, use the same list in multiple items, and use the same items in multiple lists.

The Basics of Creating Select Lists

Creating a select list is a little more complex than a normal item value. Since we're displaying the user a list of strings, and mapping them back to numeric values, we need to create this mapping.

To do so, we need to create the items that will appear in lists, and the lists which use them:

MENU_SELECT_ITEM sel_ign = { 2, {"Ignore"} };
MENU_SELECT_ITEM sel_on = { 1, {"On"} };
MENU_SELECT_ITEM sel_off = { 0, {"Off"} };
MENU_SELECT_LIST state_list[] = { &sel_ign, &sel_on, &sel_off };

Note here, for each item we specify the numeric value associated with the string, and the string to display to the user. We can use these select items in any select list, but it is important to note that you should not duplicate a numeric value in one list.

The numeric values are specified as a byte type, and are limited to 0-255.

Finally, to create the target for a menu item to use this select list, we must create a special variable that specifies how to handle the select, where to store the target value, the length of the list, and the list to use:

byte myVar = 0;
// TARGET VAR LENGTH TARGET SELECT LIST
MENU_SELECT state_select = { &myVar, MENU_SELECT_SIZE(state_list), MENU_TARGET(&state_list) };
MENU_VALUE value_sel = { TYPE_SELECT, 0, 0, MENU_TARGET(&state_select) };
MENU_ITEM item_sel = { {"Select It"}, ITEM_VALUE, 0, MENU_TARGET(&value_sel) };

The Basics of Creating Bit Flag Inputs

A bit flag input allows you to change only one bit in a target variable, for example, in the case where you want to store up to 8 on/off flags in a single byte of data to preserve RAM. The Menu Manager supports doing this by creating a special target for the MENU_VALUE you're creating:

byte theseFlags = 0;
MENU_FLAG my_flag = { 3, &theseFlags };
MENU_VALUE my_value = { TYPE_BFLAG, 0, 0, MENU_TARGET(&my_flag) };
MENU_ITEM my_item = { {"Flag Edit"}, ITEM_VALUE, 0, MENU_TARGET(&my_value) };

We'll note that the new MENU_FLAG type has two parts: the bit position, and the address of the byte containing the bit. The bit position is from the right and is of the range 0-7, so this item would modify the bit marked with 'x' in the following pattern: B1111x111

In this example, when the user interacts with the "Flag Edit" menu item, the user will be displayed the OM_MENU_FLAG_ON and OM_MENU_FLAG_OFF strings based on the value of bit 3 in the 'theseFlags' variable. When saved by the user, the correct bit value will be written back to bit 3 in 'theseFlags'.

If you want to change the strings used for On and Off, see the Setting Control Parameters section below.

The Basics of Creating Actions

An action is a function that will be called when a user presses enter or forward on that item. This can be used to display special screens, or call some other behavior more complex than just setting a parameter.

All functions being called by actions must take no parameters, and return void. When an action is called, your callback handler is called. If the menu is still enabled when your callback handler exits, the menu will be re-drawn where it was when the action was initiated, otherwise the menu will not be displayed again until the menu is re-enabled and the checkInput() method is called again. (For more info on disabling the menu, and polling inputs, see the Polling the Menu section below.)

For example, we can create a special screen that is drawn when an action is triggered, which waits until the user presses a button before returning to the menu:

MENU_ITEM item_testme = { {"Test Action"}, ITEM_ACTION, 0, MENU_TARGET(uiQwkScreen) };
...
void uiQwkScreen() {
lcd.clear();
Menu.enable(false);
lcd.print("Action!");
lcd.setCursor(0, 1);
lcd.print("Enter 2 return");
while( Menu.checkInput() != BUTTON_SELECT ) {
; // wait!
}
Menu.enable(true);
lcd.clear();
}

Initializing the Menu

After we have created all of our menu items, lists, selects, and so forth, we need to initialize the OMMenuMgr object with a root item. This root item will be the starting point when the user triggers the menu, and should be an ITEM_MENU in most cases.

Additionally, we need to specify whether our input is analog (MENU_ANALOG, default), or digital (MENU_DIGITAL).

OMMenuMgr Menu = OMMenuMgr(&menu_root, MENU_ANALOG);

Note that we always pass the root item by address, and not by value! You can always change the root item later, using the setRoot() method.

User Input

After we have created our menu structure, we must specify how to handle user input. To do this, we must tell the Menu Manager how to read our buttons.

In both analog and digital cases, we must create a two-dimensional list of how to read buttons, and their meanings. This list will always have 5 lists of 2 elements. The format is:

int map = {
{ button 1 read, button 1 definition },
{ button 2 read, button 2 definition },
...
};

The button definition is always one of the following:

BUTTON_FORWARD, BUTTON_BACK, BUTTON_INCREASE, BUTTON_DECREASE, BUTTON_SELECT

The how to read button instruction will differ based on whether you are doing analog or digital input. For digital inputs, the first element will be the Arduino digital pin # of the button, and for analog inputs, the first element will be analogRead() value associated with the button.

For digital input, we simply need to pass this array to the setDigitalButtonPins() method. Also note, that for digital inputs the input pins will be pulled HIGH internally and you are expected to swing them to LOW when pressed.

For analog input, we must also specify the pin to read the value from, and the threshold for reading the values. The threshold is very important, as analog inputs are rarely exact; this threshold is the variance that will be applied to each value during comparison. These values and the button definition array are sent to the setAnalogButtonPin() method.

The following is a complete example of initializing an analog input:

// which input is our button (use the digital pin#, not the analog pin #!)
const byte BUT_PIN = 14;
// analog button read values
const int BUTSEL_VAL = 70;
const int BUTFWD_VAL = 250;
const int BUTREV_VAL = 450;
const int BUTDEC_VAL = 655;
const int BUTINC_VAL = 830;
const byte BUT_THRESH = 60;
// mapping of analog button values for menu
const int BUT_MAP[5][2] = {
{BUTSEL_VAL, BUTTON_SELECT},
{BUTINC_VAL, BUTTON_INCREASE},
{BUTDEC_VAL, BUTTON_DECREASE},
{BUTREV_VAL, BUTTON_BACK},
{BUTFWD_VAL, BUTTON_FORWARD}
};
...
void setup() {
...
Menu.setAnalogButtonPin(BUT_PIN, BUT_MAP, BUT_THRESH);
}

If you do not wish to use the forward button, it is not required. However, you must still specify five buttons in the array. To ignore the forward button (if you want to use only four, instead of five, buttons), simply make sure that BUTTON_FORWARD is the last element in the array, and re-use one of the earlier read values.

Polling the Menu

The menu must be polled regularly, such as during your loop() function, to check for input, display the menu, or interact with it. A single method is all that needs to be called for this activity.

void loop() {
Menu.checkInput();
}

This method returns the button pressed or BUTTON_NONE if none were, so you may also use it to handle user input if you need, and disable the menu if required, see:

void loop() {
if( hideMenu ) {
Menu.enable(false);
hideMenu = false;
}
byte button = Menu.checkInput();
if( ! Menu.enable() ) {
// menu is disabled
if( button == BUTTON_SELECT ) {
// do something!
}
else if( button == BUTTON_FORWARD ) {
// re-enable Menu
Menu.enable(true);
}
}
}

Managing Display

While the Menu Manager creates the content for display, and manages what data should be displayed and when, it does not have any built-in display methodology. This allows you to use nearly any display you like, since you will be controlling how the data is sent to the display.

To achieve this, a callback model is used - you specify a function for each required display activity, and pass them as arguments to the set...Handler() methods.

Three functions are required: Draw, and Exit.

Draw handles displaying strings to the screen. It is passed four arguments: a character pointer, a row, a column, and the length of the characters stored at the address in the character pointer.

The character pointer will not always be null-terminated, and cannot be relied upon to be null-terminated. Always use the length argument, which can be relied upon.

The following shows a model handler for drawing using a standard LiquidCrystal object named 'lcd':

void setup() {
...
Menu.setDrawHandler(uiDraw);
}
...
void uiDraw(char* p_text, int p_row, int p_col, int len) {
lcd.setCursor(p_col, p_row);
for( int i = 0; i < len; i++ ) {
if( p_text[i] < '!' || p_text[i] > '~' )
lcd.write(' ');
else
lcd.write(p_text[i]);
}
}

Note that in the above function, we handle characters outside of the normal ascii range, as the MenuMgr cannot gaurantee that every character is displayable.

Exit is called when the user exits the menu, and it is cleared. It should bring you to whatever state you need to be when the menu isn't displayed.

The following is a model example of a clear callback handler:

void uiExit() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Enter for Menu");
}

Setting Control Parameters

Of course, not every display is the same. Display parameters are set at compile time, and controlled via define's.

Unfortunately, the Arduino IDE does not allow you to specify defines to the compiler, so you cannot effectively change these from the Arduino IDE. For other IDE users, you may re-define them via your build process. For Arduino IDE users, you will need to edit the library directly.

  • OM_MENU_ROWS
    • Default = 2
    • Number of rows in the display, minimum is 2
  • OM_MENU_COLS
    • Default = 16
    • Number of columns (character width) in the display. This also controls the maximum length of any label for a menu item
  • OM_MENU_LBLLEN
    • Default = OM_MENU_COLS
    • Maximum length of a select label, this can be used to reduce flash usage when only short labels are needed
  • OM_MENU_MAXDEPTH
    • Default = 3
    • Maximum nested depth of menus. You can go deeper than this, but menu history will not be retained below this level.
  • OM_MENU_DEBOUNCE
    • Default = 120
    • Debounce time for button input, in mS
  • OM_MENU_CURSOR
    • Default = ">"
    • Cursor to show for current item selection
  • OM_MENU_NOCURSOR
    • Default = " "
    • Cursor to show for displayed items not currently selected
  • OM_MENU_USE_EEPROM
  • OM_MENU_FLAG_ON
    • Default = "On"
    • The string to be displayed to the user for bit flag values where the flag is turned on
  • OM_MENU_FLAG_OFF
    • Default = "Off"
    • The string to be displayed to the user for bit flag values where the flag is turned off

Automating EEPROM Writes

The Menu Manager can automatically store changed variables to EEPROM for you, using the OMEEPROM library. You can retrieve the data, do EEPROM format versioning, and more with the OMEEPROM library.

Each menu value has a final parameter, with the EEPROM byte address to store the data. If you do not want to store the data in EEPROM, use 0 as the address, or simply not pass that parameter at all. For example:

#include "OMEEPROM.h"
#include "OMMenuMgr.h"
...
const int EEPROM_NOADDR = 0;
const int EEPROM_FOO = 10;
unsigned int foo = 1;
unsigned int bar = 1;
unsigned int baz = 1;
...
MENU_VALUE value_foo = { TYPE_UINT, 0, 0, MENU_TARGET(&foo), EEPROM_FOO };
MENU_VALUE value_bar = { TYPE_UINT, 0, 0, MENU_TARGET(&foo), EEPROM_NOADDR };
MENU_VALUE value_baz = { TYPE_UINT, 0, 0, MENU_TARGET(&baz) }; // equivalent to providing no address at the end

Now, when these values are exercised by the user, foo will be stored to EEPROM, starting at byte 10, and bar will not be stored in EEPROM.

A Complete Example

The following is a complete example of a sketch with a menu:

#include "OMMenuMgr.h"
#include <LiquidCrystal.h>
// lcd pins
const byte LCD_RS = 17;
const byte LCD_EN = 18;
const byte LCD_D4 = 11;
const byte LCD_D5 = 8;
const byte LCD_D6 = 7;
const byte LCD_D7 = 4;
const byte LCD_ROWS = 2;
const byte LCD_COLS = 16;
// button values
// which input is our button
const byte BUT_PIN = 14;
// analog button read values
const int BUTSEL_VAL = 70;
const int BUTFWD_VAL = 250;
const int BUTREV_VAL = 450;
const int BUTDEC_VAL = 655;
const int BUTINC_VAL = 830;
const byte BUT_THRESH = 60;
// mapping of analog button values for menu
const int BUT_MAP[5][2] = {
{BUTFWD_VAL, BUTTON_FORWARD},
{BUTINC_VAL, BUTTON_INCREASE},
{BUTDEC_VAL, BUTTON_DECREASE},
{BUTREV_VAL, BUTTON_BACK},
{BUTSEL_VAL, BUTTON_SELECT}
};
// ====== Test Menu ===========
byte foo = 0;
byte sel = 0;
unsigned int bar = 1;
long baz = 0;
float bak = 0.0;
// Create a list of states and values for a select input
MENU_SELECT_ITEM sel_ign = { 2, {"Ignore"} };
MENU_SELECT_ITEM sel_on = { 1, {"On"} };
MENU_SELECT_ITEM sel_off = { 0, {"Off"} };
MENU_SELECT_LIST state_list[] = { &sel_ign, &sel_on, &sel_off };
// the special target for our state input
// TARGET VAR LENGTH TARGET SELECT LIST
MENU_SELECT state_select = { &sel, MENU_SELECT_SIZE(state_list), MENU_TARGET(&state_list) };
// values to use
// TYPE MAX MIN TARGET
MENU_VALUE foo_value = { TYPE_BYTE, 100, 0, MENU_TARGET(&foo) };
MENU_VALUE bar_value = { TYPE_UINT, 10000, 100, MENU_TARGET(&bar) };
MENU_VALUE baz_value = { TYPE_LONG, 10000, 1, MENU_TARGET(&baz) };
MENU_VALUE bak_value = { TYPE_FLOAT_1000, 0, 0, MENU_TARGET(&bak) };
MENU_VALUE sel_value = { TYPE_SELECT, 0, 0, MENU_TARGET(&state_select) };
// LABEL TYPE LENGTH TARGET
MENU_ITEM item_checkme = { {"Byte Edit"}, ITEM_VALUE, 0, MENU_TARGET(&foo_value) };
MENU_ITEM item_barme = { {"UInt Edit"}, ITEM_VALUE, 0, MENU_TARGET(&bar_value) };
MENU_ITEM item_bazme = { {"Long Edit"}, ITEM_VALUE, 0, MENU_TARGET(&baz_value) };
MENU_ITEM item_bakme = { {"Float Edit"}, ITEM_VALUE, 0, MENU_TARGET(&bak_value) };
MENU_ITEM item_state = { {"Select Input"}, ITEM_VALUE, 0, MENU_TARGET(&sel_value) };
MENU_ITEM item_testme = { {"Test Action"}, ITEM_ACTION, 0, MENU_TARGET(uiQwkScreen) };
// List of items in menu level
MENU_LIST root_list[] = { &item_checkme, &item_barme, &item_bazme, &item_bakme, &item_state, &item_testme };
// Root item is always created last, so we can add all other items to it
MENU_ITEM menu_root = { {"Root"}, ITEM_MENU, MENU_SIZE(root_list), MENU_TARGET(&root_list) };
// initialize LCD object
LiquidCrystal lcd(LCD_RS, LCD_EN, LCD_D4, LCD_D5, LCD_D6, LCD_D7);
OMMenuMgr Menu(&menu_root);
void uiMenuSetup() {
lcd.begin(LCD_COLS, LCD_ROWS);
uiClear();
Menu.setDrawHandler(uiDraw);
Menu.setExitHandler(uiClear);
Menu.setAnalogButtonPin(BUT_PIN, BUT_MAP, BUT_THRESH);
Menu.enable(true);
}
void uiCheck() {
Menu.checkInput();
}
void testAction() {
digitalWrite(5, HIGH);
}
void uiDraw(char* p_text, int p_row, int p_col, int len) {
lcd.setCursor(p_col, p_row);
for( int i = 0; i < len; i++ ) {
if( p_text[i] < '!' || p_text[i] > '~' )
lcd.write(' ');
else
lcd.write(p_text[i]);
}
}
void uiClear() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Enter for Menu");
}
void uiQwkScreen() {
lcd.clear();
Menu.enable(false);
lcd.print("Action!");
lcd.setCursor(0, 1);
lcd.print("Enter 2 return");
while( Menu.checkInput() != BUTTON_SELECT ) {
; // wait!
}
Menu.enable(true);
lcd.clear();
}

Definition at line 910 of file OMMenuMgr.h.


Constructor & Destructor Documentation

OMMenuMgr ( OMMenuItem c_first,
uint8_t  c_type = MENU_ANALOG 
)

Constructor

Constructs an OMMenuMgr instance, with a specified root item, and a specified input type.

#include "OMMenuMgr.h"
...
OMMenuMgr Menu = OMMenuMgr(&rootItem, MENU_ANALOG);
Parameters:
c_firstA pointer to an OMMenuItem representing the root of the menu
c_typeThe input type for the menu, either MENU_ANALOG or MENU_DIGITAL

Definition at line 51 of file OMMenuMgr.cpp.


Member Function Documentation

uint8_t checkInput ( )

Check for User Input and Handle

Checks to see if any button has been pressed by the user, and reports back the button pressed, or BUTTON_NONE if none are pressed.

If the menu is enabled and drawn, and any button is pressed, normal handling of the menu is executed. If the menu is enabled, but not drawn, the menu will be drawn only if BUTTON_SELECT is pressed. Otherwise, no activity will occur.

Returns:
The button pressed, one of: BUTTON_NONE, BUTTON_FORWARD, BUTTON_BACK, BUTTON_INCREASE, BUTTON_DECREASE, BUTTON_SELECT

Definition at line 221 of file OMMenuMgr.cpp.

void enable ( bool  p_en)

Enable or Disable Handling of Menu

You may disable handling of menu to allow the class instance to just poll and report back the currently pressed button. This is particularly useful when executing actions from menu items, where the user input is needed.

Parameters:
p_enEnable (true), or disable (false) menu display

Definition at line 314 of file OMMenuMgr.cpp.

bool enable ( )

Get Enable Status

Returns the current enable status

Returns:
Enable status

Definition at line 326 of file OMMenuMgr.cpp.

unsigned int holdModifier ( )

Get Hold Modifier

If a button is held by the user, the hold modifier is increased every OM_MENU_DEBOUNCE period of time. In between these time periods, checkInput() returns BUTTON_NONE, to prevent duplication of input (e.g. bouncing).

By checking this value, you can determine the difference between a button being held (hold modifier > 1) and debounced, and no button being pressed. E.g.:

byte button = Menu.checkInput();
unsigned int holdMod = Menu.holdModifier();
if( button == BUTTON_NONE && holdMod > 1 ) {
// last button press is held!
}
else if( button != BUTTON_NONE ) {
// a button is pressed for the first time, or being
// held for the first debounce cycle
}
else {
// no button is pressed at all
}
Returns:
Hold modifier, >= 1

Definition at line 375 of file OMMenuMgr.cpp.

void setAnalogButtonPin ( uint8_t  p_pin,
const int  p_values[5][2],
int  p_thresh 
)

Setup Analog Button Input

For UI's with multiple buttons assigned to a single analog pin (e.g. using a resistor network to report different values), this method allows you to specify how this pin shall be read.

This method is NOOP if the menu type is not MENU_ANALOG

The digital pin # is specified, along with an array of values and their meanings, and a threshold for those values. The array of values and meanings should be two-dimensional with two values in the second dimension, and five rows in the first dimension. The two values shall represent the integer value of analogRead() assigned to that button, and the button type. e.g.:

const int[5][2] myButtons = { {150, BUTTON_FORWARD},
{250, BUTTON_INCREASE},
{350, BUTTON_DECREASE},
{450, BUTTON_BACK},
{550, BUTTON_SELECT}
};
Menu.setAnalogButtonPin(14, myButtons, 25);
Parameters:
p_pinThe Arduino Digital Pin to use
p_valuesThe list of button values and function
p_threshThe threshold deviation from the specified value to match the button read. You must provide some threshold, as the analogRead() values will vary. The range of value to be matched for each button is between (value - thresh) and (value + thresh). This threshold should be large enough to account for the variation in your circuit, but by no means should two button values overlap.

Definition at line 106 of file OMMenuMgr.cpp.

void setDigitalButtonPins ( const int  p_values[5][2])

Setup Digital Button Input

For UI's with digital button input (e.g. one digital input per button), this method allows you to specify the pins for digital input.

An array is passed that defines, for each button, it's digital pin and function. There must be two dimensions, with five rows and two data elements. The first data element indicates the Arduino digital pin, and the second element indicates the function.

For example:

const int[5][2] myButtons = { {4, BUTTON_FORWARD},
{5, BUTTON_INCREASE},
{6, BUTTON_DECREASE},
{7, BUTTON_BACK},
{8, BUTTON_SELECT}
};
Menu.setDigitalButtonPins(myButtons);
Parameters:
p_valuesThe list of button values and functions

Definition at line 150 of file OMMenuMgr.cpp.

void setDrawHandler ( void(*)(char *, int, int, int)  p_func)

Set Draw Handler Callback

Sets the draw handler callback, see Managing Display for more information

Parameters:
p_funcA function pointer for the draw handler

Definition at line 177 of file OMMenuMgr.cpp.

void setExitHandler ( void(*)()  p_func)

Set Exit Handler Callback

Sets the exit handler callback, see Managing Display for more information

Parameters:
p_funcA function pointer for the exit handler

Definition at line 191 of file OMMenuMgr.cpp.

void setRoot ( OMMenuItem p_root)

Set New Root Item

Sets new root item as the base for future calls to checkInput();

Parameters:
p_rootA pointer to an OMMenuItem

Definition at line 338 of file OMMenuMgr.cpp.

bool shown ( )

Menu Shown State

Whether or not the menu is currently being displayed.

Returns:
Whether or the menu is currently displayed (true), or not (false)

Definition at line 204 of file OMMenuMgr.cpp.


The documentation for this class was generated from the following files: