RGBMatrixDisplay/src/mode/Mode.h

144 lines
2.7 KiB
C++

#ifndef MODE_H
#define MODE_H
#include "BASICS.h"
#include "display/Display.h"
enum ModeId {
NONE,
BORDER,
CLOCK,
GAME_OF_LIFE_BLACK_WHITE,
GAME_OF_LIFE_GRAYSCALE,
GAME_OF_LIFE_COLOR_FADE,
GAME_OF_LIFE_RANDOM_COLOR,
PONG,
SPACE_INVADERS,
NEW_YEAR,
STARFIELD,
};
class Mode {
private:
struct Timer {
milliseconds_t interval;
milliseconds_t last;
};
Display &_display;
bool dirty = true;
Timer timers[2] = {
{0, 0},
{0, 0},
};
int8_t lastSecond = -1;
milliseconds_t lastSecondChange_Milliseconds = 0;
protected:
const uint8_t width;
const uint8_t height;
bool realtimeOK = false;
bool realtimeChanged = false;
tm now = {0, 0, 0, 0, 0, 0, 0, 0, 0};
milliseconds_t realtimeMilliseconds;
time_t epoch = 0;
virtual void tick(uint8_t index, milliseconds_t milliseconds) {};
virtual void step(microseconds_t microseconds) {};
virtual void draw(Display &display) {};
void timer(uint8_t index, milliseconds_t interval) {
if (index >= countof(timers)) {
return;
}
timers[index].interval = interval;
timers[index].last = millis();
}
void markDirty() {
dirty = true;
}
public:
explicit Mode(Display &display) :
_display(display),
width(display.width),
height(display.height) {
// nothing
}
virtual ~Mode() = default;
virtual const char *getName() = 0;
void loop(microseconds_t micros) {
handleRealtime();
handleTimers();
step(micros);
if (dirty) {
dirty = false;
draw(_display);
}
}
private:
void handleRealtime() {
time_t tmp;
time(&tmp);
realtimeOK = tmp > 1600000000;
if (realtimeOK) {
realtimeChanged = epoch != tmp;
if (realtimeChanged) {
epoch = tmp;
localtime_r(&tmp, &now);
now.tm_year += 1900;
now.tm_mon += 1;
}
} else {
realtimeChanged = false;
}
if (lastSecond < 0 || lastSecond != now.tm_sec) {
lastSecond = (int8_t) now.tm_sec;
lastSecondChange_Milliseconds = millis();
}
realtimeMilliseconds = millis() - lastSecondChange_Milliseconds;
}
void handleTimers() {
milliseconds_t ms = millis();
for (Timer *timer = timers; timer < timers + countof(timers); timer++) {
if (timer->interval > 0) {
milliseconds_t milliseconds = ms - timer->last;
if (milliseconds >= timer->interval) {
timer->last = ms;
tick(timer - timers, milliseconds);
}
}
}
}
};
#endif