260 lines
6.1 KiB
C++
260 lines
6.1 KiB
C++
#ifndef MODE_TIMER_H
|
|
#define MODE_TIMER_H
|
|
|
|
#include <Preferences.h>
|
|
|
|
#include "beep.h"
|
|
#include "Mode.h"
|
|
#include "Rest.h"
|
|
#include "Timer.h"
|
|
|
|
#define DEC_MIL ( 100 )
|
|
#define SEC_MIL ( 1000 )
|
|
#define MIN_MIL ( 60 * SEC_MIL )
|
|
#define HOU_MIL ( 60 * MIN_MIL )
|
|
#define DAY_MIL ( 24 * HOU_MIL )
|
|
|
|
#define ENABLE_DECIS false
|
|
|
|
enum Stage {
|
|
FIRST_HALF, SECOND_HALF, LAST_MINUTE, FINALE
|
|
};
|
|
|
|
inline uint32_t getTimerConfig(const char *name, const uint32_t fallback) {
|
|
Preferences preferences;
|
|
preferences.begin("Timer", true);
|
|
const auto configMillis = preferences.getULong(name, fallback);
|
|
preferences.end();
|
|
return configMillis;
|
|
}
|
|
|
|
inline void setTimerConfig(const char *name, const uint32_t configMillis) {
|
|
Preferences preferences;
|
|
preferences.begin("Timer", false);
|
|
preferences.putULong(name, configMillis);
|
|
preferences.end();
|
|
Serial.printf("CONFIG SET: %s.%s = %d\n", "Timer", name, configMillis);
|
|
}
|
|
|
|
inline uint32_t getTimerConfigCountdown() {
|
|
return getTimerConfig("countdown", 6 * 60 * 1000);
|
|
}
|
|
|
|
inline uint32_t getTimerConfigYellow() {
|
|
return getTimerConfig("yellow", 3 * 60 * 1000);
|
|
}
|
|
|
|
inline uint32_t getTimerConfigOrange() {
|
|
return getTimerConfig("orange", 1 * 60 * 1000);
|
|
}
|
|
|
|
inline uint32_t getTimerConfigRed() {
|
|
return getTimerConfig("red", 10 * 1000);
|
|
}
|
|
|
|
class ModeTimer final : public Mode {
|
|
|
|
Timer countdown;
|
|
|
|
Timer flash;
|
|
|
|
Timer pause;
|
|
|
|
Timer beep;
|
|
|
|
uint32_t yellow = 3 * 60 * 1000;
|
|
|
|
uint32_t orange = 1 * 60 * 1000;
|
|
|
|
uint32_t red = 10 * 1000;
|
|
|
|
bool dirty = true;
|
|
|
|
bool dirtyPrint = true;
|
|
|
|
Rest rest{0};
|
|
|
|
Rest last{0};
|
|
|
|
public:
|
|
explicit ModeTimer()
|
|
: Mode("Timer"),
|
|
countdown("countdown", [this]() {
|
|
flash.start();
|
|
dirty = true;
|
|
dirtyPrint = true;
|
|
}),
|
|
flash("flash", [this]() {
|
|
dirty = true;
|
|
dirtyPrint = true;
|
|
}),
|
|
pause("pause", [this]() {
|
|
dirty = true;
|
|
dirtyPrint = true;
|
|
}),
|
|
beep("beep", [this]() { beepSet(beep.isEven()); }) {
|
|
//
|
|
}
|
|
|
|
void init() override {
|
|
Serial.printf("Mode INIT: %s\n", name);
|
|
|
|
beepSet(false);
|
|
|
|
countdown.stop();
|
|
flash.stop();
|
|
pause.stop();
|
|
beep.stop();
|
|
|
|
const auto configMillis = getTimerConfigCountdown();
|
|
yellow = getTimerConfigYellow();
|
|
orange = getTimerConfigOrange();
|
|
red = getTimerConfigRed();
|
|
countdown.countConfig(configMillis, 1);
|
|
flash.countConfig(100, 19);
|
|
beep.countConfig(200, 1);
|
|
pause.foreverConfig(500);
|
|
|
|
dirty = true;
|
|
dirtyPrint = true;
|
|
}
|
|
|
|
void step(const uint64_t deltaMillis) override {
|
|
flash.step(deltaMillis);
|
|
pause.step(deltaMillis);
|
|
beep.step(deltaMillis);
|
|
if (!pause.isRunning()) {
|
|
countdown.step(deltaMillis);
|
|
}
|
|
}
|
|
|
|
void buttonOK() override {
|
|
if (flash.isRunning()) {
|
|
return;
|
|
}
|
|
if (!countdown.isRunning()) {
|
|
init();
|
|
doBeep(1);
|
|
countdown.start();
|
|
} else {
|
|
pause.toggle();
|
|
}
|
|
dirty = true;
|
|
dirtyPrint = true;
|
|
}
|
|
|
|
void buttonESC() override {
|
|
init();
|
|
}
|
|
|
|
void draw(Display &display) override {
|
|
if (countdown.getRestMillis() >= DAY_MIL) {
|
|
rest = Rest(intCeilDiv(countdown.getRestMillis(), HOU_MIL) * HOU_MIL);
|
|
} else if (countdown.getRestMillis() >= MIN_MIL) {
|
|
rest = Rest(intCeilDiv(countdown.getRestMillis(), SEC_MIL) * SEC_MIL);
|
|
} else {
|
|
#if ENABLE_DECIS
|
|
rest = Rest(intCeilDiv(countdown.getRestMillis(), DEC_MIL) * DEC_MIL);
|
|
#else
|
|
rest = Rest(intCeilDiv(countdown.getRestMillis(), SEC_MIL) * SEC_MIL);
|
|
#endif
|
|
}
|
|
|
|
display.clear();
|
|
if (flash.isRunning()) {
|
|
const auto state = flash.isEven();
|
|
if (state) {
|
|
display.rect(0, 0, 32, 8, WHITE);
|
|
}
|
|
beepSet(true);
|
|
} else {
|
|
if (countdown.isRunning()) {
|
|
if (pause.isRunning() && pause.isEven()) {
|
|
display.print(15, 0, ALIGN_CENTER, FONT7, BLUE, "PAUSE");
|
|
} else {
|
|
drawTime(display);
|
|
}
|
|
} else {
|
|
beepSet(false);
|
|
display.print(15, 0, ALIGN_CENTER, FONT7, RED, "-- : --");
|
|
}
|
|
}
|
|
if (dirty) {
|
|
dirty = false;
|
|
display.show();
|
|
if (dirtyPrint) {
|
|
dirtyPrint = false;
|
|
rest.log();
|
|
display.log();
|
|
}
|
|
}
|
|
last = rest;
|
|
}
|
|
|
|
private:
|
|
void doBeep(const uint32_t count) {
|
|
beepSet(true);
|
|
beep.startCount(count * 2 - 1);
|
|
}
|
|
|
|
void drawTime(Display &display) {
|
|
Color color = RED;
|
|
Stage stage = FINALE;
|
|
if (rest.millisTotal > yellow) {
|
|
color = WHITE;
|
|
stage = FIRST_HALF;
|
|
} else if (rest.millisTotal > orange) {
|
|
color = YELLOW;
|
|
stage = SECOND_HALF;
|
|
} else if (rest.millisTotal > red) {
|
|
color = ORANGE;
|
|
stage = LAST_MINUTE;
|
|
}
|
|
|
|
static int lastStage = stage;
|
|
if (lastStage != stage) {
|
|
if (stage == SECOND_HALF) {
|
|
doBeep(1);
|
|
} else if (stage == LAST_MINUTE) {
|
|
doBeep(2);
|
|
}
|
|
lastStage = stage;
|
|
}
|
|
|
|
if (rest.secondChanged(last)) {
|
|
if (stage == FINALE) {
|
|
doBeep(1);
|
|
}
|
|
}
|
|
|
|
if (rest.daysTotal > 0) {
|
|
display.print(16, 0, ALIGN_CENTER, FONT7, color, "%d. %2d", rest.daysPart, rest.hoursPart);
|
|
dirty |= rest.hourChanged(last);
|
|
dirtyPrint = true;
|
|
} else if (rest.hoursTotal > 0) {
|
|
display.print(16, 0, ALIGN_CENTER, FONT7, color, "%d:%02d:%02d", rest.hoursPart, rest.minutesPart,
|
|
rest.secondsPart);
|
|
dirty |= rest.secondChanged(last);
|
|
dirtyPrint = true;
|
|
} else if (rest.minutesTotal > 0) {
|
|
display.print(16, 0, ALIGN_CENTER, FONT7, color, "%d:%02d", rest.minutesPart, rest.secondsPart);
|
|
dirty |= rest.secondChanged(last);
|
|
dirtyPrint = true;
|
|
} else {
|
|
#if ENABLE_DECIS
|
|
display.print(16, 0, ALIGN_CENTER, FONT7, color, "%d.%d", rest.secondsPart, rest.decisPart);
|
|
#else
|
|
if (rest.secondsTotal > 9) {
|
|
display.print(16, 0, ALIGN_CENTER, FONT7, color, "%d", rest.secondsPart, rest.secondsPart);
|
|
} else {
|
|
display.print(16, 0, ALIGN_CENTER, FONT7, color, "%d %d %d", rest.secondsPart, rest.secondsPart, rest.secondsPart);
|
|
}
|
|
#endif
|
|
dirty |= rest.deciChanged(last);
|
|
dirtyPrint |= rest.secondChanged(last);
|
|
}
|
|
}
|
|
|
|
};
|
|
#endif
|