From 2e1a17d60a71ae78868625bb545aebe83380a86b Mon Sep 17 00:00:00 2001 From: Mark van Renswoude Date: Thu, 7 Dec 2017 23:43:24 +0100 Subject: [PATCH] Fixed menu and editing --- src/Config.h | 37 +++++----- src/display.cpp | 156 +++++++++++++++++++++++++++++++++-------- src/display.h | 7 +- src/menu/intensity.cpp | 51 +++++--------- src/menu/start.cpp | 39 +++++++++++ src/menu/start.h | 19 +++++ src/menu/time.cpp | 54 ++++++-------- src/screen.h | 2 +- src/screen/menu.cpp | 59 ++++++++++++++-- src/state.cpp | 25 +++++-- src/state.h | 8 +-- 11 files changed, 321 insertions(+), 136 deletions(-) create mode 100644 src/menu/start.cpp create mode 100644 src/menu/start.h diff --git a/src/Config.h b/src/Config.h index 2b45816..8552536 100644 --- a/src/Config.h +++ b/src/Config.h @@ -3,27 +3,26 @@ #include -const int PinLCDRS = 7; -const int PinLCDEN = 8; -const int PinLCDDB4 = 9; -const int PinLCDDB5 = 10; -const int PinLCDDB6 = 11; -const int PinLCDDB7 = 12; -const int PinEncoderClock = 2; -const int PinEncoderData = 3; -const int PinButton = 4; -const int PinBuzzer = 5; -const int PinLED = 6; +const uint8_t PinLCDRS = 7; +const uint8_t PinLCDEN = 8; +const uint8_t PinLCDDB4 = 9; +const uint8_t PinLCDDB5 = 10; +const uint8_t PinLCDDB6 = 11; +const uint8_t PinLCDDB7 = 12; +const uint8_t PinEncoderClock = 2; +const uint8_t PinEncoderData = 3; +const uint8_t PinButton = 4; +const uint8_t PinBuzzer = 5; +const uint8_t PinLED = 6; -const int LCDWidth = 16; -const int LCDHeight = 2; +const uint8_t LCDWidth = 16; +const uint8_t LCDHeight = 2; -const int EncoderSensitivity = 4; -const int SmallStep = 1; -const int LargeStepTreshold = 60; -const int LargeStep = 10; - -const int MenuTimeout = 2000; +const uint8_t EncoderSensitivity = 4; +const uint8_t SmallStep = 1; +const uint8_t LargeStepTreshold = 60; +const uint8_t LargeStep = 10; +const uint8_t IntensityStep = 1; const uint32_t DefaultExposureTime = 60; diff --git a/src/display.cpp b/src/display.cpp index bf10138..a677338 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -4,54 +4,150 @@ void LCDPrintLine(LiquidCrystal* display, uint8_t y, const char* value, uint8_t margin) { + display->setCursor(margin, y); + uint8_t width = LCDWidth - (2 * margin); + + if (value != NULL) + { + uint8_t length = strlen(value); + + if (length >= width) + { + char* character = (char*)value; + for (uint8_t i = 0; i < width; i++) + { + display->write(byte(*character)); + character++; + } + } + else + { + display->print(value); + width -= length; + + while (width > 0) + { + display->write(' '); + width--; + } + } + } + else + { + for (uint8_t i = 0; i < width; i++) + display->write(' '); + } } void LCDPrintLineCentered(LiquidCrystal* display, uint8_t y, const char* value, uint8_t margin) { -/* - const char* title = mItems[mSelected]->getTitle(); - uint8_t titleLength = strlen(title); - uint8_t maxWidth = LCDWidth - 2; + display->setCursor(margin, y); - display->setCursor(1, 0); + uint8_t width = LCDWidth - (2 * margin); - if (titleLength >= maxWidth) + if (value != NULL) { - // Title too long, cut off - char* character = (char*)title; - for (uint8_t i = 0; i < maxWidth; i++) + uint8_t length = strlen(value); + + if (length >= width) { - display->write(byte(*character)); - character++; + char* character = (char*)value; + for (uint8_t i = 0; i < width; i++) + { + display->write(byte(*character)); + character++; + } + } + else + { + uint8_t offset = (width - length) / 2; + width -= offset; + + for (uint8_t i = 0; i < offset; i++) + display->write(' '); + + display->print(value); + width -= length; + + while (width > 0) + { + display->write(' '); + width--; + } } } else { - // Center title - uint8_t offset = (maxWidth - titleLength) / 2; - - for (uint8_t i = 0; i < offset; i++) + for (uint8_t i = 0; i < width; i++) display->write(' '); - - display->print(title); - offset += titleLength; - - while (offset < LCDWidth - 2) - { - display->print(' '); - offset++; - } } -*/ } -const char* FormatTime(unsigned int time) +const char* UniqueString(const char* value) { - String minutes = String(time / 60); - String seconds = String(time % 60); + char* result = new char[strlen(value) + 1]; + return strcpy(result, value); +} - return (minutes + ':' + (seconds.length() == 1 ? '0' + seconds : seconds)).c_str(); -} \ No newline at end of file + +#define ASCII0 0x30 + + +const char* FormatTime(uint16_t time) +{ + uint16_t minutes = time / 60; + uint8_t seconds = time % 60; + + char* value = new char[9]; + itoa(minutes, value, 10); + + uint8_t length = strlen(value); + value[length] = ':'; length++; + + value[length] = (seconds / 10) + ASCII0; length++; + value[length] = (seconds % 10) + ASCII0; length++; + value[length] = 0; + + return value; +} + + +const char* FormatPercentage(uint8_t percentage) +{ + char* value = new char[6]; + + + itoa(percentage, value, 10); + + uint8_t length = strlen(value); + value[length] = '%'; + value[length + 1] = 0; + + return value; +} + + +const char* FormatPercentageFixedWidth(uint8_t percentage) +{ + char* value = new char[5]; + + if (percentage > 99) + { + value[0] = '1'; + value[1] = '0'; + } + else + { + value[0] = ' '; + value[1] = percentage > 9 ? (percentage / 10) + ASCII0 : ' '; + } + + value[2] = (percentage % 10) + ASCII0; + value[3] = '%'; + value[4] = 0; + + return value; +} diff --git a/src/display.h b/src/display.h index 993a01a..ca07d92 100644 --- a/src/display.h +++ b/src/display.h @@ -4,10 +4,13 @@ #include #include - void LCDPrintLine(LiquidCrystal* display, uint8_t y, const char* value, uint8_t margin = 0); void LCDPrintLineCentered(LiquidCrystal* display, uint8_t y, const char* value, uint8_t margin = 0); -const char* FormatTime(unsigned int time); +const char* UniqueString(const char* value); + +const char* FormatTime(uint16_t time); +const char* FormatPercentage(uint8_t percentage); +const char* FormatPercentageFixedWidth(uint8_t percentage); #endif \ No newline at end of file diff --git a/src/menu/intensity.cpp b/src/menu/intensity.cpp index 6fb26f9..3a57c7b 100644 --- a/src/menu/intensity.cpp +++ b/src/menu/intensity.cpp @@ -1,54 +1,41 @@ #include "intensity.h" +#include "config.h" #include "state.h" +#include "display.h" +#include "buzzer.h" -/* - 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(' '); - -*/ const char* IntensityMenuItem::getTitle() { - return "Intensity"; + return UniqueString("Intensity"); } const char* IntensityMenuItem::getValue() { - char value[5]; - itoa(GetExposureIntensity(), value, 10); - - uint8_t length = strlen(value); - value[length] = '%'; - value[length + 1] = 0; - - return value; + return FormatPercentageFixedWidth(GetExposureIntensity()); } void IntensityMenuItem::incValue() { + uint16_t exposureIntensity = GetExposureIntensity(); + + if (exposureIntensity < 100) + { + SetExposureIntensity(exposureIntensity + IntensityStep); + Buzzer::select(); + } } void IntensityMenuItem::decValue() { + uint16_t exposureIntensity = GetExposureIntensity(); + + if (exposureIntensity > IntensityStep) + { + SetExposureIntensity(exposureIntensity - IntensityStep); + Buzzer::select(); + } } \ No newline at end of file diff --git a/src/menu/start.cpp b/src/menu/start.cpp new file mode 100644 index 0000000..d7893a9 --- /dev/null +++ b/src/menu/start.cpp @@ -0,0 +1,39 @@ +#include "start.h" +#include "state.h" +#include "display.h" + +const char* StartMenuItem::getTitle() +{ + return UniqueString("Start"); +} + + +const char* StartMenuItem::getValue() +{ + const char* time = FormatTime(GetExposureTime()); + const char* intensity = FormatPercentage(GetExposureIntensity()); + + uint8_t timeLength = strlen(time); + uint8_t intensityLength = strlen(intensity); + + char* value = new char[timeLength + 3 + intensityLength + 1]; + + strcpy(value, time); + delete[] time; + + uint8_t offset = timeLength; + + value[offset] = ' '; offset++; + value[offset] = '@'; offset++; + value[offset] = ' '; offset++; + + strcpy(value + offset, intensity); + delete[] intensity; + + return value; +} + + +void StartMenuItem::execute() +{ +} diff --git a/src/menu/start.h b/src/menu/start.h new file mode 100644 index 0000000..036aced --- /dev/null +++ b/src/menu/start.h @@ -0,0 +1,19 @@ +#ifndef __startmenuitem +#define __startmenuitem + +#include "screen/menu.h" + +class StartMenuItem : public MenuItem +{ + public: + StartMenuItem() : MenuItem() { } + + const char* getTitle(); + const char* getValue(); + + bool editable() { return false; } + + void execute(); +}; + +#endif \ No newline at end of file diff --git a/src/menu/time.cpp b/src/menu/time.cpp index 47de1fc..ad6640e 100644 --- a/src/menu/time.cpp +++ b/src/menu/time.cpp @@ -1,54 +1,40 @@ #include "time.h" - -/* - 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(' '); - - - - - - if (newPosition > lastPosition) - ExposureTime += ExposureTime >= LargeStepTreshold ? LargeStep : SmallStep; - else if (ExposureTime > 0) - ExposureTime -= ExposureTime > LargeStepTreshold ? LargeStep : SmallStep; -*/ +#include "config.h" +#include "state.h" +#include "display.h" +#include "buzzer.h" const char* TimeMenuItem::getTitle() { - return "Time"; + return UniqueString("Time"); } const char* TimeMenuItem::getValue() { - return NULL; + return FormatTime(GetExposureTime()); } void TimeMenuItem::incValue() { + uint16_t exposureTime = GetExposureTime(); + + if (exposureTime < (uint16_t)-1) + { + SetExposureTime(exposureTime + (exposureTime >= LargeStepTreshold ? LargeStep : SmallStep)); + Buzzer::select(); + } } void TimeMenuItem::decValue() { + uint16_t exposureTime = GetExposureTime(); + + if (exposureTime > SmallStep) + { + SetExposureTime(exposureTime - (exposureTime > LargeStepTreshold ? LargeStep : SmallStep)); + Buzzer::select(); + } } \ No newline at end of file diff --git a/src/screen.h b/src/screen.h index e76621b..d06ec54 100644 --- a/src/screen.h +++ b/src/screen.h @@ -72,7 +72,7 @@ class ScreenManager if (mCurrent != NULL) { mCurrent->onHide(); - delete(mCurrent); + delete mCurrent; } mCurrent = new T(this); diff --git a/src/screen/menu.cpp b/src/screen/menu.cpp index e6b7b4f..80f7c97 100644 --- a/src/screen/menu.cpp +++ b/src/screen/menu.cpp @@ -3,7 +3,9 @@ #include "buzzer.h" #include "display.h" +#include "menu/start.h" #include "menu/time.h" +#include "menu/intensity.h" MenuScreen::MenuScreen(ScreenManager* screenManager) : BaseScreen(screenManager) @@ -11,9 +13,9 @@ MenuScreen::MenuScreen(ScreenManager* screenManager) : BaseScreen(screenManager) mCount = 3; mItems = new MenuItem*[mCount]; - mItems[0] = new TimeMenuItem(); + mItems[0] = new StartMenuItem(); mItems[1] = new TimeMenuItem(); - mItems[2] = new TimeMenuItem(); + mItems[2] = new IntensityMenuItem(); } @@ -47,7 +49,11 @@ void MenuScreen::printFullUpdate() void MenuScreen::printTitle() { - LCDPrintLineCentered(getDisplay(), 0, mItems[mSelected]->getTitle(), 1); + const char* title = mItems[mSelected]->getTitle(); + LCDPrintLineCentered(getDisplay(), 0, title, 1); + + if (title != NULL) + delete[] title; } @@ -73,21 +79,60 @@ void MenuScreen::printValue() { LiquidCrystal* display = getDisplay(); - display->setCursor(0, 1); - for (uint8_t x = 0; x < LCDWidth; x++) - display->write(' '); + const char* value = mItems[mSelected]->getValue(); + + if (mEditing && value != NULL) + { + uint8_t valueLength = strlen(value); + char* editingValue = new char[valueLength + 5]; + + editingValue[0] = ' '; + editingValue[1] = ' '; + strcpy(editingValue + 2, value); + editingValue[valueLength + 2] = ' '; + editingValue[valueLength + 3] = LCDCharUpDown; + editingValue[valueLength + 4] = 0; + + LCDPrintLineCentered(display, 1, editingValue); + + delete[] editingValue; + } + else + LCDPrintLineCentered(display, 1, value); + + if (value != NULL) + delete[] value; } void MenuScreen::onButton() { + if (mItems[mSelected]->editable()) + { + mEditing = !mEditing; + printScrollIndicators(); + printValue(); + } + else + { + mItems[mSelected]->execute(getScreenManager()); + } } void MenuScreen::onEncoder(long lastPosition, long newPosition) { - if (!mEditing) + if (mEditing) + { + if (newPosition > lastPosition) + mItems[mSelected]->incValue(); + else + mItems[mSelected]->decValue(); + + printValue(); + } + else { if (newPosition > lastPosition) { diff --git a/src/state.cpp b/src/state.cpp index 24ed24f..e0f4bb6 100644 --- a/src/state.cpp +++ b/src/state.cpp @@ -2,20 +2,23 @@ #include "config.h" #include -uint32_t ExposureTime = DefaultExposureTime; +uint16_t ExposureTime = DefaultExposureTime; uint8_t ExposureIntensity = DefaultExposureIntensity; uint32_t ExposureTimerStart = 0; -uint32_t GetExposureTime() +uint16_t GetExposureTime() { return ExposureTime; } -void SetExposureTime(uint32_t value) +void SetExposureTime(uint16_t value) { - ExposureTime = value; + if (value < SmallStep) + ExposureTime = SmallStep; + else + ExposureTime = value; } @@ -27,7 +30,12 @@ uint8_t GetExposureIntensity() void SetExposureIntensity(uint8_t value) { - ExposureIntensity = (value <= 100) ? value : 100; + if (value > 100) + ExposureIntensity = 100; + else if (value < IntensityStep) + ExposureIntensity = IntensityStep; + else + ExposureIntensity = value; } @@ -35,9 +43,12 @@ void LoadSettings() { uint16_t offset = 0; EEPROM.get(offset, ExposureTime); + SetExposureTime(ExposureTime); + offset += sizeof(ExposureTime); EEPROM.get(offset, ExposureIntensity); + SetExposureIntensity(ExposureIntensity); } @@ -51,7 +62,7 @@ void SaveSettings() } -void StartExposureTimer(unsigned long currentTime) +void StartExposureTimer(uint32_t currentTime) { SaveSettings(); ExposureTimerStart = currentTime; @@ -64,7 +75,7 @@ void ResetExposureTimer() } -uint32_t GetExposureTimeRemaining(unsigned long currentTime) +uint16_t GetExposureTimeRemaining(uint32_t currentTime) { uint32_t elapsed = (currentTime - ExposureTimerStart); return elapsed <= ExposureTime ? ExposureTime - elapsed : 0; diff --git a/src/state.h b/src/state.h index 6856305..4d1a0b8 100644 --- a/src/state.h +++ b/src/state.h @@ -3,8 +3,8 @@ #include -uint32_t GetExposureTime(); -void SetExposureTime(uint32_t value); +uint16_t GetExposureTime(); +void SetExposureTime(uint16_t value); uint8_t GetExposureIntensity(); void SetExposureIntensity(uint8_t value); @@ -13,8 +13,8 @@ void SetExposureIntensity(uint8_t value); void LoadSettings(); void SaveSettings(); -void StartExposureTimer(unsigned long currentTime); +void StartExposureTimer(uint32_t currentTime); void ResetExposureTimer(); -uint32_t GetExposureTimeRemaining(unsigned long currentTime); +uint16_t GetExposureTimeRemaining(uint32_t currentTime); #endif