diff --git a/platformio.ini b/platformio.ini index cb3284e..3ed92f3 100644 --- a/platformio.ini +++ b/platformio.ini @@ -12,13 +12,13 @@ platform = atmelavr board = pro16MHzatmega328 framework = arduino -upload_protocol = stk500v1 -upload_flags = -P$UPLOAD_PORT -b$UPLOAD_SPEED -board_f_cpu = 1000000L + +;upload_protocol = stk500v1 +;upload_flags = -P$UPLOAD_PORT -b$UPLOAD_SPEED +;upload_speed = 19200 + +board_f_cpu = 16000000L lib_deps = Bounce2 Encoder - -upload_port = COM7 -upload_speed = 19200 \ No newline at end of file diff --git a/src/Config.cpp b/src/Config.cpp index 77acd5f..f88fa33 100644 --- a/src/Config.cpp +++ b/src/Config.cpp @@ -1,6 +1,6 @@ #include "Config.h" -byte LCDCharArrow[8] = { +byte LCDCharArrowRightMap[8] = { B00000, B01000, B01100, @@ -10,3 +10,42 @@ byte LCDCharArrow[8] = { B00000, }; +byte LCDCharArrowLeftMap[8] = { + B00000, + B00100, + B01100, + B11100, + B01100, + B00100, + B00000, +}; + +byte LCDCharArrowRightHollowMap[8] = { + B00000, + B01000, + B00100, + B00010, + B00100, + B01000, + B00000, +}; + +byte LCDCharArrowLeftHollowMap[8] = { + B00000, + B00100, + B01000, + B10000, + B01000, + B00100, + B00000, +}; + +byte LCDCharUpDownMap[8] = { + B00000, + B00100, + B01110, + B00000, + B01110, + B00100, + B00000, +}; diff --git a/src/Config.h b/src/Config.h index d69e990..3ffe9d5 100644 --- a/src/Config.h +++ b/src/Config.h @@ -28,6 +28,16 @@ static const int LargeStep = 10; static const int MenuTimeout = 2000; -extern byte LCDCharArrow[8]; +static const uint8_t LCDCharArrowRight = 0; +static const uint8_t LCDCharArrowLeft = 1; +static const uint8_t LCDCharArrowRightHollow = 2; +static const uint8_t LCDCharArrowLeftHollow = 3; +static const uint8_t LCDCharUpDown = 4; + +extern byte LCDCharArrowRightMap[8]; +extern byte LCDCharArrowLeftMap[8]; +extern byte LCDCharArrowRightHollowMap[8]; +extern byte LCDCharArrowLeftHollowMap[8]; +extern byte LCDCharUpDownMap[8]; #endif diff --git a/src/ExposureTimer.cpp b/src/ExposureTimer.cpp index 06d4160..907a7a3 100644 --- a/src/ExposureTimer.cpp +++ b/src/ExposureTimer.cpp @@ -16,3 +16,11 @@ void StartExposureTimer(unsigned long currentTime) ExposureTimerStart = currentTime; } + +String FormatTime(unsigned int Time) +{ + String minutes = String(ExposureTime / 60); + String seconds = String(ExposureTime % 60); + + return minutes + ':' + (seconds.length() == 1 ? '0' + seconds : seconds); +} \ No newline at end of file diff --git a/src/ExposureTimer.h b/src/ExposureTimer.h index c35652d..62a89b6 100644 --- a/src/ExposureTimer.h +++ b/src/ExposureTimer.h @@ -10,4 +10,6 @@ extern unsigned long ExposureTimerStart; void ResetExposureTime(); void StartExposureTimer(unsigned long currentTime); +String FormatTime(unsigned int Time); + #endif diff --git a/src/Screen/BaseMenuScreen.cpp b/src/Screen/BaseMenuScreen.cpp new file mode 100644 index 0000000..ae6bf78 --- /dev/null +++ b/src/Screen/BaseMenuScreen.cpp @@ -0,0 +1,119 @@ +#include "Screen/BaseMenuScreen.h" +#include "Config.h" +#include "Buzzer.h" + + +void BaseMenuScreen::setEnableMenuScroll(bool value) +{ + if (value != mEnableMenuScroll) + { + mEnableMenuScroll = value; + printScrollIndicators(); + } +} + + +void BaseMenuScreen::onShow() +{ + printTitle(); + printScrollIndicators(); + printValue(); +} + + +void BaseMenuScreen::onHide() +{ +} + + +void BaseMenuScreen::printTitle() +{ + LiquidCrystal* display = getDisplay(); + + const char* title = getTitle(); + uint8_t titleLength = strlen(title); + uint8_t maxWidth = LCDWidth - 2; + + display->setCursor(1, 0); + + if (titleLength >= maxWidth) + { + // Title too long, cut off + char* character = (char*)title; + for (uint8_t i = 0; i < maxWidth; i++) + { + display->write(byte(*character)); + character++; + } + } + else + { + // Center title + uint8_t offset = (maxWidth - titleLength) / 2; + + for (uint8_t i = 0; i < offset; i++) + display->write(' '); + + display->print(title); + offset += titleLength; + + while (offset < LCDWidth - 2) + { + display->print(' '); + offset++; + } + } +} + + +void BaseMenuScreen::printScrollIndicators() +{ + LiquidCrystal* display = getDisplay(); + + display->setCursor(0, 0); + if (hasPrevious()) + display->write(getEnableMenuScroll() ? LCDCharArrowLeft : LCDCharArrowLeftHollow); + else + display->write(' '); + + display->setCursor(LCDWidth - 1, 0); + if (hasNext()) + display->write(getEnableMenuScroll() ? LCDCharArrowRight : LCDCharArrowRightHollow); + else + display->write(' '); +} + + +void BaseMenuScreen::printValue() +{ + LiquidCrystal* display = getDisplay(); + + display->setCursor(0, 1); + for (uint8_t x = 0; x < LCDWidth; x++) + display->write(' '); +} + + + +void BaseMenuScreen::onEncoder(long lastPosition, long newPosition) +{ + if (mEnableMenuScroll) + { + if (newPosition > lastPosition) + { + if (hasNext()) + { + buzzSelect(); + gotoNext(); + } + } + else + { + if (hasPrevious()) + { + buzzSelect(); + gotoPrevious(); + } + } + } +} diff --git a/src/Screen/BaseMenuScreen.h b/src/Screen/BaseMenuScreen.h new file mode 100644 index 0000000..6454f6e --- /dev/null +++ b/src/Screen/BaseMenuScreen.h @@ -0,0 +1,41 @@ +#ifndef __BaseMenuScreen +#define __BaseMenuScreen + +#include +#include "ScreenManager.h" + +/* + * Base menu screen + * Provides the base for a menu screen, allows scrolling to + * the previous or next menu screen or performs an action. + */ +class BaseMenuScreen : public BaseScreen +{ + private: + bool mEnableMenuScroll = true; + + protected: + bool getEnableMenuScroll() { return mEnableMenuScroll; } + void setEnableMenuScroll(bool value); + + virtual bool hasPrevious() = 0; + virtual bool hasNext() = 0; + + virtual const char* getTitle() = 0; + virtual void gotoPrevious() {} + virtual void gotoNext() {} + + void printTitle(); + void printScrollIndicators(); + virtual void printValue(); + + public: + BaseMenuScreen(ScreenManager* screenManager) : BaseScreen(screenManager) { } + + virtual void onShow(); + virtual void onHide(); + + virtual void onEncoder(long lastPosition, long newPosition); +}; + +#endif \ No newline at end of file diff --git a/src/Screen/ScreenCountdown.cpp b/src/Screen/CountdownScreen.cpp similarity index 59% rename from src/Screen/ScreenCountdown.cpp rename to src/Screen/CountdownScreen.cpp index f19290f..2d4a2cc 100644 --- a/src/Screen/ScreenCountdown.cpp +++ b/src/Screen/CountdownScreen.cpp @@ -1,18 +1,21 @@ -#include "ScreenCountdown.h" -#include "ScreenSetTime.h" +#include "CountdownScreen.h" +#include "Screen/SetTimeScreen.h" #include "ExposureTimer.h" #include "Config.h" #include "Buzzer.h" -void ScreenCountdown::printRemainingTime() +void CountdownScreen::printRemainingTime() { getDisplay()->setCursor(0, 1); - printTime(ExposureTime - ((getCurrentTime() - ExposureTimerStart) / 1000)); + String time = FormatTime(ExposureTime - ((getCurrentTime() - ExposureTimerStart) / 1000)); + + // TODO blank out, center, etc + getDisplay()->print(time); } -void ScreenCountdown::onShow() +void CountdownScreen::onShow() { mLastDisplayed = -1; @@ -24,27 +27,27 @@ void ScreenCountdown::onShow() } -void ScreenCountdown::onHide() +void CountdownScreen::onHide() { digitalWrite(PinLED, LOW); } -void ScreenCountdown::onButton() +void CountdownScreen::onButton() { // TODO Confirmation? buzzClick(); - getScreenManager()->show(); + getScreenManager()->show(); } -void ScreenCountdown::onEncoder(long lastPosition, long newPosition) +void CountdownScreen::onEncoder(long lastPosition, long newPosition) { // TODO Allow adding / removing time? } -void ScreenCountdown::onTick() +void CountdownScreen::onTick() { long elapsed = (getCurrentTime() - ExposureTimerStart) / 1000; @@ -59,7 +62,7 @@ void ScreenCountdown::onTick() buzzCompleted(); ExposureTimerStart = 0; - getScreenManager()->show(); + getScreenManager()->show(); } else if (elapsed != mLastDisplayed) { diff --git a/src/Screen/ScreenCountdown.h b/src/Screen/CountdownScreen.h similarity index 66% rename from src/Screen/ScreenCountdown.h rename to src/Screen/CountdownScreen.h index 48cb77b..9927cda 100644 --- a/src/Screen/ScreenCountdown.h +++ b/src/Screen/CountdownScreen.h @@ -1,5 +1,5 @@ -#ifndef __ScreenCountdown -#define __ScreenCountdown +#ifndef __CountdownScreen +#define __CountdownScreen #include "ScreenManager.h" @@ -7,20 +7,20 @@ * Countdown screen * Shows the remaining time. */ -class ScreenCountdown : public BaseScreen +class CountdownScreen : public BaseScreen { private: int mLastDisplayed; - + protected: void printRemainingTime(); - + public: - ScreenCountdown(ScreenManager* screenManager) : BaseScreen(screenManager) { } - + CountdownScreen(ScreenManager* screenManager) : BaseScreen(screenManager) { } + void onShow(); void onHide(); - + void onButton(); void onEncoder(long lastPosition, long newPosition); void onTick(); diff --git a/src/Screen/IntensityScreen.cpp b/src/Screen/IntensityScreen.cpp new file mode 100644 index 0000000..99c58f5 --- /dev/null +++ b/src/Screen/IntensityScreen.cpp @@ -0,0 +1,84 @@ +#include "Screen/IntensityScreen.h" +#include "Screen/SetTimeScreen.h" +#include "Screen/StartScreen.h" +#include "ExposureTimer.h" +#include "Buzzer.h" +#include "Config.h" + + +void IntensityScreen::printValue() +{ + LiquidCrystal* display = getDisplay(); + display->setCursor(0, 1); + + String intensity = "100%"; + uint8_t offset = (LCDWidth - intensity.length()) / 2; + + for (uint8_t space = 0; space < offset; space++) + display->print(' '); + + display->print(intensity); + offset += intensity.length(); + + if (getEditMode()) + { + display->write(LCDCharUpDown); + offset++; + } + + for (uint8_t space = offset; space < LCDWidth; space++) + display->print(' '); +} + + +void IntensityScreen::gotoPrevious() +{ + buzzSelect(); + getScreenManager()->show(); +} + + +void IntensityScreen::gotoNext() +{ + buzzSelect(); + getScreenManager()->show(); +} + + +void IntensityScreen::onHide() +{ +} + + +void IntensityScreen::onButton() +{ + buzzSelect(); + setEditMode(!getEditMode()); + printValue(); +} + + +void IntensityScreen::onEncoder(long lastPosition, long newPosition) +{ + if (getEditMode()) + { + buzzSelect(); + +/* + if (newPosition > lastPosition) + ExposureTime += ExposureTime >= LargeStepTreshold ? LargeStep : SmallStep; + else if (ExposureTime > 0) + ExposureTime -= ExposureTime > LargeStepTreshold ? LargeStep : SmallStep; + */ + + printValue(); + } + else + BaseMenuScreen::onEncoder(lastPosition, newPosition); +} + + +void IntensityScreen::onTick() +{ +} + diff --git a/src/Screen/IntensityScreen.h b/src/Screen/IntensityScreen.h new file mode 100644 index 0000000..42de608 --- /dev/null +++ b/src/Screen/IntensityScreen.h @@ -0,0 +1,36 @@ +#ifndef __IntensityScreen +#define __IntensityScreen + +#include "ScreenManager.h" +#include "Screen/BaseMenuScreen.h" + +/* + * Intensity screen + * Allows changing of the intensity. + */ +class IntensityScreen : public BaseMenuScreen +{ + protected: + inline bool getEditMode() { return !getEnableMenuScroll(); } + inline void setEditMode(bool value) { setEnableMenuScroll(!value); } + + bool hasPrevious() { return true; } + bool hasNext() { return true; } + + const char* getTitle() { return "Intensity"; } + void gotoPrevious(); + void gotoNext(); + + void printValue(); + + public: + IntensityScreen(ScreenManager* screenManager) : BaseMenuScreen(screenManager) { } + + void onHide(); + + void onButton(); + void onEncoder(long lastPosition, long newPosition); + void onTick(); +}; + +#endif diff --git a/src/Screen/ScreenMenu.cpp b/src/Screen/ScreenMenu.cpp deleted file mode 100644 index e677a39..0000000 --- a/src/Screen/ScreenMenu.cpp +++ /dev/null @@ -1,100 +0,0 @@ -#include "ScreenMenu.h" -#include "ScreenSetTime.h" -#include "ScreenCountdown.h" -#include "ExposureTimer.h" -#include "Config.h" -#include "Buzzer.h" - - -void ScreenMenu::updateLastActivity() -{ - mLastActivity = getCurrentTime(); -} - - -void ScreenMenu::printExposureTime() -{ - getDisplay()->setCursor(0, 1); - printTime(ExposureTime); -} - - -void ScreenMenu::printMenuCursor() -{ - getDisplay()->setCursor(0, 0); - getDisplay()->write(mSelected == 0 ? (byte)0 : ' '); - - getDisplay()->setCursor(9, 0); - getDisplay()->write(mSelected == 1 ? (byte)0 : ' '); -} - - -void ScreenMenu::onShow() -{ - updateLastActivity(); - mSelected = 0; - - getDisplay()->setCursor(0, 0); - getDisplay()->print(" Start Reset "); - - printMenuCursor(); - printExposureTime(); -} - - -void ScreenMenu::onHide() -{ -} - - -void ScreenMenu::onButton() -{ - buzzClick(); - - switch (mSelected) - { - case 0: - digitalWrite(PinLED, HIGH); - - StartExposureTimer(getCurrentTime()); - getScreenManager()->show(); - break; - - case 1: - ResetExposureTime(); - getScreenManager()->show(); - } -} - - -void ScreenMenu::onEncoder(long lastPosition, long newPosition) -{ - updateLastActivity(); - - if (newPosition > lastPosition) - { - if (mSelected < 1) - { - buzzSelect(); - mSelected++; - printMenuCursor(); - } - } - else - { - if (mSelected > 0) - { - buzzSelect(); - mSelected--; - printMenuCursor(); - } - } -} - - -void ScreenMenu::onTick() -{ - if (getCurrentTime() - mLastActivity >= MenuTimeout) - getScreenManager()->show(); -} - diff --git a/src/Screen/ScreenMenu.h b/src/Screen/ScreenMenu.h deleted file mode 100644 index cbf2764..0000000 --- a/src/Screen/ScreenMenu.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef __ScreenMenu -#define __ScreenMenu - -#include "ScreenManager.h" - -/* - * Menu screen - * Allows starting the timer or resetting the time to the last used value. - */ -class ScreenMenu : public BaseScreen -{ - private: - int mSelected; - unsigned long mLastActivity; - - protected: - void updateLastActivity(); - - void printExposureTime(); - void printMenuCursor(); - - public: - ScreenMenu(ScreenManager* screenManager) : BaseScreen(screenManager) { } - - void onShow(); - void onHide(); - - void onButton(); - void onEncoder(long lastPosition, long newPosition); - void onTick(); -}; - -#endif diff --git a/src/Screen/ScreenSetTime.cpp b/src/Screen/ScreenSetTime.cpp deleted file mode 100644 index 1f0f3ed..0000000 --- a/src/Screen/ScreenSetTime.cpp +++ /dev/null @@ -1,52 +0,0 @@ -#include "ScreenSetTime.h" -#include "Screen/ScreenMenu.h" -#include "ExposureTimer.h" -#include "Buzzer.h" -#include "Config.h" - - -void ScreenSetTime::printExposureTime() -{ - getDisplay()->setCursor(0, 1); - printTime(ExposureTime); -} - - -void ScreenSetTime::onShow() -{ - getDisplay()->setCursor(0, 0); - getDisplay()->print("Exposure time: "); - - printExposureTime(); -} - - -void ScreenSetTime::onHide() -{ -} - - -void ScreenSetTime::onButton() -{ - buzzClick(); - getScreenManager()->show(); -} - - -void ScreenSetTime::onEncoder(long lastPosition, long newPosition) -{ - buzzSelect(); - - if (newPosition > lastPosition) - ExposureTime += ExposureTime >= LargeStepTreshold ? LargeStep : SmallStep; - else if (ExposureTime > 0) - ExposureTime -= ExposureTime > LargeStepTreshold ? LargeStep : SmallStep; - - printExposureTime(); -} - - -void ScreenSetTime::onTick() -{ -} - diff --git a/src/Screen/ScreenSetTime.h b/src/Screen/ScreenSetTime.h deleted file mode 100644 index fca59e9..0000000 --- a/src/Screen/ScreenSetTime.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef __ScreenSetTime -#define __ScreenSetTime - -#include "ScreenManager.h" - -/* - * Time screen - * Allows changing of the exposure time. Pressing the button will switch to the menu. - */ -class ScreenSetTime : public BaseScreen -{ - protected: - void printExposureTime(); - - public: - ScreenSetTime(ScreenManager* screenManager) : BaseScreen(screenManager) { } - - void onShow(); - void onHide(); - - void onButton(); - void onEncoder(long lastPosition, long newPosition); - void onTick(); -}; - -#endif diff --git a/src/Screen/SetTimeScreen.cpp b/src/Screen/SetTimeScreen.cpp new file mode 100644 index 0000000..2e7f0fd --- /dev/null +++ b/src/Screen/SetTimeScreen.cpp @@ -0,0 +1,74 @@ +#include "Screen/SetTimeScreen.h" +#include "Screen/IntensityScreen.h" +#include "ExposureTimer.h" +#include "Buzzer.h" +#include "Config.h" + + +void SetTimeScreen::printValue() +{ + LiquidCrystal* display = getDisplay(); + display->setCursor(0, 1); + + String time = FormatTime(ExposureTime); + uint8_t offset = (LCDWidth - time.length()) / 2; + + for (uint8_t space = 0; space < offset; space++) + display->print(' '); + + display->print(time); + offset += time.length(); + + if (getEditMode()) + { + display->write(LCDCharUpDown); + offset++; + } + + for (uint8_t space = offset; space < LCDWidth; space++) + display->print(' '); +} + + +void SetTimeScreen::gotoNext() +{ + buzzSelect(); + getScreenManager()->show(); +} + + +void SetTimeScreen::onHide() +{ +} + + +void SetTimeScreen::onButton() +{ + buzzSelect(); + setEditMode(!getEditMode()); + printValue(); +} + + +void SetTimeScreen::onEncoder(long lastPosition, long newPosition) +{ + if (getEditMode()) + { + buzzSelect(); + + if (newPosition > lastPosition) + ExposureTime += ExposureTime >= LargeStepTreshold ? LargeStep : SmallStep; + else if (ExposureTime > 0) + ExposureTime -= ExposureTime > LargeStepTreshold ? LargeStep : SmallStep; + + printValue(); + } + else + BaseMenuScreen::onEncoder(lastPosition, newPosition); +} + + +void SetTimeScreen::onTick() +{ +} + diff --git a/src/Screen/SetTimeScreen.h b/src/Screen/SetTimeScreen.h new file mode 100644 index 0000000..464d843 --- /dev/null +++ b/src/Screen/SetTimeScreen.h @@ -0,0 +1,35 @@ +#ifndef __SetTimeScreen +#define __SetTimeScreen + +#include "ScreenManager.h" +#include "Screen/BaseMenuScreen.h" + +/* + * Time screen + * Allows changing of the exposure time. + */ +class SetTimeScreen : public BaseMenuScreen +{ + protected: + inline bool getEditMode() { return !getEnableMenuScroll(); } + inline void setEditMode(bool value) { setEnableMenuScroll(!value); } + + bool hasPrevious() { return false; } + bool hasNext() { return true; } + + const char* getTitle() { return "Time"; } + void gotoNext(); + + void printValue(); + + public: + SetTimeScreen(ScreenManager* screenManager) : BaseMenuScreen(screenManager) { } + + void onHide(); + + void onButton(); + void onEncoder(long lastPosition, long newPosition); + void onTick(); +}; + +#endif diff --git a/src/Screen/StartScreen.cpp b/src/Screen/StartScreen.cpp new file mode 100644 index 0000000..c4f2e77 --- /dev/null +++ b/src/Screen/StartScreen.cpp @@ -0,0 +1,30 @@ +#include "Screen/StartScreen.h" +#include "Screen/IntensityScreen.h" +#include "ExposureTimer.h" +#include "Buzzer.h" +#include "Config.h" + + +void StartScreen::gotoPrevious() +{ + buzzSelect(); + getScreenManager()->show(); +} + + +void StartScreen::onHide() +{ +} + + +void StartScreen::onButton() +{ + buzzSelect(); + //setEditMode(!getEditMode()); +} + + +void StartScreen::onTick() +{ +} + diff --git a/src/Screen/StartScreen.h b/src/Screen/StartScreen.h new file mode 100644 index 0000000..7369150 --- /dev/null +++ b/src/Screen/StartScreen.h @@ -0,0 +1,29 @@ +#ifndef __StartScreen +#define __StartScreen + +#include "ScreenManager.h" +#include "Screen/BaseMenuScreen.h" + +/* + * Start screen + * Allows starting the exposure. + */ +class StartScreen : public BaseMenuScreen +{ + protected: + bool hasPrevious() { return true; } + bool hasNext() { return false; } + + const char* getTitle() { return "Start"; } + void gotoPrevious(); + + public: + StartScreen(ScreenManager* screenManager) : BaseMenuScreen(screenManager) { } + + void onHide(); + + void onButton(); + void onTick(); +}; + +#endif diff --git a/src/ScreenManager.cpp b/src/ScreenManager.cpp index f637161..287e2b5 100644 --- a/src/ScreenManager.cpp +++ b/src/ScreenManager.cpp @@ -17,22 +17,3 @@ LiquidCrystal* BaseScreen::getDisplay() return mScreenManager->getDisplay(); } - -void BaseScreen::printTime(int value) -{ - String minutes = String(value / 60); - String seconds = String(value % 60); - int textLength = minutes.length() + 1 + 2; - - getDisplay()->print(minutes); - getDisplay()->print(":"); - - if (seconds.length() == 1) - getDisplay()->print("0"); - - getDisplay()->print(seconds); - - for (int space = textLength + 1; space < LCDWidth; space++) - getDisplay()->print(" "); -} - diff --git a/src/ScreenManager.h b/src/ScreenManager.h index f0340b8..f1c4b85 100644 --- a/src/ScreenManager.h +++ b/src/ScreenManager.h @@ -17,9 +17,6 @@ class BaseScreen unsigned long getCurrentTime(); LiquidCrystal* getDisplay(); - - void printTime(int value); - public: BaseScreen(ScreenManager* screenManager) { diff --git a/src/main.cpp b/src/main.cpp index 2a04dff..979b7ac 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,7 +4,7 @@ #include #include "Config.h" #include "ScreenManager.h" -#include "Screen/ScreenSetTime.h" +#include "Screen/SetTimeScreen.h" #include "Buzzer.h" #include "ExposureTimer.h" @@ -36,11 +36,15 @@ void setup() ResetExposureTime(); - lcd.createChar(0, LCDCharArrow); + lcd.createChar(LCDCharArrowRight, LCDCharArrowRightMap); + lcd.createChar(LCDCharArrowLeft, LCDCharArrowLeftMap); + lcd.createChar(LCDCharArrowRightHollow, LCDCharArrowRightHollowMap); + lcd.createChar(LCDCharArrowLeftHollow, LCDCharArrowLeftHollowMap); + lcd.createChar(LCDCharUpDown, LCDCharUpDownMap); lcd.begin(LCDWidth, LCDHeight); screenManager = new ScreenManager(&lcd, ¤tTime); - screenManager->show(); + screenManager->show(); buzzStartup(); }