From 399723d77aa8dc54a3d966e232bf1c47f0d9773e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Patrick=20Ha=C3=9Fel?=
Date: Tue, 31 Dec 2024 12:01:32 +0100
Subject: [PATCH] modifiable date for countdown + COUNT_DOWN_SLEEP
---
src/config.cpp | 3 +-
src/config.h | 1 +
src/display/Display.cpp | 28 +++++++
src/display/Display.h | 9 +-
src/mode.cpp | 7 +-
src/mode/CountDown/CountDown.h | 149 +++++++++++++++++++--------------
src/mode/Mode.h | 7 +-
src/server.cpp | 48 ++++++++---
8 files changed, 171 insertions(+), 81 deletions(-)
diff --git a/src/config.cpp b/src/config.cpp
index d3921a4..2876edc 100644
--- a/src/config.cpp
+++ b/src/config.cpp
@@ -83,9 +83,10 @@ bool validateChecksum(uint32_t checksumEEPROM, Config &tmp) {
}
void config_defaults() {
- config.mode = GAME_OF_LIFE_GRAYSCALE;
+ config.mode = COUNT_DOWN_SLEEP;
config.speed = 1.0;
config.brightness = 16;
+ config.date = {0};
Serial.printf("Config DEFAULTS loaded.\n");
}
diff --git a/src/config.h b/src/config.h
index be1ff0d..a0cf06b 100644
--- a/src/config.h
+++ b/src/config.h
@@ -7,6 +7,7 @@ struct Config {
ModeId mode;
double speed;
uint8_t brightness;
+ tm date;
};
extern Config config;
diff --git a/src/display/Display.cpp b/src/display/Display.cpp
index 9d059d6..c374b69 100644
--- a/src/display/Display.cpp
+++ b/src/display/Display.cpp
@@ -106,6 +106,34 @@ bool SYMBOLS[SYMBOL_COUNT][DISPLAY_CHAR_WIDTH * DISPLAY_CHAR_HEIGHT] = {
X, _, _,
_, _, X,
},
+ {
+ X, X, X,
+ _, X, _,
+ _, X, _,
+ _, X, _,
+ _, X, _,
+ },
+ {
+ _, X, _,
+ X, _, X,
+ X, X, X,
+ X, _, X,
+ X, _, X,
+ },
+ {
+ _, X, X,
+ X, _, _,
+ X, X, X,
+ X, _, X,
+ _, X, _,
+ },
+ {
+ X, X, X,
+ X, _, _,
+ X, X, X,
+ X, _, _,
+ X, X, X,
+ },
// this must always be the last symbol (fallback)
{
X, X, X,
diff --git a/src/display/Display.h b/src/display/Display.h
index 0fd9a34..07607a5 100644
--- a/src/display/Display.h
+++ b/src/display/Display.h
@@ -5,9 +5,16 @@
#include "Adafruit_NeoPixel.h"
#include "Vector.h"
-#define SYMBOL_COUNT 16
+#define SYMBOL_COUNT 20
+
#define SYMBOL_DASH 13
#define SYMBOL_PERCENT 14
+
+#define SYMBOL_T 15
+#define SYMBOL_A 16
+#define SYMBOL_G 17
+#define SYMBOL_E 18
+
#define DISPLAY_CHAR_WIDTH 3
#define DISPLAY_CHAR_HEIGHT 5
diff --git a/src/mode.cpp b/src/mode.cpp
index 8bcbba2..b82ea1e 100644
--- a/src/mode.cpp
+++ b/src/mode.cpp
@@ -99,10 +99,13 @@ void loadNewMode() {
mode = new SpaceInvaders(display);
break;
case COUNT_DOWN:
- mode = new CountDown(display, false);
+ mode = new CountDown(display, false, false);
break;
case COUNT_DOWN_BARS:
- mode = new CountDown(display, true);
+ mode = new CountDown(display, true, false);
+ break;
+ case COUNT_DOWN_SLEEP:
+ mode = new CountDown(display, false, true);
break;
case STARFIELD:
mode = new Starfield(display);
diff --git a/src/mode/CountDown/CountDown.h b/src/mode/CountDown/CountDown.h
index 329b234..bbba1b4 100644
--- a/src/mode/CountDown/CountDown.h
+++ b/src/mode/CountDown/CountDown.h
@@ -14,14 +14,22 @@ private:
uint16_t days = 0;
+ uint16_t hours = 0;
+
+ uint16_t minutes = 0;
+
+ uint16_t seconds = 0;
+
uint8_t level = 0;
bool bars;
+ bool plus1DayForSleepingCount;
+
public:
- CountDown(Display &display, bool bars) :
- Mode(display), bars(bars) {
+ CountDown(Display &display, bool bars, bool plus1DayForSleepingCount) :
+ Mode(display), bars(bars), plus1DayForSleepingCount(plus1DayForSleepingCount) {
for (auto &firework: fireworks) {
firework.init(display);
}
@@ -40,25 +48,45 @@ protected:
void step(microseconds_t microseconds) override {
if (!realtimeOK) {
setMode(NO_TIME);
- } else if (now.tm_mon != 1 || now.tm_mday != 1 || now.tm_hour != 0) {
- days = getDayCountForYear(now.tm_year) - now.tm_yday - 1;
- setMode(COUNTDOWN);
- if (days == 0) {
- loopLastDay();
- } else {
- loopMultipleDays();
- }
- } else {
+ return;
+ }
+ if (dateReached()) {
setMode(FIREWORK);
for (auto &firework: fireworks) {
firework.step(microseconds);
}
markDirty();
+ return;
+ }
+
+ // GRRRRRRR...
+ config.date.tm_year -= 1900;
+ config.date.tm_mon -= 1;
+ const time_t dateEpochSeconds = mktime(&config.date);
+ config.date.tm_year += 1900;
+ config.date.tm_mon += 1;
+ // ---
+
+ const double diffSeconds = difftime(dateEpochSeconds, nowEpochSeconds);
+ days = (int) floor(diffSeconds / (24 * 60 * 60));
+ hours = (int) floor(diffSeconds / (60 * 60)) % 24;
+ minutes = (int) floor(diffSeconds / 60) % 60;
+ seconds = (int) diffSeconds % 60;
+// Serial.printf("now=%4d.%02d.%02d (%ld), conf=%4d.%02d.%02d (%ld), diff=%f, %dd %2d:%02d:%02d\n",
+// now.tm_year, now.tm_mon, now.tm_mday, nowEpochSeconds,
+// config.date.tm_year, config.date.tm_mon, config.date.tm_mday, dateEpochSeconds,
+// diffSeconds,
+// days, hours, minutes, seconds);
+ setMode(COUNTDOWN);
+ if (days == 0) {
+ loopLastDay();
+ } else {
+ loopMultipleDays();
}
}
void loopLastDay() {
- int levelTmp = (int) round(32 * realtimeMilliseconds / 1000.0);;
+ int levelTmp = (int) round(32 * realtimeMilliseconds / 1000.0);
if (level != levelTmp) {
level = levelTmp;
markDirty();
@@ -71,17 +99,21 @@ protected:
}
}
+ bool dateReached() {
+ return now.tm_year == config.date.tm_year && now.tm_mon == config.date.tm_mon && now.tm_mday == config.date.tm_mday;
+ }
+
void draw(Display &display) override {
display.clear();
if (!realtimeOK) {
drawNoTime(display);
- } else if (now.tm_mon == 1 && now.tm_mday == 1 && now.tm_hour == 0) {
+ } else if (dateReached()) {
for (auto &firework: fireworks) {
firework.draw(display);
}
drawYear(display, now.tm_year);
} else {
- drawCountdown(display, now);
+ drawCountdown(display);
}
}
@@ -102,25 +134,37 @@ private:
}
}
- void drawCountdown(Display &display, const tm &now) {
- uint8_t hours = (24 - now.tm_hour - (now.tm_min > 0 || now.tm_sec > 0 ? 1 : 0));
- uint8_t minutes = (60 - now.tm_min - (now.tm_sec > 0 ? 1 : 0)) % 60;
- uint8_t seconds = (60 - now.tm_sec) % 60;
- if (days <= 0 && bars) {
- drawCountdownBars(display, hours, minutes, seconds);
+ void drawCountdown(Display &display) {
+ if (plus1DayForSleepingCount) {
+ drawSleepingCount(display);
+ } else if (days <= 0 && bars) {
+ drawCountdownBars(display);
} else {
- drawCountdownNumbers(display, hours, minutes, seconds);
+ drawCountdownNumbers(display);
}
}
- void drawCountdownBars(Display &display, uint8_t hours, uint8_t minutes, uint8_t seconds) {
- drawBar(display, 0, 0, 24, 1, 0, 24, hours, RED, MAGENTA, 0);
- drawBar(display, 0, 2, 30, 2, 0, 60, minutes, BLUE, VIOLET, 5);
- drawBar(display, 0, 5, 30, 2, 0, 60, seconds, GREEN, YELLOW, 5);
+ void drawSleepingCount(Display &display) const {
+ int sleepCount = days + 1;
+ int y = 1;
+ uint8_t x = display.print2(3 * (DISPLAY_CHAR_WIDTH + 1), y, sleepCount, WHITE);
+ x += 2;
+ x += display.print(x, y, SYMBOL_T, WHITE, true) + 1;
+ x += display.print(x, y, SYMBOL_A, WHITE, true) + 1;
+ x += display.print(x, y, SYMBOL_G, WHITE, true) + 1;
+ if (sleepCount != 1) {
+ display.print(x, y, SYMBOL_E, WHITE, true);
+ }
}
- void drawBar(Display &display, uint8_t _x, uint8_t _y, uint8_t _w, uint8_t _h, uint8_t min, uint8_t max, uint8_t value, const Color &color, const Color &tickColor, uint8_t ticks) {
- auto totalOnCount = (uint8_t) round(((double) value - min) / (max - min) * _w * _h);
+ void drawCountdownBars(Display &display) const {
+ drawBar(display, 0, 24, 1, 24, hours, RED, MAGENTA, 0);
+ drawBar(display, 2, 30, 2, 60, minutes, BLUE, VIOLET, 5);
+ drawBar(display, 5, 30, 2, 60, seconds, GREEN, YELLOW, 5);
+ }
+
+ static void drawBar(Display &display, uint8_t _y, uint8_t _w, uint8_t _h, uint8_t max, uint8_t value, const Color &color, const Color &tickColor, uint8_t ticks) {
+ auto totalOnCount = (uint8_t) round((double) value / max * _w * _h);
uint8_t doneOnCount = 0;
for (uint8_t y = 0; y < _h; y++) {
for (uint8_t x = 0; x < _w; x++) {
@@ -134,20 +178,12 @@ private:
c = tickColor;
}
}
- display.set(_x + x, _y + y, c);
+ display.set(x, _y + y, c);
}
}
}
- static Color factor(Color color, double factor) {
- return {
- (uint8_t) round(color.r * factor),
- (uint8_t) round(color.g * factor),
- (uint8_t) round(color.b * factor),
- };
- }
-
- void drawCountdownNumbers(Display &display, uint8_t hours, uint8_t minutes, uint8_t seconds) const {
+ void drawCountdownNumbers(Display &display) const {
uint8_t x = 0;
if (days > 0) {
drawDay(display, days, &x);
@@ -179,40 +215,36 @@ private:
x += display.print(x, 1, 10, WHITE, true);
x += display.print(x, 1, SYMBOL_DASH, WHITE, true);
x++;
- x += display.print(x, 1, SYMBOL_DASH, WHITE, true);
+ display.print(x, 1, SYMBOL_DASH, WHITE, true);
}
static void drawDay(Display &display, int days, uint8_t *x) {
if (days >= 100) {
- *x += display.print(*x, 1, days / 100, WHITE, true);
+ *x += display.print(*x, 1, days / 100, WHITE, true) + 1;
} else {
- *x += 3;
+ *x += DISPLAY_CHAR_WIDTH + 1;
}
- (*x)++;
if (days >= 10) {
- *x += display.print(*x, 1, days / 10 % 10, WHITE, true);
+ *x += display.print(*x, 1, days / 10 % 10, WHITE, true) + 1;
} else {
- *x += 3;
+ *x += DISPLAY_CHAR_WIDTH + 1;
}
- (*x)++;
*x += display.print(*x, 1, days % 10, WHITE, true);
}
static void drawHour(Display &display, int days, int hours, uint8_t *x) {
if (days > 0 || hours >= 10) {
- *x += display.print(*x, 1, hours / 10, WHITE, true);
+ *x += display.print(*x, 1, hours / 10, WHITE, true) + 1;
} else {
- *x += 3;
+ *x += DISPLAY_CHAR_WIDTH + 1;
}
- (*x)++;
*x += display.print(*x, 1, hours % 10, WHITE, true);
}
static void draw2Digit(Display &display, int value, uint8_t *x) {
- *x += display.print(*x, 1, value / 10, WHITE, true);
- (*x)++;
+ *x += display.print(*x, 1, value / 10, WHITE, true) + 1;
*x += display.print(*x, 1, value % 10, WHITE, true);
}
@@ -234,23 +266,12 @@ private:
}
}
- static int getDayCountForYear(int year) {
- bool leapYear = year % 4 == 0 && (year % 400 == 0 || year % 100 != 0);
- if (leapYear) {
- return 366;
- }
- return 365;
- }
-
static void drawYear(Display &display, int year) {
uint8_t x = 8;
- x += display.print(x, 1, year / 1000 % 10, WHITE, true);
- x++;
- x += display.print(x, 1, year / 100 % 10, WHITE, true);
- x++;
- x += display.print(x, 1, year / 10 % 10, WHITE, true);
- x++;
- x += display.print(x, 1, year / 1 % 10, WHITE, true);
+ x += display.print(x, 1, year / 1000 % 10, WHITE, true) + 1;
+ x += display.print(x, 1, year / 100 % 10, WHITE, true) + 1;
+ x += display.print(x, 1, year / 10 % 10, WHITE, true) + 1;
+ display.print(x, 1, year / 1 % 10, WHITE, true);
}
};
diff --git a/src/mode/Mode.h b/src/mode/Mode.h
index e59b1a9..9536657 100644
--- a/src/mode/Mode.h
+++ b/src/mode/Mode.h
@@ -21,6 +21,7 @@ enum ModeId {
SPACE_INVADERS,
COUNT_DOWN,
COUNT_DOWN_BARS,
+ COUNT_DOWN_SLEEP,
STARFIELD,
MATRIX,
POWER,
@@ -63,7 +64,7 @@ protected:
milliseconds_t realtimeMilliseconds = 0;
- time_t epoch = 0;
+ time_t nowEpochSeconds = 0;
virtual void tick(uint8_t index, microseconds_t microseconds) {};
@@ -127,9 +128,9 @@ private:
tmp += ((FAKE_DAYS * 24 + FAKE_HOURS) * 60 + FAKE_MINUTES) * 60 + FAKE_SECONDS;
realtimeOK = tmp > 1600000000;
if (realtimeOK) {
- realtimeChanged = epoch != tmp;
+ realtimeChanged = nowEpochSeconds != tmp;
if (realtimeChanged) {
- epoch = tmp;
+ nowEpochSeconds = tmp;
localtime_r(&tmp, &now);
now.tm_year += 1900;
now.tm_mon += 1;
diff --git a/src/server.cpp b/src/server.cpp
index 7c26226..37f5591 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -13,7 +13,7 @@ body {
font-size: 8vw;
margin: 0;
}
-button{
+button.player{
width: 33vmin;
height: 33vmin;
font-size: 9vw;
@@ -61,6 +61,8 @@ void web_fps_on();
void web_fps_off();
+void web_config_date();
+
void server_setup() {
server.on("/", web_index);
server.on("/player", web_player);
@@ -73,6 +75,7 @@ void server_setup() {
server.on("/slower", web_slower);
server.on("/fps/on", web_fps_on);
server.on("/fps/off", web_fps_off);
+ server.on("/config/date", web_config_date);
server.begin();
}
@@ -103,10 +106,11 @@ void web_index() {
server.sendContent(R"(SPACE_INVADERS
)");
server.sendContent(R"(COUNT_DOWN
)");
server.sendContent(R"(COUNT_DOWN_BARS
)");
- server.sendContent(R"(STARFIELD
)");
- server.sendContent(R"(MATRIX
)");
- server.sendContent(R"(POWER
)");
- server.sendContent(R"(ENERGY
)");
+ server.sendContent(R"(COUNT_DOWN_SLEEP
)");
+ server.sendContent(R"(STARFIELD
)");
+ server.sendContent(R"(MATRIX
)");
+ server.sendContent(R"(POWER
)");
+ server.sendContent(R"(ENERGY
)");
server.sendContent(R"(
)");
server.sendContent(R"()");
@@ -114,6 +118,14 @@ void web_index() {
server.sendContent(R"(Geschwindigkeit: + / -
)");
server.sendContent(R"(FPS: EIN / AUS
)");
server.sendContent(R"(
)");
+
+ server.sendContent(R"()");
+ server.sendContent(R"()");
+ server.sendContent(R"()");
+ server.sendContent(R"()");
+ server.sendContent(R"()");
+ server.sendContent(R"(
)");
+
server.client().flush();
}
@@ -141,7 +153,7 @@ void web_player() {
server.sendContent(R"(← | )");
server.sendContent(R"()");
- snprintf(buffer, sizeof buffer, R"( )", index);
+ snprintf(buffer, sizeof buffer, R"( )", index);
server.sendContent(buffer);
server.sendContent(R"( | )");
@@ -152,17 +164,17 @@ void web_player() {
server.sendContent(R"()");
server.sendContent(R"()");
- snprintf(buffer, sizeof buffer, R"( )", index);
+ snprintf(buffer, sizeof buffer, R"( )", index);
server.sendContent(buffer);
server.sendContent(R"( | )");
server.sendContent(R"()");
- snprintf(buffer, sizeof buffer, R"( )", index);
+ snprintf(buffer, sizeof buffer, R"( )", index);
server.sendContent(buffer);
server.sendContent(R"( | )");
server.sendContent(R"()");
- snprintf(buffer, sizeof buffer, R"( )", index);
+ snprintf(buffer, sizeof buffer, R"( )", index);
server.sendContent(buffer);
server.sendContent(R"( | )");
@@ -173,7 +185,7 @@ void web_player() {
server.sendContent(R"( | )");
server.sendContent(R"()");
- snprintf(buffer, sizeof buffer, R"( )", index);
+ snprintf(buffer, sizeof buffer, R"( )", index);
server.sendContent(buffer);
server.sendContent(R"( | )");
@@ -272,3 +284,19 @@ void web_fps_off() {
display.fpsShow = false;
server.send(200);
}
+
+void web_config_date() {
+ double year = strtod(server.arg("year").c_str(), nullptr);
+ double month = strtod(server.arg("month").c_str(), nullptr);
+ double day = strtod(server.arg("day").c_str(), nullptr);
+ if (!isnan(year)) {
+ config.date.tm_year = (int) year;
+ config.date.tm_mon = (int) month;
+ config.date.tm_mday = (int) day;
+ config.date.tm_hour = 0;
+ config.date.tm_min = 0;
+ config.date.tm_sec = 0;
+ server.send(200);
+ }
+ server.send(400);
+}