From 0be4b62da9163a2e222b9ae8ed179310e6256e63 Mon Sep 17 00:00:00 2001 From: Mark van Renswoude Date: Fri, 8 Dec 2017 22:32:04 +0100 Subject: [PATCH] Fixed countdown timer Added sound settings Changed edit arrows to indicate for min/max values --- src/Buzzer.cpp | 19 +++++++++----- src/Config.cpp | 20 ++++++++++++++ src/Config.h | 7 ++++- src/main.cpp | 17 +++++++----- src/menu/intensity.cpp | 30 ++++++++++----------- src/menu/intensity.h | 6 +++-- src/menu/sound.cpp | 56 ++++++++++++++++++++++++++++++++++++++++ src/menu/sound.h | 22 ++++++++++++++++ src/menu/start.cpp | 3 ++- src/menu/start.h | 2 +- src/menu/time.cpp | 30 +++++++++++---------- src/menu/time.h | 6 +++-- src/screen.cpp | 2 +- src/screen.h | 10 +++---- src/screen/countdown.cpp | 19 ++++++++++---- src/screen/countdown.h | 2 +- src/screen/menu.cpp | 44 ++++++++++++++++++++++++++----- src/screen/menu.h | 10 ++++--- src/state.cpp | 27 +++++++++++++++++-- src/state.h | 14 ++++++++++ 20 files changed, 274 insertions(+), 72 deletions(-) create mode 100644 src/menu/sound.cpp create mode 100644 src/menu/sound.h diff --git a/src/Buzzer.cpp b/src/Buzzer.cpp index e930d27..59441e3 100644 --- a/src/Buzzer.cpp +++ b/src/Buzzer.cpp @@ -1,6 +1,7 @@ #include "buzzer.h" #include #include "config.h" +#include "state.h" void Buzzer::playNote(uint16_t frequency, uint16_t duration) @@ -13,28 +14,34 @@ void Buzzer::playNote(uint16_t frequency, uint16_t duration) void Buzzer::startup() { - playNote(1000, 50); + if (GetBuzzer() == BuzzerSetting::CompletedButtonStartup) + playNote(1000, 50); } void Buzzer::select() { - playNote(1000, 1); + if (GetBuzzer() <= BuzzerSetting::CompletedButton) + playNote(1000, 1); } void Buzzer::click() { - playNote(1000, 25); + if (GetBuzzer() <= BuzzerSetting::CompletedButton) + playNote(1000, 25); } void Buzzer::completed() { - for (int i = 0; i < 3; i++) + if (GetBuzzer() <= BuzzerSetting::Completed) { - playNote(1000, 250); - delay(500); + for (int i = 0; i < 3; i++) + { + playNote(1000, 250); + delay(500); + } } } diff --git a/src/Config.cpp b/src/Config.cpp index f4a54ba..8ab1b4a 100644 --- a/src/Config.cpp +++ b/src/Config.cpp @@ -49,3 +49,23 @@ uint8_t LCDCharUpDownMap[8] = { B00100, B00000, }; + +uint8_t LCDCharUpMap[8] = { + B00000, + B00100, + B01110, + B00000, + B00000, + B00000, + B00000, +}; + +uint8_t LCDCharDownMap[8] = { + B00000, + B00000, + B00000, + B00000, + B01110, + B00100, + B00000, +}; diff --git a/src/Config.h b/src/Config.h index 8552536..864e056 100644 --- a/src/Config.h +++ b/src/Config.h @@ -15,6 +15,7 @@ const uint8_t PinButton = 4; const uint8_t PinBuzzer = 5; const uint8_t PinLED = 6; +// Note: an LCD size of at least 16x2 is assumed for all text to fit const uint8_t LCDWidth = 16; const uint8_t LCDHeight = 2; @@ -22,7 +23,7 @@ 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 uint8_t IntensityStep = 5; const uint32_t DefaultExposureTime = 60; @@ -33,11 +34,15 @@ const uint8_t LCDCharArrowLeft = 1; const uint8_t LCDCharArrowRightHollow = 2; const uint8_t LCDCharArrowLeftHollow = 3; const uint8_t LCDCharUpDown = 4; +const uint8_t LCDCharUp = 5; +const uint8_t LCDCharDown = 6; extern uint8_t LCDCharArrowRightMap[8]; extern uint8_t LCDCharArrowLeftMap[8]; extern uint8_t LCDCharArrowRightHollowMap[8]; extern uint8_t LCDCharArrowLeftHollowMap[8]; extern uint8_t LCDCharUpDownMap[8]; +extern uint8_t LCDCharUpMap[8]; +extern uint8_t LCDCharDownMap[8]; #endif diff --git a/src/main.cpp b/src/main.cpp index 83df5ca..cdf68ff 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -18,7 +18,7 @@ LiquidCrystal lcd(PinLCDRS, PinLCDEN, PinLCDDB4, PinLCDDB5, PinLCDDB6, PinLCDDB7 #ifndef ResetEEPROM ScreenManager* screenManager; -unsigned long currentTime; +uint32_t currentTime; Encoder encoder(PinEncoderData, PinEncoderClock); Bounce button = Bounce(); @@ -41,6 +41,8 @@ void setup() lcd.createChar(LCDCharArrowRightHollow, LCDCharArrowRightHollowMap); lcd.createChar(LCDCharArrowLeftHollow, LCDCharArrowLeftHollowMap); lcd.createChar(LCDCharUpDown, LCDCharUpDownMap); + lcd.createChar(LCDCharUp, LCDCharUpMap); + lcd.createChar(LCDCharDown, LCDCharDownMap); lcd.begin(LCDWidth, LCDHeight); screenManager = new ScreenManager(&lcd, ¤tTime); @@ -50,7 +52,7 @@ void setup() } -long lastPosition = 0; +int32_t lastPosition = 0; bool isPressed = false; @@ -59,7 +61,7 @@ void loop() currentTime = millis(); button.update(); - long newPosition = encoder.read(); + int32_t newPosition = encoder.read(); if (abs(newPosition - lastPosition) >= EncoderSensitivity) { screenManager->getCurrent()->onEncoder(lastPosition, newPosition); @@ -82,18 +84,21 @@ void loop() #else +#include + void setup() { pinMode(PinBuzzer, OUTPUT); lcd.begin(LCDWidth, LCDHeight); - for (int i = 0 ; i < EEPROM.length() ; i++) + for (uint16_t i = 0 ; i < EEPROM.length() ; i++) { EEPROM.update(i, 0); } - ExposureTime = DefaultExposureTime; - ExposureIntensity = DefaultExposureIntensity; + SetExposureTime(DefaultExposureTime); + SetExposureIntensity(DefaultExposureIntensity); + SetBuzzer(BuzzerSetting::CompletedButtonStartup); SaveSettings(); lcd.setCursor(0, 0); diff --git a/src/menu/intensity.cpp b/src/menu/intensity.cpp index 3a57c7b..224c823 100644 --- a/src/menu/intensity.cpp +++ b/src/menu/intensity.cpp @@ -17,25 +17,25 @@ const char* IntensityMenuItem::getValue() } -void IntensityMenuItem::incValue() +bool IntensityMenuItem::canIncrement() { - uint16_t exposureIntensity = GetExposureIntensity(); - - if (exposureIntensity < 100) - { - SetExposureIntensity(exposureIntensity + IntensityStep); - Buzzer::select(); - } + return GetExposureIntensity() < 100; } -void IntensityMenuItem::decValue() +bool IntensityMenuItem::canDecrement() { - uint16_t exposureIntensity = GetExposureIntensity(); + return GetExposureIntensity() > IntensityStep; +} - if (exposureIntensity > IntensityStep) - { - SetExposureIntensity(exposureIntensity - IntensityStep); - Buzzer::select(); - } + +void IntensityMenuItem::incrementValue() +{ + SetExposureIntensity(GetExposureIntensity() + IntensityStep); +} + + +void IntensityMenuItem::decrementValue() +{ + SetExposureIntensity(GetExposureIntensity() - IntensityStep); } \ No newline at end of file diff --git a/src/menu/intensity.h b/src/menu/intensity.h index f133794..132d73b 100644 --- a/src/menu/intensity.h +++ b/src/menu/intensity.h @@ -13,8 +13,10 @@ class IntensityMenuItem : public MenuItem bool editable() { return true; } - void incValue(); - void decValue(); + bool canIncrement(); + bool canDecrement(); + void incrementValue(); + void decrementValue(); }; #endif \ No newline at end of file diff --git a/src/menu/sound.cpp b/src/menu/sound.cpp new file mode 100644 index 0000000..83f4262 --- /dev/null +++ b/src/menu/sound.cpp @@ -0,0 +1,56 @@ +#include "sound.h" +#include "config.h" +#include "state.h" +#include "display.h" +#include "buzzer.h" + + +const char* SoundMenuItem::getTitle() +{ + return UniqueString("Sound"); +} + + +const char* SoundMenuItem::getValue() +{ + switch (GetBuzzer()) + { + case BuzzerSetting::CompletedButtonStartup: + return UniqueString("All"); + + case BuzzerSetting::CompletedButton: + return UniqueString("Alarm/button"); + + case BuzzerSetting::Completed: + return UniqueString("Alarm only"); + + case BuzzerSetting::None: + return UniqueString("None"); + } + + return NULL; +} + + +bool SoundMenuItem::canIncrement() +{ + return GetBuzzer() > BuzzerSetting::First; +} + + +bool SoundMenuItem::canDecrement() +{ + return GetBuzzer() < BuzzerSetting::Last; +} + + +void SoundMenuItem::incrementValue() +{ + SetBuzzer((BuzzerSetting)((uint8_t)GetBuzzer() - 1)); +} + + +void SoundMenuItem::decrementValue() +{ + SetBuzzer((BuzzerSetting)((uint8_t)GetBuzzer() + 1)); +} \ No newline at end of file diff --git a/src/menu/sound.h b/src/menu/sound.h new file mode 100644 index 0000000..65b1203 --- /dev/null +++ b/src/menu/sound.h @@ -0,0 +1,22 @@ +#ifndef __soundmenuitem +#define __soundmenuitem + +#include "screen/menu.h" + +class SoundMenuItem : public MenuItem +{ + public: + SoundMenuItem() : MenuItem() { } + + const char* getTitle(); + const char* getValue(); + + bool editable() { return true; } + + bool canIncrement(); + bool canDecrement(); + void incrementValue(); + void decrementValue(); +}; + +#endif \ No newline at end of file diff --git a/src/menu/start.cpp b/src/menu/start.cpp index a2b8e13..6c038ec 100644 --- a/src/menu/start.cpp +++ b/src/menu/start.cpp @@ -35,7 +35,8 @@ const char* StartMenuItem::getValue() } -void StartMenuItem::execute(ScreenManager* screenManager) +void StartMenuItem::execute(ScreenManager* screenManager, uint32_t currentTime) { + StartExposureTimer(currentTime); screenManager->show(); } diff --git a/src/menu/start.h b/src/menu/start.h index 9fea889..7b5a6c6 100644 --- a/src/menu/start.h +++ b/src/menu/start.h @@ -13,7 +13,7 @@ class StartMenuItem : public MenuItem bool editable() { return false; } - void execute(ScreenManager* screenManager); + void execute(ScreenManager* screenManager, uint32_t currentTime); }; #endif \ No newline at end of file diff --git a/src/menu/time.cpp b/src/menu/time.cpp index ad6640e..6fd0c8b 100644 --- a/src/menu/time.cpp +++ b/src/menu/time.cpp @@ -16,25 +16,27 @@ const char* TimeMenuItem::getValue() } -void TimeMenuItem::incValue() +bool TimeMenuItem::canIncrement() { - uint16_t exposureTime = GetExposureTime(); - - if (exposureTime < (uint16_t)-1) - { - SetExposureTime(exposureTime + (exposureTime >= LargeStepTreshold ? LargeStep : SmallStep)); - Buzzer::select(); - } + return GetExposureTime() < (uint16_t)-1; } -void TimeMenuItem::decValue() +bool TimeMenuItem::canDecrement() +{ + return GetExposureTime() > SmallStep; +} + + +void TimeMenuItem::incrementValue() { uint16_t exposureTime = GetExposureTime(); + SetExposureTime(exposureTime + (exposureTime >= LargeStepTreshold ? LargeStep : SmallStep)); +} - if (exposureTime > SmallStep) - { - SetExposureTime(exposureTime - (exposureTime > LargeStepTreshold ? LargeStep : SmallStep)); - Buzzer::select(); - } + +void TimeMenuItem::decrementValue() +{ + uint16_t exposureTime = GetExposureTime(); + SetExposureTime(exposureTime - (exposureTime > LargeStepTreshold ? LargeStep : SmallStep)); } \ No newline at end of file diff --git a/src/menu/time.h b/src/menu/time.h index 9f46bc0..265bf5e 100644 --- a/src/menu/time.h +++ b/src/menu/time.h @@ -13,8 +13,10 @@ class TimeMenuItem : public MenuItem bool editable() { return true; } - void incValue(); - void decValue(); + bool canIncrement(); + bool canDecrement(); + void incrementValue(); + void decrementValue(); }; #endif \ No newline at end of file diff --git a/src/screen.cpp b/src/screen.cpp index f578089..9014894 100644 --- a/src/screen.cpp +++ b/src/screen.cpp @@ -7,7 +7,7 @@ ScreenManager* BaseScreen::getScreenManager() return mScreenManager; } -unsigned long BaseScreen::getCurrentTime() +uint32_t BaseScreen::getCurrentTime() { return mScreenManager->getCurrentTime(); } diff --git a/src/screen.h b/src/screen.h index d06ec54..921b85b 100644 --- a/src/screen.h +++ b/src/screen.h @@ -13,7 +13,7 @@ class BaseScreen protected: ScreenManager* getScreenManager(); - unsigned long getCurrentTime(); + uint32_t getCurrentTime(); LiquidCrystal* getDisplay(); public: @@ -28,7 +28,7 @@ class BaseScreen virtual void onHide() = 0; virtual void onButton() = 0; - virtual void onEncoder(long lastPosition, long newPosition) = 0; + virtual void onEncoder(int32_t lastPosition, int32_t newPosition) = 0; virtual void onTick() = 0; }; @@ -38,12 +38,12 @@ class ScreenManager { private: LiquidCrystal* mDisplay; - unsigned long* mCurrentTime; + uint32_t* mCurrentTime; BaseScreen* mCurrent = NULL; public: - ScreenManager(LiquidCrystal* display, unsigned long* currentTime) + ScreenManager(LiquidCrystal* display, uint32_t* currentTime) { mDisplay = display; mCurrentTime = currentTime; @@ -56,7 +56,7 @@ class ScreenManager } - inline unsigned long getCurrentTime() + inline uint32_t getCurrentTime() { return *mCurrentTime; } diff --git a/src/screen/countdown.cpp b/src/screen/countdown.cpp index 5d8546b..5e6ef18 100644 --- a/src/screen/countdown.cpp +++ b/src/screen/countdown.cpp @@ -6,6 +6,12 @@ #include "buzzer.h" +inline uint32_t intDivCeil(uint32_t x, uint32_t y) +{ + return x / y + (x % y != 0); +} + + void CountdownScreen::printRemainingTime() { LCDPrintLineCentered(getDisplay(), 1, FormatTime(mLastDisplayed)); @@ -16,10 +22,12 @@ void CountdownScreen::onShow() { LCDPrintLineCentered(getDisplay(), 0, "Exposing..."); - mLastDisplayed = GetExposureTimeRemaining(getCurrentTime()) / 1000; + uint32_t remaining = GetExposureTimeRemaining(getCurrentTime()); + mLastDisplayed = intDivCeil(remaining, 1000); + printRemainingTime(); - digitalWrite(PinLED, HIGH); + analogWrite(PinLED, map(GetExposureIntensity(), 0, 100, 0, 255)); } @@ -37,7 +45,7 @@ void CountdownScreen::onButton() } -void CountdownScreen::onEncoder(long lastPosition, long newPosition) +void CountdownScreen::onEncoder(int32_t lastPosition, int32_t newPosition) { // TODO Allow adding / removing time? } @@ -45,13 +53,14 @@ void CountdownScreen::onEncoder(long lastPosition, long newPosition) void CountdownScreen::onTick() { - uint32_t remaining = GetExposureTimeRemaining(getCurrentTime()) / 1000; + uint32_t remaining = GetExposureTimeRemaining(getCurrentTime()); + remaining = intDivCeil(remaining, 1000); if (remaining == 0) { mLastDisplayed = 0; - LCDPrintLine(getDisplay(), 0, "Done!"); + LCDPrintLineCentered(getDisplay(), 0, "Done!"); printRemainingTime(); digitalWrite(PinLED, LOW); diff --git a/src/screen/countdown.h b/src/screen/countdown.h index 745ccd5..82e68f1 100644 --- a/src/screen/countdown.h +++ b/src/screen/countdown.h @@ -22,7 +22,7 @@ class CountdownScreen : public BaseScreen void onHide(); void onButton(); - void onEncoder(long lastPosition, long newPosition); + void onEncoder(int32_t lastPosition, int32_t newPosition); void onTick(); }; diff --git a/src/screen/menu.cpp b/src/screen/menu.cpp index 80f7c97..10052ff 100644 --- a/src/screen/menu.cpp +++ b/src/screen/menu.cpp @@ -2,20 +2,23 @@ #include "config.h" #include "buzzer.h" #include "display.h" +#include "state.h" #include "menu/start.h" #include "menu/time.h" #include "menu/intensity.h" +#include "menu/sound.h" MenuScreen::MenuScreen(ScreenManager* screenManager) : BaseScreen(screenManager) { - mCount = 3; + mCount = 4; mItems = new MenuItem*[mCount]; mItems[0] = new StartMenuItem(); mItems[1] = new TimeMenuItem(); mItems[2] = new IntensityMenuItem(); + mItems[3] = new SoundMenuItem(); } @@ -90,7 +93,19 @@ void MenuScreen::printValue() editingValue[1] = ' '; strcpy(editingValue + 2, value); editingValue[valueLength + 2] = ' '; - editingValue[valueLength + 3] = LCDCharUpDown; + + bool canIncrement = mItems[mSelected]->canIncrement(); + bool canDecrement = mItems[mSelected]->canDecrement(); + + if (canIncrement && canDecrement) + editingValue[valueLength + 3] = LCDCharUpDown; + else if (canIncrement) + editingValue[valueLength + 3] = LCDCharUp; + else if (canDecrement) + editingValue[valueLength + 3] = LCDCharDown; + else + editingValue[valueLength + 3] = ' '; + editingValue[valueLength + 4] = 0; LCDPrintLineCentered(display, 1, editingValue); @@ -110,25 +125,42 @@ void MenuScreen::onButton() { if (mItems[mSelected]->editable()) { + Buzzer::select(); + + if (mEditing) + SaveSettings(); + mEditing = !mEditing; printScrollIndicators(); printValue(); } else { - mItems[mSelected]->execute(getScreenManager()); + mItems[mSelected]->execute(getScreenManager(), getCurrentTime()); } } -void MenuScreen::onEncoder(long lastPosition, long newPosition) +void MenuScreen::onEncoder(int32_t lastPosition, int32_t newPosition) { if (mEditing) { if (newPosition > lastPosition) - mItems[mSelected]->incValue(); + { + if (mItems[mSelected]->canIncrement()) + { + mItems[mSelected]->incrementValue(); + Buzzer::select(); + } + } else - mItems[mSelected]->decValue(); + { + if (mItems[mSelected]->canDecrement()) + { + mItems[mSelected]->decrementValue(); + Buzzer::select(); + } + } printValue(); } diff --git a/src/screen/menu.h b/src/screen/menu.h index 6e4ad64..da7f004 100644 --- a/src/screen/menu.h +++ b/src/screen/menu.h @@ -14,11 +14,13 @@ class MenuItem virtual bool editable() { return false; } // Editable = true - virtual void incValue() { } - virtual void decValue() { } + virtual bool canIncrement() { return true; } + virtual bool canDecrement() { return true; } + virtual void incrementValue() { } + virtual void decrementValue() { } // Editable = false - virtual void execute(ScreenManager* screenManager) { } + virtual void execute(ScreenManager* screenManager, uint32_t currentTime) { } }; class MenuScreen : public BaseScreen @@ -44,7 +46,7 @@ class MenuScreen : public BaseScreen void onHide(); void onButton(); - void onEncoder(long lastPosition, long newPosition); + void onEncoder(int32_t lastPosition, int32_t newPosition); void onTick(); }; diff --git a/src/state.cpp b/src/state.cpp index e0f4bb6..08372e6 100644 --- a/src/state.cpp +++ b/src/state.cpp @@ -5,6 +5,7 @@ uint16_t ExposureTime = DefaultExposureTime; uint8_t ExposureIntensity = DefaultExposureIntensity; uint32_t ExposureTimerStart = 0; +BuzzerSetting Buzzer = BuzzerSetting::CompletedButtonStartup; uint16_t GetExposureTime() @@ -39,6 +40,18 @@ void SetExposureIntensity(uint8_t value) } +BuzzerSetting GetBuzzer() +{ + return Buzzer; +} + + +void SetBuzzer(BuzzerSetting value) +{ + Buzzer = value; +} + + void LoadSettings() { uint16_t offset = 0; @@ -49,6 +62,12 @@ void LoadSettings() EEPROM.get(offset, ExposureIntensity); SetExposureIntensity(ExposureIntensity); + + offset += sizeof(ExposureIntensity); + + EEPROM.get(offset, Buzzer); + if (Buzzer < BuzzerSetting::First || Buzzer > BuzzerSetting::Last) + Buzzer = BuzzerSetting::CompletedButtonStartup; } @@ -59,12 +78,14 @@ void SaveSettings() offset += sizeof(ExposureTime); EEPROM.put(offset, ExposureIntensity); + offset += sizeof(ExposureIntensity); + + EEPROM.put(offset, (uint8_t)Buzzer); } void StartExposureTimer(uint32_t currentTime) { - SaveSettings(); ExposureTimerStart = currentTime; } @@ -78,5 +99,7 @@ void ResetExposureTimer() uint16_t GetExposureTimeRemaining(uint32_t currentTime) { uint32_t elapsed = (currentTime - ExposureTimerStart); - return elapsed <= ExposureTime ? ExposureTime - elapsed : 0; + uint32_t exposureTimeMs = ExposureTime * 1000; + + return elapsed <= exposureTimeMs ? exposureTimeMs - elapsed : 0; } \ No newline at end of file diff --git a/src/state.h b/src/state.h index 4d1a0b8..0b35c4f 100644 --- a/src/state.h +++ b/src/state.h @@ -3,12 +3,26 @@ #include +enum BuzzerSetting +{ + CompletedButtonStartup = 0, + CompletedButton = 1, + Completed = 2, + None = 3, + + First = CompletedButtonStartup, + Last = None +}; + uint16_t GetExposureTime(); void SetExposureTime(uint16_t value); uint8_t GetExposureIntensity(); void SetExposureIntensity(uint8_t value); +BuzzerSetting GetBuzzer(); +void SetBuzzer(BuzzerSetting value); + void LoadSettings(); void SaveSettings();