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:
Thu Oct 09 10:03:04 2014 +0000
Revision:
26:0cfd95d8f270
Parent:
25:24654d08a99a
Child:
27:b6c3dd9a1d8c
Updated with correct cursor positions

Who changed what in which revision?

UserRevisionLine numberNew contents of line
vtraveller 25:24654d08a99a 1 #include "mbed.h"
vtraveller 25:24654d08a99a 2 #include "module.h"
vtraveller 25:24654d08a99a 3 #include "extra_chars.h"
vtraveller 25:24654d08a99a 4
vtraveller 25:24654d08a99a 5 #include "MenuManager.h"
vtraveller 25:24654d08a99a 6
vtraveller 25:24654d08a99a 7 MenuManager::MenuManager
vtraveller 25:24654d08a99a 8 (
vtraveller 25:24654d08a99a 9 Module ** in_pModules,
vtraveller 25:24654d08a99a 10 size_t in_nModules,
vtraveller 25:24654d08a99a 11 LCD & in_cLCD,
vtraveller 25:24654d08a99a 12 Keys & in_cKeys
vtraveller 25:24654d08a99a 13 )
vtraveller 25:24654d08a99a 14 : m_pModules(in_pModules)
vtraveller 25:24654d08a99a 15 , m_nModules(in_nModules)
vtraveller 25:24654d08a99a 16 , m_cLCD(in_cLCD)
vtraveller 25:24654d08a99a 17 , m_cKeys(in_cKeys)
vtraveller 25:24654d08a99a 18 , m_eMode(Module::eModeLast)
vtraveller 25:24654d08a99a 19 , m_nMenuPos(0)
vtraveller 25:24654d08a99a 20 , m_nIndex(0)
vtraveller 25:24654d08a99a 21 , m_nCursorX(0)
vtraveller 25:24654d08a99a 22 , m_nCursorY(0)
vtraveller 25:24654d08a99a 23 {
vtraveller 25:24654d08a99a 24 }
vtraveller 25:24654d08a99a 25
vtraveller 25:24654d08a99a 26 void MenuManager::changeModule(bool in_bUp)
vtraveller 25:24654d08a99a 27 {
vtraveller 25:24654d08a99a 28 size_t nModule = (m_nMenuPos + m_nCursorY) % m_nModules;
vtraveller 25:24654d08a99a 29 m_pModules[nModule]->change(m_nIndex,in_bUp);
vtraveller 25:24654d08a99a 30 }
vtraveller 25:24654d08a99a 31
vtraveller 25:24654d08a99a 32 void MenuManager::createChars()
vtraveller 25:24654d08a99a 33 {
vtraveller 25:24654d08a99a 34 //uint8_t k_aUp[] = { 0x4,0xe,0x1f,0x15,0x4,0x4,0x4,0x4 };
vtraveller 25:24654d08a99a 35 //uint8_t k_aDown[] = { 0x4,0x4,0x4,0x4,0x15,0x1f,0xe,0x4 };
vtraveller 25:24654d08a99a 36
vtraveller 25:24654d08a99a 37 uint8_t k_aUp[] = { 0x0,0x0,0x4,0xe,0x1f,0x0,0x0 };
vtraveller 25:24654d08a99a 38 uint8_t k_aDown[] = { 0x0,0x0,0x1f,0xe,0x4,0x0,0x0 };
vtraveller 25:24654d08a99a 39 uint8_t k_aRight[] = { 0x0,0x8,0xc,0xe,0xc,0x8,0x0 };
vtraveller 25:24654d08a99a 40 uint8_t k_aLeft[] = { 0x0,0x2,0x6,0xe,0x6,0x2,0x0 };
vtraveller 25:24654d08a99a 41 uint8_t k_aDegree[] = { 0xc,0x12,0x12,0xc,0x0,0x0,0x0,0x0 };
vtraveller 25:24654d08a99a 42
vtraveller 25:24654d08a99a 43 m_cLCD.createChar(eUp,k_aUp);
vtraveller 25:24654d08a99a 44 m_cLCD.createChar(eDown,k_aDown);
vtraveller 25:24654d08a99a 45 m_cLCD.createChar(eRight,k_aRight);
vtraveller 25:24654d08a99a 46 m_cLCD.createChar(eLeft,k_aLeft);
vtraveller 25:24654d08a99a 47 m_cLCD.createChar(eDegree,k_aDegree);
vtraveller 25:24654d08a99a 48 }
vtraveller 25:24654d08a99a 49
vtraveller 25:24654d08a99a 50 void MenuManager::initialise()
vtraveller 25:24654d08a99a 51 {
vtraveller 25:24654d08a99a 52 createChars();
vtraveller 25:24654d08a99a 53
vtraveller 25:24654d08a99a 54 m_cLCD.setCursor(0,0);
vtraveller 25:24654d08a99a 55 m_cLCD._putc(eUp);
vtraveller 25:24654d08a99a 56
vtraveller 25:24654d08a99a 57 m_cLCD.setCursor(0,m_cLCD.rows() - 1);
vtraveller 25:24654d08a99a 58 m_cLCD._putc(eDown);
vtraveller 25:24654d08a99a 59
vtraveller 25:24654d08a99a 60 m_nCursorX = 2;
vtraveller 25:24654d08a99a 61 m_nCursorY = 0;
vtraveller 25:24654d08a99a 62 }
vtraveller 25:24654d08a99a 63
vtraveller 25:24654d08a99a 64 void MenuManager::loop()
vtraveller 25:24654d08a99a 65 {
vtraveller 25:24654d08a99a 66 setMode(Module::eModeMenu);
vtraveller 25:24654d08a99a 67
vtraveller 25:24654d08a99a 68 m_nMenuPos = 0;
vtraveller 25:24654d08a99a 69 m_nIndex = 0;
vtraveller 25:24654d08a99a 70
vtraveller 25:24654d08a99a 71 initialise();
vtraveller 25:24654d08a99a 72
vtraveller 25:24654d08a99a 73 showModules();
vtraveller 25:24654d08a99a 74
vtraveller 25:24654d08a99a 75 while (true)
vtraveller 25:24654d08a99a 76 {
vtraveller 25:24654d08a99a 77 uint8_t nKeys = m_cKeys.readButtons();
vtraveller 25:24654d08a99a 78 if (Keys::eButtonNone != nKeys)
vtraveller 25:24654d08a99a 79 {
vtraveller 25:24654d08a99a 80 processKeys(nKeys);
vtraveller 25:24654d08a99a 81 }
vtraveller 25:24654d08a99a 82 else
vtraveller 25:24654d08a99a 83 {
vtraveller 25:24654d08a99a 84 switch (m_eMode)
vtraveller 25:24654d08a99a 85 {
vtraveller 25:24654d08a99a 86 case Module::eModeMenu:
vtraveller 25:24654d08a99a 87 showModules(true);
vtraveller 25:24654d08a99a 88
vtraveller 25:24654d08a99a 89 int nOffsetX = m_pModules[m_nMenuPos]->getCursorOffset(m_nIndex);
vtraveller 25:24654d08a99a 90 m_cLCD.setCursor(m_nCursorY + nOffsetX,m_nCursorY);
vtraveller 25:24654d08a99a 91 break;
vtraveller 25:24654d08a99a 92 }
vtraveller 25:24654d08a99a 93 }
vtraveller 25:24654d08a99a 94
vtraveller 25:24654d08a99a 95 wait(0.2);
vtraveller 25:24654d08a99a 96 }
vtraveller 25:24654d08a99a 97 }
vtraveller 25:24654d08a99a 98
vtraveller 25:24654d08a99a 99 void MenuManager::processKeys(uint8_t in_nKeys)
vtraveller 25:24654d08a99a 100 {
vtraveller 25:24654d08a99a 101 // Change mode based on select
vtraveller 25:24654d08a99a 102 if (in_nKeys & Keys::eButtonSelect)
vtraveller 25:24654d08a99a 103 {
vtraveller 25:24654d08a99a 104 Module::EModes eMode = (Module::EModes)((m_eMode + 1) % Module::eModeLast);
vtraveller 25:24654d08a99a 105 setMode(eMode);
vtraveller 25:24654d08a99a 106
vtraveller 25:24654d08a99a 107 // Start at top corner
vtraveller 25:24654d08a99a 108 if (Module::eModeSelect == m_eMode)
vtraveller 25:24654d08a99a 109 {
vtraveller 25:24654d08a99a 110 m_nIndex = 0;
vtraveller 25:24654d08a99a 111 m_nCursorY = 0;
vtraveller 25:24654d08a99a 112 }
vtraveller 25:24654d08a99a 113 }
vtraveller 25:24654d08a99a 114
vtraveller 25:24654d08a99a 115 switch (m_eMode)
vtraveller 25:24654d08a99a 116 {
vtraveller 25:24654d08a99a 117 case Module::eModeMenu:
vtraveller 25:24654d08a99a 118 setCursor(false,false);
vtraveller 25:24654d08a99a 119 showTracking(false);
vtraveller 25:24654d08a99a 120
vtraveller 25:24654d08a99a 121 if (in_nKeys & Keys::eButtonUp) m_nMenuPos--;
vtraveller 25:24654d08a99a 122 if (in_nKeys & Keys::eButtonDown) m_nMenuPos++;
vtraveller 25:24654d08a99a 123
vtraveller 25:24654d08a99a 124 m_nMenuPos = m_nMenuPos % m_nModules;
vtraveller 25:24654d08a99a 125 break;
vtraveller 25:24654d08a99a 126
vtraveller 25:24654d08a99a 127 case Module::eModeSelect:
vtraveller 25:24654d08a99a 128 setCursor(true,false);
vtraveller 25:24654d08a99a 129 showTracking(true);
vtraveller 25:24654d08a99a 130
vtraveller 25:24654d08a99a 131 if (m_nCursorY > 0 && (in_nKeys & Keys::eButtonUp)) m_nCursorY--;
vtraveller 25:24654d08a99a 132 if ((m_nCursorY < m_cLCD.rows() - 1) && (in_nKeys & Keys::eButtonDown)) m_nCursorY++;
vtraveller 25:24654d08a99a 133
vtraveller 25:24654d08a99a 134 if (in_nKeys & Keys::eButtonLeft) m_nIndex--;
vtraveller 25:24654d08a99a 135 if (in_nKeys & Keys::eButtonRight) m_nIndex++;
vtraveller 25:24654d08a99a 136 break;
vtraveller 25:24654d08a99a 137
vtraveller 25:24654d08a99a 138 case Module::eModeChange:
vtraveller 25:24654d08a99a 139 setCursor(false,true);
vtraveller 25:24654d08a99a 140 showTracking(true);
vtraveller 25:24654d08a99a 141
vtraveller 25:24654d08a99a 142 if (in_nKeys & (Keys::eButtonUp | Keys::eButtonDown))
vtraveller 25:24654d08a99a 143 {
vtraveller 25:24654d08a99a 144 bool bUp = (in_nKeys & Keys::eButtonUp) ? true : false;
vtraveller 25:24654d08a99a 145 changeModule(bUp);
vtraveller 25:24654d08a99a 146 }
vtraveller 25:24654d08a99a 147
vtraveller 25:24654d08a99a 148 if (in_nKeys & Keys::eButtonLeft) m_nIndex--;
vtraveller 25:24654d08a99a 149 if (in_nKeys & Keys::eButtonRight) m_nIndex++;
vtraveller 25:24654d08a99a 150 break;
vtraveller 25:24654d08a99a 151 }
vtraveller 25:24654d08a99a 152
vtraveller 25:24654d08a99a 153 updateDisplay();
vtraveller 25:24654d08a99a 154 }
vtraveller 25:24654d08a99a 155
vtraveller 25:24654d08a99a 156 void MenuManager::setCursor(bool in_bCursor,bool in_bBlink)
vtraveller 25:24654d08a99a 157 {
vtraveller 25:24654d08a99a 158 m_cLCD.showCursor(in_bCursor);
vtraveller 25:24654d08a99a 159 m_cLCD.showBlink(in_bBlink);
vtraveller 25:24654d08a99a 160 }
vtraveller 25:24654d08a99a 161
vtraveller 25:24654d08a99a 162 void MenuManager::setMode(Module::EModes in_eMode)
vtraveller 25:24654d08a99a 163 {
vtraveller 25:24654d08a99a 164 m_eMode = in_eMode;
vtraveller 25:24654d08a99a 165
vtraveller 25:24654d08a99a 166 for (size_t i = 0; i < m_nModules; i++)
vtraveller 25:24654d08a99a 167 {
vtraveller 25:24654d08a99a 168 m_pModules[i]->onModeChange(m_eMode);
vtraveller 25:24654d08a99a 169 }
vtraveller 25:24654d08a99a 170 }
vtraveller 25:24654d08a99a 171
vtraveller 25:24654d08a99a 172 void MenuManager::showModules(bool in_bRefresh)
vtraveller 25:24654d08a99a 173 {
vtraveller 25:24654d08a99a 174 for (size_t i = 0; i < m_cLCD.rows(); i++)
vtraveller 25:24654d08a99a 175 {
vtraveller 25:24654d08a99a 176 size_t nPos = (m_nMenuPos + i) % m_nModules;
vtraveller 25:24654d08a99a 177 m_cLCD.setCursor(2,i);
vtraveller 25:24654d08a99a 178
vtraveller 25:24654d08a99a 179 if (m_pModules[nPos]->canRefresh() || !in_bRefresh) m_pModules[nPos]->show(in_bRefresh);
vtraveller 25:24654d08a99a 180 }
vtraveller 25:24654d08a99a 181 }
vtraveller 25:24654d08a99a 182
vtraveller 25:24654d08a99a 183 void MenuManager::showTracking(bool in_bShow)
vtraveller 25:24654d08a99a 184 {
vtraveller 26:0cfd95d8f270 185 int nX = (m_cLCD.rows() >= 4) ? 0:1;
vtraveller 26:0cfd95d8f270 186 int nTop = nX ? 0:1;
vtraveller 26:0cfd95d8f270 187 int nBottom = m_cLCD.rows() - (nX ? 1:2);
vtraveller 26:0cfd95d8f270 188
vtraveller 25:24654d08a99a 189 if (in_bShow)
vtraveller 25:24654d08a99a 190 {
vtraveller 26:0cfd95d8f270 191 m_cLCD.setCursor(nX,nTop);
vtraveller 25:24654d08a99a 192 m_cLCD._putc(eLeft);
vtraveller 25:24654d08a99a 193
vtraveller 26:0cfd95d8f270 194 m_cLCD.setCursor(nX,nBottom);
vtraveller 26:0cfd95d8f270 195 m_cLCD._putc(eRight);
vtraveller 25:24654d08a99a 196 }
vtraveller 25:24654d08a99a 197 else
vtraveller 25:24654d08a99a 198 {
vtraveller 26:0cfd95d8f270 199 m_cLCD.setCursor(nX,nTop);
vtraveller 25:24654d08a99a 200 m_cLCD._putc(' ');
vtraveller 25:24654d08a99a 201
vtraveller 26:0cfd95d8f270 202 m_cLCD.setCursor(nX,nBottom);
vtraveller 26:0cfd95d8f270 203 m_cLCD._putc(' ');
vtraveller 25:24654d08a99a 204 }
vtraveller 25:24654d08a99a 205 }
vtraveller 25:24654d08a99a 206
vtraveller 25:24654d08a99a 207 void MenuManager::updateDisplay()
vtraveller 25:24654d08a99a 208 {
vtraveller 25:24654d08a99a 209 showModules();
vtraveller 25:24654d08a99a 210
vtraveller 25:24654d08a99a 211 size_t nCurrent = (m_nMenuPos + m_nCursorY) % m_nModules;
vtraveller 25:24654d08a99a 212
vtraveller 25:24654d08a99a 213 int nOffsetX = m_pModules[nCurrent]->getCursorOffset(m_nIndex);
vtraveller 25:24654d08a99a 214
vtraveller 25:24654d08a99a 215 // If we didn't have anything, move the line
vtraveller 25:24654d08a99a 216 if (-1 == nOffsetX)
vtraveller 25:24654d08a99a 217 {
vtraveller 25:24654d08a99a 218 m_nCursorY = (m_nCursorY + 1) % m_cLCD.rows();
vtraveller 25:24654d08a99a 219
vtraveller 25:24654d08a99a 220 nCurrent = (m_nMenuPos + m_nCursorY) % m_nModules;
vtraveller 25:24654d08a99a 221
vtraveller 25:24654d08a99a 222 m_nIndex = 0;
vtraveller 25:24654d08a99a 223 nOffsetX = m_pModules[nCurrent]->getCursorOffset(m_nIndex);
vtraveller 25:24654d08a99a 224 }
vtraveller 25:24654d08a99a 225
vtraveller 25:24654d08a99a 226 if ((size_t)-1 != m_nIndex)
vtraveller 25:24654d08a99a 227 {
vtraveller 25:24654d08a99a 228 // Move cursor to new position
vtraveller 25:24654d08a99a 229 m_cLCD.setCursor(m_nCursorX + nOffsetX,m_nCursorY);
vtraveller 25:24654d08a99a 230 }
vtraveller 25:24654d08a99a 231 else
vtraveller 25:24654d08a99a 232 {
vtraveller 25:24654d08a99a 233 // If nothing to show - hide everything
vtraveller 25:24654d08a99a 234 setCursor(false,false);
vtraveller 25:24654d08a99a 235 }
vtraveller 25:24654d08a99a 236 }