ModeBase with 'instance'
This commit is contained in:
parent
328785d187
commit
e47bc86299
@ -13,7 +13,7 @@ platform = espressif32
|
||||
board = esp32dev
|
||||
framework = arduino
|
||||
lib_deps = https://github.com/adafruit/Adafruit_NeoPixel
|
||||
build_flags = -D PROG_ALL=true
|
||||
build_flags = -D ENABLE_ALL=true -D ENABLE_OTA=false
|
||||
;upload_port = 10.0.0.120
|
||||
;upload_protocol = espota
|
||||
upload_port = /dev/ttyUSB0
|
||||
|
||||
17
src/main.cpp
17
src/main.cpp
@ -1,10 +1,14 @@
|
||||
#include <WiFi.h>
|
||||
|
||||
#if ENABLE_OTA
|
||||
#include <ArduinoOTA.h>
|
||||
#endif
|
||||
|
||||
#include "mode/Mode.h"
|
||||
#include "display/Display.h"
|
||||
#include <WebServer.h>
|
||||
|
||||
#if PROG_ALL
|
||||
#if ENABLE_ALL
|
||||
|
||||
#include "mode/GameOfLife/GameOfLife.h"
|
||||
#include "mode/Pong/Pong.h"
|
||||
@ -18,7 +22,7 @@
|
||||
|
||||
enum ModeId {
|
||||
NONE,
|
||||
#if PROG_ALL
|
||||
#if ENABLE_ALL
|
||||
BORDER,
|
||||
CLOCK,
|
||||
GAME_OF_LIFE_BLACK_WHITE,
|
||||
@ -41,7 +45,7 @@ ModeId currentModeId = NONE;
|
||||
|
||||
microseconds_t lastMicros = 0;
|
||||
|
||||
Mode *mode = nullptr;
|
||||
ModeBase *mode = nullptr;
|
||||
|
||||
double speed = 1.0;
|
||||
|
||||
@ -107,6 +111,8 @@ void setup() {
|
||||
Serial.println("\n\n\nStartup!");
|
||||
|
||||
WiFi.begin("HappyNet", "1Grausame!Sackratte7");
|
||||
|
||||
#if ENABLE_OTA
|
||||
ArduinoOTA.onStart([]() {
|
||||
display.clear();
|
||||
display.loop();
|
||||
@ -127,6 +133,7 @@ void setup() {
|
||||
display.loop();
|
||||
});
|
||||
ArduinoOTA.begin();
|
||||
#endif
|
||||
|
||||
server.on("", web_index);
|
||||
server.on("/", web_index);
|
||||
@ -144,7 +151,9 @@ void setup() {
|
||||
void setSpeed(double value);
|
||||
|
||||
void loop() {
|
||||
#if ENABLE_OTA
|
||||
ArduinoOTA.handle();
|
||||
#endif
|
||||
server.handleClient();
|
||||
bool hasIp = (uint32_t) WiFi.localIP() != 0;
|
||||
if (!connected) {
|
||||
@ -225,7 +234,7 @@ void loadNewMode() {
|
||||
switch (currentModeId) {
|
||||
case NONE:
|
||||
break;
|
||||
#if PROG_ALL
|
||||
#if ENABLE_ALL
|
||||
case BORDER:
|
||||
mode = new Border(&display);
|
||||
break;
|
||||
|
||||
4
src/mode/Clock/Clock.cpp
Normal file
4
src/mode/Clock/Clock.cpp
Normal file
@ -0,0 +1,4 @@
|
||||
#include "Clock.h"
|
||||
|
||||
template<>
|
||||
Clock *Mode<Clock>::instance = nullptr;
|
||||
@ -3,7 +3,7 @@
|
||||
|
||||
#include "mode/Mode.h"
|
||||
|
||||
class Clock : public Mode {
|
||||
class Clock : public Mode<Clock> {
|
||||
|
||||
public:
|
||||
|
||||
|
||||
4
src/mode/GameOfLife/GameOfLife.cpp
Normal file
4
src/mode/GameOfLife/GameOfLife.cpp
Normal file
@ -0,0 +1,4 @@
|
||||
#include "GameOfLife.h"
|
||||
|
||||
template<>
|
||||
GameOfLife *Mode<GameOfLife>::instance = nullptr;
|
||||
@ -9,7 +9,7 @@ enum ColorMode {
|
||||
BLACK_WHITE, GRAYSCALE, COLOR_FADE, RANDOM_COLOR
|
||||
};
|
||||
|
||||
class GameOfLife : public Mode {
|
||||
class GameOfLife : public Mode<GameOfLife> {
|
||||
|
||||
private:
|
||||
|
||||
|
||||
4
src/mode/Mode.cpp
Normal file
4
src/mode/Mode.cpp
Normal file
@ -0,0 +1,4 @@
|
||||
#include "Mode.h"
|
||||
|
||||
//template<typename T>
|
||||
//T *Mode<T>::instance = nullptr;
|
||||
@ -6,84 +6,20 @@
|
||||
#include "BASICS.h"
|
||||
#include "display/Display.h"
|
||||
#include "Timer.h"
|
||||
#include "ModeBase.h"
|
||||
|
||||
class Mode {
|
||||
|
||||
private:
|
||||
|
||||
Timer *timers[TIMER_COUNT]{};
|
||||
|
||||
uint8_t timerCount = 0;
|
||||
template<typename T>
|
||||
class Mode : public ModeBase {
|
||||
|
||||
protected:
|
||||
|
||||
Display *display;
|
||||
static T *instance;
|
||||
|
||||
public:
|
||||
|
||||
explicit Mode(Display *display) :
|
||||
display(display) {
|
||||
for (Timer **timer = timers; timer < timers + TIMER_COUNT; timer++) {
|
||||
*timer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~Mode() {
|
||||
destroyAllTimers();
|
||||
};
|
||||
|
||||
virtual const char *getName() = 0;
|
||||
|
||||
void step(microseconds_t dt) {
|
||||
for (Timer **timer = timers; timer < timers + TIMER_COUNT; timer++) {
|
||||
if (*timer != nullptr) {
|
||||
(*timer)->step(dt);
|
||||
}
|
||||
}
|
||||
doStep(dt);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
virtual void doStep(microseconds_t dt) {};
|
||||
|
||||
Timer *createTimer(long long millisecondsInterval, Timer::Callback callback) {
|
||||
for (Timer **timer = timers; timer < timers + TIMER_COUNT; timer++) {
|
||||
if (*timer == nullptr) {
|
||||
*timer = new Timer(millisecondsInterval * 1000, callback);
|
||||
timerCount++;
|
||||
return *timer;
|
||||
}
|
||||
}
|
||||
Serial.printf("ERROR: Cannot create more than %d timers!\n", TIMER_COUNT);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool destroyTimer(Timer *t) {
|
||||
for (Timer **timer = timers; timer < timers + TIMER_COUNT; timer++) {
|
||||
if (*timer == t) {
|
||||
_destroyTimer(timer);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Serial.printf("ERROR: No such timer.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
void destroyAllTimers() {
|
||||
for (Timer **timer = timers; timer < timers + TIMER_COUNT; timer++) {
|
||||
if (*timer != nullptr) {
|
||||
_destroyTimer(timer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void _destroyTimer(Timer **timer) {
|
||||
timerCount--;
|
||||
free(*timer);
|
||||
*timer = nullptr;
|
||||
ModeBase(display) {
|
||||
instance = (T *) this;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
91
src/mode/ModeBase.h
Normal file
91
src/mode/ModeBase.h
Normal file
@ -0,0 +1,91 @@
|
||||
#ifndef MODE_BASE_H
|
||||
#define MODE_BASE_H
|
||||
|
||||
#define TIMER_COUNT 10
|
||||
|
||||
#include "BASICS.h"
|
||||
#include "display/Display.h"
|
||||
#include "Timer.h"
|
||||
|
||||
class ModeBase {
|
||||
|
||||
private:
|
||||
|
||||
Timer *timers[TIMER_COUNT]{};
|
||||
|
||||
uint8_t timerCount = 0;
|
||||
|
||||
protected:
|
||||
|
||||
Display *display;
|
||||
|
||||
public:
|
||||
|
||||
explicit ModeBase(Display *display) :
|
||||
display(display) {
|
||||
for (Timer **timer = timers; timer < timers + TIMER_COUNT; timer++) {
|
||||
*timer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~ModeBase() {
|
||||
destroyAllTimers();
|
||||
};
|
||||
|
||||
virtual const char *getName() = 0;
|
||||
|
||||
void step(microseconds_t dt) {
|
||||
for (Timer **timer = timers; timer < timers + TIMER_COUNT; timer++) {
|
||||
if (*timer != nullptr) {
|
||||
(*timer)->step(dt);
|
||||
}
|
||||
}
|
||||
doStep(dt);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
virtual void doStep(microseconds_t dt) {};
|
||||
|
||||
Timer *createTimer(long long millisecondsInterval, Timer::Callback callback) {
|
||||
for (Timer **timer = timers; timer < timers + TIMER_COUNT; timer++) {
|
||||
if (*timer == nullptr) {
|
||||
*timer = new Timer(millisecondsInterval * 1000, callback);
|
||||
timerCount++;
|
||||
return *timer;
|
||||
}
|
||||
}
|
||||
Serial.printf("ERROR: Cannot create more than %d timers!\n", TIMER_COUNT);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool destroyTimer(Timer *t) {
|
||||
for (Timer **timer = timers; timer < timers + TIMER_COUNT; timer++) {
|
||||
if (*timer == t) {
|
||||
_destroyTimer(timer);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Serial.printf("ERROR: No such timer.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
void destroyAllTimers() {
|
||||
for (Timer **timer = timers; timer < timers + TIMER_COUNT; timer++) {
|
||||
if (*timer != nullptr) {
|
||||
_destroyTimer(timer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void _destroyTimer(Timer **timer) {
|
||||
timerCount--;
|
||||
free(*timer);
|
||||
*timer = nullptr;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -1,3 +1,4 @@
|
||||
#include "NewYear.h"
|
||||
|
||||
NewYear *NewYear::instance = nullptr;
|
||||
template<>
|
||||
NewYear *Mode<NewYear>::instance = nullptr;
|
||||
@ -6,9 +6,7 @@
|
||||
#include "mode/Mode.h"
|
||||
#include "Firework.h"
|
||||
|
||||
class NewYear : public Mode {
|
||||
|
||||
static NewYear *instance;
|
||||
class NewYear : public Mode<NewYear> {
|
||||
|
||||
Firework fireworksBegin[MAX_FIREWORKS];
|
||||
Firework *fireworksEnd = fireworksBegin + MAX_FIREWORKS;
|
||||
@ -23,68 +21,39 @@ class NewYear : public Mode {
|
||||
}
|
||||
|
||||
void step(Timer *timer, uint32_t counter, uint32_t currentCount) {
|
||||
display->clear();
|
||||
tm t{};
|
||||
getLocalTime(&t);
|
||||
int year = t.tm_year + 1900;
|
||||
int mon = t.tm_mon + 1;
|
||||
int day = t.tm_mday;
|
||||
int hour = t.tm_hour;
|
||||
int min = t.tm_min;
|
||||
int sec = t.tm_sec;
|
||||
#if PROG_ALL
|
||||
#else
|
||||
hour = 23;
|
||||
min = 59;
|
||||
sec = 55 + (int) (counter * 50 / 1000);
|
||||
while (sec >= 60) {
|
||||
min++;
|
||||
sec -= 60;
|
||||
}
|
||||
while (min >= 60) {
|
||||
hour++;
|
||||
min -= 60;
|
||||
}
|
||||
while (hour >= 24) {
|
||||
day++;
|
||||
hour -= 24;
|
||||
}
|
||||
while (day > 31) {
|
||||
mon++;
|
||||
day -= 31;
|
||||
}
|
||||
while (mon > 12) {
|
||||
year++;
|
||||
mon -= 12;
|
||||
}
|
||||
Serial.printf("%04i-%02i-%02i %02i:%02i:%02i\n", year, mon, day, hour, min, sec);
|
||||
#endif
|
||||
if (mon == 12 && day == 31) {
|
||||
size_t h = (24 - hour - (min > 0 || sec > 0 ? 1 : 0));
|
||||
size_t m = (60 - min - (sec > 0 ? 1 : 0)) % 60;
|
||||
size_t s = (60 - sec) % 60;
|
||||
uint8_t x = 0;
|
||||
if (h >= 10) {
|
||||
display->print(&x, 1, h / 10, COLOR_WHITE);
|
||||
} else {
|
||||
x += 3;
|
||||
}
|
||||
x++;
|
||||
display->print(&x, 1, h % 10, COLOR_WHITE);
|
||||
display->print(&x, 1, 10, COLOR_WHITE);
|
||||
display->print(&x, 1, m / 10, COLOR_WHITE);
|
||||
x++;
|
||||
display->print(&x, 1, m % 10, COLOR_WHITE);
|
||||
display->print(&x, 1, 10, COLOR_WHITE);
|
||||
display->print(&x, 1, s / 10, COLOR_WHITE);
|
||||
x++;
|
||||
display->print(&x, 1, s % 10, COLOR_WHITE);
|
||||
display->clear();
|
||||
if (t.tm_mon + 1 == 12 && t.tm_mday == 31) {
|
||||
drawCountdown(t);
|
||||
} else {
|
||||
drawYear(counter, year);
|
||||
drawFirework(timer);
|
||||
drawYear(counter, t.tm_year + 1900);
|
||||
drawFirework(timer->interval);
|
||||
}
|
||||
}
|
||||
|
||||
void drawCountdown(const tm &time) {
|
||||
size_t h = (24 - time.tm_hour - (time.tm_min > 0 || time.tm_sec > 0 ? 1 : 0));
|
||||
size_t m = (60 - time.tm_min - (time.tm_sec > 0 ? 1 : 0)) % 60;
|
||||
size_t s = (60 - time.tm_sec) % 60;
|
||||
uint8_t x = 0;
|
||||
if (h >= 10) {
|
||||
display->print(&x, 1, h / 10, COLOR_WHITE);
|
||||
} else {
|
||||
x += 3;
|
||||
}
|
||||
x++;
|
||||
display->print(&x, 1, h % 10, COLOR_WHITE);
|
||||
display->print(&x, 1, 10, COLOR_WHITE);
|
||||
display->print(&x, 1, m / 10, COLOR_WHITE);
|
||||
x++;
|
||||
display->print(&x, 1, m % 10, COLOR_WHITE);
|
||||
display->print(&x, 1, 10, COLOR_WHITE);
|
||||
display->print(&x, 1, s / 10, COLOR_WHITE);
|
||||
x++;
|
||||
display->print(&x, 1, s % 10, COLOR_WHITE);
|
||||
}
|
||||
|
||||
void drawYear(uint32_t counter, int year) {
|
||||
uint8_t x = 8;
|
||||
display->print(&x, 1, year / 1000 % 10, counter % 64 != 0 ? COLOR_WHITE : COLOR_BLACK);
|
||||
@ -96,10 +65,10 @@ class NewYear : public Mode {
|
||||
display->print(&x, 1, year / 1 % 10, counter % 64 != 3 ? COLOR_WHITE : COLOR_BLACK);
|
||||
}
|
||||
|
||||
void drawFirework(const Timer *timer) const {
|
||||
void drawFirework(microseconds_t dt) const {
|
||||
for (auto *firework = (Firework *) fireworksBegin; firework < fireworksEnd; firework++) {
|
||||
if (firework->isAlive()) {
|
||||
firework->step(timer->interval);
|
||||
firework->step(dt);
|
||||
firework->draw();
|
||||
}
|
||||
}
|
||||
@ -111,7 +80,6 @@ public:
|
||||
Mode(display) {
|
||||
createTimer(500, [](Timer *timer, uint32_t counter, uint32_t currentCount) { instance->launch(timer, counter, currentCount); });
|
||||
createTimer(50, [](Timer *timer, uint32_t counter, uint32_t currentCount) { instance->step(timer, counter, currentCount); });
|
||||
instance = this;
|
||||
for (Firework *firework = fireworksBegin; firework < fireworksEnd; firework++) {
|
||||
firework->init(display);
|
||||
}
|
||||
|
||||
@ -1,12 +1,4 @@
|
||||
#include "Pong.h"
|
||||
|
||||
Pong *Pong::instance = nullptr;
|
||||
|
||||
void Pong::resetPlayer() {
|
||||
player0.size = 3;
|
||||
player0.score = 0;
|
||||
player0.position = (display->height - player0.size) / 2;
|
||||
player1.size = 3;
|
||||
player1.score = 0;
|
||||
player1.position = (display->height - player1.size) / 2;
|
||||
}
|
||||
template<>
|
||||
Pong *Mode<Pong>::instance = nullptr;
|
||||
@ -5,7 +5,7 @@
|
||||
#include "Player.h"
|
||||
#include "display/Vector.h"
|
||||
|
||||
class Pong : public Mode {
|
||||
class Pong : public Mode<Pong> {
|
||||
|
||||
private:
|
||||
|
||||
@ -13,8 +13,6 @@ private:
|
||||
SCORE, PLAY, OVER
|
||||
};
|
||||
|
||||
static Pong *instance;
|
||||
|
||||
Player player0;
|
||||
|
||||
Player player1;
|
||||
@ -27,13 +25,16 @@ private:
|
||||
|
||||
microseconds_t timeout = 0;
|
||||
|
||||
static void tick(Timer *timer, uint32_t totalCount, uint32_t currentCount) {
|
||||
instance->_tick(timer, totalCount, currentCount);
|
||||
void resetPlayer() {
|
||||
player0.size = 3;
|
||||
player0.score = 0;
|
||||
player0.position = (display->height - player0.size) / 2;
|
||||
player1.size = 3;
|
||||
player1.score = 0;
|
||||
player1.position = (display->height - player1.size) / 2;
|
||||
}
|
||||
|
||||
void resetPlayer();
|
||||
|
||||
void _tick(Timer *timer, uint32_t totalCount, uint32_t currentCount) {
|
||||
void tick(Timer *timer, uint32_t totalCount, uint32_t currentCount) {
|
||||
switch (status) {
|
||||
case SCORE:
|
||||
timeout -= currentCount * timer->interval;
|
||||
@ -133,7 +134,7 @@ public:
|
||||
position(display->width / 2.0, display->height / 2.0),
|
||||
velocity(random(360), exp10(1)) {
|
||||
instance = this;
|
||||
createTimer(100, &tick);
|
||||
createTimer(100, [](Timer *timer, uint32_t counter, uint32_t currentCount) { instance->tick(timer, counter, currentCount); });
|
||||
spawnBall(random(2) == 0 ? -1 : +1);
|
||||
resetPlayer();
|
||||
}
|
||||
|
||||
4
src/mode/SpaceInvaders/SpaceInvaders.cpp
Normal file
4
src/mode/SpaceInvaders/SpaceInvaders.cpp
Normal file
@ -0,0 +1,4 @@
|
||||
#include "SpaceInvaders.h"
|
||||
|
||||
template<>
|
||||
SpaceInvaders *Mode<SpaceInvaders>::instance = nullptr;
|
||||
@ -18,7 +18,7 @@ struct Invader {
|
||||
uint8_t y;
|
||||
};
|
||||
|
||||
class SpaceInvaders : public Mode {
|
||||
class SpaceInvaders : public Mode<SpaceInvaders> {
|
||||
|
||||
private:
|
||||
|
||||
@ -80,7 +80,7 @@ public:
|
||||
Serial.println("WINNER!");
|
||||
reset();
|
||||
}
|
||||
if (swarmY + (invadersCountY - 1) * 2 >= display->height - 1) { // TODO this is only correct if there still are any invaders in the accu row (otherwise we "Game Over" too early)
|
||||
if (swarmY + (invadersCountY - 1) * 2 >= display->height - 1) { // TODO this is only correct if there still are any invaders in the last row (otherwise we "Game Over" too early)
|
||||
Serial.println("GAME OVER");
|
||||
reset();
|
||||
}
|
||||
|
||||
4
src/mode/Test/Border.cpp
Normal file
4
src/mode/Test/Border.cpp
Normal file
@ -0,0 +1,4 @@
|
||||
#include "Border.h"
|
||||
|
||||
template<>
|
||||
Border *Mode<Border>::instance = nullptr;
|
||||
@ -3,7 +3,7 @@
|
||||
|
||||
#include "mode/Mode.h"
|
||||
|
||||
class Border : public Mode {
|
||||
class Border : public Mode<Border> {
|
||||
|
||||
public:
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user