Emil 5. Geburtstag + Creeper

This commit is contained in:
Patrick Haßel 2025-01-19 23:59:22 +01:00
parent 0d73d112b1
commit 6b4ed1658c
3 changed files with 482 additions and 373 deletions

View File

@ -1,145 +1,180 @@
#include "Display.h" #include "Display.h"
bool SYMBOLS[SYMBOL_COUNT][DISPLAY_CHAR_WIDTH * DISPLAY_CHAR_HEIGHT] = { 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, 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, 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, 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, _, _,
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, 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,
_, 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, _, _, 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,
_, 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, 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, _, _,
X, _, _,
X, _, _,
X, _, _,
X, X, X,
},
{
_, _, _,
_, _, _,
_, _, _,
_, _, _,
_, _, _,
},
// this must always be the last symbol (fallback)
{
X, X, X,
X, X, X,
X, X, X,
X, X, X,
X, X, X,
},
}; };

View File

@ -5,15 +5,21 @@
#include "Adafruit_NeoPixel.h" #include "Adafruit_NeoPixel.h"
#include "Vector.h" #include "Vector.h"
#define SYMBOL_COUNT 20 #define SYMBOL_COUNT 26
#define SYMBOL_J 11
#define SYMBOL_X 12
#define SYMBOL_DASH 13 #define SYMBOL_DASH 13
#define SYMBOL_PERCENT 14 #define SYMBOL_PERCENT 14
#define SYMBOL_T 15 #define SYMBOL_T 15
#define SYMBOL_A 16 #define SYMBOL_A 16
#define SYMBOL_G 17 #define SYMBOL_G 17
#define SYMBOL_E 18 #define SYMBOL_E 18
#define SYMBOL_H 19
#define SYMBOL_R 20
#define SYMBOL_I 21
#define SYMBOL_L 22
#define SYMBOL_SPACE 23
#define DISPLAY_CHAR_WIDTH 3 #define DISPLAY_CHAR_WIDTH 3
#define DISPLAY_CHAR_HEIGHT 5 #define DISPLAY_CHAR_HEIGHT 5
@ -48,11 +54,10 @@ private:
public: public:
Display(uint8_t width, uint8_t height) : Display(uint8_t width, uint8_t height) : width(width), height(height),
width(width), height(height), pixelCount(width * height),
pixelCount(width * height), pixelByteCount(pixelCount * sizeof(Color)),
pixelByteCount(pixelCount * sizeof(Color)), leds(pixelCount, GPIO_NUM_13) {
leds(pixelCount, GPIO_NUM_13) {
buffer = (Color *) malloc(pixelByteCount); buffer = (Color *) malloc(pixelByteCount);
if (buffer == nullptr) { if (buffer == nullptr) {
Serial.print("+-----------------------------------------------+\n"); Serial.print("+-----------------------------------------------+\n");
@ -130,15 +135,15 @@ public:
} }
bool showIfZero = false; bool showIfZero = false;
// Serial.printf("x=%d, y=%d, value=%d, align=%s, digitCount=%d, divider=%d\n", x, y, value, align == LEFT ? "LEFT" : "RIGHT", digitCount, divider); // Serial.printf("x=%d, y=%d, value=%d, align=%s, digitCount=%d, divider=%d\n", x, y, value, align == LEFT ? "LEFT" : "RIGHT", digitCount, divider);
for (int digitPos = 0; digitPos < digitCount; ++digitPos) { for (int digitPos = 0; digitPos < digitCount; ++digitPos) {
const int digitVal = value / divider % 10; const int digitVal = value / divider % 10;
showIfZero |= digitVal != 0 || (digitPos == digitCount - 1); showIfZero |= digitVal != 0 || (digitPos == digitCount - 1);
x += print(x, y, digitVal, color, showIfZero) + 1; x += print(x, y, digitVal, color, showIfZero) + 1;
// Serial.printf(" digitPos=%d, x=%d, y=%d, digitVal=%d, showIfZero=%s, divider=%d\n", digitPos, x, y, digitVal, showIfZero ? "true" : "false", divider); // Serial.printf(" digitPos=%d, x=%d, y=%d, digitVal=%d, showIfZero=%s, divider=%d\n", digitPos, x, y, digitVal, showIfZero ? "true" : "false", divider);
divider /= 10; divider /= 10;
} }
// Serial.println(); // Serial.println();
return x; return x;
} }
@ -164,6 +169,57 @@ public:
return DISPLAY_CHAR_WIDTH; return DISPLAY_CHAR_WIDTH;
} }
// TODO REMOVE QUICK & DIRTY
uint8_t printM(uint8_t xPos, uint8_t yPos, Color color) {
bool sym[5][5] = {
{X,_,_,_,X},
{X,X,_,X,X},
{X,_,X,_,X},
{X,_,_,_,X},
{X,_,_,_,X},
};
for (int y = 0; y < countof(sym); ++y) {
for (int x = 0; x < countof(sym[0]); ++x) {
if (sym[y][x]) {
set(xPos + x, yPos + y, color);
} else {
set(xPos + x, yPos + y, BLACK);
}
}
}
return countof(sym[0]);
}
// TODO REMOVE QUICK & DIRTY
uint8_t printCreeper(uint8_t xPos, uint8_t yPos) {
Color G = GREEN;
Color I = {128, 255, 128};
Color O = BLACK;
Color sym[7][7] = {
{G, G, G, G, G, G, G},
{G, I, I, I, I, I, G},
{G, I, O, I, O, I, G},
{G, I, I, I, I, I, G},
{G, I, O, O, O, I, G},
{G, I, O, I, O, I, G},
{G, G, G, G, G, G, G},
};
for (int y = 0; y < countof(sym); ++y) {
for (int x = 0; x < countof(sym[0]); ++x) {
set(xPos + x, yPos + y, sym[y][x]);
}
}
return countof(sym[0]);
}
// TODO REMOVE QUICK & DIRTY
uint8_t printI(uint8_t xPos, uint8_t yPos, Color color) {
for (int y = 0; y < 5; ++y) {
set(xPos, yPos + y, color);
}
return 1;
}
void set(Vector pos, Color color) { void set(Vector pos, Color color) {
set((uint8_t) round(pos.x), (uint8_t) round(pos.y), color); set((uint8_t) round(pos.x), (uint8_t) round(pos.y), color);
} }
@ -183,10 +239,10 @@ public:
return; return;
} }
buffer[index] = { buffer[index] = {
// yes, correct order is GRB !!! // yes, correct order is GRB !!!
(uint8_t) (color.g * brightness >> 8), (uint8_t) (color.g * brightness >> 8),
(uint8_t) (color.r * brightness >> 8), (uint8_t) (color.r * brightness >> 8),
(uint8_t) (color.b * brightness >> 8) (uint8_t) (color.b * brightness >> 8)
}; };
} }

View File

@ -1,7 +1,7 @@
#ifndef MODE_COUNT_DOWN_H #ifndef MODE_COUNT_DOWN_H
#define MODE_COUNT_DOWN_H #define MODE_COUNT_DOWN_H
#define MAX_FIREWORKS 5 #define MAX_FIREWORKS 6
#include "mode/Mode.h" #include "mode/Mode.h"
#include "CountDownFirework.h" #include "CountDownFirework.h"
@ -10,269 +10,287 @@ class CountDown : public Mode {
private: private:
Firework fireworks[MAX_FIREWORKS]; Firework fireworks[MAX_FIREWORKS];
uint16_t days = 0; uint16_t days = 0;
uint16_t hours = 0; uint16_t hours = 0;
uint16_t minutes = 0; uint16_t minutes = 0;
uint16_t seconds = 0; uint16_t seconds = 0;
uint8_t level = 0; uint8_t level = 0;
bool bars; bool bars;
bool plus1DayForSleepingCount; bool plus1DayForSleepingCount;
public: public:
CountDown(Display &display, bool bars, bool plus1DayForSleepingCount) : CountDown(Display& display, bool bars, bool plus1DayForSleepingCount) : Mode(display), bars(bars), plus1DayForSleepingCount(plus1DayForSleepingCount) {
Mode(display), bars(bars), plus1DayForSleepingCount(plus1DayForSleepingCount) { for (auto& firework: fireworks) {
for (auto &firework: fireworks) { firework.init(display);
firework.init(display);
}
} }
}
const char *getName() override { const char *getName() override {
if (bars) { if (bars) {
return "CountDown (Bars)"; return "CountDown (Bars)";
} else { } else {
return "CountDown (Numbers)"; return "CountDown (Numbers)";
}
} }
}
protected: protected:
void step(microseconds_t microseconds) override { void step(microseconds_t microseconds) override {
if (!realtimeOK) { if (!realtimeOK) {
setMode(NO_TIME); setMode(NO_TIME);
return; return;
} }
if (dateReached()) { if (dateReached()) {
setMode(FIREWORK); setMode(FIREWORK);
for (auto &firework: fireworks) { for (auto& firework: fireworks) {
firework.step(microseconds); 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();
} }
markDirty();
return;
} }
void loopLastDay() { // GRRRRRRR...
int levelTmp = (int) round(32 * realtimeMilliseconds / 1000.0); config.date.tm_year -= 1900;
if (level != levelTmp) { config.date.tm_mon -= 1;
level = levelTmp; const time_t dateEpochSeconds = mktime(&config.date);
markDirty(); config.date.tm_year += 1900;
} config.date.tm_mon += 1;
} // ---
void loopMultipleDays() { const double diffSeconds = difftime(dateEpochSeconds, nowEpochSeconds);
if (realtimeChanged) { days = (int) floor(diffSeconds / (24 * 60 * 60));
markDirty(); 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();
} }
}
bool dateReached() { void loopLastDay() {
return now.tm_year == config.date.tm_year && now.tm_mon == config.date.tm_mon && now.tm_mday == config.date.tm_mday; int levelTmp = (int) round(32 * realtimeMilliseconds / 1000.0);
if (level != levelTmp) {
level = levelTmp;
markDirty();
} }
}
void draw(Display &display) override { void loopMultipleDays() {
display.clear(); if (realtimeChanged) {
if (!realtimeOK) { markDirty();
drawNoTime(display);
} else if (dateReached()) {
for (auto &firework: fireworks) {
firework.draw(display);
}
drawYear(display, now.tm_year);
} else {
drawCountdown(display);
}
} }
}
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 (dateReached()) {
for (auto& firework: fireworks) {
firework.draw(display);
}
drawYear(display, now.tm_year);
} else {
drawCountdown(display);
}
}
private: private:
enum State { enum State {
NO_TIME, NO_TIME,
COUNTDOWN, COUNTDOWN,
FIREWORK, FIREWORK,
}; };
State _state = NO_TIME; State _state = NO_TIME;
void setMode(State state) { void setMode(State state) {
if (_state != state) { if (_state != state) {
_state = state; _state = state;
markDirty(); markDirty();
}
}
void drawCountdown(Display& display) {
if (plus1DayForSleepingCount) {
drawSleepingCount(display);
} else if (days <= 0 && bars) {
drawCountdownBars(display);
} else {
drawCountdownNumbers(display);
}
}
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 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++) {
if (doneOnCount >= totalOnCount) {
return;
}
doneOnCount++;
Color c = color;
if (ticks != 0) {
if (doneOnCount % ticks == 0) {
c = tickColor;
}
}
display.set(x, _y + y, c);
} }
} }
}
void drawCountdown(Display &display) { void drawCountdownNumbers(Display& display) const {
if (plus1DayForSleepingCount) { uint8_t x = 0;
drawSleepingCount(display); if (days > 0) {
} else if (days <= 0 && bars) { drawDay(display, days, &x);
drawCountdownBars(display); x += display.print(x, 1, 10, WHITE, true);
} else { } else {
drawCountdownNumbers(display);
}
}
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 += 2;
x += display.print(x, y, SYMBOL_T, WHITE, true) + 1; }
x += display.print(x, y, SYMBOL_A, WHITE, true) + 1; drawHour(display, days, hours, &x);
x += display.print(x, y, SYMBOL_G, WHITE, true) + 1; x += display.print(x, 1, 10, WHITE, true);
if (sleepCount != 1) { draw2Digit(display, minutes, &x);
display.print(x, y, SYMBOL_E, WHITE, true); if (days <= 0) {
x += display.print(x, 1, 10, WHITE, true);
draw2Digit(display, seconds, &x);
drawSubSecondsBar(display);
} else {
drawSecondsBar(display, seconds);
}
}
static void drawNoTime(Display& display) {
uint8_t x = 2;
x += display.print(x, 1, SYMBOL_DASH, WHITE, true);
x++;
x += display.print(x, 1, SYMBOL_DASH, WHITE, true);
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);
x += display.print(x, 1, 10, WHITE, true);
x += display.print(x, 1, SYMBOL_DASH, WHITE, true);
x++;
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) + 1;
} else {
*x += DISPLAY_CHAR_WIDTH + 1;
}
if (days >= 10) {
*x += display.print(*x, 1, days / 10 % 10, WHITE, true) + 1;
} else {
*x += DISPLAY_CHAR_WIDTH + 1;
}
*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) + 1;
} else {
*x += DISPLAY_CHAR_WIDTH + 1;
}
*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) + 1;
*x += display.print(*x, 1, value % 10, WHITE, true);
}
static void drawSecondsBar(Display& display, int seconds) {
for (int pos = 0; pos < 30; pos++) {
if (pos <= seconds - 30) {
display.set(pos + 1, 7, GREEN);
} else if (pos <= seconds) {
display.set(pos + 1, 7, RED);
} }
} }
}
void drawCountdownBars(Display &display) const { void drawSubSecondsBar(Display& display) const {
drawBar(display, 0, 24, 1, 24, hours, RED, MAGENTA, 0); for (int pos = 0; pos < 32; pos++) {
drawBar(display, 2, 30, 2, 60, minutes, BLUE, VIOLET, 5); if (pos < 32 - level) {
drawBar(display, 5, 30, 2, 60, seconds, GREEN, YELLOW, 5); display.set(pos, 7, GREEN);
}
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++) {
if (doneOnCount >= totalOnCount) {
return;
}
doneOnCount++;
Color c = color;
if (ticks != 0) {
if (doneOnCount % ticks == 0) {
c = tickColor;
}
}
display.set(x, _y + y, c);
}
} }
} }
}
void drawCountdownNumbers(Display &display) const { // ReSharper disable CppDFAUnusedValue
void drawYear(Display& display, int year) const {
if (plus1DayForSleepingCount) {
uint8_t x = 0; uint8_t x = 0;
if (days > 0) { x += display.print(x, 1,SYMBOL_E, WHITE, true);
drawDay(display, days, &x); x += 1;
x += display.print(x, 1, 10, WHITE, true); x += display.printM(x, 1, WHITE);
} else { x += 1;
x += 2; x += display.printI(x, 1, WHITE);
} x += 1;
drawHour(display, days, hours, &x); x += display.print(x, 1,SYMBOL_L, WHITE, true);
x += display.print(x, 1, 10, WHITE, true); x += 4;
draw2Digit(display, minutes, &x); x += display.print(x, 1, 5, WHITE, true);
if (days <= 0) { x += 2;
x += display.print(x, 1, 10, WHITE, true); display.printCreeper(x, 0);
draw2Digit(display, seconds, &x); } else {
drawSubSecondsBar(display);
} else {
drawSecondsBar(display, seconds);
}
}
static void drawNoTime(Display &display) {
uint8_t x = 2;
x += display.print(x, 1, SYMBOL_DASH, WHITE, true);
x++;
x += display.print(x, 1, SYMBOL_DASH, WHITE, true);
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);
x += display.print(x, 1, 10, WHITE, true);
x += display.print(x, 1, SYMBOL_DASH, WHITE, true);
x++;
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) + 1;
} else {
*x += DISPLAY_CHAR_WIDTH + 1;
}
if (days >= 10) {
*x += display.print(*x, 1, days / 10 % 10, WHITE, true) + 1;
} else {
*x += DISPLAY_CHAR_WIDTH + 1;
}
*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) + 1;
} else {
*x += DISPLAY_CHAR_WIDTH + 1;
}
*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) + 1;
*x += display.print(*x, 1, value % 10, WHITE, true);
}
static void drawSecondsBar(Display &display, int seconds) {
for (int pos = 0; pos < 30; pos++) {
if (pos <= seconds - 30) {
display.set(pos + 1, 7, GREEN);
} else if (pos <= seconds) {
display.set(pos + 1, 7, RED);
}
}
}
void drawSubSecondsBar(Display &display) const {
for (int pos = 0; pos < 32; pos++) {
if (pos < 32 - level) {
display.set(pos, 7, GREEN);
}
}
}
static void drawYear(Display &display, int year) {
uint8_t x = 8; uint8_t x = 8;
x += display.print(x, 1, year / 1000 % 10, WHITE, true) + 1; 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 / 100 % 10, WHITE, true) + 1;
x += display.print(x, 1, year / 10 % 10, WHITE, true) + 1; x += display.print(x, 1, year / 10 % 10, WHITE, true) + 1;
display.print(x, 1, year / 1 % 10, WHITE, true); x += display.print(x, 1, year / 1 % 10, WHITE, true);
} }
}
// ReSharper restore CppDFAUnusedValue
}; };