Example of how to use an Ada Fruit RGB LCD with the Ada Fruit RGB LCD Shield Library

Dependencies:   AdaFruit_RGBLCDShield MCP23017 mbed RTclock

Dependents:   SX1276_GPS

Fork of MCP_test by Wim Huiskamp

Updated the Adafruit RGB LCD Shield test app with a module system.

It pulls in RTclock which is another library I did for controlling the DS1307 RTC in a sane way (marries stdlib time and the RTC together cleanly). You don't need an RTC to run the example, it'll just use stdlib time instead. This class also maps RTC to system time, so if you loose the RTC the mbed will free run.

Four modules are defined in the modules folder plus the module base class. These examples provide:

  • title menu item
  • time menu item (updates automatically)
  • date menu item
  • fake temp menu item

Press select to switch modes: menu->cursor->change

Menu switches menu items going up/down. Cursor allows you to move around editable fields using the cursor keys / marker. Change allows you to move left/right on a particular line and change values by using up/down on an item with the blink box.

Custom fonts are defined for UI arrows and degree character.

If you want a menu item to update over time then you need to implement the canRefresh() member function in any child module you derive from class Module. Make it return true to receive update requests in your show() member function. Date and time both check when refreshing to see if anything has changed, then update.

main() registers a table of modules with the MenuManager. Others can be added easily by creating children derived from the Module base class..

Depending on what you want to do you may need to adjust the loop wait time in MenuManager::loop(). If you don't balance this based on work you need to do then the key presses may get a little lively. I may adjust the key checking to be fixed to 200ms regardless of loop wait time, however the catch there is that you'll consume more power the more loops you do so the wait is still important.

Happy coding!

Committer:
vtraveller
Date:
Sun Aug 10 15:45:03 2014 +0000
Revision:
11:96146db429de
Parent:
10:3fcab08717fc
Child:
13:9641bc42db92
Added support for changing time.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
wim 0:88d87b1c1f8b 1 #include "mbed.h"
vtraveller 4:d70e37f6c6bd 2 #include "Adafruit_RGBLCDShield.h"
vtraveller 10:3fcab08717fc 3 #include "RTclock.h"
vtraveller 10:3fcab08717fc 4 #include "extra_chars.h"
vtraveller 10:3fcab08717fc 5
vtraveller 10:3fcab08717fc 6 #include "module.h"
vtraveller 10:3fcab08717fc 7 #include "DateModule.h"
vtraveller 10:3fcab08717fc 8 #include "TempModule.h"
vtraveller 10:3fcab08717fc 9 #include "TimeModule.h"
vtraveller 10:3fcab08717fc 10 #include "TitleModule.h"
wim 0:88d87b1c1f8b 11
vtraveller 3:ed09f95739df 12 Serial pc(SERIAL_TX, SERIAL_RX);
wim 0:88d87b1c1f8b 13
vtraveller 10:3fcab08717fc 14 MCP23017 mcp23017 = MCP23017(I2C_SDA, I2C_SCL, 0x40, true);
vtraveller 7:d087e901b74b 15 Adafruit_RGBLCDShield lcd(mcp23017);
vtraveller 10:3fcab08717fc 16 RTclock rtc(I2C_SDA, I2C_SCL);
vtraveller 10:3fcab08717fc 17
vtraveller 10:3fcab08717fc 18 const int k_nWidthLCD = 16;
vtraveller 10:3fcab08717fc 19 const int k_nHeightLCD = 2;
vtraveller 9:1501fb01ded6 20
vtraveller 10:3fcab08717fc 21 enum EModes
vtraveller 9:1501fb01ded6 22 {
vtraveller 10:3fcab08717fc 23 eModeMenu = 0,
vtraveller 10:3fcab08717fc 24 eModeSelect,
vtraveller 10:3fcab08717fc 25 eModeChange,
vtraveller 10:3fcab08717fc 26 eModeLast
vtraveller 9:1501fb01ded6 27 };
vtraveller 9:1501fb01ded6 28
vtraveller 11:96146db429de 29 void ChangeModule
vtraveller 11:96146db429de 30 (
vtraveller 11:96146db429de 31 Module ** in_pModuleList,
vtraveller 11:96146db429de 32 size_t in_nModuleListSize,
vtraveller 11:96146db429de 33 size_t in_nMenuPos,
vtraveller 11:96146db429de 34 int in_nIndexX,
vtraveller 11:96146db429de 35 int in_nCursorY,
vtraveller 11:96146db429de 36 bool in_bUp
vtraveller 11:96146db429de 37 )
vtraveller 11:96146db429de 38 {
vtraveller 11:96146db429de 39 size_t nModule = (in_nMenuPos + in_nCursorY) % in_nModuleListSize;
vtraveller 11:96146db429de 40 in_pModuleList[nModule]->change(in_nIndexX,in_nCursorY,in_bUp);
vtraveller 11:96146db429de 41 }
vtraveller 11:96146db429de 42
vtraveller 9:1501fb01ded6 43 void CreateChars()
vtraveller 9:1501fb01ded6 44 {
vtraveller 10:3fcab08717fc 45 //uint8_t k_aUp[] = { 0x4,0xe,0x1f,0x15,0x4,0x4,0x4,0x4 };
vtraveller 10:3fcab08717fc 46 //uint8_t k_aDown[] = { 0x4,0x4,0x4,0x4,0x15,0x1f,0xe,0x4 };
vtraveller 10:3fcab08717fc 47
vtraveller 10:3fcab08717fc 48 uint8_t k_aUp[] = { 0x0,0x0,0x4,0xe,0x1f,0x0,0x0 };
vtraveller 10:3fcab08717fc 49 uint8_t k_aDown[] = { 0x0,0x0,0x1f,0xe,0x4,0x0,0x0 };
vtraveller 10:3fcab08717fc 50 uint8_t k_aRight[] = { 0x0,0x8,0xc,0xe,0xc,0x8,0x0 };
vtraveller 10:3fcab08717fc 51 uint8_t k_aLeft[] = { 0x0,0x2,0x6,0xe,0x6,0x2,0x0 };
vtraveller 9:1501fb01ded6 52 uint8_t k_aDegree[] = { 0xc,0x12,0x12,0xc,0x0,0x0,0x0,0x0 };
vtraveller 9:1501fb01ded6 53
vtraveller 9:1501fb01ded6 54 lcd.createChar(eUp,k_aUp);
vtraveller 9:1501fb01ded6 55 lcd.createChar(eDown,k_aDown);
vtraveller 10:3fcab08717fc 56 lcd.createChar(eRight,k_aRight);
vtraveller 10:3fcab08717fc 57 lcd.createChar(eLeft,k_aLeft);
vtraveller 9:1501fb01ded6 58 lcd.createChar(eDegree,k_aDegree);
vtraveller 9:1501fb01ded6 59 }
vtraveller 9:1501fb01ded6 60
vtraveller 9:1501fb01ded6 61 void Initialise()
vtraveller 9:1501fb01ded6 62 {
vtraveller 10:3fcab08717fc 63 // Spin up RTC
vtraveller 10:3fcab08717fc 64 rtc.mapTime();
vtraveller 10:3fcab08717fc 65
vtraveller 10:3fcab08717fc 66 // Initialise LCD
vtraveller 10:3fcab08717fc 67 lcd.begin(k_nWidthLCD,k_nHeightLCD);
vtraveller 9:1501fb01ded6 68 CreateChars();
vtraveller 9:1501fb01ded6 69
vtraveller 9:1501fb01ded6 70 lcd.setCursor(0,0);
vtraveller 9:1501fb01ded6 71 lcd._putc(eUp);
vtraveller 9:1501fb01ded6 72
vtraveller 9:1501fb01ded6 73 lcd.setCursor(0,1);
vtraveller 9:1501fb01ded6 74 lcd._putc(eDown);
vtraveller 9:1501fb01ded6 75 }
vtraveller 10:3fcab08717fc 76
vtraveller 10:3fcab08717fc 77 void SetCursor(bool in_bCursor,bool in_bBlink)
vtraveller 3:ed09f95739df 78 {
vtraveller 10:3fcab08717fc 79 if (in_bCursor) lcd.cursor(); else lcd.noCursor();
vtraveller 10:3fcab08717fc 80 if (in_bBlink) lcd.blink(); else lcd.noBlink();
vtraveller 10:3fcab08717fc 81 }
vtraveller 10:3fcab08717fc 82
vtraveller 10:3fcab08717fc 83 void ShowModules
vtraveller 10:3fcab08717fc 84 (
vtraveller 10:3fcab08717fc 85 Module ** in_pModuleList,
vtraveller 10:3fcab08717fc 86 size_t in_nModuleListSize,
vtraveller 10:3fcab08717fc 87 size_t in_nPos,
vtraveller 10:3fcab08717fc 88 bool in_bRefresh = false
vtraveller 10:3fcab08717fc 89 )
vtraveller 10:3fcab08717fc 90 {
vtraveller 10:3fcab08717fc 91 lcd.setCursor(2,0);
vtraveller 3:ed09f95739df 92
vtraveller 10:3fcab08717fc 93 if (in_pModuleList[in_nPos]->canRefresh() || !in_bRefresh) in_pModuleList[in_nPos]->show();
vtraveller 10:3fcab08717fc 94
vtraveller 10:3fcab08717fc 95 size_t nPos = (in_nPos + 1) % in_nModuleListSize;
vtraveller 10:3fcab08717fc 96 lcd.setCursor(2,1);
vtraveller 10:3fcab08717fc 97
vtraveller 10:3fcab08717fc 98 if (in_pModuleList[nPos]->canRefresh() || !in_bRefresh) in_pModuleList[nPos]->show();
vtraveller 3:ed09f95739df 99 }
wim 0:88d87b1c1f8b 100
vtraveller 10:3fcab08717fc 101 void ShowTracking(bool in_bShow)
vtraveller 3:ed09f95739df 102 {
vtraveller 10:3fcab08717fc 103 if (in_bShow)
vtraveller 4:d70e37f6c6bd 104 {
vtraveller 10:3fcab08717fc 105 lcd.setCursor(1,0);
vtraveller 10:3fcab08717fc 106 lcd._putc(eLeft);
vtraveller 4:d70e37f6c6bd 107
vtraveller 10:3fcab08717fc 108 lcd.setCursor(1,1);
vtraveller 10:3fcab08717fc 109 lcd._putc(eRight);
vtraveller 10:3fcab08717fc 110 }
vtraveller 10:3fcab08717fc 111 else
vtraveller 10:3fcab08717fc 112 {
vtraveller 10:3fcab08717fc 113 lcd.setCursor(1,0);
vtraveller 10:3fcab08717fc 114 lcd._putc(' ');
vtraveller 4:d70e37f6c6bd 115
vtraveller 10:3fcab08717fc 116 lcd.setCursor(1,1);
vtraveller 10:3fcab08717fc 117 lcd._putc(' ');
vtraveller 10:3fcab08717fc 118 }
vtraveller 10:3fcab08717fc 119 }
vtraveller 10:3fcab08717fc 120
vtraveller 10:3fcab08717fc 121 void UpdateDisplay
vtraveller 10:3fcab08717fc 122 (
vtraveller 10:3fcab08717fc 123 Module ** in_pModuleList,
vtraveller 10:3fcab08717fc 124 size_t in_nModuleListSize,
vtraveller 10:3fcab08717fc 125 size_t in_nMenuPos,
vtraveller 10:3fcab08717fc 126 int & inout_nIndexX,
vtraveller 10:3fcab08717fc 127 int in_nCursorX,
vtraveller 10:3fcab08717fc 128 int & inout_nCursorY
vtraveller 10:3fcab08717fc 129 )
vtraveller 10:3fcab08717fc 130 {
vtraveller 10:3fcab08717fc 131 ShowModules(in_pModuleList,in_nModuleListSize,in_nMenuPos);
vtraveller 10:3fcab08717fc 132
vtraveller 10:3fcab08717fc 133 size_t nCurrent = (in_nMenuPos + inout_nCursorY) % in_nModuleListSize;
vtraveller 10:3fcab08717fc 134 inout_nIndexX = in_pModuleList[nCurrent]->setCursor(inout_nIndexX,in_nCursorX,inout_nCursorY);
vtraveller 10:3fcab08717fc 135
vtraveller 10:3fcab08717fc 136 // If we didn't have anything, move the line
vtraveller 10:3fcab08717fc 137 if (-1 == inout_nIndexX)
vtraveller 10:3fcab08717fc 138 {
vtraveller 10:3fcab08717fc 139 inout_nCursorY = (inout_nCursorY + 1) % k_nHeightLCD;
vtraveller 4:d70e37f6c6bd 140
vtraveller 10:3fcab08717fc 141 nCurrent = (in_nMenuPos + inout_nCursorY) % in_nModuleListSize;
vtraveller 10:3fcab08717fc 142 inout_nIndexX = in_pModuleList[nCurrent]->setCursor(0,in_nCursorX,inout_nCursorY);
vtraveller 4:d70e37f6c6bd 143 }
vtraveller 9:1501fb01ded6 144
vtraveller 10:3fcab08717fc 145 // If nothing to show - hide everything
vtraveller 10:3fcab08717fc 146 if (-1 == inout_nIndexX) SetCursor(false,false);
vtraveller 3:ed09f95739df 147 }
vtraveller 3:ed09f95739df 148
vtraveller 3:ed09f95739df 149 int main()
vtraveller 9:1501fb01ded6 150 {
vtraveller 9:1501fb01ded6 151 pc.printf("\r\nInitialise LCD\r\n");
vtraveller 9:1501fb01ded6 152
vtraveller 10:3fcab08717fc 153 Initialise();
vtraveller 10:3fcab08717fc 154
vtraveller 10:3fcab08717fc 155 EModes eMode = eModeMenu;
vtraveller 10:3fcab08717fc 156 size_t nMenuPos = 0;
vtraveller 7:d087e901b74b 157
vtraveller 10:3fcab08717fc 158 // Set up display modules
vtraveller 10:3fcab08717fc 159 Module * aModules[] =
vtraveller 10:3fcab08717fc 160 {
vtraveller 10:3fcab08717fc 161 new TitleModule(lcd),
vtraveller 10:3fcab08717fc 162 new TimeModule(lcd,rtc),
vtraveller 10:3fcab08717fc 163 new DateModule(lcd,rtc),
vtraveller 10:3fcab08717fc 164 new TempModule(lcd)
vtraveller 10:3fcab08717fc 165 };
vtraveller 9:1501fb01ded6 166
vtraveller 10:3fcab08717fc 167 ShowModules(aModules,_countof(aModules),nMenuPos);
vtraveller 10:3fcab08717fc 168
vtraveller 10:3fcab08717fc 169 int nIndexX = 0;
vtraveller 10:3fcab08717fc 170 int nCursorY = 0;
vtraveller 10:3fcab08717fc 171
vtraveller 4:d70e37f6c6bd 172 while (true)
vtraveller 4:d70e37f6c6bd 173 {
vtraveller 10:3fcab08717fc 174 uint8_t nKeys = lcd.readButtons();
vtraveller 9:1501fb01ded6 175 if (nKeys)
vtraveller 9:1501fb01ded6 176 {
vtraveller 10:3fcab08717fc 177 // Change mode based on select
vtraveller 10:3fcab08717fc 178 if (nKeys & BUTTON_SELECT)
vtraveller 10:3fcab08717fc 179 {
vtraveller 10:3fcab08717fc 180 eMode = (EModes)((eMode + 1) % eModeLast);
vtraveller 10:3fcab08717fc 181
vtraveller 10:3fcab08717fc 182 // Start at top corner
vtraveller 10:3fcab08717fc 183 if (eModeSelect == eMode)
vtraveller 10:3fcab08717fc 184 {
vtraveller 10:3fcab08717fc 185 nIndexX = 0;
vtraveller 10:3fcab08717fc 186 nCursorY = 0;
vtraveller 10:3fcab08717fc 187 }
vtraveller 10:3fcab08717fc 188 }
vtraveller 10:3fcab08717fc 189
vtraveller 10:3fcab08717fc 190 switch (eMode)
vtraveller 10:3fcab08717fc 191 {
vtraveller 10:3fcab08717fc 192 case eModeMenu:
vtraveller 10:3fcab08717fc 193 SetCursor(false,false);
vtraveller 10:3fcab08717fc 194 ShowTracking(false);
vtraveller 10:3fcab08717fc 195
vtraveller 10:3fcab08717fc 196 if (nKeys & BUTTON_UP) nMenuPos--;
vtraveller 10:3fcab08717fc 197 if (nKeys & BUTTON_DOWN) nMenuPos++;
vtraveller 10:3fcab08717fc 198
vtraveller 10:3fcab08717fc 199 nMenuPos = nMenuPos % _countof(aModules);
vtraveller 10:3fcab08717fc 200 break;
vtraveller 10:3fcab08717fc 201
vtraveller 10:3fcab08717fc 202 case eModeSelect:
vtraveller 10:3fcab08717fc 203 SetCursor(true,false);
vtraveller 10:3fcab08717fc 204 ShowTracking(true);
vtraveller 10:3fcab08717fc 205
vtraveller 10:3fcab08717fc 206 if (nCursorY > 0 && (nKeys & BUTTON_UP)) nCursorY--;
vtraveller 10:3fcab08717fc 207 if ((nCursorY < k_nHeightLCD - 1) && (nKeys & BUTTON_DOWN)) nCursorY++;
vtraveller 10:3fcab08717fc 208
vtraveller 10:3fcab08717fc 209 if (nKeys & BUTTON_LEFT) nIndexX--;
vtraveller 11:96146db429de 210 if (nKeys & BUTTON_RIGHT) nIndexX++;
vtraveller 10:3fcab08717fc 211 break;
vtraveller 10:3fcab08717fc 212
vtraveller 10:3fcab08717fc 213 case eModeChange:
vtraveller 10:3fcab08717fc 214 SetCursor(false,true);
vtraveller 10:3fcab08717fc 215 ShowTracking(true);
vtraveller 11:96146db429de 216
vtraveller 11:96146db429de 217 if (nKeys & (BUTTON_UP | BUTTON_DOWN))
vtraveller 11:96146db429de 218 {
vtraveller 11:96146db429de 219 bool bUp = (nKeys & BUTTON_UP) ? true : false;
vtraveller 11:96146db429de 220 ChangeModule(aModules,_countof(aModules),nMenuPos,nIndexX,nCursorY,bUp);
vtraveller 11:96146db429de 221 }
vtraveller 11:96146db429de 222
vtraveller 11:96146db429de 223 if (nKeys & BUTTON_LEFT) nIndexX--;
vtraveller 11:96146db429de 224 if (nKeys & BUTTON_RIGHT) nIndexX++;
vtraveller 10:3fcab08717fc 225 break;
vtraveller 10:3fcab08717fc 226 }
vtraveller 9:1501fb01ded6 227
vtraveller 10:3fcab08717fc 228 UpdateDisplay(aModules,_countof(aModules),nMenuPos,nIndexX,2,nCursorY);
vtraveller 9:1501fb01ded6 229 }
vtraveller 10:3fcab08717fc 230 else
vtraveller 10:3fcab08717fc 231 {
vtraveller 10:3fcab08717fc 232 switch (eMode)
vtraveller 10:3fcab08717fc 233 {
vtraveller 10:3fcab08717fc 234 case eModeMenu:
vtraveller 10:3fcab08717fc 235 ShowModules(aModules,_countof(aModules),nMenuPos,true);
vtraveller 10:3fcab08717fc 236 aModules[nMenuPos]->setCursor(nIndexX,2,nCursorY);
vtraveller 10:3fcab08717fc 237 break;
vtraveller 10:3fcab08717fc 238 }
vtraveller 10:3fcab08717fc 239 }
vtraveller 10:3fcab08717fc 240
vtraveller 4:d70e37f6c6bd 241 wait(0.2);
vtraveller 10:3fcab08717fc 242 }
wim 0:88d87b1c1f8b 243 }