2x16 LCD Menu Class ?
#1
Posted 09 February 2011 - 11:23 AM
I've managed to get an DF Robot LCD Keypad working with the netduinoso I have a 2 x 16 LCD screen and 5 buttons (nominally Up, Down, Left, Right and Select).
I'm wondering if there already has been Menu system built for a 2x16 or one that can be adapted. (I've searched and found little).
I'm happy to have a go building one ... but I've can't recall any 2-line menu system that I'd like to emulate.
Any suggestions on style or good working examples greatly appreciated.
Thanks
#2
Posted 15 February 2011 - 01:31 PM
#3
Posted 17 February 2011 - 12:37 AM
Thomas ... I recall the old HP printers. Seem to remember that they had Up, Down, Select and a Cancel button as well.Hi Steve,
One option to emulate or get inspiration from could be the menu system used in the older HP laser printers...
I'm going to do something similar on a little Arduino based board (http://www.hackmeist...cd-io-backpack/), but with only up, down and select (http://www.sparkfun.com/products/8184).
/Thomas
Anyhow, I think I'll be implementing a very similar thing.
If I use a menu structure that contains
<MenuTag>
<Menutext>
<ParentTag>
and store these in an array. Then have the buttons do the following:
[Left] or [Right] Move along the array for next item with same ParentTag
[Up] or [Down] Move back to the array item that is in ParentTag (Top menu has no ParentTag so stay there)
[Select] Move to 1st menu item that has MenuTag as it's ParentTag. If not found then you are at the bottom level of the menu so Raise a menuSelectedEvent passing back MenuTag
So the menus can be as deep and wide as you want. All that is required in your own code is to handle the menSelectedEvent where you have a Switch statement that can be used to call the appropriate process based on the menuReturned evant args.
Here is the 1st cut of the code
class Winder :IDisposable { // Constants for timer operations const int KEY_TIMEOUT = 200; // Milliseconds between menu operations const int TURN_OFF = -1; const int TURN_ON_NOW = 0; const int TURN_ON_SOON = 100; // Control Timers Timer keyTimer; // For Haydon motor there are 2 axis EasyStepper HaydonRotate = new EasyStepper(); EasyStepper HaydonLinear = new EasyStepper(); // Menu elements: create the structure public struct menu { public menu(string menuTag, string menuText, string parentTag) { this.menuTag = menuTag; this.menuText = menuText; this.parentTag = parentTag; } public string menuTag; public string menuText; public string parentTag; } // Fill the menu static menu[] myMenu = new menu[] { new menu() { menuTag = "MainMenu", menuText = "Main Menu", parentTag="MainMenu" }, new menu() { menuTag = "JogMenu", menuText = "Jog Menu", parentTag="MainMenu" }, new menu() { menuTag = "Jog2Menu", menuText = "Jog2 Menu", parentTag="JogMenu" } , new menu() { menuTag = "Jog3Menu", menuText = "Jog3 Menu", parentTag="JogMenu" } , new menu() { menuTag = "Jog4Menu", menuText = "Jog4 Menu", parentTag="JogMenu" } , new menu() { menuTag = "SetupMenu", menuText = "Setup Menu", parentTag="MainMenu" }, new menu() { menuTag = "Setup2Menu", menuText = "Setup2 Menu", parentTag="SetupMenu" } , new menu() { menuTag = "Setup3Menu", menuText = "Setup3 Menu", parentTag="SetupMenu" } , new menu() { menuTag = "Setup4Menu", menuText = "Setup4 Menu", parentTag="SetupMenu" } , }; // Set the current menu to the top element public menu currentMenu = myMenu[0]; public void Run() { // Initialize LCD Keypad LCDKeypad.Initialize(); // Display the welcome splash screen DisplayWelcome(); DisplayMenu(currentMenu); // Initialize rotating motor and linear motor HaydonRotate.Initialize(200, Pins.GPIO_PIN_D3, Pins.GPIO_PIN_D4, Pins.GPIO_PIN_D0, Pins.GPIO_PIN_D1); HaydonLinear.Initialize(200, Pins.GPIO_PIN_D8, Pins.GPIO_PIN_D9, Pins.GPIO_PIN_D5, Pins.GPIO_PIN_D6); // Set up timer to check for Keys keyTimer = new Timer(on_keyTimerTick, null, TURN_ON_NOW, KEY_TIMEOUT); } public void Dispose() { keyTimer.Dispose(); } #region Menu Handling private void DisplayWelcome() { // const byte ARROW_RIGHT = 126; // const byte ARROW_LEFT = 127; LCDKeypad.SetCustomChars(1, new byte[] { 0, 2, 6, 14, 6, 2, 0 }); // Left LCDKeypad.SetCustomChars(2, new byte[] { 0, 8, 12, 14, 12, 8, 0 }); // Right LCDKeypad.SetCustomChars(3, new byte[] { 0, 0, 4, 14, 31, 0, 0 }); // Up LCDKeypad.SetCustomChars(4, new byte[] { 0, 0, 31, 14, 4, 0, 0 }); // Down LCDKeypad.SetCustomChars(5, new byte[] { 14, 1, 1, 29, 25, 22, 0 }); // Clockwise LCDKeypad.SetCustomChars(6, new byte[] { 14, 16, 16, 23, 19, 13, 0 });// AntiClockwise LCDKeypad.SetCustomChars(7, new byte[] { 4, 14, 31, 4, 4, 31, 31 }); // Out LCDKeypad.SetCustomChars(0, new byte[] { 4, 4, 31, 14, 4, 31, 31 }); // In LCDKeypad.Clear(); LCDKeypad.ModeForwardStatic(); LCDKeypad.CursorInvisible(); LCDKeypad.Print(0, 0, Resources.GetString(Resources.StringResources.WelcomeMsg1)); LCDKeypad.Print(1, 1, Resources.GetString(Resources.StringResources.WelcomeMsg2)); Thread.Sleep(2000); LCDKeypad.Clear(); } public void on_keyTimerTick(object state) { doMenuStuff(); } private void doMenuStuff() { switch (LCDKeypad.GetKey()) { case LCDKeypad.Keys.None: break; case LCDKeypad.Keys.Up: cancelMenu(); break; case LCDKeypad.Keys.Down: cancelMenu(); break; case LCDKeypad.Keys.Right: getNextMenu(); break; case LCDKeypad.Keys.Left: getPriorMenu(); break; case LCDKeypad.Keys.Select: selectMenu(); break; default: break; } } #endregion private void getNextMenu() { bool foundFlag = false; bool endFlag = true; // Set current Position foreach (menu tempMenu in myMenu) { // Loop to the current item if (tempMenu.menuTag == currentMenu.menuTag) { foundFlag = true; continue; // jump to next item } if (foundFlag) { if (tempMenu.parentTag == currentMenu.parentTag) { // If next item is same parent, set as current currentMenu = tempMenu; endFlag = false; break; // stop looking } } } // If we get to the end, loop back to the top if (!endFlag) { DisplayMenu(currentMenu); } else { // Couldn't find next menu so loop back to top foreach (menu tempMenu in myMenu) { if (tempMenu.parentTag == currentMenu.parentTag) { currentMenu = tempMenu; break; } } DisplayMenu(currentMenu); } } private void getPriorMenu() { menu priorMenu = currentMenu; // Set current Position foreach (menu tempMenu in myMenu) { if (tempMenu.parentTag == currentMenu.parentTag ) { // If next item is same parent and not the current item, set as current if (tempMenu.menuTag != currentMenu.menuTag) { priorMenu = tempMenu; } } // Loop to the current item if (tempMenu.menuTag == currentMenu.menuTag) { currentMenu = priorMenu; break; } } DisplayMenu(currentMenu); } public void selectMenu() { bool isMenu = false; // Check if this is a menu or option foreach (menu tempMenu in myMenu) { if (tempMenu.parentTag == currentMenu.menuTag) { currentMenu = tempMenu; isMenu = true; break; } } // If menu item then display if (isMenu) { DisplayMenu(currentMenu); } else { RunThisOption(currentMenu.menuTag); } } public void cancelMenu() { // Go back up one level foreach (menu tempMenu in myMenu) { if (tempMenu.menuTag == currentMenu.parentTag) { currentMenu = tempMenu; break; } } // Display DisplayMenu(currentMenu); } public void RunThisOption(string selectedItem) { switch (selectedItem) { case "Setup4Menu": Debug.Print("Setup4Menu selected"); break; default: Debug.Print("Unknown item selected"); break; } } public void DisplayMenu(menu thisMenu) { LCDKeypad.Print(0, 0, " "); LCDKeypad.Print(0, 0, thisMenu.parentTag); LCDKeypad.Print(1, 0, " "); LCDKeypad.Print(1, 0, thisMenu.menuText); } } }
#4
Posted 11 February 2012 - 02:29 PM
#5
Posted 11 February 2012 - 03:31 PM
#6
Posted 11 February 2012 - 04:31 PM
#7
Posted 13 February 2012 - 01:46 PM
0 user(s) are reading this topic
0 members, 0 guests, 0 anonymous users