#include #include #include "mode/Mode.h" #include "display/Display.h" #include #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("NONE
"); server.sendContent("BORDER
"); server.sendContent("CLOCK
"); server.sendContent("GAME_OF_LIFE_BLACK_WHITE
"); server.sendContent("GAME_OF_LIFE_GRAYSCALE
"); server.sendContent("GAME_OF_LIFE_COLOR_FADE
"); server.sendContent("GAME_OF_LIFE_RANDOM_COLOR
"); server.sendContent("PONG
"); server.sendContent("SPACE_INVADERS
"); server.sendContent("NEW_YEAR
"); server.sendContent("Helligkeit: + / -
"); 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); }