├── Arduino_LCD_Menu.ino ├── MenuEntry.cpp ├── MenuEntry.h ├── MenuIntHelper.cpp ├── MenuIntHelper.h ├── MenuLCD.cpp ├── MenuLCD.h ├── MenuManager.cpp ├── MenuManager.h └── readme /Arduino_LCD_Menu.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Arduino_LCD_Menu Library 3 | Copyright Dustin Andrews, David Andrews 2012 4 | Licensed under the follwing license: 5 | 6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 7 | following conditions are met: 8 | 9 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 10 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the distribution. 12 | The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 15 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 16 | AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 17 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 18 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 19 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | */ 21 | 22 | 23 | #include 24 | #include "MenuEntry.h" 25 | #include "MenuLCD.h" 26 | #include "MenuManager.h" 27 | 28 | //This example is a Stopwatch and Timer. Although it is mostly functional, it might not be the best 29 | // user interface. The layout was created more to provide examples of a stopwatch/timer. 30 | 31 | 32 | //Edit your particular harware setup here - See LiquidCrystal documentation for details 33 | const int LCDD7 = 4; 34 | const int LCDD6 = 6; 35 | const int LCDD5 = 7; 36 | const int LCDD4 = 8; 37 | const int LCDE = 9; 38 | const int LCDRS = 10; 39 | 40 | //Now create the MenuLCD and MenuManager classes. 41 | MenuLCD g_menuLCD( LCDRS, LCDE, LCDD4, LCDD5, LCDD6, LCDD7, 16, 2); 42 | MenuManager g_menuManager( &g_menuLCD);//pass the g_menuLCD object to the g_menuManager with the & operator. 43 | 44 | //Global variables used by the sample application 45 | //when the display is showing user results (e.g. time elapsed), the next "select" should send it back into the menu. 46 | unsigned int g_isDisplaying = false; 47 | int g_timerTime = 23; 48 | long g_timerRunning = false; 49 | long g_timerTarget = 0; 50 | long g_autoReset = false; 51 | long g_stopMillis = 0; 52 | long g_startMillis = 0; 53 | 54 | byte g_smiley[8] = { 55 | B00000, 56 | B10001, 57 | B00000, 58 | B00000, 59 | B10001, 60 | B01110, 61 | B00000, 62 | }; 63 | 64 | byte g_frown[8] = { 65 | B00000, 66 | B10001, 67 | B00000, 68 | B00000, 69 | B00000, 70 | B01110, 71 | B10001, 72 | }; 73 | 74 | 75 | //end Global variables section 76 | 77 | //setupMenus 78 | //This function is called during setup to populate the menu with the tree of nodes 79 | //This can be a bit brain-bending to write. If you draw a tree you want for your menu first 80 | // this code can be a little easier to write. Add the nodes in a depth-first order for 81 | // the easiest code and least amount of temporary variables. 82 | // http://en.wikipedia.org/wiki/Depth-first 83 | // The MenuManager code is the same for building the menu as for selecting it via inputs. 84 | // You create the menu entries and then move about the menu structure using Up, Down, Select as if you 85 | // were selecting them via the inputs, and then use either AddChild or Add sibling from the selected node 86 | // to create your menu. 87 | // 88 | // This sample code is a simple stopwatch. Our menu will look like this: 89 | // Stopwatch 90 | // |-Start 91 | // |-Stop 92 | // |-Reset 93 | // Timer 94 | // |-Set Time 95 | // |-AutoReset 96 | // | |-On 97 | // | |-Off 98 | // |-Start 99 | // |-Stop 100 | // Credits 101 | 102 | 103 | void setupMenus() 104 | { 105 | g_menuLCD.MenuLCDSetup(); 106 | //Add nodes via a depth-first traversal order 107 | MenuEntry * p_menuEntryRoot; 108 | //Add root node 109 | //MenuEntry( char * menuText, void * userData/*=0*/, MENU_ACTION_CALLBACK_FUNC func); 110 | p_menuEntryRoot = new MenuEntry("Stopwatch", NULL, NULL); 111 | g_menuManager.addMenuRoot( p_menuEntryRoot ); 112 | g_menuManager.addChild( new MenuEntry("Stopwatch Start", NULL, WatchStartCallback) ); 113 | g_menuManager.addChild( new MenuEntry("Stopwatch Stop", NULL, WatchStopCallback ) ); 114 | g_menuManager.addChild( new MenuEntry("Reset", NULL, WatchResetCallback) ); 115 | g_menuManager.addChild( new MenuEntry("Back", (void *) &g_menuManager, MenuEntry_BackCallbackFunc) ); 116 | 117 | g_menuManager.addSibling( new MenuEntry("Timer", NULL, NULL ) ); 118 | //Now we want to select the "Timer" entry so we can add children under that node 119 | //"Timer" is one down from "Stopwatch", so we issue the down command 120 | g_menuManager.MenuDown(); 121 | g_menuManager.addChild( new MenuEntry("Set Time", NULL, SetTimeCallback ) ); 122 | //now move down to the "Time" node to add children by selecting the "Timer" node 123 | g_menuManager.MenuSelect(); 124 | //Add "time"'s sibling "AutoReset" and select it 125 | g_menuManager.addSibling( new MenuEntry( "AutoReset", NULL, NULL) ); 126 | g_menuManager.MenuDown(); 127 | 128 | //Add "AutoReset"'s children 129 | //Use the built-in BOOL setting callbacks from MenuEntry.h: MenuEntry_Bool*CallbackFunc 130 | g_menuManager.addChild( new MenuEntry( "Turn Reset On", (void *) (&g_autoReset), MenuEntry_BoolTrueCallbackFunc ) ); 131 | g_menuManager.addChild( new MenuEntry( "Turn Reset Off", (void *) (&g_autoReset), MenuEntry_BoolFalseCallbackFunc ) ); 132 | g_menuManager.addChild( new MenuEntry("Back", (void *) &g_menuManager, MenuEntry_BackCallbackFunc) ); 133 | 134 | //Add timer start and stop 135 | g_menuManager.addSibling( new MenuEntry( "Countdown Start", NULL, TimerStartCallback) ); 136 | g_menuManager.addSibling( new MenuEntry( "Countdown Stop", NULL, TimerStopCallback) ); 137 | g_menuManager.addSibling( new MenuEntry("Back", (void *) &g_menuManager, MenuEntry_BackCallbackFunc) ); 138 | 139 | //Get the selection state back to the root for startup and to add the last entry 140 | g_menuManager.SelectRoot(); 141 | g_menuManager.addSibling( new MenuEntry( "Credits", NULL, CreditsCallback) ); 142 | //Make sure the menu is drawn correctly after all changes are done 143 | g_menuManager.DrawMenu(); 144 | 145 | g_menuManager.addSibling( new MenuEntry( "Draw Smiley", NULL, SmileyCallback) ); 146 | 147 | g_menuLCD.getLCD()->createChar( 0, g_smiley ); 148 | g_menuLCD.getLCD()->createChar( 1, g_frown ); 149 | } 150 | 151 | 152 | 153 | void setup() 154 | { 155 | Serial.begin(115200); 156 | Serial.print("Ready."); 157 | setupMenus(); 158 | } 159 | 160 | 161 | 162 | void loop() 163 | { 164 | //The example shows using bytes on the serial port to move the menu. You can hook up your buttons or other controls. 165 | char incomingByte = 0; 166 | if (Serial.available() > 0) 167 | { 168 | incomingByte = Serial.read(); 169 | } 170 | switch( incomingByte ) 171 | { 172 | case 'u': 173 | g_menuManager.DoMenuAction( MENU_ACTION_UP ); 174 | break; 175 | case 'd': 176 | g_menuManager.DoMenuAction( MENU_ACTION_DOWN ); 177 | break; 178 | case 's': 179 | if( g_isDisplaying ) 180 | { 181 | g_isDisplaying = false; 182 | g_menuManager.DrawMenu(); 183 | } 184 | else 185 | { 186 | g_menuManager.DoMenuAction( MENU_ACTION_SELECT ); 187 | } 188 | break; 189 | case 'b': 190 | g_menuManager.DoMenuAction( MENU_ACTION_BACK ); 191 | break; 192 | default: 193 | break; 194 | } 195 | if( g_timerRunning && g_timerTarget < millis()) 196 | { 197 | long time = millis(); 198 | 199 | Serial.print( "time = " ); 200 | Serial.println( time ); 201 | 202 | Serial.println("Timer Goes Off HERE!"); 203 | if( g_autoReset) 204 | { 205 | Serial.print( "timer target was "); 206 | Serial.println( g_timerTarget ); 207 | g_timerTarget = time + ( g_timerTime *1000 ); 208 | Serial.print( "timer target is now "); 209 | Serial.println( g_timerTarget ); 210 | Serial.print( "timerTime is " ); 211 | Serial.println( g_timerTime ); 212 | Serial.println( "--------" ); 213 | } 214 | else 215 | { 216 | g_timerRunning = false; 217 | } 218 | } 219 | } 220 | 221 | //This is a sample callback funtion for when a menu item with no children (aka command) is selected 222 | void WatchStartCallback( char* pMenuText, void *pUserData ) 223 | { 224 | g_startMillis = millis(); 225 | char *pTextLines[2] = {"Clock Started", "" }; 226 | g_menuLCD.PrintMenu( pTextLines, 2, 3 ); 227 | g_isDisplaying = true; 228 | } 229 | 230 | 231 | //This is a sample callback funtion for when a menu item with no children (aka command) is selected 232 | void WatchStopCallback( char* pMenuText, void *pUserData ) 233 | { 234 | g_stopMillis = millis(); 235 | 236 | char strSeconds[50]; 237 | dtostrf( ((float)(g_stopMillis-g_startMillis))/1000, 1, 2, strSeconds ); 238 | char *pTextLines[2] = {"Elapsed Time", strSeconds }; 239 | g_menuLCD.PrintMenu( pTextLines, 2, 3 ); 240 | g_isDisplaying = true; 241 | } 242 | 243 | //This is a sample callback funtion for when a menu item with no children (aka command) is selected 244 | void WatchResetCallback( char* pMenuText, void *pUserData ) 245 | { 246 | g_startMillis = 0; 247 | g_stopMillis = 0; 248 | char *pTextLines[2] = {"Clock reset", "" }; 249 | g_menuLCD.PrintMenu( pTextLines, 2, 3 ); 250 | } 251 | 252 | //This callback uses the built-in Int Input routine in MenuManager.h to request input of a integer number from the 253 | //user. Control will pass to the DoIntInput function until the user finishes. the g_timerTime will be set to the 254 | //value the user selects. 255 | void SetTimeCallback( char* pMenuText, void *pUserData ) 256 | { 257 | char *pLabel = "Timer seconds"; 258 | int iNumLabelLines = 1; 259 | int iMin = 1; 260 | int iMax = 1000; 261 | int iStart = 60; 262 | //Each user input action (such as a turn of rotary enocoder or push of button 263 | //will step this amount 264 | int iStep = 5; 265 | 266 | g_menuManager.DoIntInput( iMin, iMax, iStart, iStep, &pLabel, iNumLabelLines, &g_timerTime ); 267 | Serial.print("Timer time" ); 268 | Serial.println( g_timerTime ); 269 | } 270 | //This is a sample callback funtion for when a menu item with no children (aka command) is selected 271 | void TimerStartCallback( char* pMenuText, void *pUserData ) 272 | { 273 | g_timerTarget = millis() + (g_timerTime * 1000);//This is buggy- doesn't handle wrap-around of the millis output. Too bad :( 274 | Serial.print( "timer target = "); 275 | Serial.println( g_timerTarget ); 276 | Serial.print( "time = " ); 277 | Serial.println( millis()); 278 | g_timerRunning = true; 279 | char strSeconds[50]; 280 | itoa( g_timerTime, strSeconds, 10 ); 281 | char *pTextLines[2] = {"Go!", strSeconds }; 282 | g_menuLCD.PrintMenu( pTextLines, 2, 3 ); 283 | g_isDisplaying = true; 284 | } 285 | 286 | 287 | //This is a sample callback funtion for when a menu item with no children (aka command) is selected 288 | void TimerStopCallback( char* pMenuText, void *pUserData ) 289 | { 290 | g_timerRunning = false; 291 | } 292 | 293 | void CreditsCallback( char* pMenuText, void *pUserData ) 294 | { 295 | char *pTextLines[2] = {"David Andrews ", "Dustin Andrews" }; 296 | g_menuLCD.PrintMenu( pTextLines, 2, 1 ); 297 | delay(5000); 298 | char *pTextLines2[2] = {"http://authenti","cinvention.com"}; 299 | g_menuLCD.PrintMenu( pTextLines2, 2, 5 ); 300 | g_isDisplaying = true; 301 | } 302 | 303 | void SmileyCallback( char* pMenuText, void *pUserData ) 304 | { 305 | for( int i = 0; i < 10 ; ++i ) 306 | { 307 | g_menuLCD.ClearLCD(); 308 | g_menuLCD.getLCD()->setCursor( 8,0 ); 309 | g_menuLCD.getLCD()->print( (char)0 ); 310 | delay(500); 311 | g_menuLCD.ClearLCD(); 312 | g_menuLCD.getLCD()->setCursor( 8,0 ); 313 | g_menuLCD.getLCD()->print( (char)1 ); 314 | delay(500); 315 | } 316 | } 317 | 318 | -------------------------------------------------------------------------------- /MenuEntry.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Arduino_LCD_Menu Library 3 | Copyright Dustin Andrews, David Andrews 2012 4 | Licensed under the follwing license: 5 | 6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 7 | following conditions are met: 8 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 9 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer 10 | in the documentation and/or other materials provided with the distribution. 11 | The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 14 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 15 | AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 16 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 17 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 18 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 19 | */ 20 | 21 | 22 | #include 23 | #include "MenuEntry.h" 24 | #include "MenuManager.h" 25 | 26 | MenuEntry::MenuEntry( char * menuText, void * userData, MENU_ACTION_CALLBACK_FUNC func) 27 | { 28 | m_menuText = strdup(menuText); 29 | m_userData = userData; 30 | m_nextSibling = NULL; 31 | m_prevSibling = NULL; 32 | m_child = NULL; 33 | m_parent = NULL; 34 | m_callback = func; 35 | } 36 | 37 | void MenuEntry::ExecuteCallback() 38 | { 39 | if( m_callback != NULL ) 40 | { 41 | m_callback(m_menuText, m_userData); 42 | } 43 | } 44 | 45 | bool MenuEntry::addChild(MenuEntry* child) 46 | { 47 | child->setParent( this ); 48 | if(m_child != NULL) 49 | { 50 | m_child->addSibling( child ); 51 | } 52 | else 53 | { 54 | m_child = child; 55 | } 56 | return true; 57 | } 58 | 59 | bool MenuEntry::addSibling( MenuEntry* sibling) 60 | { 61 | sibling->setParent( m_parent ); 62 | if( m_nextSibling != NULL ) 63 | { 64 | m_nextSibling->addSibling(sibling); 65 | } 66 | else 67 | { 68 | m_nextSibling = sibling; 69 | sibling->setPrevSibling( this ); 70 | } 71 | } 72 | 73 | void MenuEntry::setPrevSibling( MenuEntry * pPrevSibling) 74 | { 75 | m_prevSibling = pPrevSibling; 76 | } 77 | 78 | char * MenuEntry::getMenuText() 79 | { 80 | return m_menuText; 81 | } 82 | 83 | MenuEntry *MenuEntry::getNextSibling() 84 | { 85 | return m_nextSibling; 86 | } 87 | MenuEntry *MenuEntry::getPrevSibling() 88 | { 89 | return m_prevSibling; 90 | } 91 | MenuEntry *MenuEntry::getChild() 92 | { 93 | return m_child; 94 | } 95 | MenuEntry *MenuEntry::getParent() 96 | { 97 | return m_parent; 98 | } 99 | void MenuEntry::setParent( MenuEntry * parent) 100 | { 101 | m_parent = parent; 102 | } 103 | 104 | void MenuEntry_BoolTrueCallbackFunc( char * pMenuText, void * pUserData ) 105 | { 106 | *((unsigned int *)pUserData) = true; 107 | } 108 | 109 | void MenuEntry_BoolFalseCallbackFunc( char * pMenuText, void * pUserData ) 110 | { 111 | *((unsigned int *)pUserData) = false; 112 | } 113 | 114 | void MenuEntry_BackCallbackFunc( char * pMenuText, void * pUserData ) 115 | { 116 | ((MenuManager *)pUserData)->DoMenuAction( MENU_ACTION_BACK ); 117 | } 118 | 119 | 120 | 121 | -------------------------------------------------------------------------------- /MenuEntry.h: -------------------------------------------------------------------------------- 1 | /* 2 | Arduino_LCD_Menu Library 3 | Copyright Dustin Andrews, David Andrews 2012 4 | Licensed under the follwing license: 5 | 6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 7 | following conditions are met: 8 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 9 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer 10 | in the documentation and/or other materials provided with the distribution. 11 | The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 14 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 15 | AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 16 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 17 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 18 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 19 | */ 20 | 21 | 22 | #include 23 | 24 | #ifndef MenuEntry_h 25 | #define MenuEntry_h 1 26 | 27 | 28 | typedef void (*MENU_ACTION_CALLBACK_FUNC)( char * pMenuText, void * pUserData ); 29 | 30 | 31 | //To use these functions, pass a function pointer as the argument to the MenuEntry constructor. 32 | //pUserData should point to an unsigned int that will be set to true or false. 33 | void MenuEntry_BoolTrueCallbackFunc( char * pMenuText, void * pUserData ); 34 | void MenuEntry_BoolFalseCallbackFunc( char * pMenuText, void * pUserData ); 35 | 36 | //Use this callback function for a "Back" menu item for hardware that doesn't include a back button 37 | //pUserData should point to a MenfsuManager object. 38 | void MenuEntry_BackCallbackFunc( char * pMenuText, void * pUserData ); 39 | 40 | //The MenuEntry class represents one menu item in the overall menu system, such as "Set Time" or "Back" 41 | //The MenuEntry classes point to each other to create a tree of menu items. You can navigate 42 | // the classes using the get* calls. MenuManager uses the get* calls to figure out what to draw to the LCD 43 | class MenuEntry 44 | { 45 | public: 46 | //Constructor to create each entry. 47 | MenuEntry( char * menuText, void * userData, MENU_ACTION_CALLBACK_FUNC func); 48 | //add a child menu item. They will be kept it the order they are added, from top to bottom. 49 | bool addChild( MenuEntry* child); 50 | //Add a menu item as a sibling of this one, at the end of the sibling chain. 51 | bool addSibling( MenuEntry* sibling); 52 | //Sets the previous sibling, mostly used during menu creation to notify a new entry where it's 53 | //previous pointer needs to point. 54 | void setPrevSibling( MenuEntry* prevSibling); 55 | //Can set the action call back dynamically. Overrides what was passed to the constructor. 56 | bool addActionCallback( MENU_ACTION_CALLBACK_FUNC pCallback); 57 | 58 | char* getMenuText(); 59 | //Sets the previous sibling, mostly used during menu creation to notify a new entry where it's 60 | //previous pointer needs to point. 61 | void setParent( MenuEntry* parent ); 62 | 63 | MenuEntry *getNextSibling(); 64 | MenuEntry *getPrevSibling(); 65 | MenuEntry *getChild(); 66 | MenuEntry *getParent(); 67 | //This call will call the action callback for use when the menu item is selected. 68 | //if this menu entry has any children, the callback will not be executed. 69 | void ExecuteCallback(); 70 | 71 | bool isBackEntry() { return (m_callback == MenuEntry_BackCallbackFunc); } 72 | 73 | 74 | private: 75 | void* m_userData; 76 | char* m_menuText; 77 | MenuEntry* m_parent; 78 | MenuEntry* m_child; 79 | MenuEntry* m_nextSibling; 80 | MENU_ACTION_CALLBACK_FUNC m_callback; 81 | MenuEntry* m_prevSibling; 82 | }; 83 | 84 | 85 | 86 | #endif 87 | 88 | -------------------------------------------------------------------------------- /MenuIntHelper.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Arduino_LCD_Menu Library 3 | Copyright Dustin Andrews, David Andrews 2012 4 | Licensed under the follwing license: 5 | 6 | 7 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 8 | following conditions are met: 9 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 10 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the distribution. 12 | The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 15 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 16 | AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 17 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 18 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 19 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | */ 21 | #include "MenuIntHelper.h" 22 | 23 | MenuIntHelper::MenuIntHelper( int iMin, int iMax, int iStart, int iStep ): 24 | m_min( iMin), m_max( iMax ), m_curNum( iStart ), m_step( iStep) 25 | { 26 | } 27 | int MenuIntHelper::numIncrease() 28 | { 29 | //This function may have bugs when m_max is near the MAXINT limit 30 | //but if your UI requires users to input MAXINT numbers, you have bigger problems. 31 | if( m_curNum + m_step <= m_max ) 32 | { 33 | m_curNum += m_step; 34 | } 35 | return m_curNum; 36 | } 37 | int MenuIntHelper::numDecrease() 38 | { 39 | if( m_curNum - m_step >= m_min ) 40 | { 41 | m_curNum -= m_step; 42 | } 43 | return m_curNum; 44 | } 45 | int MenuIntHelper::getInt() 46 | { 47 | return m_curNum; 48 | } 49 | 50 | -------------------------------------------------------------------------------- /MenuIntHelper.h: -------------------------------------------------------------------------------- 1 | /* 2 | Arduino_LCD_Menu Library 3 | Copyright Dustin Andrews, David Andrews 2012 4 | Licensed under the follwing license: 5 | 6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 7 | following conditions are met: 8 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 9 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer 10 | in the documentation and/or other materials provided with the distribution. 11 | The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 14 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 15 | AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 16 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 17 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 18 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 19 | */ 20 | 21 | 22 | #ifndef MenuIntHelper_H 23 | 24 | #define MenuIntHelper_H 1 25 | class MenuIntHelper 26 | { 27 | public: 28 | MenuIntHelper( int iMin, int iMax, int iStart, int iStep ); 29 | int numIncrease(); 30 | int numDecrease(); 31 | int getInt(); 32 | private: 33 | int m_curNum; 34 | int m_min; 35 | int m_max; 36 | int m_step; 37 | }; 38 | #endif 39 | 40 | 41 | -------------------------------------------------------------------------------- /MenuLCD.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Arduino_LCD_Menu Library 3 | Copyright Dustin Andrews, David Andrews 2012 4 | Licensed under the follwing license: 5 | 6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 7 | following conditions are met: 8 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 9 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer 10 | in the documentation and/or other materials provided with the distribution. 11 | The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 14 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 15 | AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 16 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 17 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 18 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 19 | */ 20 | 21 | #include 22 | #include 23 | #include "MenuLCD.h" 24 | 25 | MenuLCD::MenuLCD(int LCDRS, int LCDE, int LCDD4, int LCDD5, int LCDD6, int LCDD7, int characters, int lines) 26 | : m_LCDRS( LCDRS ), 27 | m_LCDE( LCDE ), 28 | m_LCDD4( LCDD4 ), 29 | m_LCDD5( LCDD5 ), 30 | m_LCDD6( LCDD6 ), 31 | m_LCDD7( LCDD7 ), 32 | m_characters( characters ), 33 | m_lines( lines ) 34 | { 35 | } 36 | 37 | bool MenuLCD::MenuLCDSetup() 38 | { 39 | m_pLCD = new LiquidCrystal(m_LCDRS, m_LCDE, m_LCDD4, m_LCDD5, m_LCDD6, m_LCDD7); 40 | m_pLCD->begin(m_characters, m_lines); 41 | } 42 | 43 | bool MenuLCD::PrintMenu( char* pString[], int nLines, int nSelectedLine = 0 ) 44 | { 45 | m_pLCD->clear(); 46 | for( int i =0; i < nLines; i++ ) 47 | 48 | { 49 | if( i == nSelectedLine ) 50 | {//this line should be surrounded by [] 51 | m_pLCD->setCursor(0, i); 52 | m_pLCD->write( '['); 53 | m_pLCD->setCursor(1,i); 54 | m_pLCD->print( pString[i] ); 55 | m_pLCD->setCursor(m_characters - 1, i); 56 | m_pLCD->write( ']'); 57 | } 58 | else 59 | { 60 | m_pLCD->setCursor(0,i); 61 | m_pLCD->print( pString[i] ); 62 | } 63 | 64 | } 65 | } 66 | 67 | void MenuLCD::WipeMenu( char* pString[], int nLines, MenuLCD::Direction dir ) 68 | { 69 | char lineBuff[ 256 ]; 70 | m_pLCD->clear(); 71 | for( int i = 0; i < m_characters; ++i ) 72 | { 73 | for( int j =0; j < nLines; ++j ) 74 | { 75 | m_pLCD->setCursor( 0, j ); 76 | m_pLCD->setCursor(0,j); 77 | if (strlen( pString[j] ) > i ) 78 | { 79 | if( dir == LEFT ) 80 | { 81 | strcpy(lineBuff, (pString[j] + i ) ); 82 | strcat(lineBuff, " " ); 83 | } 84 | else 85 | { 86 | lineBuff[0] = '\0'; 87 | for( int k = 0; k < i; ++k ) 88 | { 89 | strcat(lineBuff, " " ); 90 | } 91 | strcat(lineBuff, pString[j]); 92 | } 93 | } 94 | else 95 | { 96 | strcpy(lineBuff, " " ); 97 | } 98 | m_pLCD->print( lineBuff ); 99 | 100 | } 101 | delay(50); 102 | } 103 | } 104 | 105 | 106 | bool MenuLCD::PrintLineRight( char* pString, int iRow ) 107 | { 108 | //clear the line 109 | char buff[ m_characters ]; 110 | for( int i = 0; i < m_characters; ++i ) 111 | { 112 | buff[i] = ' '; 113 | } 114 | m_pLCD->setCursor( 0, iRow ); 115 | m_pLCD->print( buff ); 116 | //now print the new number 117 | m_pLCD->setCursor(m_characters - strlen(pString),iRow); 118 | m_pLCD->print( pString ); 119 | } 120 | 121 | bool MenuLCD::PrintLine( char* pString, int iRow ) 122 | { 123 | //clear the line 124 | m_pLCD->setCursor( 0, iRow ); 125 | m_pLCD->print( pString ); 126 | } 127 | 128 | int MenuLCD::getLines() 129 | { 130 | return m_lines; 131 | } 132 | int MenuLCD::getCharacters() 133 | { 134 | return m_characters; 135 | } 136 | void MenuLCD::ClearLCD() 137 | { 138 | m_pLCD->clear(); 139 | } 140 | 141 | LiquidCrystal * MenuLCD::getLCD() 142 | { 143 | return m_pLCD; 144 | } 145 | 146 | -------------------------------------------------------------------------------- /MenuLCD.h: -------------------------------------------------------------------------------- 1 | /* 2 | Arduino_LCD_Menu Library 3 | Copyright Dustin Andrews, David Andrews 2012 4 | Licensed under the follwing license: 5 | 6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 7 | following conditions are met: 8 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 9 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer 10 | in the documentation and/or other materials provided with the distribution. 11 | The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 14 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 15 | AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 16 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 17 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 18 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 19 | */ 20 | 21 | #include 22 | 23 | #ifndef MenuLCD_H 24 | 25 | #define MenuLCD_H 1 26 | class MenuLCD 27 | { 28 | public: 29 | MenuLCD(int LCDRS, int LCDE, int LCDD4, int LCDD5, int LCDD6, int LCDD7, int characters, int lines); 30 | bool MenuLCDSetup(); 31 | bool PrintMenu( char ** pString, int nLines, int nSelectedLine /*= 0*/ ); 32 | bool PrintLineRight( char* pString, int iRow ); 33 | bool PrintLine( char* pString, int iRow ); 34 | int getLines(); 35 | int getCharacters(); 36 | void ClearLCD(); 37 | LiquidCrystal * getLCD(); 38 | 39 | enum Direction{ LEFT, RIGHT }; 40 | 41 | 42 | void WipeMenu( char* pString[], int nLines, MenuLCD::Direction dir ); 43 | 44 | 45 | private: 46 | LiquidCrystal* m_pLCD; 47 | int m_LCDRS; 48 | int m_LCDE; 49 | int m_LCDD4; 50 | int m_LCDD5; 51 | int m_LCDD6; 52 | int m_LCDD7; 53 | int m_characters; 54 | int m_lines; 55 | }; 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /MenuManager.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Arduino_LCD_Menu Library 3 | Copyright Dustin Andrews, David Andrews 2012 4 | Licensed under the follwing license: 5 | 6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 7 | following conditions are met: 8 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 9 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer 10 | in the documentation and/or other materials provided with the distribution. 11 | The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 14 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 15 | AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 16 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 17 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 18 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 19 | */ 20 | 21 | 22 | 23 | #include "MenuManager.h" 24 | #include "MenuEntry.h" 25 | 26 | MenuManager::MenuManager(MenuLCD* pMenuLCD) 27 | : m_pMenuLCD( pMenuLCD), 28 | m_fDoingIntInput( false ) 29 | { 30 | } 31 | 32 | bool MenuManager::addMenuRoot( MenuEntry * p_menuItem) 33 | { 34 | m_pRootMenuEntry = p_menuItem; 35 | m_pCurrentMenuEntry = p_menuItem; 36 | } 37 | 38 | void MenuManager::addSibling( MenuEntry * p_menuItem) 39 | { 40 | m_pCurrentMenuEntry->addSibling( p_menuItem ); 41 | } 42 | 43 | void MenuManager::addChild( MenuEntry * p_menuItem) 44 | { 45 | m_pCurrentMenuEntry->addChild( p_menuItem ); 46 | } 47 | 48 | 49 | MenuEntry * MenuManager::getMenuRoot() 50 | { 51 | return m_pRootMenuEntry; 52 | } 53 | 54 | 55 | void MenuManager::WipeMenu( MenuLCD::Direction dir ) 56 | { 57 | if( dir == MenuLCD::LEFT ) 58 | { 59 | for( int i = 0; i < m_pMenuLCD->getCharacters(); ++i ) 60 | { 61 | m_pMenuLCD->getLCD()->scrollDisplayLeft(); 62 | delay(75); 63 | } 64 | } 65 | else 66 | { 67 | for( int i = 0; i < m_pMenuLCD->getCharacters(); ++i ) 68 | { 69 | m_pMenuLCD->getLCD()->scrollDisplayRight(); 70 | delay(75); 71 | } 72 | } 73 | } 74 | 75 | 76 | void MenuManager::DrawMenu() 77 | { 78 | if( m_pCurrentMenuEntry->getNextSibling() == NULL ) 79 | { 80 | if( m_pCurrentMenuEntry->getPrevSibling() != NULL ) 81 | { 82 | char *pMenuTexts[2] = {m_pCurrentMenuEntry->getPrevSibling()->getMenuText(), m_pCurrentMenuEntry->getMenuText()}; 83 | m_pMenuLCD->PrintMenu( pMenuTexts, 2, 1 ); 84 | } 85 | else 86 | { 87 | char * pText = m_pCurrentMenuEntry->getMenuText(); 88 | m_pMenuLCD->PrintMenu( &pText, 1, 0 ); 89 | } 90 | } 91 | else 92 | { 93 | char *pMenuTexts[2] = {m_pCurrentMenuEntry->getMenuText(), m_pCurrentMenuEntry->getNextSibling()->getMenuText()}; 94 | m_pMenuLCD->PrintMenu( pMenuTexts, 2, 0 ); 95 | } 96 | } 97 | 98 | void MenuManager::DoMenuAction( MENU_ACTION action ) 99 | { 100 | if( m_fDoingIntInput == true ) 101 | { 102 | int iNewNum = m_pMenuIntHelper->getInt(); 103 | char buff[64]; 104 | switch (action ) 105 | { 106 | case MENU_ACTION_UP: 107 | iNewNum = m_pMenuIntHelper->numDecrease(); 108 | itoa( iNewNum, buff, 10 ); 109 | DrawInputRow( buff ); 110 | *m_pInt = iNewNum; 111 | break; 112 | case MENU_ACTION_DOWN: 113 | iNewNum = m_pMenuIntHelper->numIncrease(); 114 | itoa( iNewNum, buff, 10 ); 115 | DrawInputRow( buff ); 116 | *m_pInt = iNewNum; 117 | break; 118 | case MENU_ACTION_SELECT: 119 | m_fDoingIntInput = false; 120 | DrawMenu(); 121 | break; 122 | case MENU_ACTION_BACK: 123 | m_fDoingIntInput = false; 124 | DrawMenu(); 125 | break; 126 | } 127 | } 128 | else 129 | { 130 | m_pMenuLCD->ClearLCD(); 131 | delay(10); 132 | DrawMenu(); 133 | switch (action ) 134 | { 135 | case MENU_ACTION_UP: 136 | this->MenuUp(); 137 | break; 138 | case MENU_ACTION_DOWN: 139 | this->MenuDown(); 140 | break; 141 | case MENU_ACTION_SELECT: 142 | this->MenuSelect(); 143 | break; 144 | case MENU_ACTION_BACK: 145 | this->MenuBack(); 146 | break; 147 | } 148 | } 149 | } 150 | 151 | void MenuManager::MenuUp() 152 | { 153 | MenuEntry *prev = m_pCurrentMenuEntry->getPrevSibling(); 154 | if( prev != NULL ) 155 | { 156 | m_pCurrentMenuEntry = prev; 157 | } 158 | else 159 | { 160 | //Flash? 161 | } 162 | DrawMenu(); 163 | } 164 | 165 | void MenuManager::MenuDown() 166 | { 167 | MenuEntry *next = m_pCurrentMenuEntry->getNextSibling(); 168 | if( next != NULL ) 169 | { 170 | m_pCurrentMenuEntry = next; 171 | } 172 | else 173 | { 174 | //Flash? 175 | } 176 | DrawMenu(); 177 | 178 | } 179 | 180 | void MenuManager::MenuSelect() 181 | { 182 | MenuEntry *child = m_pCurrentMenuEntry->getChild(); 183 | if( child != NULL ) 184 | { 185 | WipeMenu( MenuLCD::LEFT); 186 | m_pCurrentMenuEntry = child; 187 | DrawMenu(); 188 | } 189 | else 190 | { 191 | if( !m_pCurrentMenuEntry->isBackEntry() ) 192 | { 193 | WipeMenu( MenuLCD::LEFT); 194 | } 195 | m_pCurrentMenuEntry->ExecuteCallback(); 196 | if( !m_fDoingIntInput ) 197 | { 198 | DrawMenu(); 199 | } 200 | } 201 | } 202 | 203 | void MenuManager::MenuBack() 204 | { 205 | if( m_pCurrentMenuEntry->getParent() != NULL ) 206 | { 207 | WipeMenu( MenuLCD::RIGHT); 208 | m_pCurrentMenuEntry = m_pCurrentMenuEntry->getParent(); 209 | DrawMenu(); 210 | } 211 | } 212 | 213 | void MenuManager::SelectRoot() 214 | { 215 | m_pCurrentMenuEntry = m_pRootMenuEntry; 216 | } 217 | 218 | void MenuManager::DrawInputRow( char *pString ) 219 | { 220 | m_pMenuLCD->PrintLineRight( pString, m_pMenuLCD->getLines() - 1 ); 221 | } 222 | 223 | void MenuManager::DoIntInput( int iMin, int iMax, int iStart, int iSteps, char **label, int iLabelLines, int *pInt ) 224 | { 225 | char buff[64]; 226 | m_fDoingIntInput = true; 227 | m_pInt = pInt; 228 | *pInt = iStart; 229 | //The MenuIntHelper class will keep track of the input, but all other logic will stay here 230 | if( m_pMenuIntHelper != NULL ) 231 | { 232 | delete m_pMenuIntHelper; 233 | } 234 | m_pMenuIntHelper = new MenuIntHelper( iMin, iMax, iStart, iSteps ); 235 | //print the label 236 | m_pMenuLCD->PrintMenu( label, iLabelLines, -1 ); 237 | m_iIntLine = iLabelLines; //Off by one because index is zero based 238 | itoa( m_pMenuIntHelper->getInt(), buff, 10 ); 239 | DrawInputRow( buff ); 240 | } 241 | 242 | -------------------------------------------------------------------------------- /MenuManager.h: -------------------------------------------------------------------------------- 1 | /* 2 | Arduino_LCD_Menu Library 3 | Copyright Dustin Andrews, David Andrews 2012 4 | Licensed under the follwing license: 5 | 6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 7 | following conditions are met: 8 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 9 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer 10 | in the documentation and/or other materials provided with the distribution. 11 | The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 14 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 15 | AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 16 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 17 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 18 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 19 | */ 20 | 21 | 22 | #include "MenuEntry.h" 23 | #include "MenuLCD.h" 24 | #include "MenuIntHelper.h" 25 | 26 | enum MENU_ACTION { MENU_ACTION_UP, MENU_ACTION_DOWN, MENU_ACTION_SELECT, MENU_ACTION_BACK }; 27 | 28 | class MenuManager 29 | { 30 | public: 31 | MenuManager(MenuLCD* pMenuLCD); 32 | bool addMenuRoot( MenuEntry * p_menuEntry); 33 | MenuEntry * getMenuRoot(); 34 | void DrawMenu(); 35 | void DoMenuAction( MENU_ACTION action ); 36 | void MenuUp(); 37 | void MenuDown(); 38 | void MenuSelect(); 39 | void MenuBack(); 40 | void addChild( MenuEntry * p_menuEntry ); 41 | void addSibling( MenuEntry * p_menuEntry ); 42 | void SelectRoot(); 43 | void DoIntInput( int iMin, int iMax, int iStart, int iSteps, char **label, int iLabelLines, int *pInt ); 44 | void DrawInputRow( char *pString ); 45 | 46 | void WipeMenu( MenuLCD::Direction dir); 47 | 48 | 49 | 50 | private: 51 | MenuEntry* m_pRootMenuEntry; 52 | MenuEntry* m_pCurrentMenuEntry; 53 | MenuLCD* m_pMenuLCD; 54 | unsigned int m_fDoingIntInput; 55 | MenuIntHelper *m_pMenuIntHelper; 56 | int m_iIntLine; 57 | int *m_pInt; 58 | }; 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /readme: -------------------------------------------------------------------------------- 1 | Adruino_LCD_MENU README 2 | 3 | By David Andrews - May 6, 2012 4 | 5 | License: Modified BSD (See complete license at end) 6 | 7 | Purpose: To shorten the time to get an Adriuno project running using a menuing system. 8 | 9 | Getting Started: Open the Arduino_Menu_LCD.ino sketch in the Arduino IDE. Upload the sketch. In the serial window, send the following keys to control the menu: 10 | 11 | u - move UP 12 | d - move DOWN 13 | s - Select a menu option 14 | b - move back in the menu tree 15 | 16 | The idea is that you can invoke the menu system when appropriate, and have the Menu code drive all the navigation by piping your hardware inputs into the appropriate call in MenuManager. When a menu item is selected that has an action associated with it, the menu system calls your callback so you can accomplish whatever the menu item is supposed to do. 17 | 18 | This library builds on top of the Liquid Crystal library for doing LCD output. On a new system, you should verify that you can create simple outputs using the Liquid Crystal library first, then move to this library to do your menuing. 19 | 20 | The built-in actions right now are: 21 | 22 | Back - Add a menu item labled "Back" and pass it the MenuEntry_BackCallbackFunc pointer, and you now have a Back menu entry (in case you don't have a hardware back button) 23 | 24 | BoolTrue/False - These set a boolean to true or false so you can have off/on functionality easily. This callback needs some more thinking and work right now to provide user feedback that the option was selected. 25 | 26 | 27 | In addition, there is a MenuIntHelper class that assists in taking an integer input and setting a value. (See MenuIntHelper.h) 28 | 29 | 30 | /* 31 | Arduino_LCD_Menu Library 32 | Copyright Dustin Andrews, David Andrews 2012 33 | Licensed under the follwing license: 34 | 35 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 36 | following conditions are met: 37 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 38 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer 39 | in the documentation and/or other materials provided with the distribution. 40 | The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. 41 | 42 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 43 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 44 | AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 45 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 46 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 47 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 48 | */ 49 | --------------------------------------------------------------------------------