I created an LCD menu library for a project I was working on, and I figured others may be able to reuse it so I have published it under a BSD license on github. (Just let me know if you want a different license, I am happy to re-publish for you)
The library is designed to make it easy to create a menu-driven interface on a simple LCD such as a 16x2 or 16x4. The library depends on the Liquid Crystal library to do all the drawing, but abstracts away some of the menu-intensive code.
The user is responsible for hooking up hardware navigation buttons/devices to the menu code, so you can choose when to pass control to the Menu library to do your menu navigation, and when to do do your own thing with the LCD.
For instance, if you have an app that is using the LCD to do its primary output, you can use this library to create a Settings UI to do some tweaking (code below is for a Sous vide monitor):
//Set up the root node first
MenuEntry * p_menuEntryRoot = new MenuEntry("Settings", NULL, NULL);
g_menuManager.addMenuRoot( p_menuEntryRoot );
g_menuManager.addChild( new MenuEntry("Temp ", NULL, TempCallback) );
g_menuManager.addChild( new MenuEntry("Time", NULL, TimeCallback ) );
g_menuManager.addChild( new MenuEntry("Beep Off", (void *)&g_beep, MenuEntry_BoolFalseCallbackFunc) );
g_menuManager.addChild( new MenuEntry("Beep On", (void *)&beep, MenuEntry_BoolTrueCallbackFunc) );
g_menuManager.addChild( new MenuEntry("Back", (void *)&g_MenuManager, MenuEntry_BackCallbackFunc) );\
There is also some support for getting a number from the user:
void TempCallback( char* menuText, void *userData )
char *label = "Temp F";
int numLabelLines = 1;
int min = 100;
int max = 200;
int start = 135;
//Each user input action (such as a turn of rotary enocoder or push of button
//will step this amount
int iStep = 1;
g_menuManager.DoIntInput( min, max, start, step, &label, numLabelLines, &g_temp );
That code will get a number from the user and set it in the g_temp variable.
This code was designed to work with an LCD and a clickable rotary encoder, such as this one: http://www.sparkfun.com/products/9117
. To use the rotary encoder, you can detect rotate up, rotate down, and click. You pass these events to the MenuManager as "Menu_UP", "Menu_Down", and "Menu_Select" actions. If you have a seperate hardware back button, you can pass this as "Menu_Back", or you can add "Back" items to all your menus to support backing up.
The code works well for simple use cases, but I hope to add more functionality soon.
The setup is a bit tough to read for more complicated menus, so if you have suggestions for a simpler way to declare tree structures such as the menus built here, I would be all ears.
The code includes an fairly complex sample stopwatch/timer. You can get it here: http://github.com/DavidAndrews/Arduino_LCD_Menu
Please give it a try and let me know what you think. The coding style is all over the place. I am trying to clean it up as I go, but I am not there yet. I will [soon] remove all the hungarian and try to settle on something consistent. My corporate coding style is showing, but I am working on exercising it from my brain.
Testing has been a bit ad-hoc, but I will try to address bugs quickly or accept submitted bug fixes even quicker.
We are creating an open hardware project to go along with this, which should be ready in time for Maker Faire, so keep an eye open at http://www.authenticinvention.com