Fixed countdown timer

Added sound settings
Changed edit arrows to indicate for min/max values
This commit is contained in:
Mark van Renswoude 2017-12-08 22:32:04 +01:00
parent 1cdb3e476a
commit 0be4b62da9
20 changed files with 274 additions and 72 deletions

View File

@ -1,6 +1,7 @@
#include "buzzer.h" #include "buzzer.h"
#include <Arduino.h> #include <Arduino.h>
#include "config.h" #include "config.h"
#include "state.h"
void Buzzer::playNote(uint16_t frequency, uint16_t duration) void Buzzer::playNote(uint16_t frequency, uint16_t duration)
@ -13,23 +14,28 @@ void Buzzer::playNote(uint16_t frequency, uint16_t duration)
void Buzzer::startup() void Buzzer::startup()
{ {
if (GetBuzzer() == BuzzerSetting::CompletedButtonStartup)
playNote(1000, 50); playNote(1000, 50);
} }
void Buzzer::select() void Buzzer::select()
{ {
if (GetBuzzer() <= BuzzerSetting::CompletedButton)
playNote(1000, 1); playNote(1000, 1);
} }
void Buzzer::click() void Buzzer::click()
{ {
if (GetBuzzer() <= BuzzerSetting::CompletedButton)
playNote(1000, 25); playNote(1000, 25);
} }
void Buzzer::completed() void Buzzer::completed()
{
if (GetBuzzer() <= BuzzerSetting::Completed)
{ {
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++)
{ {
@ -37,6 +43,7 @@ void Buzzer::completed()
delay(500); delay(500);
} }
} }
}
void Buzzer::memoryCleared() void Buzzer::memoryCleared()

View File

@ -49,3 +49,23 @@ uint8_t LCDCharUpDownMap[8] = {
B00100, B00100,
B00000, B00000,
}; };
uint8_t LCDCharUpMap[8] = {
B00000,
B00100,
B01110,
B00000,
B00000,
B00000,
B00000,
};
uint8_t LCDCharDownMap[8] = {
B00000,
B00000,
B00000,
B00000,
B01110,
B00100,
B00000,
};

View File

@ -15,6 +15,7 @@ const uint8_t PinButton = 4;
const uint8_t PinBuzzer = 5; const uint8_t PinBuzzer = 5;
const uint8_t PinLED = 6; 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 LCDWidth = 16;
const uint8_t LCDHeight = 2; const uint8_t LCDHeight = 2;
@ -22,7 +23,7 @@ const uint8_t EncoderSensitivity = 4;
const uint8_t SmallStep = 1; const uint8_t SmallStep = 1;
const uint8_t LargeStepTreshold = 60; const uint8_t LargeStepTreshold = 60;
const uint8_t LargeStep = 10; const uint8_t LargeStep = 10;
const uint8_t IntensityStep = 1; const uint8_t IntensityStep = 5;
const uint32_t DefaultExposureTime = 60; const uint32_t DefaultExposureTime = 60;
@ -33,11 +34,15 @@ const uint8_t LCDCharArrowLeft = 1;
const uint8_t LCDCharArrowRightHollow = 2; const uint8_t LCDCharArrowRightHollow = 2;
const uint8_t LCDCharArrowLeftHollow = 3; const uint8_t LCDCharArrowLeftHollow = 3;
const uint8_t LCDCharUpDown = 4; const uint8_t LCDCharUpDown = 4;
const uint8_t LCDCharUp = 5;
const uint8_t LCDCharDown = 6;
extern uint8_t LCDCharArrowRightMap[8]; extern uint8_t LCDCharArrowRightMap[8];
extern uint8_t LCDCharArrowLeftMap[8]; extern uint8_t LCDCharArrowLeftMap[8];
extern uint8_t LCDCharArrowRightHollowMap[8]; extern uint8_t LCDCharArrowRightHollowMap[8];
extern uint8_t LCDCharArrowLeftHollowMap[8]; extern uint8_t LCDCharArrowLeftHollowMap[8];
extern uint8_t LCDCharUpDownMap[8]; extern uint8_t LCDCharUpDownMap[8];
extern uint8_t LCDCharUpMap[8];
extern uint8_t LCDCharDownMap[8];
#endif #endif

View File

@ -18,7 +18,7 @@ LiquidCrystal lcd(PinLCDRS, PinLCDEN, PinLCDDB4, PinLCDDB5, PinLCDDB6, PinLCDDB7
#ifndef ResetEEPROM #ifndef ResetEEPROM
ScreenManager* screenManager; ScreenManager* screenManager;
unsigned long currentTime; uint32_t currentTime;
Encoder encoder(PinEncoderData, PinEncoderClock); Encoder encoder(PinEncoderData, PinEncoderClock);
Bounce button = Bounce(); Bounce button = Bounce();
@ -41,6 +41,8 @@ void setup()
lcd.createChar(LCDCharArrowRightHollow, LCDCharArrowRightHollowMap); lcd.createChar(LCDCharArrowRightHollow, LCDCharArrowRightHollowMap);
lcd.createChar(LCDCharArrowLeftHollow, LCDCharArrowLeftHollowMap); lcd.createChar(LCDCharArrowLeftHollow, LCDCharArrowLeftHollowMap);
lcd.createChar(LCDCharUpDown, LCDCharUpDownMap); lcd.createChar(LCDCharUpDown, LCDCharUpDownMap);
lcd.createChar(LCDCharUp, LCDCharUpMap);
lcd.createChar(LCDCharDown, LCDCharDownMap);
lcd.begin(LCDWidth, LCDHeight); lcd.begin(LCDWidth, LCDHeight);
screenManager = new ScreenManager(&lcd, &currentTime); screenManager = new ScreenManager(&lcd, &currentTime);
@ -50,7 +52,7 @@ void setup()
} }
long lastPosition = 0; int32_t lastPosition = 0;
bool isPressed = false; bool isPressed = false;
@ -59,7 +61,7 @@ void loop()
currentTime = millis(); currentTime = millis();
button.update(); button.update();
long newPosition = encoder.read(); int32_t newPosition = encoder.read();
if (abs(newPosition - lastPosition) >= EncoderSensitivity) if (abs(newPosition - lastPosition) >= EncoderSensitivity)
{ {
screenManager->getCurrent()->onEncoder(lastPosition, newPosition); screenManager->getCurrent()->onEncoder(lastPosition, newPosition);
@ -82,18 +84,21 @@ void loop()
#else #else
#include <EEPROM.h>
void setup() void setup()
{ {
pinMode(PinBuzzer, OUTPUT); pinMode(PinBuzzer, OUTPUT);
lcd.begin(LCDWidth, LCDHeight); 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); EEPROM.update(i, 0);
} }
ExposureTime = DefaultExposureTime; SetExposureTime(DefaultExposureTime);
ExposureIntensity = DefaultExposureIntensity; SetExposureIntensity(DefaultExposureIntensity);
SetBuzzer(BuzzerSetting::CompletedButtonStartup);
SaveSettings(); SaveSettings();
lcd.setCursor(0, 0); lcd.setCursor(0, 0);

View File

@ -17,25 +17,25 @@ const char* IntensityMenuItem::getValue()
} }
void IntensityMenuItem::incValue() bool IntensityMenuItem::canIncrement()
{ {
uint16_t exposureIntensity = GetExposureIntensity(); return GetExposureIntensity() < 100;
if (exposureIntensity < 100)
{
SetExposureIntensity(exposureIntensity + IntensityStep);
Buzzer::select();
}
} }
void IntensityMenuItem::decValue() bool IntensityMenuItem::canDecrement()
{ {
uint16_t exposureIntensity = GetExposureIntensity(); return GetExposureIntensity() > IntensityStep;
}
if (exposureIntensity > IntensityStep)
void IntensityMenuItem::incrementValue()
{ {
SetExposureIntensity(exposureIntensity - IntensityStep); SetExposureIntensity(GetExposureIntensity() + IntensityStep);
Buzzer::select();
} }
void IntensityMenuItem::decrementValue()
{
SetExposureIntensity(GetExposureIntensity() - IntensityStep);
} }

View File

@ -13,8 +13,10 @@ class IntensityMenuItem : public MenuItem
bool editable() { return true; } bool editable() { return true; }
void incValue(); bool canIncrement();
void decValue(); bool canDecrement();
void incrementValue();
void decrementValue();
}; };
#endif #endif

56
src/menu/sound.cpp Normal file
View File

@ -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));
}

22
src/menu/sound.h Normal file
View File

@ -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

View File

@ -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<CountdownScreen>(); screenManager->show<CountdownScreen>();
} }

View File

@ -13,7 +13,7 @@ class StartMenuItem : public MenuItem
bool editable() { return false; } bool editable() { return false; }
void execute(ScreenManager* screenManager); void execute(ScreenManager* screenManager, uint32_t currentTime);
}; };
#endif #endif

View File

@ -16,25 +16,27 @@ const char* TimeMenuItem::getValue()
} }
void TimeMenuItem::incValue() bool TimeMenuItem::canIncrement()
{
return GetExposureTime() < (uint16_t)-1;
}
bool TimeMenuItem::canDecrement()
{
return GetExposureTime() > SmallStep;
}
void TimeMenuItem::incrementValue()
{ {
uint16_t exposureTime = GetExposureTime(); uint16_t exposureTime = GetExposureTime();
if (exposureTime < (uint16_t)-1)
{
SetExposureTime(exposureTime + (exposureTime >= LargeStepTreshold ? LargeStep : SmallStep)); SetExposureTime(exposureTime + (exposureTime >= LargeStepTreshold ? LargeStep : SmallStep));
Buzzer::select();
}
} }
void TimeMenuItem::decValue() void TimeMenuItem::decrementValue()
{ {
uint16_t exposureTime = GetExposureTime(); uint16_t exposureTime = GetExposureTime();
if (exposureTime > SmallStep)
{
SetExposureTime(exposureTime - (exposureTime > LargeStepTreshold ? LargeStep : SmallStep)); SetExposureTime(exposureTime - (exposureTime > LargeStepTreshold ? LargeStep : SmallStep));
Buzzer::select();
}
} }

View File

@ -13,8 +13,10 @@ class TimeMenuItem : public MenuItem
bool editable() { return true; } bool editable() { return true; }
void incValue(); bool canIncrement();
void decValue(); bool canDecrement();
void incrementValue();
void decrementValue();
}; };
#endif #endif

View File

@ -7,7 +7,7 @@ ScreenManager* BaseScreen::getScreenManager()
return mScreenManager; return mScreenManager;
} }
unsigned long BaseScreen::getCurrentTime() uint32_t BaseScreen::getCurrentTime()
{ {
return mScreenManager->getCurrentTime(); return mScreenManager->getCurrentTime();
} }

View File

@ -13,7 +13,7 @@ class BaseScreen
protected: protected:
ScreenManager* getScreenManager(); ScreenManager* getScreenManager();
unsigned long getCurrentTime(); uint32_t getCurrentTime();
LiquidCrystal* getDisplay(); LiquidCrystal* getDisplay();
public: public:
@ -28,7 +28,7 @@ class BaseScreen
virtual void onHide() = 0; virtual void onHide() = 0;
virtual void onButton() = 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; virtual void onTick() = 0;
}; };
@ -38,12 +38,12 @@ class ScreenManager
{ {
private: private:
LiquidCrystal* mDisplay; LiquidCrystal* mDisplay;
unsigned long* mCurrentTime; uint32_t* mCurrentTime;
BaseScreen* mCurrent = NULL; BaseScreen* mCurrent = NULL;
public: public:
ScreenManager(LiquidCrystal* display, unsigned long* currentTime) ScreenManager(LiquidCrystal* display, uint32_t* currentTime)
{ {
mDisplay = display; mDisplay = display;
mCurrentTime = currentTime; mCurrentTime = currentTime;
@ -56,7 +56,7 @@ class ScreenManager
} }
inline unsigned long getCurrentTime() inline uint32_t getCurrentTime()
{ {
return *mCurrentTime; return *mCurrentTime;
} }

View File

@ -6,6 +6,12 @@
#include "buzzer.h" #include "buzzer.h"
inline uint32_t intDivCeil(uint32_t x, uint32_t y)
{
return x / y + (x % y != 0);
}
void CountdownScreen::printRemainingTime() void CountdownScreen::printRemainingTime()
{ {
LCDPrintLineCentered(getDisplay(), 1, FormatTime(mLastDisplayed)); LCDPrintLineCentered(getDisplay(), 1, FormatTime(mLastDisplayed));
@ -16,10 +22,12 @@ void CountdownScreen::onShow()
{ {
LCDPrintLineCentered(getDisplay(), 0, "Exposing..."); LCDPrintLineCentered(getDisplay(), 0, "Exposing...");
mLastDisplayed = GetExposureTimeRemaining(getCurrentTime()) / 1000; uint32_t remaining = GetExposureTimeRemaining(getCurrentTime());
mLastDisplayed = intDivCeil(remaining, 1000);
printRemainingTime(); 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? // TODO Allow adding / removing time?
} }
@ -45,13 +53,14 @@ void CountdownScreen::onEncoder(long lastPosition, long newPosition)
void CountdownScreen::onTick() void CountdownScreen::onTick()
{ {
uint32_t remaining = GetExposureTimeRemaining(getCurrentTime()) / 1000; uint32_t remaining = GetExposureTimeRemaining(getCurrentTime());
remaining = intDivCeil(remaining, 1000);
if (remaining == 0) if (remaining == 0)
{ {
mLastDisplayed = 0; mLastDisplayed = 0;
LCDPrintLine(getDisplay(), 0, "Done!"); LCDPrintLineCentered(getDisplay(), 0, "Done!");
printRemainingTime(); printRemainingTime();
digitalWrite(PinLED, LOW); digitalWrite(PinLED, LOW);

View File

@ -22,7 +22,7 @@ class CountdownScreen : public BaseScreen
void onHide(); void onHide();
void onButton(); void onButton();
void onEncoder(long lastPosition, long newPosition); void onEncoder(int32_t lastPosition, int32_t newPosition);
void onTick(); void onTick();
}; };

View File

@ -2,20 +2,23 @@
#include "config.h" #include "config.h"
#include "buzzer.h" #include "buzzer.h"
#include "display.h" #include "display.h"
#include "state.h"
#include "menu/start.h" #include "menu/start.h"
#include "menu/time.h" #include "menu/time.h"
#include "menu/intensity.h" #include "menu/intensity.h"
#include "menu/sound.h"
MenuScreen::MenuScreen(ScreenManager* screenManager) : BaseScreen(screenManager) MenuScreen::MenuScreen(ScreenManager* screenManager) : BaseScreen(screenManager)
{ {
mCount = 3; mCount = 4;
mItems = new MenuItem*[mCount]; mItems = new MenuItem*[mCount];
mItems[0] = new StartMenuItem(); mItems[0] = new StartMenuItem();
mItems[1] = new TimeMenuItem(); mItems[1] = new TimeMenuItem();
mItems[2] = new IntensityMenuItem(); mItems[2] = new IntensityMenuItem();
mItems[3] = new SoundMenuItem();
} }
@ -90,7 +93,19 @@ void MenuScreen::printValue()
editingValue[1] = ' '; editingValue[1] = ' ';
strcpy(editingValue + 2, value); strcpy(editingValue + 2, value);
editingValue[valueLength + 2] = ' '; editingValue[valueLength + 2] = ' ';
bool canIncrement = mItems[mSelected]->canIncrement();
bool canDecrement = mItems[mSelected]->canDecrement();
if (canIncrement && canDecrement)
editingValue[valueLength + 3] = LCDCharUpDown; 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; editingValue[valueLength + 4] = 0;
LCDPrintLineCentered(display, 1, editingValue); LCDPrintLineCentered(display, 1, editingValue);
@ -110,25 +125,42 @@ void MenuScreen::onButton()
{ {
if (mItems[mSelected]->editable()) if (mItems[mSelected]->editable())
{ {
Buzzer::select();
if (mEditing)
SaveSettings();
mEditing = !mEditing; mEditing = !mEditing;
printScrollIndicators(); printScrollIndicators();
printValue(); printValue();
} }
else 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 (mEditing)
{ {
if (newPosition > lastPosition) if (newPosition > lastPosition)
mItems[mSelected]->incValue(); {
if (mItems[mSelected]->canIncrement())
{
mItems[mSelected]->incrementValue();
Buzzer::select();
}
}
else else
mItems[mSelected]->decValue(); {
if (mItems[mSelected]->canDecrement())
{
mItems[mSelected]->decrementValue();
Buzzer::select();
}
}
printValue(); printValue();
} }

View File

@ -14,11 +14,13 @@ class MenuItem
virtual bool editable() { return false; } virtual bool editable() { return false; }
// Editable = true // Editable = true
virtual void incValue() { } virtual bool canIncrement() { return true; }
virtual void decValue() { } virtual bool canDecrement() { return true; }
virtual void incrementValue() { }
virtual void decrementValue() { }
// Editable = false // Editable = false
virtual void execute(ScreenManager* screenManager) { } virtual void execute(ScreenManager* screenManager, uint32_t currentTime) { }
}; };
class MenuScreen : public BaseScreen class MenuScreen : public BaseScreen
@ -44,7 +46,7 @@ class MenuScreen : public BaseScreen
void onHide(); void onHide();
void onButton(); void onButton();
void onEncoder(long lastPosition, long newPosition); void onEncoder(int32_t lastPosition, int32_t newPosition);
void onTick(); void onTick();
}; };

View File

@ -5,6 +5,7 @@
uint16_t ExposureTime = DefaultExposureTime; uint16_t ExposureTime = DefaultExposureTime;
uint8_t ExposureIntensity = DefaultExposureIntensity; uint8_t ExposureIntensity = DefaultExposureIntensity;
uint32_t ExposureTimerStart = 0; uint32_t ExposureTimerStart = 0;
BuzzerSetting Buzzer = BuzzerSetting::CompletedButtonStartup;
uint16_t GetExposureTime() uint16_t GetExposureTime()
@ -39,6 +40,18 @@ void SetExposureIntensity(uint8_t value)
} }
BuzzerSetting GetBuzzer()
{
return Buzzer;
}
void SetBuzzer(BuzzerSetting value)
{
Buzzer = value;
}
void LoadSettings() void LoadSettings()
{ {
uint16_t offset = 0; uint16_t offset = 0;
@ -49,6 +62,12 @@ void LoadSettings()
EEPROM.get(offset, ExposureIntensity); EEPROM.get(offset, ExposureIntensity);
SetExposureIntensity(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); offset += sizeof(ExposureTime);
EEPROM.put(offset, ExposureIntensity); EEPROM.put(offset, ExposureIntensity);
offset += sizeof(ExposureIntensity);
EEPROM.put(offset, (uint8_t)Buzzer);
} }
void StartExposureTimer(uint32_t currentTime) void StartExposureTimer(uint32_t currentTime)
{ {
SaveSettings();
ExposureTimerStart = currentTime; ExposureTimerStart = currentTime;
} }
@ -78,5 +99,7 @@ void ResetExposureTimer()
uint16_t GetExposureTimeRemaining(uint32_t currentTime) uint16_t GetExposureTimeRemaining(uint32_t currentTime)
{ {
uint32_t elapsed = (currentTime - ExposureTimerStart); uint32_t elapsed = (currentTime - ExposureTimerStart);
return elapsed <= ExposureTime ? ExposureTime - elapsed : 0; uint32_t exposureTimeMs = ExposureTime * 1000;
return elapsed <= exposureTimeMs ? exposureTimeMs - elapsed : 0;
} }

View File

@ -3,12 +3,26 @@
#include <Arduino.h> #include <Arduino.h>
enum BuzzerSetting
{
CompletedButtonStartup = 0,
CompletedButton = 1,
Completed = 2,
None = 3,
First = CompletedButtonStartup,
Last = None
};
uint16_t GetExposureTime(); uint16_t GetExposureTime();
void SetExposureTime(uint16_t value); void SetExposureTime(uint16_t value);
uint8_t GetExposureIntensity(); uint8_t GetExposureIntensity();
void SetExposureIntensity(uint8_t value); void SetExposureIntensity(uint8_t value);
BuzzerSetting GetBuzzer();
void SetBuzzer(BuzzerSetting value);
void LoadSettings(); void LoadSettings();
void SaveSettings(); void SaveSettings();