Vinícius Alves
/
MenuLCD_copy
Então PARA...
Revision 0:92357d1220f3, committed 2017-05-19
- Comitter:
- ViniR
- Date:
- Fri May 19 13:07:52 2017 +0000
- Commit message:
- Ent?o PARA...
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TextLCD_HelloWorld2.lib Fri May 19 13:07:52 2017 +0000 @@ -0,0 +1,1 @@ +https://developer.mbed.org/users/ViniR/code/MenuLCD/#8ed644ed983b
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Fri May 19 13:07:52 2017 +0000 @@ -0,0 +1,311 @@ +#include "mbed.h" +#include "menbed.h" +#include "TextLCD.h" +#include "Adafruit_ST7735.h" + +Serial pc(USBTX, USBRX); +DigitalIn enable(D2); +//float photocellVoltage(void) {return 0;} + +Adafruit_ST7735 tft(D11, D12, D13, D10, D8, D9); // MOSI, MISO, SCLK, SSEL, TFT_DC, TFT_RST + +void testlines(uint16_t color); +void testfastlines(uint16_t color1, uint16_t color2); +void IniciandoMaquina(void); +void Alerta(void); +void MenuPrincipal(void); +void Aguarde(void); +void Executando(void); + +//Serial pc(USBTX, USBRX); // tx, rx +//I2C i2c_lcd(D14,D15); // SDA, SCL +//TextLCD_I2C lcd(&i2c_lcd, 0x7E, TextLCD::LCD20x4); // I2C exp: I2C bus, PCF8574 Slaveaddress, LCD Type + +int main() { + + // Use this initializer if you're using a 1.8" TFT + tft.initR(INITR_BLACKTAB); // initialize a ST7735S chip, black tab + + //iniciando máquina + IniciandoMaquina(); + wait_ms(5000); + Alerta(); + wait_ms(5000); + MenuPrincipal(); + wait_ms(5000); + Aguarde(); + wait_ms(5000); + Executando(); + wait_ms(5000); + //InicioProcessoReferenciamento(); + //wait_ms(5000); + + +//lcd.setBacklight(TextLCD::LightOn); + + // Declare all the submenus so that they can be referenced in the + // definitions of other menus + MenbedMenu *rootMenu; + MenbedMenu *measurementMenu; + MenbedMenu *controlMenu; + MenbedMenu *aboutMenu; + + // Root menu--to create a menu, we first create an array of pointers to + // all the menu items that will populate the menu. The MenbedMenuItem + // constructor take five arguments: the function to be executed when the + // item is selected; the child menu to open when the item is selected; + // a boolean indicating whether the child menu is actually this menu's + // ancestor, (useful when creating "go to root menu" items); a parameter + // object that holds a value to be viewed or modified; and a text string + // indicating what the menu item should say. The text string may contain + // a printf-style specifier for a float that is bracketed by \t characters + // to offset it from the surrounding text. If the float specified is + // found, it will be replaced by the value of the parameter. + MenbedMenuItem *rootMenuItems[5] = { + new MenbedMenuItem (NULL, &measurementMenu, false, NULL, "Controle Manual"), // function,child,bollean,data,text + new MenbedMenuItem (NULL, &controlMenu, false, NULL, "Arquivos"), + new MenbedMenuItem (NULL, &aboutMenu, false, NULL, "Configuracoes"), + new MenbedMenuItem (NULL, &rootMenu, false, NULL, "Referenciamento"), + new MenbedMenuItem (NULL, &rootMenu, false, NULL, "Capacitivo"), + }; + // After we have the array of pointers to menu items, we pass the number of + // elements in the arry and the array itself to the MenbedMenu constructor. + rootMenu = new MenbedMenu (5, rootMenuItems); + + // Measurements menu--the first item of the measurement menu displays the + // voltage and the resistor divider junction formed between a photocell and + // a fixed resistor. To print this voltage as part of a menu item, we + // create a MenbedMenuParam object that takes as arguments to its + // constructor: a pointer to a function that returns a float containing the + // value of the parameter; a pointer to a function that we would call to + // change the value of the parameter; a boolean (irrevelant here) + // indicating whether the parameter, if it were modifiable by the user, + // should be updated as the user is changing its value or whether its + // should only be updated after the user has confirmed the new value; a + // minimum value for the parameter; a maximum value; and a step size. + //MenbedMenuParam photocellParam (photocellVoltage, NULL, false, 0.0, 0.0, 0.0); + + // Having created the parameter, we pass it as the 4th argument of the + // MenbedMenuItem constructor. Note the \t-offset %.2f format specified + // in the menu item text. The menu system will call the photocellVoltage + // function specified in the parameter constructor above and then print the + // float that it returns in place of the %.2f in the menu text. + + MenbedMenuItem *measurementMenuItems[2] = { + //new MenbedMenuItem (NULL, NULL, false, &photocellParam, "Photocell: \t%.2f\tV"), + new MenbedMenuItem (NULL, &rootMenu, true, NULL, "lee") }; + measurementMenu = new MenbedMenu (2, measurementMenuItems); + + // Controls menu--We have modifiable parameters in the first and second + // meu items of the controls menu. Walking through the first parameter + // constructor, the getLed1Pwm function pointer points to a function that + // returns the current value of the PWM duty cycle. The setLed1Pwm + // function pointer points to a function which sets the PWM duty cycle. + // The boolean set to true indicates that as soon as the user makes a + // change to the parameter, the setLed1Pwm function will be called. The + // menu system will not wait for the user to confirm his change before + // making the call. The 0.0 and 100.0 represent the minimum and + // maximum PWM values. The final 1.0 paramter is the step size when + // changing the PWM duty cycle. + // MenbedMenuParam pwmParam1 (getLed1Pwm, setLed1Pwm, true, 0.0, 100.0, 1.0); + // The only different in this parameter from the one above is that the PWM + // duty cycle is not updated (setLed2Pwm is not called) until the user + // confirms the new duty cycle. If the user cancels his modifications + // (either by pushing the cancel button or pushing and holding the select + // button) setLed2PWM is never called. + // MenbedMenuParam pwmParam2 (getLed2Pwm, setLed2Pwm, false, 0.0, 100.0, 1.0); + // The third, fourth, and fifth items of the control menu demonstrate + // functions when a menu item is selected. The ability to call a function + // can be combined with either displaying a submenu or editing a parameter. + MenbedMenuItem *controlMenuItems[6] = { + // new MenbedMenuItem (NULL, NULL, false, &pwmParam1, "LED1 PWM: \t%.0f\t%"), + // new MenbedMenuItem (NULL, NULL, false, &pwmParam2, "LED2 PWM: \t%.0f\t%"), + // new MenbedMenuItem (toggleLed3, NULL, false, NULL, "Toggle LED3"), + // new MenbedMenuItem (lightLed4, NULL, false, NULL, "Light LED4"), + // new MenbedMenuItem (extinguishLed4, NULL, false, NULL, "Extinguish LED4"), + new MenbedMenuItem (NULL, &rootMenu, true, NULL, "Home") }; + controlMenu = new MenbedMenu (6, controlMenuItems); + + // About menu--there's nothing fancy here, but the lack of a "Home" item + // forces the user to employ the cancel button, either directly or by + // pushing and hold the select button, to return to the root menu. + MenbedMenuItem *aboutMenuItems[3] = { + new MenbedMenuItem (NULL, NULL, false, NULL, " NXP3915"), + new MenbedMenuItem (NULL, NULL, false, NULL, " Copyright 2011"), + new MenbedMenuItem (NULL, NULL, false, NULL, " xxxxxxxx@xxx.xxx") }; + aboutMenu = new MenbedMenu (3, aboutMenuItems); + + // Having created the menus, menu items, and item parameters, we are ready + // to instantiate the display. MenbedDisplayHD44780 extends MenbedDisplay + // and implements the all-important writeLine function allong with some + // other less important functions. The pins we pass to the constructor + // specify the physical interface connection to the LCD. + MenbedDisplayHD44780 *hd44780Lcd = new MenbedDisplayHD44780 + (D8, D9, D4, D5, D6, D7, MenbedDisplayHD44780::LCD20x4); + + // Now, we have the menu objects and the display object. All we have to do + // is create the menbed menu system. The number of buttons used by the + // menu system is specified by the number of pins passed to the Menbed + // constructor. The pin order is select, down, up, cancel. With + // constructor overloading, we can opt out of using the cancel and up + // buttons. + + /* Four buttons (select, down, up, cancel ) */ + Menbed menbed(D10, D11, D12, D13, + rootMenu, + hd44780Lcd); +} + +void testlines(uint16_t color) +{ + tft.fillScreen(ST7735_BLACK); + for (int16_t x=0; x < tft.width(); x+=6) { + tft.drawLine(0, 0, x, tft.height()-1, color); + } + for (int16_t y=0; y < tft.height(); y+=6) { + tft.drawLine(0, 0, tft.width()-1, y, color); + } + + tft.fillScreen(ST7735_BLACK); + for (int16_t x=0; x < tft.width(); x+=6) { + tft.drawLine(tft.width()-1, 0, x, tft.height()-1, color); + } + for (int16_t y=0; y < tft.height(); y+=6) { + tft.drawLine(tft.width()-1, 0, 0, y, color); + } + + tft.fillScreen(ST7735_BLACK); + for (int16_t x=0; x < tft.width(); x+=6) { + tft.drawLine(0, tft.height()-1, x, 0, color); + } + for (int16_t y=0; y < tft.height(); y+=6) { + tft.drawLine(0, tft.height()-1, tft.width()-1, y, color); + } + + tft.fillScreen(ST7735_BLACK); + for (int16_t x=0; x < tft.width(); x+=6) { + tft.drawLine(tft.width()-1, tft.height()-1, x, 0, color); + } + for (int16_t y=0; y < tft.height(); y+=6) { + tft.drawLine(tft.width()-1, tft.height()-1, 0, y, color); + } +} + +void testfastlines(uint16_t color1, uint16_t color2) +{ + tft.fillScreen(ST7735_BLACK); + for (int16_t y=0; y < tft.height(); y+=5) { + tft.drawFastHLine(0, y, tft.width(), color1); + } + for (int16_t x=0; x < tft.width(); x+=5) { + tft.drawFastVLine(x, 0, tft.height(), color2); + } +} + + + +void IniciandoMaquina() +{ + tft.setTextWrap(true); + tft.fillScreen(ST7735_BLACK); + int x = 0; + while(x < 5) { + tft.fillScreen(ST7735_BLACK); + tft.setCursor(0,50); + tft.setTextColor(ST7735_WHITE); + tft.setTextSize(2); + tft.printf("Iniciando Pet-Finder"); + tft.setCursor(0,100); + tft.printf("Aguarde"); + wait_ms(100); + tft.fillScreen(ST7735_BLACK); + tft.setCursor(0,50); + tft.setTextColor(ST7735_WHITE); + tft.setTextSize(2); + tft.printf("Iniciando Pet-Finder"); + tft.setCursor(0,100); + tft.printf("Aguarde..."); + wait_ms(100); + x += 1; + } +} + + + +void Alerta() { + tft.setTextWrap(true); + int x = 0; + while(x < 10) { + tft.fillScreen(ST7735_BLACK); + tft.setCursor(0,50); + tft.setTextColor(ST7735_WHITE); + tft.setTextSize(2); + tft.printf("!!ALERTA!!"); + wait_ms(200); + tft.fillScreen(ST7735_RED); + tft.setTextSize(2); + tft.printf("!!ALERTA!!"); + wait_ms(300); + x += 1; + } + +} + +void MenuPrincipal() { + tft.fillScreen(ST7735_BLACK); + tft.setCursor(0,0); + tft.setTextColor(ST7735_WHITE); + tft.setTextSize(2); + tft.printf("Pet-Finder"); + tft.setCursor(0,40); + tft.printf("Data:"); + tft.setCursor(0,55); + tft.printf("15/05/2017"); + tft.setCursor(0,80); + tft.printf("Horario:"); + tft.setCursor(0,95); + tft.printf("17h27"); + wait_ms(200); + + } + +void Aguarde() { + int x = 0; + while(x < 5) { + tft.fillScreen(ST7735_BLACK); + tft.setCursor(0,70); + tft.setTextSize(2); + tft.printf("Aguarde..."); + wait_ms(800); + x += 1; + } +} + +void Executando() { + int x = 0; + tft.fillScreen(ST7735_WHITE); + tft.setTextColor(ST7735_BLACK); + while(x < 3) { + tft.fillScreen(ST7735_GREEN); + tft.setCursor(0,70); + tft.setTextSize(2); + tft.printf("Executando"); + wait_ms(800); + tft.fillScreen(ST7735_WHITE); + tft.setTextColor(ST7735_BLACK); + tft.setCursor(0,70); + tft.printf("Executando"); + wait_ms(400); + x += 1; + + } + tft.fillScreen(ST7735_GREEN); + tft.setCursor(0,70); + tft.printf("Executando"); +} + + +// ---------------------------------------------------------------------------------------------------------------- + + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Fri May 19 13:07:52 2017 +0000 @@ -0,0 +1,1 @@ +https://mbed.org/users/mbed_official/code/mbed/builds/4eea097334d6 \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/menbed/displays/include/menbedDisplayHD44780.h Fri May 19 13:07:52 2017 +0000 @@ -0,0 +1,79 @@ +/* This code based on mbed TextLCD Library, for a 4-bit LCD based on HD44780, + * Copyright (c) 2007-2010, sford, http://mbed.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef _MENBEDDISPLAYHD44780_H_ +#define _MENBEDDISPLAYHD44780_H_ + +#include "mbed.h" +#include "menbedDisplay.h" + +class MenbedDisplayHD44780 : public MenbedDisplay { +public: + + /** LCD panel format */ + enum LCDSize { + LCD16x2, /**< 16x2 LCD panel */ + LCD16x2B, /**< 16x2 LCD panel alternate addressing */ + LCD20x2, /**< 20x2 LCD panel */ + LCD20x4, /**< 20x4 LCD panel (default) */ + }; + + MenbedDisplayHD44780 (PinName rs, PinName e, PinName d4, PinName d5, PinName d6, PinName d7, LCDSize size = LCD20x4); + + virtual bool writeLine (const char *line, uint8_t row); + virtual void showUpArrow (bool show); + virtual void showDownArrow (bool show); + virtual uint8_t getLines (void); + virtual uint8_t getLineLength (void); + +protected: + enum ArrowSelectorChar { + CharUP, + CharUP_SELECT, + CharSELECT, + CharDOWN_SELECT, + CharDOWN + }; + + DigitalOut rs, e; + BusOut d; + LCDSize size; + + bool upArrowVisible, downArrowVisible; + bool topLineSelected, bottomLineSelected; + int cursorCol, cursorRow; + + bool gotoPosition(int row, int column); + void clear(); + void cursorOn(); + void cursorOff(); + + int address(int column, int row); + void writeByte(int value); + void writeCommand(int command); + void writeData(int data); + void loadCustomChars(void); + int rows(); + int columns(); +}; + +#endif /* _MENBEDDISPLAYHD44780_H_ */ \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/menbed/displays/menbedDisplayHD44780.cpp Fri May 19 13:07:52 2017 +0000 @@ -0,0 +1,369 @@ +/* This code based on mbed TextLCD Library, for a 4-bit LCD based on HD44780, + * Copyright (c) 2007-2010, sford, http://mbed.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "mbed.h" +#include "include/menbedDisplayHD44780.h" +#include "menbedDisplay.h" + +MenbedDisplayHD44780::MenbedDisplayHD44780 (PinName rs, PinName e, + PinName d4, PinName d5, PinName d6, PinName d7, LCDSize size) : + rs(rs), e(e), d(d4, d5, d6, d7), size(size) +{ + this->e = 1; + this->rs = 0; + + upArrowVisible = false; + downArrowVisible = false; + topLineSelected = false; + bottomLineSelected = false; + cursorCol = -1; + cursorRow = -1; + + wait(0.015); // Wait 15ms to ensure powered up + + // send "Display Settings" 3 times (Only top nibble of 0x30 as we've got 4-bit bus) + for (int i=0; i<3; i++) { + writeByte(0x3); + wait(0.00164); // this command takes 1.64ms, so wait for it + } + + writeByte(0x2); // 4-bit mode + wait(0.000040f); // most instructions take 40us + + writeCommand(0x28); // Function set 001 BW N F - - + writeCommand(0x0C); // Display on but keep cursor and blinking off + writeCommand(0x6); // Cursor Direction and Display Shift : 0000 01 CD S (CD 0-left, 1-right S(hift) 0-no, 1-yes + + loadCustomChars(); + + clear(); +} + + +bool MenbedDisplayHD44780::writeLine (const char *line, uint8_t row) +{ + int i = 0; + int cursorPos = -1; + + if (row >= rows()) + return false; + + // Skip writing to the left-most column to leave space for the selector + // and up/down arrows that will be filled in later. + gotoPosition (row, 1); + + while ((line[i] != '\0') && (line[i] != '\n') && (i+1 < columns())) + { + // Place the cursor at the end of the active parameter, when it exists. + // A parameter is active when it is highlighted as indicated by the + // MSB of the character code being set. + if ((i > 0) && (line[i-1] & 0x80) && !(line[i] & 0x80)) + cursorPos = i-1; + + // Print each character to the display after clearing its MSB so that + // it prints as a standard ASCII character. + writeData (line[i] & ~0x80); + i++; + } + + // If the first character of the line is not highlighted but the last is, + // a parameter must be selected for editing, and we place the cursor at + // the end of the parameter which, in this special case, corresponds to + // the end of the line. + if (!(line[0] & 0x80) && (line[i-1] & 0x80)) + cursorPos = i-1; + + // Fill the remainder of the row with spaces to overwrite any old data + while (i++ < columns() - 1) + writeData(' '); + + // Now go back and fill in the selector and up/down arrows + gotoPosition(row, 0); + if ((line[0] & 0x80) && (cursorPos == -1)) + { + if (row == 0) + topLineSelected = true; + else if (row == rows() - 1) + bottomLineSelected = true; + + if ((row == 0) && upArrowVisible) + writeData (CharUP_SELECT); + else if ((row == rows() - 1) && downArrowVisible) + writeData (CharDOWN_SELECT); + else + writeData (CharSELECT); + } + else + { + if (row == 0) + topLineSelected = false; + else if (row == rows() - 1) + bottomLineSelected = false; + + if ((row == 0) && upArrowVisible) + writeData (CharUP); + else if ((row == rows() - 1) && downArrowVisible) + writeData (CharDOWN); + else + writeData (' '); + } + + // If a parameter is being edited, we turn on the blinking cursor. + if (cursorPos != -1) + { + cursorRow = row; + cursorCol = cursorPos + 1; + gotoPosition (cursorRow, cursorCol); // Add 1 to account for selector col. + cursorOn(); + } + // If this line used to contain the cursor but should not any more reset + // the cursor row and column position and turn it off. + else if (row == cursorRow) + { + cursorRow = -1; + cursorCol = -1; + cursorOff(); + } + + return true; +} + + +void MenbedDisplayHD44780::showUpArrow (bool show) +{ + upArrowVisible = show; + + gotoPosition (0, 0); + + if (show && topLineSelected) + writeData (CharUP_SELECT); + else if (!show && topLineSelected) + writeData (CharSELECT); + else if (show && !topLineSelected) + writeData (CharUP); + else + writeData(' '); + + // Return cursor to its original location + if ((cursorRow >= 0) && (cursorCol >= 0)) + gotoPosition (cursorRow, cursorCol); +} + + +void MenbedDisplayHD44780::showDownArrow (bool show) +{ + downArrowVisible = show; + + gotoPosition (rows() - 1, 0); + + if (show && bottomLineSelected) + writeData (CharDOWN_SELECT); + else if (!show && bottomLineSelected) + writeData (CharSELECT); + else if (show && !bottomLineSelected) + writeData (CharDOWN); + else + writeData(' '); + + // Return cursor to its original location + if ((cursorRow >= 0) && (cursorCol >= 0)) + gotoPosition (cursorRow, cursorCol); +} + + +uint8_t MenbedDisplayHD44780::getLines (void) +{ + return rows(); +} + + +uint8_t MenbedDisplayHD44780::getLineLength (void) +{ + return columns(); +} + + +void MenbedDisplayHD44780::clear() +{ + writeCommand (0x01); // Clear, and set cursor to 0 + wait (0.050f); + gotoPosition (0, 0); +} + + +bool MenbedDisplayHD44780::gotoPosition(int row, int column) +{ + if ((column < 0) || (column >= columns()) || (row < 0) || (row >= rows())) + return false; + + writeCommand (address (row, column)); + return true; +} + + +void MenbedDisplayHD44780::cursorOn() +{ + writeCommand(0x0D); // Display and blinking on, cursor off +} + + +void MenbedDisplayHD44780::cursorOff() +{ + writeCommand(0x0C); // Display on, cursor and blinking off +} + + +void MenbedDisplayHD44780::writeCommand(int command) { + rs = 0; + writeByte(command); +} + + +void MenbedDisplayHD44780::writeData(int data) { + rs = 1; + writeByte(data); +} + + +void MenbedDisplayHD44780::writeByte(int value) { + d = value >> 4; + wait(0.000040f); // most instructions take 40us + e = 0; + wait(0.000040f); + e = 1; + d = value >> 0; + wait(0.000040f); + e = 0; + wait(0.000040f); // most instructions take 40us + e = 1; +} + + +int MenbedDisplayHD44780::address(int row, int column) { + switch (size) { + case LCD20x4: + switch (row) { + case 0: + return 0x80 + column; + case 1: + return 0xc0 + column; + case 2: + return 0x94 + column; + case 3: + return 0xd4 + column; + } + case LCD16x2B: + return 0x80 + (row * 40) + column; + case LCD16x2: + case LCD20x2: + default: + return 0x80 + (row * 0x40) + column; + } +} + + +int MenbedDisplayHD44780::columns() +{ + switch (size) { + case LCD20x4: + case LCD20x2: + return 20; + case LCD16x2: + case LCD16x2B: + default: + return 16; + } +} + + +int MenbedDisplayHD44780::rows() +{ + switch (size) { + case LCD20x4: + return 4; + case LCD16x2: + case LCD16x2B: + case LCD20x2: + default: + return 2; + } +} + + +void MenbedDisplayHD44780::loadCustomChars (void) +{ + + // Up arrow + writeCommand(0x40 + (8 * CharUP)); + writeData(0x04); + writeData(0x0E); + writeData(0x1F); + writeData(0x00); + writeData(0x00); + writeData(0x00); + writeData(0x00); + writeData(0x00); + + // Up arrow with selector + writeCommand(0x40 + (8 * CharUP_SELECT)); + writeData(0x04); + writeData(0x0E); + writeData(0x1F); + writeData(0x00); + writeData(0x1F); + writeData(0x1F); + writeData(0x00); + writeData(0x00); + + // Selector alone + writeCommand(0x40 + (8 * CharSELECT)); + writeData(0x00); + writeData(0x00); + writeData(0x00); + writeData(0x1F); + writeData(0x1F); + writeData(0x00); + writeData(0x00); + writeData(0x00); + + // Down arrow with selector + writeCommand(0x40 + (8 * CharDOWN_SELECT)); + writeData(0x00); + writeData(0x00); + writeData(0x1F); + writeData(0x1F); + writeData(0x00); + writeData(0x1F); + writeData(0x0E); + writeData(0x04); + + // Down arrow + writeCommand(0x40 + (8 * CharDOWN)); + writeData(0x00); + writeData(0x00); + writeData(0x00); + writeData(0x00); + writeData(0x00); + writeData(0x1F); + writeData(0x0E); + writeData(0x04); +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/menbed/include/menbed.h Fri May 19 13:07:52 2017 +0000 @@ -0,0 +1,42 @@ +#ifndef _MENBED_H_ +#define _MENBED_H_ + +#include "menbedButtonEvent.h" +#include "menbedButtonHandler.h" +#include "menbedButtonHandlerTimespec.h" +#include "menbedNavigator.h" +#include "menbedMenu.h" +#include "menbedMenuItem.h" +#include "menbedRefresher.h" + +#include "../displays/include/menbedDisplayHD44780.h" + + +class Menbed { +public: + Menbed (PinName select, PinName down, PinName up, PinName cancel, + MenbedMenu *rootMenu, + MenbedDisplay *display); + + Menbed (PinName select, PinName down, PinName up, + MenbedMenu *rootMenu, + MenbedDisplay *display); + + Menbed (PinName select, PinName down, + MenbedMenu *rootMenu, + MenbedDisplay *display); + + Menbed (PinName select, PinName down, PinName up, PinName cancel, + MenbedButtonHandlerTimespec *timespec, + MenbedMenu *rootMenu, + MenbedDisplay *display); + + ~Menbed (); +protected: + MenbedButtonHandler *buttonHandler; + MenbedNavigator *navigator; + MenbedDisplayer *displayer; + MenbedRefresher *refresher; +}; + +#endif /* _MENBED_H_ */ \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/menbed/include/menbedButtonEvent.h Fri May 19 13:07:52 2017 +0000 @@ -0,0 +1,25 @@ +#ifndef _MENBEDBUTTONEVENT_H_ +#define _MENBEDBUTTONEVENT_H_ + +#include "mbed.h" + +class MenbedButtonEvent { +public: + enum ButtonName { + ButtonSelect, + ButtonDown, + ButtonUp, + ButtonCancel }; + + enum ButtonAction { + BUTTON_ACTION_PUSHED, + BUTTON_ACTION_RELEASED_SHORT, + BUTTON_ACTION_RELEASED_LONG, + BUTTON_ACTION_HELD_LONG }; + + ButtonName name; + ButtonAction action; + uint8_t numButtons; +}; + +#endif /* _MENBEDBUTTONEVENT_H_ */ \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/menbed/include/menbedButtonHandler.h Fri May 19 13:07:52 2017 +0000 @@ -0,0 +1,38 @@ +#ifndef _MENBEDBUTTONHANDLER_H_ +#define _MENBEDBUTTONHANDLER_H_ + +#include "mbed.h" +#include "menbedNavigator.h" +#include "menbedButtonHandlerTimespec.h" + +class MenbedButtonHandler { +public: + MenbedButtonHandler(PinName selectPin, PinName downPin, PinName upPin, PinName cancelPin, + MenbedButtonHandlerTimespec *timespec, MenbedNavigator *navigator); + MenbedButtonHandler(PinName selectPin, PinName downPin, PinName upPin, + MenbedButtonHandlerTimespec *timespec, MenbedNavigator *navigator); + MenbedButtonHandler(PinName selectPin, PinName downPin, + MenbedButtonHandlerTimespec *timespec, MenbedNavigator *navigator); + +protected: + DigitalIn *select, *down, *up, *cancel; + MenbedButtonHandlerTimespec *timespec; + MenbedNavigator *navigator; + + Ticker ticker; + uint32_t tickerPeriod_us; + uint32_t currentTime_us; + + int numButtons; + + uint32_t buttonPushedTime_us[4]; // Absolute time button first depressed + bool buttonDebounced[4]; // Keep track of which buttons are debounced + uint32_t buttonLastTypematicTime_us[4]; // Abs. time of last virtual push + bool buttonAlreadyDepressed[4]; // Keep track of state b/t calls to tick() + + void init (void); + void tick (void); + bool isButtonDepressed (MenbedButtonEvent::ButtonName); +}; + +#endif /* _MENBEDBUTTONHANDLER_H_ */ \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/menbed/include/menbedButtonHandlerTimespec.h Fri May 19 13:07:52 2017 +0000 @@ -0,0 +1,24 @@ +#ifndef _MENBEDBUTTONHANDLERTIMESPEC_H_ +#define _MENBEDBUTTONHANDLERTIMESPEC_H_ + +#include "mbed.h" + +class MenbedButtonHandlerTimespec { +public: + uint32_t scanPeriod_us; + uint32_t debounceDelay_us; + uint32_t longReleaseDelay_us; + uint32_t typematicPeriod_us; + uint32_t typematicX10Delay_us; + uint32_t typematicX10Period_us; + + MenbedButtonHandlerTimespec (); + MenbedButtonHandlerTimespec (uint32_t scanPeriod_us, + uint32_t debounceDelay_us, + uint32_t longReleaseDelay_us, uint32_t typematicPeriod_us, + uint32_t typematicX10Delay_us, uint32_t typematicX10Period_us); + + bool dummy() {return false;} +}; + +#endif /* _MENBEDBUTTONHANDLERTIMESPEC_H_ */ \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/menbed/include/menbedDisplay.h Fri May 19 13:07:52 2017 +0000 @@ -0,0 +1,15 @@ +#ifndef _MENBEDDISPLAY_H_ +#define _MENBEDDISPLAY_H_ + +#include "mbed.h" + +class MenbedDisplay { +public: + virtual bool writeLine (const char *line, uint8_t row) = 0; + virtual void showUpArrow (bool show) = 0; + virtual void showDownArrow (bool show) = 0; + virtual uint8_t getLines (void) = 0; + virtual uint8_t getLineLength (void) = 0; +}; + +#endif /* _MENBEDDISPLAY_H_ */ \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/menbed/include/menbedDisplayer.h Fri May 19 13:07:52 2017 +0000 @@ -0,0 +1,18 @@ +#ifndef _MENBEDDISPLAYER_H_ +#define _MENBEDDISPLAYER_H_ + +#include "menbedMenuMessage.h" +#include "menbedDisplay.h" + +class MenbedDisplayer { +public: + MenbedDisplayer (MenbedDisplay *display); + void update (MenbedMenuMessage *menuMessage); + MenbedDisplay *getDisplay (void) {return display;} +protected: + MenbedDisplay *display; + + void extractLine (char *catenatedText, uint8_t lineNum, char *extractedText); +}; + +#endif /* _MENBEDDISPLAYER_H_ */ \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/menbed/include/menbedMenu.h Fri May 19 13:07:52 2017 +0000 @@ -0,0 +1,21 @@ +#ifndef _MENBEDMENU_H_ +#define _MENBEDMENU_H_ + +#include <vector> + +#include "mbed.h" +#include "menbedMenuItem.h" + +class MenbedMenuItem; + +class MenbedMenu { +public: + MenbedMenu *parentMenu; + int8_t parentSelectedItemIndex; + uint8_t parentTopOfScreenItemIndex; + vector<MenbedMenuItem*> menuItems; + + MenbedMenu (uint8_t nItems, MenbedMenuItem *items[]); +}; + +#endif /* _MENBEDMENU_H_ */ \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/menbed/include/menbedMenuItem.h Fri May 19 13:07:52 2017 +0000 @@ -0,0 +1,47 @@ +#ifndef _MENBEDMENUITEM_H_ +#define _MENBEDMENUITEM_H_ + +#include <vector> +#include "mbed.h" +#include "menbedMenu.h" +#include "menbedMenuParam.h" + +class MenbedMenu; + +class MenbedMenuItem { +public: + // Pointer to function that will be called when menu item selected. This + // may be a null pointer if no function should be called. + void (*selFcn)(); + // New menu to display when item selected. This can be set to null if a + // new menu item should not be called when the menu item is selected. + MenbedMenu **childMenu; + // If true, childMenuIsAncestor indicates that the child menu's parent menu + // should be set to null. This will prevent the user from moving to the + // from the child menu back to the current menu. This is useful when the + // menu item is something like "Goto root menu". Once the user is in the + // root menu, we don't want the user to press and hold the select key or + // press the cancel key in order to return to the current menu. + bool childMenuIsAncestor; + // Pointer a structure which itself points to a float that will be displayed + // in place of the %f in the text of the menu item. If the param struct + // has an inc memeber that is non-zero, the parameter can be modified by the + // user. In particular, when the user selects this menu item, the parameter + // is highlighted and the user can then use the up and down buttons to + // modify its value. + MenbedMenuParam *param; + // Array of char pointers to the strings that will be catenated to form + // the text of the menu item. To insert either a menu parameter or state + // variable into the menu item text, make one of the strings a printf-style + // conversion specifier for a float. (Note: only floats are allowed, + // integer are not.) The last string must be an empty string ("") to + // indicate it is the last string in the array. If the empty string is + // omitted, unpredictable behavior will result. + char *text; + + MenbedMenuItem (void (*selFcn)(), MenbedMenu **childMenu, + bool childMenuIsAncestor, MenbedMenuParam *param, + char *text); +}; + +#endif /* _MENBEDMENUITEM_H_ */ \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/menbed/include/menbedMenuMessage.h Fri May 19 13:07:52 2017 +0000 @@ -0,0 +1,16 @@ +#ifndef _MENBEDMENUMESSAGE_H_ +#define _MENBEDMENUMESSAGE_H_ + +#include "mbed.h" + +class MenbedMenuMessage { +public: + char *text; + bool showUpArrow; + bool showDownArrow; + + MenbedMenuMessage (uint8_t numLines, uint8_t lineLength); + ~MenbedMenuMessage (); +}; + +#endif /* _MENBEDMENUMESSAGE_H_ */ \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/menbed/include/menbedMenuParam.h Fri May 19 13:07:52 2017 +0000 @@ -0,0 +1,51 @@ +#ifndef _MENBEDMENUPARAM_H_ +#define _MENBEDMENUPARAM_H_ +#include <string> +class MenbedMenuParam { +public: + // Copy of the initial value; + float initVal; + string initValString; + // Temporary copy of the parameter used to the hold the modified value + // before it is committed. + float tempVal; + + MenbedMenuParam (float (*initValFcn)(void), void (*finalValFcn)(float), + bool liveUpdate, float min, float max, + float inc); + + float getVal (void); + void setVal (float v); + bool liveUpdate (void) {return _liveUpdate;} + float min (void) {return _min;} + float max (void) {return _max;} + float inc (void) {return _inc;} + +protected: + // Pointer to a function returning a float containing the current value of + // the parameter. + float (*initValFcn)(void); + // Pointer to a function taking a float that is called when the parameter + // value is modified. + string (*initValStringFcn)(void); + // Pointer to a function taking a float that is called when the parameter + // value is modified. + void (*finalValFcn)(float); + // Boolean indicating whether the finalValFcn should be called each time + // the user makes a change to the variable or whether it should only be + // called once the user confirms the change. + void (*finalValStringFcn)(string); + // Boolean indicating whether the finalValFcn should be called each time + // the user makes a change to the variable or whether it should only be + // called once the user confirms the change. + bool _liveUpdate; + // Minimum allowable value. + float _min; + // Maximum allowable value. + float _max; + // Amount by which to increment/decrement the parameter with each presses of + // the up/down button. + float _inc; +}; + +#endif /* _MENBEDMENUPARAM_H_ */ \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/menbed/include/menbedNavigator.h Fri May 19 13:07:52 2017 +0000 @@ -0,0 +1,38 @@ +#ifndef _MENBEDNAVIGATOR_H_ +#define _MENBEDNAVIGATOR_H_ + +#include "menbedButtonEvent.h" +#include "menbedStructure.h" +#include "menbedDisplayer.h" +#include "menbedMenu.h" + +class MenbedNavigator { +public: + MenbedNavigator (MenbedMenu *rootMenu, MenbedDisplayer *displayer); + void updateDisplay (void); + void handleButtonEvent (MenbedButtonEvent buttonEvent); +protected: + MenbedMenu *activeMenu; + uint8_t numButtons; + uint8_t numLines; + uint8_t lineLength; + MenbedDisplayer *displayer; + + int8_t selectedItemIndex; + uint8_t topOfScreenItemIndex; + bool paramEditMode; + + void selectItem (void); + void gotoParent (void); + void moveUp (void); + void moveDown (void); + void incParam (void); + void decParam (void); + void saveParam (void); + void restoreParam (void); + void printMenu (char *menuStr); + void printItem (MenbedMenuItem *item, char *line, bool itemSel, bool paramSel); + bool checkConvSpec (const char *s); +}; + +#endif /* _MENBEDNAVIGATOR_H_ */ \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/menbed/include/menbedRefresher.h Fri May 19 13:07:52 2017 +0000 @@ -0,0 +1,21 @@ +#ifndef _MENBEDREFRESHER_H_ +#define _MENBEDREFRESHER_H_ + +#include "mbed.h" +#include "menbedNavigator.h" + +class MenbedRefresher +{ +public: + MenbedRefresher (MenbedNavigator *navigator); + MenbedRefresher (MenbedNavigator *navigator, uint32_t refreshPeriod_us); + void refreshed (void); + +protected: + Ticker ticker; + MenbedNavigator *navigator; + uint32_t refreshPeriod_us; +}; + + +#endif /* _MENBEDREFRESHER_H_ */ \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/menbed/include/menbedStructure.h Fri May 19 13:07:52 2017 +0000 @@ -0,0 +1,71 @@ +#ifndef _MENBEDSTRUCTURE_H_ +#define _MENBEDSTRUCTURE_H_ + +#include "mbed.h" + +struct menuParam; +struct menuItem; +struct menu; + +typedef struct menuParam menuParam_t; +typedef struct menuItem menuItem_t; +typedef struct menu menu_t; + +struct menuParam{ + // Pointer to a function returning a float containing the current value of + // the parameter. + float (*initValFcn)(void); + // Pointer to a function taking a float that is called when the parameter + // value is modified. + void (*finalValFcn)(float); + // Copy of the initial value; + float initVal; + // Temporary copy of the parameter used to the hold the modified value + // before it is committed. + float tempVal; + // Boolean indicating whether the finalValFcn should be called each time + // the user makes a change to the variable or whether it should only be + // called once the user confirms the change. + bool liveUpdate; + // Minimum allowable value. + float min; + // Maximum allowable value. + float max; + // Amount by which to increment/decrement the parameter with each presses of + // the up/down button. + float inc; +}; + +struct menuItem{ + // Pointer to function that will be called when menu item selected. This + // may be a null pointer if no function should be called. + void (*selFcn)(); + // New menu to display when item selected. This can be set to null if a + // new menu item should not be called when the menu item is selected. + menu_t *childMenu; + // If true, childMenuIsAncestor indicates that the child menu's parent menu + // should be set to null. This will prevent the user from moving to the + // from the child menu back to the current menu. This is useful when the + // menu item is something like "Goto root menu". Once the user is in the + // root menu, we don't want the user to press and hold the select key or + // press the cancel key in order to return to the current menu. + bool childMenuIsAncestor; + // Pointer a structure which itself points to a float that will be displayed + // in place of the %f in the text of the menu item. If the param struct + // has an inc memeber that is non-zero, the parameter can be modified by the + // user. In particular, when the user selects this menu item, the parameter + // is highlighted and the user can then use the up and down buttons to + // modify its value. + menuParam_t *param; + // Array of char pointers to the strings that will be catenated to form + // the text of the menu item. To insert either a menu parameter or state + // variable into the menu item text, make one of the strings a printf-style + // conversion specifier for a float. (Note: only floats are allowed, + // integer are not.) The last string must be an empty string ("") to + // indicate it is the last string in the array. If the empty string is + // omitted, unpredictable behavior will result. + char *text[]; +}; + + +#endif /* _MENBEDSTRUCTURE_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/menbed/menbed.cpp Fri May 19 13:07:52 2017 +0000 @@ -0,0 +1,57 @@ +#include "mbed.h" +#include "include/menbed.h" + +Menbed::Menbed (PinName select, PinName down, PinName up, PinName cancel, + MenbedMenu *rootMenu, + MenbedDisplay *display) +{ + MenbedButtonHandlerTimespec *timespec = new MenbedButtonHandlerTimespec(); + + displayer = new MenbedDisplayer (display); + navigator = new MenbedNavigator (rootMenu, displayer); + buttonHandler = new MenbedButtonHandler (select, down, up, cancel, timespec, navigator); + refresher = new MenbedRefresher (navigator); +} + +Menbed::Menbed (PinName select, PinName down, PinName up, + MenbedMenu *rootMenu, + MenbedDisplay *display) +{ + MenbedButtonHandlerTimespec *timespec = new MenbedButtonHandlerTimespec(); + + displayer = new MenbedDisplayer (display); + navigator = new MenbedNavigator (rootMenu, displayer); + buttonHandler = new MenbedButtonHandler (select, down, up, timespec, navigator); + refresher = new MenbedRefresher (navigator); +} + +Menbed::Menbed (PinName select, PinName down, + MenbedMenu *rootMenu, + MenbedDisplay *display) +{ + MenbedButtonHandlerTimespec *timespec = new MenbedButtonHandlerTimespec(); + + displayer = new MenbedDisplayer (display); + navigator = new MenbedNavigator (rootMenu, displayer); + buttonHandler = new MenbedButtonHandler (select, down, timespec, navigator); + refresher = new MenbedRefresher (navigator); +} + +Menbed::Menbed(PinName select, PinName down, PinName up, PinName cancel, + MenbedButtonHandlerTimespec *timespec, + MenbedMenu *rootMenu, + MenbedDisplay *display) +{ + displayer = new MenbedDisplayer (display); + navigator = new MenbedNavigator (rootMenu, displayer); + buttonHandler = new MenbedButtonHandler (select, down, up, cancel, timespec, navigator); + refresher = new MenbedRefresher (navigator); +} + +Menbed::~Menbed() +{ + delete refresher; + delete buttonHandler; + delete navigator; + delete displayer; +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/menbed/menbedButtonHandler.cpp Fri May 19 13:07:52 2017 +0000 @@ -0,0 +1,201 @@ +#include "mbed.h" +#include "include/menbedNavigator.h" +#include "include/menbedButtonHandlerTimespec.h" +#include "include/menbedButtonHandler.h" + +MenbedButtonHandler::MenbedButtonHandler (PinName selectPin, PinName downPin, + PinName upPin, PinName cancelPin, MenbedButtonHandlerTimespec *timespec, + MenbedNavigator *navigator) : + //select(select), down(down), up(up), cancel(cancel), + timespec(timespec), navigator(navigator) +{ + select = new DigitalIn(selectPin); + down = new DigitalIn(downPin); + up = new DigitalIn(upPin); + cancel = new DigitalIn(cancelPin); + + numButtons = 4; + + select->mode (PullDown); + down->mode (PullDown); + up->mode (PullDown); + cancel->mode (PullDown); + + init(); +} + + +MenbedButtonHandler::MenbedButtonHandler (PinName selectPin, PinName downPin, + PinName upPin, MenbedButtonHandlerTimespec *timespec, + MenbedNavigator *navigator) : + timespec(timespec), navigator(navigator) +{ + select = new DigitalIn(selectPin); + down = new DigitalIn(downPin); + up = new DigitalIn(upPin); + + numButtons = 3; + + select->mode (PullDown); + down->mode (PullDown); + up->mode (PullDown); + + init(); +} + + +MenbedButtonHandler::MenbedButtonHandler (PinName selectPin, PinName downPin, + MenbedButtonHandlerTimespec *timespec, + MenbedNavigator *navigator) : + timespec(timespec), navigator(navigator) +{ + select = new DigitalIn(selectPin); + down = new DigitalIn(downPin); + + numButtons = 2; + + select->mode (PullDown); + down->mode (PullDown); + + init(); +} + + +void MenbedButtonHandler::init() +{ + for (int i=0; i<4; i++) + { + buttonDebounced[i] = false; + buttonAlreadyDepressed[i] = false; + } + + currentTime_us = 0; + ticker.attach_us (this, &MenbedButtonHandler::tick, + timespec->scanPeriod_us); +} + + +void MenbedButtonHandler::tick (void) +{ + // Accumulated amount of time that buttons have been continuously depressed + uint32_t buttonDepressedTime_us; + bool buttonCurrentlyDepressed; + + MenbedButtonEvent buttonEvent; + buttonEvent.numButtons = numButtons; + + currentTime_us += timespec->scanPeriod_us; + + // Cycle through each of the buttons + for (int i=MenbedButtonEvent::ButtonSelect; + (i<=MenbedButtonEvent::ButtonCancel) && (i<numButtons); + i++) + { + buttonEvent.name = (MenbedButtonEvent::ButtonName)i; + buttonCurrentlyDepressed = + isButtonDepressed((MenbedButtonEvent::ButtonName)i); + + // The amount of time the current button has been depressed is + // the current time minus the time which the button was first + // depressed. + buttonDepressedTime_us = currentTime_us - buttonPushedTime_us[i]; + + if (buttonCurrentlyDepressed && buttonAlreadyDepressed[i]) + { + if ((buttonDepressedTime_us >= timespec->typematicX10Delay_us) && + (currentTime_us - buttonLastTypematicTime_us[i] >= + timespec->typematicX10Period_us )) + { + buttonLastTypematicTime_us[i] = currentTime_us; + buttonEvent.action = MenbedButtonEvent::BUTTON_ACTION_PUSHED; + navigator->handleButtonEvent (buttonEvent); + } + else if ((buttonDepressedTime_us >= + timespec->typematicPeriod_us) + && (currentTime_us - buttonLastTypematicTime_us[i] >= + timespec->typematicPeriod_us)) + { + buttonLastTypematicTime_us[i] = currentTime_us; + buttonEvent.action = MenbedButtonEvent::BUTTON_ACTION_PUSHED; + navigator->handleButtonEvent (buttonEvent); + } + else if ((buttonDepressedTime_us >= timespec->debounceDelay_us) + && (!buttonDebounced[i])) + { + buttonLastTypematicTime_us[i] = currentTime_us; + buttonDebounced[i] = true; + buttonEvent.action = MenbedButtonEvent::BUTTON_ACTION_PUSHED; + navigator->handleButtonEvent (buttonEvent); + } + + if (buttonDebounced[i] && + (buttonDepressedTime_us >= + timespec->longReleaseDelay_us)) + { + buttonEvent.action = MenbedButtonEvent::BUTTON_ACTION_HELD_LONG; + navigator->handleButtonEvent (buttonEvent); + } + + buttonAlreadyDepressed[i] = true; + } + // Otherwise, if the button was just depressed, we indicate that it + // has not yet debounced and record the time so that we know when it + // was first pressed. + else if (buttonCurrentlyDepressed && !buttonAlreadyDepressed[i]) + { + buttonDebounced[i] = false; + buttonPushedTime_us[i] = currentTime_us; + + buttonAlreadyDepressed[i] = true; + } + // Otherwise, if the button is not depressed but it was previously + // depressed and the amount of time it was depressed exceeds the + // debounce time, then we say the button has been released. + else if (!buttonCurrentlyDepressed && buttonAlreadyDepressed[i]) + { + if (buttonDebounced[i]) + { + if (buttonDepressedTime_us >= + timespec->longReleaseDelay_us) + { + buttonEvent.action = MenbedButtonEvent::BUTTON_ACTION_RELEASED_LONG; + navigator->handleButtonEvent (buttonEvent); + } + else + { + buttonEvent.action = MenbedButtonEvent::BUTTON_ACTION_RELEASED_SHORT; + navigator->handleButtonEvent (buttonEvent); + } + } + + buttonAlreadyDepressed[i] = false; + } + } +} + + +bool MenbedButtonHandler::isButtonDepressed (MenbedButtonEvent::ButtonName name) +{ + switch (name) + { + case MenbedButtonEvent::ButtonSelect: + return *select; + case MenbedButtonEvent::ButtonDown: + if (numButtons >= 2) + return *down; + else + return false; + case MenbedButtonEvent::ButtonUp: + if (numButtons >= 3) + return *up; + else + return false; + case MenbedButtonEvent::ButtonCancel: + if (numButtons == 4) + return *cancel; + else + return false; + } + + return false; +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/menbed/menbedButtonHandlerTimespec.cpp Fri May 19 13:07:52 2017 +0000 @@ -0,0 +1,20 @@ +#include "mbed.h" +#include "include/menbedButtonHandlerTimespec.h" + +MenbedButtonHandlerTimespec::MenbedButtonHandlerTimespec () : + scanPeriod_us(10000), debounceDelay_us(45000), + longReleaseDelay_us(2500000), typematicPeriod_us(333000), + typematicX10Delay_us(2997000), typematicX10Period_us(33000) +{} + +MenbedButtonHandlerTimespec::MenbedButtonHandlerTimespec ( + uint32_t scanPeriod_us, + uint32_t debounceDelay_us, + uint32_t longReleaseDelay_us, uint32_t typematicPeriod_us, + uint32_t typematicX10Delay_us, uint32_t typematicX10Period_us) : + scanPeriod_us(scanPeriod_us), debounceDelay_us(debounceDelay_us), + longReleaseDelay_us(longReleaseDelay_us), + typematicPeriod_us(typematicPeriod_us), + typematicX10Delay_us(typematicX10Delay_us), + typematicX10Period_us(typematicX10Period_us) +{} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/menbed/menbedDisplayer.cpp Fri May 19 13:07:52 2017 +0000 @@ -0,0 +1,81 @@ +#include "mbed.h" +#include "include/menbedMenuMessage.h" +#include "include/menbedDisplayer.h" + +MenbedDisplayer::MenbedDisplayer (MenbedDisplay *display) : + display(display) +{ +} + + +void MenbedDisplayer::update (MenbedMenuMessage *menuMessage) +{ + char *text = new char[display->getLineLength()+1]; + + for (int i=0; i<display->getLines(); i++) + { + extractLine (menuMessage->text, i, text); + display->writeLine (text, i); + } + + // Print the up and down arrows if requested + display->showUpArrow (menuMessage->showUpArrow); + display->showDownArrow (menuMessage->showDownArrow); + + delete[] text; +} + + +void MenbedDisplayer::extractLine (char *catenatedText, uint8_t lineNum, + char *extractedText) +{ + char *subText, *endText; + size_t bytesToCopy; + + extractedText[0] = '\0'; + + // Return with just a blank line if the line number to be extracted exceeds + // the number of lines in the menu + if (lineNum > display->getLines() - 1) + return; + + // We loop through the catenatedString finding each \n. These \n + // characters separate the substrings that we are trying to extract. + subText = catenatedText; + while (lineNum > 0) + { + subText = strchr (subText, '\n'); + + // If the \n character was not found, the catenatedText string does not + // contain enough \n-separated substrings. + if (subText == (char *)NULL) + { + extractedText[0] = '\0'; + return; + } + + // Increment the subText pointer because the strchr() command returned + // a pointer to the \n character found, but next time through the loop + // we want to find the next \n, not the same \n again. + subText++; + lineNum--; + } + + // If there are strings following the one we are trying to extract, we + // change the \n terminating the string to be extracted into a \0 so that + // we can use the strlen function to determine the length of the string + // we are trying to extract. If there are no additional \n-separated + // strings following the one we are attempting to extract, strlen should + // work on subText without modification. + if ((endText = strchr (subText, '\n')) != (char *)NULL) + bytesToCopy = endText - subText + 1; + else + bytesToCopy = strlen(subText); + + // Copy the string found in the \n-separated substring number specified by + // the lineNum parameter to the extracted string. + strncpy (extractedText, subText, bytesToCopy); + + // Replace the \n at the end of extractedText string with a \0 + extractedText[bytesToCopy-1] = '\0'; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/menbed/menbedMenu.cpp Fri May 19 13:07:52 2017 +0000 @@ -0,0 +1,13 @@ +#include "mbed.h" +#include "include/menbedMenuItem.h" +#include "include/menbedMenu.h" + +MenbedMenu::MenbedMenu (uint8_t nItems, MenbedMenuItem *items[]) +{ + parentMenu = NULL; + parentSelectedItemIndex = -1; + parentTopOfScreenItemIndex = 0; + + for (int i = 0; i<nItems; i++) + menuItems.push_back (items[i]); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/menbed/menbedMenuItem.cpp Fri May 19 13:07:52 2017 +0000 @@ -0,0 +1,9 @@ +#include "mbed.h" +#include "include/menbedMenuItem.h" + +MenbedMenuItem::MenbedMenuItem (void (*selFcn)(), MenbedMenu **childMenu, + bool childMenuIsAncestor, MenbedMenuParam *param, char *text) : + selFcn(selFcn), childMenu(childMenu), + childMenuIsAncestor(childMenuIsAncestor), param(param), + text(text) +{}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/menbed/menbedMenuMessage.cpp Fri May 19 13:07:52 2017 +0000 @@ -0,0 +1,12 @@ +#include "mbed.h" +#include "include/menbedMenuMessage.h" + +MenbedMenuMessage::MenbedMenuMessage (uint8_t numLines, uint8_t lineLength) +{ + text = new char[numLines * lineLength + 1]; +} + +MenbedMenuMessage::~MenbedMenuMessage() +{ + delete[] text; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/menbed/menbedMenuParam.cpp Fri May 19 13:07:52 2017 +0000 @@ -0,0 +1,29 @@ +#include "mbed.h" +#include "include/menbedMenuParam.h" +#include <string> + +MenbedMenuParam::MenbedMenuParam ( + float (*initValFcn)(void), void (*finalValFcn)(float), + bool liveUpdate, float min, float max, + float inc) : + initValFcn(initValFcn), finalValFcn(finalValFcn), _liveUpdate(liveUpdate), + _min(min), _max(max), _inc(inc) +{ +} + + +float MenbedMenuParam::getVal (void) +{ + if (initValFcn == NULL) + return 0.0; + + return initValFcn(); +} + +void MenbedMenuParam::setVal (float v) +{ + if (finalValFcn == NULL) + return; + + finalValFcn(v); +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/menbed/menbedNavigator.cpp Fri May 19 13:07:52 2017 +0000 @@ -0,0 +1,477 @@ +#include "mbed.h" +#include "include/menbedNavigator.h" +#include "include/menbedButtonEvent.h" +#include "include/menbedMenuMessage.h" +#include "include/menbedMenu.h" +#include <cstdio> + +extern void toggleLed3(); + +MenbedNavigator::MenbedNavigator(MenbedMenu *rootMenu, + MenbedDisplayer *displayer) : + activeMenu(rootMenu), displayer(displayer) +{ + selectedItemIndex = -1; + topOfScreenItemIndex = 0; + paramEditMode = false; + + numLines = displayer->getDisplay()->getLines(); + lineLength = displayer->getDisplay()->getLineLength(); +} + +void MenbedNavigator::updateDisplay() +{ + MenbedMenuMessage menuMsg (numLines, lineLength); + + printMenu (menuMsg.text); + menuMsg.showUpArrow = (topOfScreenItemIndex >= 1); + menuMsg.showDownArrow = (topOfScreenItemIndex + numLines < (int)(activeMenu->menuItems.size())); + + displayer->update (&menuMsg); +} + + +void MenbedNavigator::handleButtonEvent (MenbedButtonEvent buttonEvent) +{ + numButtons = buttonEvent.numButtons; + + switch (buttonEvent.name) + { + case MenbedButtonEvent::ButtonSelect: // Select + if (!paramEditMode && (buttonEvent.action == + MenbedButtonEvent::BUTTON_ACTION_RELEASED_SHORT)) + selectItem(); + else if (paramEditMode && (buttonEvent.action == + MenbedButtonEvent::BUTTON_ACTION_RELEASED_SHORT)) + saveParam(); + else if ((numButtons < 4) && + paramEditMode && (buttonEvent.action == + MenbedButtonEvent::BUTTON_ACTION_HELD_LONG)) + restoreParam(); + else if ((numButtons < 4) && !paramEditMode && + (buttonEvent.action == + MenbedButtonEvent::BUTTON_ACTION_HELD_LONG)) + gotoParent(); + break; + + case MenbedButtonEvent::ButtonDown: + if (paramEditMode && + (buttonEvent.action == MenbedButtonEvent::BUTTON_ACTION_PUSHED)) + decParam(); + else if (!paramEditMode && + (buttonEvent.action == MenbedButtonEvent::BUTTON_ACTION_PUSHED)) + moveDown(); + break; + + case MenbedButtonEvent::ButtonUp: + if (numButtons > 2) + { + if (paramEditMode && + (buttonEvent.action == MenbedButtonEvent::BUTTON_ACTION_PUSHED)) + incParam(); + else if (!paramEditMode && + (buttonEvent.action == MenbedButtonEvent::BUTTON_ACTION_PUSHED)) + moveUp(); + } + break; + + case MenbedButtonEvent::ButtonCancel: + if (numButtons > 3) + { + if (paramEditMode && + (buttonEvent.action == MenbedButtonEvent::BUTTON_ACTION_PUSHED)) + restoreParam(); + else if (!paramEditMode && + (buttonEvent.action == MenbedButtonEvent::BUTTON_ACTION_PUSHED)) + gotoParent(); + } + break; + } + + updateDisplay(); + //menuRefresh_refreshed(); +} + + +void MenbedNavigator::selectItem() +{ + MenbedMenu **childMenuPtr; + MenbedMenu *childMenu; + + if ((selectedItemIndex < 0) || + (selectedItemIndex >= (int)(activeMenu->menuItems.size()))) + return; + + // If it exists, execute the function associated with the menu item + if (activeMenu->menuItems[selectedItemIndex]->selFcn != NULL) + activeMenu->menuItems[selectedItemIndex]->selFcn(); + + // Show the child menu associated with the menu item. Initially, the first + // item in the child menu is placed at the top of the screen, but is it + // left unselected. + childMenuPtr = activeMenu->menuItems[selectedItemIndex]->childMenu; + if (childMenuPtr != NULL) + { + childMenu = *(activeMenu->menuItems[selectedItemIndex]->childMenu); + + if (!activeMenu->menuItems[selectedItemIndex]->childMenuIsAncestor) + { + childMenu->parentMenu = activeMenu; + childMenu->parentSelectedItemIndex = selectedItemIndex; + childMenu->parentTopOfScreenItemIndex = topOfScreenItemIndex; + } + else + childMenu->parentMenu = NULL; + + activeMenu = childMenu; + topOfScreenItemIndex = 0; + selectedItemIndex = -1; + } + // Otherwise, if the current menu item has a parameter that can be modified, + // we switch to the parameter editing mode. + else if ((activeMenu->menuItems[selectedItemIndex]->param != NULL) && + (activeMenu->menuItems[selectedItemIndex]->param->inc() != 0)) + { + // All incrementing and decrementing of the parameter actually happens + // to a shadow variable in the param structure named tempValue. The + // parameter value used by the other parts of the system is not updated + // until the user is done editing the parameter. + activeMenu->menuItems[selectedItemIndex]->param->initVal = + activeMenu->menuItems[selectedItemIndex]->param->getVal(); + activeMenu->menuItems[selectedItemIndex]->param->tempVal = + activeMenu->menuItems[selectedItemIndex]->param->initVal; + paramEditMode = true; + } +} + + +void MenbedNavigator::gotoParent() +{ + if (activeMenu->parentMenu == NULL) + return; + + selectedItemIndex = activeMenu->parentSelectedItemIndex; + topOfScreenItemIndex = activeMenu->parentTopOfScreenItemIndex; + activeMenu = activeMenu->parentMenu; +} + + +void MenbedNavigator::moveUp() +{ + // If we're already at the top of the menu, do nothing + if (selectedItemIndex <= -1) + return; + // If the top item of the menu is already selected, we send a NOP message + // which deselects the top line and displays the down arrow if the menu + // contains more items than can fit on the screen. In effect, this allows + // the user to deselect all menu items which adds a nice look to the system. + else if (selectedItemIndex == 0) + selectedItemIndex = -1; + // If the currently selected menu item is the also the one at the top of the + // screen, we need to scroll the screen down and add the item above the + // currently selected one to the top of the screen. + else if (selectedItemIndex == topOfScreenItemIndex) + { + selectedItemIndex--; + topOfScreenItemIndex--; + } + // The selected item is not the top item on the screen. All we need to do + // is select the item above the currently selected item. + else + selectedItemIndex--; +} + + + +void MenbedNavigator::moveDown() +{ + // If the last item of the menu is already selected, our behavior depends + // on how many buttons are present. If there is no up button, we cycle + // back to the top of the menu. Otherwise, if an up button is present, + // we do nothing. + if (selectedItemIndex >= ((int)(activeMenu->menuItems.size()) - 1)) + { + if (numButtons < 3) + { + selectedItemIndex = -1; + topOfScreenItemIndex = 0; + } + else + ; + } + // If the menu item displayed at the bottom of the screen is already + // selected, we will need to scroll the screen up to make room for a new + // line at the bottom of the screen. + else if (selectedItemIndex == + (topOfScreenItemIndex + numLines - 1)) + { + selectedItemIndex++; + topOfScreenItemIndex++; + } + // Otherwise, if the currently selected menu item is now the one displayed + // at the bottom of the screen, we simply change which of the visible items + // is highlighted. + else + selectedItemIndex++; + +} + + +void MenbedNavigator::incParam() +{ + float inc; + float tempVal; + + if (paramEditMode != true) + return; + + inc = activeMenu->menuItems[selectedItemIndex]->param->inc(); + + // Initialize our own local copy of the parameter's temporary value. We do + // this so that we can more easily check for violations of the allowed min + // and max values. + tempVal = activeMenu->menuItems[selectedItemIndex]->param->tempVal; + tempVal += inc; + + // Check the bounds on the parameter. + if (tempVal > activeMenu->menuItems[selectedItemIndex]->param->max()) + tempVal = activeMenu->menuItems[selectedItemIndex]->param->max(); + else if (tempVal < activeMenu->menuItems[selectedItemIndex]->param->min()) + tempVal = activeMenu->menuItems[selectedItemIndex]->param->min(); + + // Assign the local temp. value back to the temporary value in the active + // parameter structue. + activeMenu->menuItems[selectedItemIndex]->param->tempVal = tempVal; + + // If the parameter is configured to produce live updates, call the + // finalValFcn. + if (activeMenu->menuItems[selectedItemIndex]->param->liveUpdate()) + activeMenu->menuItems[selectedItemIndex]->param->setVal(tempVal); +} + + +void MenbedNavigator::decParam() +{ + float inc; + float tempVal; + + if (paramEditMode != true) + return; + + inc = activeMenu->menuItems[selectedItemIndex]->param->inc(); + + // Initialize our own local copy of the parameter's temporary value. We do + // this so that we can more easily check for violations of the allowed min + // and max values. + tempVal = activeMenu->menuItems[selectedItemIndex]->param->tempVal; + tempVal -= inc; + + // Check the bounds on the parameter. + if (tempVal > activeMenu->menuItems[selectedItemIndex]->param->max()) + tempVal = activeMenu->menuItems[selectedItemIndex]->param->max(); + // If we reach the minimum parameter value when we only have a down button + // and not an up button connected to the system, we wrap the parameter + // value back around to its maximum. Otherwise, if there is an up button + // present, we peg the parameter at its minimum value. + else if (tempVal < activeMenu->menuItems[selectedItemIndex]->param->min()) + { + if (numButtons >= 3) + tempVal = activeMenu->menuItems[selectedItemIndex]->param->min(); + else + tempVal = activeMenu->menuItems[selectedItemIndex]->param->max(); + } + + // Assign the local temp. value back to the temporary value in the active + // parameter structue. + activeMenu->menuItems[selectedItemIndex]->param->tempVal = tempVal; + + // If the parameter is configured to produce live updates, call the + // finalValFcn. + if (activeMenu->menuItems[selectedItemIndex]->param->liveUpdate()) + activeMenu->menuItems[selectedItemIndex]->param->setVal(tempVal); +} + + +void MenbedNavigator::saveParam() +{ + // Save the changes made the shadow variable tempValue to the real parameter + // value that is used by the rest of the application. + activeMenu->menuItems[selectedItemIndex]->param->setVal ( + activeMenu->menuItems[selectedItemIndex]->param->tempVal + ); + paramEditMode = false; +} + + +void MenbedNavigator::restoreParam() +{ + // Revert any changes made the parameter by calling the finalValFcn with + // the initVal that was stored when we first began editing this parameter. + activeMenu->menuItems[selectedItemIndex]->param->setVal( + activeMenu->menuItems[selectedItemIndex]->param->initVal + ); + paramEditMode = false; +} + + +void MenbedNavigator::printMenu (char *menuStr) +{ + uint8_t i; + char *lineStr = new char[lineLength]; + bool itemSel; + + menuStr[0] = '\0'; + + for (i=topOfScreenItemIndex; i<topOfScreenItemIndex + numLines; i++) + { + // Make sure we don't try to print more menu items than exist in the + // active menu. + if (i > ((int)activeMenu->menuItems.size() - 1)) + { + strcat (menuStr, "\n"); + continue; + } + + itemSel = (i == selectedItemIndex); + + printItem (activeMenu->menuItems[i], lineStr, itemSel, + paramEditMode && itemSel); + + strncat (menuStr, lineStr, lineLength); + strcat (menuStr, "\n"); + } + + delete[] lineStr; +} + + +void MenbedNavigator::printItem (MenbedMenuItem *item, char *line, bool itemSel, + bool paramSel) +{ + uint8_t i = 0; + int8_t j; + char *tempStr = new char[lineLength]; + char *frontTab, *backTab; + char *subStr = new char[lineLength]; + uint8_t copySize; + + // Clear the line of text + line[0] = '\0'; + + // Iterate over the element in the array of text strings in the provided + // menu item until an empty string is found indicating the end of the text + // that should be printed for the current line. For safety, we assume there + // are a maximum of three element in the array: 1) text before the + // parameter, 2) the parameter, and 3) text after the parameter. + + frontTab = item->text; + while ((strlen (frontTab) > 0) && (i < 3)) + { + backTab = strchr (frontTab, '\t'); + if (backTab == NULL) + { + backTab = frontTab + strlen(frontTab); + i = 3; // force our way out of the while loop + } + + copySize = backTab - frontTab; + if (copySize >= lineLength) + copySize = lineLength - 1; + + strncpy (subStr, frontTab, copySize); + subStr[copySize] = '\0'; + + // If the current string in the array is a printf-style conversion + // specifier for a float, we replace it with the parameter value. + if (checkConvSpec (subStr)) + { + // If the user is currently editing the parameter, print the value + // of the shadow variable tempValue instead of the parameters actual + // value. The tempValue is not copied over to the value field of + // the structure until the user is done editing the parameter. To + // show that the parameter is being edited, we highlight the value + // by inverting the text. + if (paramSel) + { + snprintf (tempStr, lineLength, subStr, item->param->tempVal); + + // We highlight the parameter by inverting the characters on the + // screen. The menu system only allows the standard (0-127) + // ASCII character, so we use the MSB/7th bit of each character + // to indicate that it should be inverted when printed on the + // screen. + for (j=strlen(tempStr) - 1; j>=0; j--) + tempStr[j] |= 0x80; + + } + // If the user is not currently editing the parameter, we display + // the value pointed to by the value field of the param structure. + else + snprintf (tempStr, lineLength, + subStr, item->param->getVal()); + + // Attach the parameter string to the growing line. + strncat (line, tempStr, lineLength); + } + // If the string is not a printf-style conversion specifier for a float, + // simply catenate the string with the growing line of text. + else + { + strncat (line, subStr, lineLength); + } + + frontTab = backTab + 1; + i++; + } + + // Append a space to the very end of the line. The LCD driver looks to the + // last character in the line to determine whether to highlight any + // remaining whitespace after the text ends. This approach causes problems + // when the parameter is the last text on the line and we are in parameter + // modification mode. Without the extra space at the end of the line, the + // LCD controller will highlight the rest of the line even though it is only + // the parameter itself that should be highlighted. + strncat (line, " ", lineLength); + + // If the parameter has not been selected for modification but the menu item + // is currently selected, we highlight the entire line. In the menu system, + // the only allowable character are the standard ASCII codes (0-127). We + // use the (MSB) 7th bit of every character to indicate whether it should be + // highlighted/inverted. + if (!paramSel && itemSel) + { + // Set the MSB of each character to invert it when displayed. + for (j = strlen(line) - 1; j>= 0; j--) + line[j] |= 0x80; + } + + delete[] tempStr; + delete[] subStr; +} + + +// Returns true if the provided string is a printf-style conversion specifier +// for a float (conversion character is f, e, E, g, or G). Otherwise, returns +// false. +bool MenbedNavigator::checkConvSpec (const char *s) +{ + char lastChar; + + // Conversion specifications must begin with a '%'. + if (s[0] != '%') + return false; + + // Identify the last last character in the conversion specification + lastChar = s[strlen(s) - 1]; + + // Check that the last character in the conversion specification is either a + // 'f', 'e', 'E', 'g', or 'G'--the conversion specifiers for floats. If it + // is, the conversion specification is probably a valid conversion + // specification. + if ((lastChar == 'f') || (lastChar == 'e') || (lastChar == 'E') || + (lastChar == 'g') || (lastChar == 'G')) + return true; + + // Otherwise, it is not. + return false; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/menbed/menbedRefresher.cpp Fri May 19 13:07:52 2017 +0000 @@ -0,0 +1,22 @@ +#include "mbed.h" +#include "include/menbedRefresher.h" +#include "include/menbedNavigator.h" + +MenbedRefresher::MenbedRefresher (MenbedNavigator *navigator) : + navigator(navigator), refreshPeriod_us(50000) +{ + ticker.attach_us (navigator, &MenbedNavigator::updateDisplay, refreshPeriod_us); +} + +MenbedRefresher::MenbedRefresher (MenbedNavigator *navigator, uint32_t refreshPeriod_us) : + navigator(navigator), refreshPeriod_us(refreshPeriod_us) +{ + ticker.attach_us (navigator, &MenbedNavigator::updateDisplay, refreshPeriod_us); +} + +void MenbedRefresher::refreshed (void) +{ + // Detatch and then re-attached the ticker to reset it + ticker.detach(); + ticker.attach_us (navigator, &MenbedNavigator::updateDisplay, refreshPeriod_us); +} \ No newline at end of file