132 lines
2.2 KiB
C++
132 lines
2.2 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 {
|
|
millis_t interval;
|
|
millis_t last;
|
|
};
|
|
|
|
Display &_display;
|
|
|
|
bool dirty = true;
|
|
|
|
Timer timers[2] = {
|
|
{0, 0},
|
|
{0, 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};
|
|
|
|
time_t epoch = 0;
|
|
|
|
virtual void tick(uint8_t index, millis_t dt) {};
|
|
|
|
virtual void step(microseconds_t dt) {};
|
|
|
|
virtual void draw(Display &display) {};
|
|
|
|
void timer(uint8_t index, millis_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 dt) {
|
|
realtime();
|
|
|
|
handleTimers();
|
|
|
|
step(dt);
|
|
|
|
if (dirty) {
|
|
dirty = false;
|
|
draw(_display);
|
|
}
|
|
}
|
|
|
|
private:
|
|
|
|
void realtime() {
|
|
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;
|
|
}
|
|
}
|
|
|
|
void handleTimers() {
|
|
millis_t ms = millis();
|
|
for (Timer *timer = timers; timer < timers + sizeof(timers); timer++) {
|
|
if (timer->interval > 0) {
|
|
millis_t dt = ms - timer->last;
|
|
if (dt >= timer->interval) {
|
|
timer->last = ms;
|
|
tick(timer - timers, dt);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
};
|
|
|
|
#endif
|