RGBMatrixDisplay/src/main.cpp

266 lines
6.1 KiB
C++

#include <WiFi.h>
#include <ArduinoOTA.h>
#include "mode/Mode.h"
#include "display/Display.h"
#include <WebServer.h>
#if PROG_ALL
#include "mode/GameOfLife/GameOfLife.h"
#include "mode/Pong/Pong.h"
#include "mode/Test/Border.h"
#include "mode/Clock/Clock.h"
#include "mode/SpaceInvaders/SpaceInvaders.h"
#endif
#include "mode/NewYear/NewYear.h"
enum ModeId {
NONE,
#if PROG_ALL
BORDER,
CLOCK,
GAME_OF_LIFE_BLACK_WHITE,
GAME_OF_LIFE_GRAYSCALE,
GAME_OF_LIFE_COLOR_FADE,
GAME_OF_LIFE_RANDOM_COLOR,
PONG,
SPACE_INVADERS,
#endif
NEW_YEAR,
};
WebServer server(80);
Display display(32, 8);
ModeId newModeId = NEW_YEAR;
ModeId currentModeId = NONE;
microseconds_t lastMicros = 0;
Mode *mode = nullptr;
double speed = 1.0;
bool connected = false;
void checkMode();
void stepMode();
void unloadOldMode();
void loadNewMode();
void setBrightness(int value);
void web_index() {
server.setContentLength(CONTENT_LENGTH_UNKNOWN);
server.send(200, "text/html", "");
server.sendContent("<a href='/mode?mode=0'>NONE</a><br>");
server.sendContent("<a href='/mode?mode=1'>BORDER</a><br>");
server.sendContent("<a href='/mode?mode=2'>CLOCK</a><br>");
server.sendContent("<a href='/mode?mode=3'>GAME_OF_LIFE_BLACK_WHITE</a><br>");
server.sendContent("<a href='/mode?mode=4'>GAME_OF_LIFE_GRAYSCALE</a><br>");
server.sendContent("<a href='/mode?mode=5'>GAME_OF_LIFE_COLOR_FADE</a><br>");
server.sendContent("<a href='/mode?mode=6'>GAME_OF_LIFE_RANDOM_COLOR</a><br>");
server.sendContent("<a href='/mode?mode=7'>PONG</a><br>");
server.sendContent("<a href='/mode?mode=8'>SPACE_INVADERS</a><br>");
server.sendContent("<a href='/mode?mode=9'>NEW_YEAR</a><br>");
server.sendContent("Helligkeit: <a href='/brighter'>+</a> / <a href='/darker'>-</a><br>");
server.client().flush();
}
void web_setMode() {
if (!server.hasArg("mode")) {
server.send(400, "text/plain", "Missing 'mode'");
return;
}
double value = strtod(server.arg("mode").c_str(), nullptr);
if (isnan(value)) {
server.send(400, "text/plain", "'mode' not a number");
return;
}
newModeId = (ModeId) value;
server.sendHeader("location", "/");
server.send(301, "text/plain", "ok");
}
void web_brighter() {
setBrightness(display.getBrightness() + 10);
}
void web_darker() {
setBrightness(max(1, display.getBrightness() - 10));
}
void setup() {
delay(500);
Serial.begin(115200);
Serial.println("\n\n\nStartup!");
WiFi.begin("HappyNet", "1Grausame!Sackratte7");
ArduinoOTA.onStart([]() {
display.clear();
display.loop();
});
ArduinoOTA.onProgress([](unsigned int total, unsigned int progress) {
double ratio = (double) progress / (double) total;
auto index = (uint16_t) round(ratio * (double) display.pixelCount);
auto color = (uint8_t) round(ratio * 255.0);
display.setIndex(index, 255 - color, color, 0);
display.loop();
});
ArduinoOTA.onEnd([]() {
display.clear();
display.loop();
});
ArduinoOTA.onError([](int error) {
display.clear();
display.loop();
});
ArduinoOTA.begin();
server.on("", web_index);
server.on("/", web_index);
server.on("/mode", web_setMode);
server.on("/mode/", web_setMode);
server.on("/brighter", web_brighter);
server.on("/brighter/", web_brighter);
server.on("/darker", web_darker);
server.on("/darker/", web_darker);
server.begin();
display.setup();
}
void setSpeed(double value);
void loop() {
ArduinoOTA.handle();
server.handleClient();
bool hasIp = (uint32_t) WiFi.localIP() != 0;
if (!connected) {
if (hasIp) {
connected = true;
Serial.printf("WiFi connected: %s\n", WiFi.localIP().toString().c_str());
configTime(3600, 3600, WiFi.gatewayIP().toString().c_str());
}
} else {
if (!hasIp) {
connected = false;
Serial.println("WiFi disconnected!");
}
}
if (Serial.available()) {
int input = Serial.read();
switch (input) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
newModeId = (ModeId) (input - '0');
break;
case '+':
setBrightness(display.getBrightness() + 10);
break;
case '-':
setBrightness(max(1, display.getBrightness() - 10));
break;
case ',':
setSpeed(speed / 1.1);
break;
case '.':
setSpeed(speed * 1.1);
break;
}
}
checkMode();
display.loop();
stepMode();
}
void setBrightness(int value) {
display.setBrightness(value);
Serial.printf("Setting brightness to %5.1f%%\n", value / 2.55);
}
void setSpeed(double value) {
speed = value;
Serial.printf("Setting speed to %6.2fx\n", value);
}
void checkMode() {
if (currentModeId != newModeId) {
unloadOldMode();
loadNewMode();
}
}
void unloadOldMode() {
if (mode != nullptr) {
delete mode;
mode = nullptr;
}
display.clear();
}
void loadNewMode() {
currentModeId = newModeId;
lastMicros = 0;
switch (currentModeId) {
case NONE:
break;
#if PROG_ALL
case BORDER:
mode = new Border(&display);
break;
case CLOCK:
mode = new Clock(&display);
break;
case GAME_OF_LIFE_BLACK_WHITE:
mode = new GameOfLife(&display, BLACK_WHITE);
break;
case GAME_OF_LIFE_GRAYSCALE:
mode = new GameOfLife(&display, GRAYSCALE);
break;
case GAME_OF_LIFE_COLOR_FADE:
mode = new GameOfLife(&display, COLOR_FADE);
break;
case GAME_OF_LIFE_RANDOM_COLOR:
mode = new GameOfLife(&display, RANDOM_COLOR);
break;
case PONG:
mode = new Pong(&display);
break;
case SPACE_INVADERS:
mode = new SpaceInvaders(&display);
break;
#endif
case NEW_YEAR:
mode = new NewYear(&display);
break;
}
Serial.printf("Mode: %s\n", mode == nullptr ? "None" : mode->getName());
}
void stepMode() {
if (mode == nullptr) {
return;
}
auto currentMicros = (int64_t) micros();
microseconds_t dt = (microseconds_t) min(1000000.0, max(1.0, (double) (currentMicros - lastMicros) * speed));
lastMicros = currentMicros;
mode->step(dt);
}