From 6328cd81457450925871110ee9e1a42f287ae320 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20Ha=C3=9Fel?= Date: Tue, 3 Jan 2023 09:11:52 +0100 Subject: [PATCH] Clean up --- src/display.cpp | 17 ++ src/display.h | 10 ++ src/display/Display.cpp | 12 +- src/display/Display.h | 6 +- src/main.cpp | 341 ++-------------------------------------- src/mode.cpp | 103 ++++++++++++ src/mode.h | 12 ++ src/serial.cpp | 45 ++++++ src/serial.h | 8 + src/server.cpp | 98 ++++++++++++ src/server.h | 8 + src/wifi.cpp | 98 ++++++++++++ src/wifi.h | 8 + 13 files changed, 430 insertions(+), 336 deletions(-) create mode 100644 src/display.cpp create mode 100644 src/display.h create mode 100644 src/mode.cpp create mode 100644 src/mode.h create mode 100644 src/serial.cpp create mode 100644 src/serial.h create mode 100644 src/server.cpp create mode 100644 src/server.h create mode 100644 src/wifi.cpp create mode 100644 src/wifi.h diff --git a/src/display.cpp b/src/display.cpp new file mode 100644 index 0000000..96c1237 --- /dev/null +++ b/src/display.cpp @@ -0,0 +1,17 @@ +#include "display.h" +#include "config.h" + +Display display(32, 8); + +void setBrightness(int brightness) { + brightness = max(1, min(brightness, 255)); + if (display.getBrightness() == brightness) { + return; + } + + config.brightness = brightness; + display.setBrightness(brightness); + config_set_dirty(); + + Serial.printf("Setting brightness to %5.1f%%\n", brightness / 2.55); +} diff --git a/src/display.h b/src/display.h new file mode 100644 index 0000000..60cddab --- /dev/null +++ b/src/display.h @@ -0,0 +1,10 @@ +#ifndef MEDIATABLE_DISPLAY_H +#define MEDIATABLE_DISPLAY_H + +#include "display/Display.h" + +extern Display display; + +void setBrightness(int brightness); + +#endif diff --git a/src/display/Display.cpp b/src/display/Display.cpp index cdcccc2..6078fd9 100644 --- a/src/display/Display.cpp +++ b/src/display/Display.cpp @@ -2,12 +2,12 @@ bool SYMBOLS[SYMBOL_COUNT][DISPLAY_CHAR_WIDTH * DISPLAY_CHAR_HEIGHT] = { { - X, X, X, - X, _, X, - X, _, X, - X, _, X, - X, X, X, - }, + X, X, X, + X, _, X, + X, _, X, + X, _, X, + X, X, X, + }, { _, _, X, _, X, X, diff --git a/src/display/Display.h b/src/display/Display.h index d4d974f..d0077c0 100644 --- a/src/display/Display.h +++ b/src/display/Display.h @@ -120,11 +120,11 @@ public: leds.show(); } - void setBrightness(int brightness) { - leds.setBrightness(max(0, min(brightness, 255))); + void setBrightness(uint8_t brightness) { + leds.setBrightness(brightness); } - int getBrightness() { + uint8_t getBrightness() { return leds.getBrightness(); } diff --git a/src/main.cpp b/src/main.cpp index 3aa8adf..98d2eda 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,347 +1,34 @@ -#include - -#include - -#include "mode/Mode.h" -#include "display/Display.h" -#include -#include -#include - -#include "mode/GameOfLife/GameOfLife.h" -#include "mode/Pong/Pong.h" -#include "mode/Clock/Clock.h" -#include "mode/SpaceInvaders/SpaceInvaders.h" -#include "mode/NewYear/NewYear.h" -#include "mode/Border/Border.h" +#include "serial.h" #include "config.h" +#include "wifi.h" -WebServer server(80); +#include "server.h" -Display display(32, 8); - -ModeId currentModeId = NONE; - -microseconds_t lastMicros = 0; - -ModeBase *mode = nullptr; - -bool connected = false; - -void mode_check(); - -void mode_step(); - -void unloadOldMode(); - -void loadNewMode(); - -void setBrightness(int brightness); - -void setSpeed(double speed); - -void serial_read(); - -void wifi_loop(); - -void ntp_setup(); - -uint32_t ip2int(const IPAddress &ip); - -void setMode(ModeId 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.sendContent("Geschwindigkeit: + / -
"); - 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; - } - setMode((ModeId) value); - server.sendHeader("location", "/"); - server.send(301, "text/plain", "ok"); -} - -void setMode(ModeId value) { - if (config.mode == value) { - return; - } - config.mode = value; - config_set_dirty(); -} - -void web_brighter() { - setBrightness(display.getBrightness() + 10); - server.sendHeader("location", "/"); - server.send(301, "text/plain", "ok"); -} - -void web_darker() { - setBrightness(max(1, display.getBrightness() - 10)); - server.sendHeader("location", "/"); - server.send(301, "text/plain", "ok"); -} - -void web_faster() { - setSpeed(config.speed * 1.1); - server.sendHeader("location", "/"); - server.send(301, "text/plain", "ok"); -} - -void web_slower() { - setSpeed(config.speed / 1.1); - server.sendHeader("location", "/"); - server.send(301, "text/plain", "ok"); -} +#include "mode.h" +#include "display.h" void setup() { delay(500); - Serial.begin(115200); - Serial.println("\n\n\nStartup!"); - - WiFi.begin("HappyNet", "1Grausame!Sackratte7"); - yield(); - - ArduinoOTA.onStart([]() { - Serial.print("\n\nOTA Update: "); - display.clear(); - display.loop(); - }); - ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { - double ratio = (double) progress / (double) total; - Serial.printf("\rOTA Update: %3.0f%%", ratio * 100); - - 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([]() { - Serial.println("\nOTA Success!\n"); - display.clear(); - display.loop(); - }); - ArduinoOTA.onError([](int error) { - Serial.println("\nOTA Failure!\n"); - display.clear(); - display.loop(); - }); - ArduinoOTA.begin(); - yield(); + serial_setup(); config_setup(); + wifi_setup(); + + server_setup(); display.setup(); - yield(); display.setBrightness(config.brightness); - - 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.on("/faster", web_faster); - server.on("/faster/", web_faster); - server.on("/slower", web_slower); - server.on("/slower/", web_slower); - server.begin(); } void loop() { - yield(); - ArduinoOTA.handle(); - serial_read(); - server.handleClient(); + serial_loop(); config_loop(); wifi_loop(); - mode_check(); + + server_loop(); + + mode_loop(); display.loop(); - mode_step(); -} -void timeSyncCallback(struct timeval *tv) { - Serial.printf("timeSyncCallback: %ld\n", tv->tv_sec); -} - -void wifi_loop() { - bool hasIp = (uint32_t) WiFi.localIP() != 0; - if (!connected) { - if (hasIp) { - connected = true; - Serial.printf("WiFi connected: %s\n", WiFi.localIP().toString().c_str()); - ntp_setup(); - } - } else { - if (!hasIp) { - connected = false; - Serial.println("WiFi disconnected!"); - } - } -} - -uint32_t ip2int(const IPAddress &ip) { - return ((ip[0] * 256 + ip[1]) * 256 + ip[2]) * 256 + ip[3]; -} - -void ntp_setup() { - char calculatedGateway[16] = {0}; - uint32_t local = ip2int(WiFi.localIP()); - uint32_t netmask = ip2int(WiFi.subnetMask()); - uint32_t gateway = local & netmask + 1; - snprintf( - calculatedGateway, - sizeof(calculatedGateway), - "%u.%u.%u.%u", - (gateway >> 24) & 0xFF, - (gateway >> 16) & 0xFF, - (gateway >> 8) & 0xFF, - (gateway >> 0) & 0xFF - ); - sntp_set_time_sync_notification_cb(timeSyncCallback); - Serial.printf("configTime(%s / %s / %s)\n", WiFi.gatewayIP().toString().c_str(), calculatedGateway, "pool.ntp.org"); - configTime(3600, 3600, WiFi.gatewayIP().toString().c_str(), calculatedGateway, "pool.ntp.org"); yield(); } - -void serial_read() { - 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': - setMode((ModeId) (input - '0')); - break; - case '+': - setBrightness(display.getBrightness() + 10); - break; - case '-': - setBrightness(max(1, display.getBrightness() - 10)); - break; - case ',': - setSpeed(config.speed / 1.1); - break; - case '.': - setSpeed(config.speed * 1.1); - break; - default: - Serial.printf("Unknown command: %c\n", input); - break; - } - } -} - -void setBrightness(int brightness) { - brightness = max(0, min(brightness, 255)); - if (display.getBrightness() == brightness) { - return; - } - config.brightness = brightness; - display.setBrightness(brightness); - config_set_dirty(); - Serial.printf("Setting brightness to %5.1f%%\n", brightness / 2.55); -} - -void setSpeed(double speed) { - speed = min(max(0.01, speed), 10000.0); - if (config.speed == speed) { - return; - } - config.speed = speed; - config_set_dirty(); - Serial.printf("Setting speed to %6.2fx\n", config.speed); -} - -void mode_check() { - if (currentModeId != config.mode) { - unloadOldMode(); - loadNewMode(); - } -} - -void unloadOldMode() { - if (mode != nullptr) { - delete mode; - mode = nullptr; - } - display.clear(); -} - -void loadNewMode() { - currentModeId = config.mode; - lastMicros = 0; - switch (currentModeId) { - 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; - case NEW_YEAR: - mode = new NewYear(&display); - break; - default: - Serial.print("No mode loaded.\n"); - break; - } - Serial.printf("Mode: %s\n", mode == nullptr ? "None" : mode->getName()); -} - -void mode_step() { - if (mode == nullptr) { - return; - } - auto currentMicros = (int64_t) micros(); - microseconds_t dt = (microseconds_t) min(1000000.0, max(1.0, (double) (currentMicros - lastMicros) * config.speed)); - lastMicros = currentMicros; - mode->step(dt); -} diff --git a/src/mode.cpp b/src/mode.cpp new file mode 100644 index 0000000..b9bfc27 --- /dev/null +++ b/src/mode.cpp @@ -0,0 +1,103 @@ +#include "mode.h" +#include "config.h" +#include "mode/Border/Border.h" +#include "mode/Clock/Clock.h" +#include "mode/GameOfLife/GameOfLife.h" +#include "mode/Pong/Pong.h" +#include "mode/SpaceInvaders/SpaceInvaders.h" +#include "mode/NewYear/NewYear.h" +#include "display.h" + +ModeId currentModeId = NONE; + +microseconds_t lastMicros = 0; + +ModeBase *mode = nullptr; + +void unloadOldMode(); + +void loadNewMode(); + +void mode_step(); + +void mode_loop() { + if (currentModeId != config.mode) { + unloadOldMode(); + loadNewMode(); + } + mode_step(); +} + +void setMode(ModeId value) { + if (config.mode == value) { + return; + } + config.mode = value; + config_set_dirty(); +} + +void setSpeed(double speed) { + speed = min(max(0.01, speed), 10000.0); + if (config.speed == speed) { + return; + } + config.speed = speed; + config_set_dirty(); + Serial.printf("Setting speed to %6.2fx\n", config.speed); +} + +void unloadOldMode() { + if (mode != nullptr) { + delete mode; + mode = nullptr; + } + display.clear(); +} + +void loadNewMode() { + currentModeId = config.mode; + lastMicros = 0; + switch (currentModeId) { + 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; + case NEW_YEAR: + mode = new NewYear(&display); + break; + default: + Serial.print("No mode loaded.\n"); + break; + } + Serial.printf("Mode: %s\n", mode == nullptr ? "None" : mode->getName()); +} + +void mode_step() { + if (mode == nullptr) { + return; + } + auto currentMicros = (int64_t) micros(); + microseconds_t dt = (microseconds_t) min(1000000.0, max(1.0, (double) (currentMicros - lastMicros) * config.speed)); + lastMicros = currentMicros; + mode->step(dt); +} diff --git a/src/mode.h b/src/mode.h new file mode 100644 index 0000000..89d8ed8 --- /dev/null +++ b/src/mode.h @@ -0,0 +1,12 @@ +#ifndef MEDIATABLE_MODE_H +#define MEDIATABLE_MODE_H + +#include "mode/Mode.h" + +void mode_loop(); + +void setMode(ModeId value); + +void setSpeed(double speed); + +#endif diff --git a/src/serial.cpp b/src/serial.cpp new file mode 100644 index 0000000..a0ebcc6 --- /dev/null +++ b/src/serial.cpp @@ -0,0 +1,45 @@ +#include +#include "serial.h" +#include "display.h" +#include "config.h" +#include "mode.h" + +void serial_setup() { + Serial.begin(115200); + Serial.println("\n\n\nStartup!"); +} + +void serial_loop() { + 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': + setMode((ModeId)(input - '0')); + break; + case '+': + setBrightness(display.getBrightness() + 10); + break; + case '-': + setBrightness(display.getBrightness() - 10); + break; + case ',': + setSpeed(config.speed / 1.1); + break; + case '.': + setSpeed(config.speed * 1.1); + break; + default: + Serial.printf("Unknown command: %c\n", input); + break; + } + } +} diff --git a/src/serial.h b/src/serial.h new file mode 100644 index 0000000..63e001d --- /dev/null +++ b/src/serial.h @@ -0,0 +1,8 @@ +#ifndef MEDIATABLE_SERIAL_H +#define MEDIATABLE_SERIAL_H + +void serial_loop(); + +void serial_setup(); + +#endif diff --git a/src/server.cpp b/src/server.cpp new file mode 100644 index 0000000..c825fdc --- /dev/null +++ b/src/server.cpp @@ -0,0 +1,98 @@ +#include +#include +#include "server.h" +#include "mode/Mode.h" +#include "mode.h" +#include "display.h" +#include "config.h" + +WebServer server(80); + +void web_index(); + +void web_setMode(); + +void web_brighter(); + +void web_darker(); + +void web_faster(); + +void web_slower(); + +void server_setup() { + 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.on("/faster", web_faster); + server.on("/faster/", web_faster); + server.on("/slower", web_slower); + server.on("/slower/", web_slower); + server.begin(); +} + +void server_loop() { + server.handleClient(); +} + +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.sendContent("Geschwindigkeit: + / -
"); + 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; + } + setMode((ModeId) value); + server.sendHeader("location", "/"); + server.send(301, "text/plain", "ok"); +} + +void web_brighter() { + setBrightness(display.getBrightness() + 10); + server.sendHeader("location", "/"); + server.send(301, "text/plain", "ok"); +} + +void web_darker() { + setBrightness(max(1, display.getBrightness() - 10)); + server.sendHeader("location", "/"); + server.send(301, "text/plain", "ok"); +} + +void web_faster() { + setSpeed(config.speed * 1.1); + server.sendHeader("location", "/"); + server.send(301, "text/plain", "ok"); +} + +void web_slower() { + setSpeed(config.speed / 1.1); + server.sendHeader("location", "/"); + server.send(301, "text/plain", "ok"); +} diff --git a/src/server.h b/src/server.h new file mode 100644 index 0000000..aa4bab5 --- /dev/null +++ b/src/server.h @@ -0,0 +1,8 @@ +#ifndef MEDIATABLE_SERVER_H +#define MEDIATABLE_SERVER_H + +void server_setup(); + +void server_loop(); + +#endif diff --git a/src/wifi.cpp b/src/wifi.cpp new file mode 100644 index 0000000..ddfaea1 --- /dev/null +++ b/src/wifi.cpp @@ -0,0 +1,98 @@ +#include "wifi.h" +#include "display.h" + +#include +#include +#include + +bool connected = false; + +void ntp_setup(); + +uint32_t ip2int(const IPAddress &ip); + +void timeSyncCallback(struct timeval *tv); + +char *calculateGateway(char *calculatedGateway, size_t size); + +void wifi_setup() { + WiFi.begin("HappyNet", "1Grausame!Sackratte7"); + yield(); + + ArduinoOTA.onStart([]() { + Serial.print("\n\nOTA Update: "); + display.clear(); + display.loop(); + }); + ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { + double ratio = (double) progress / (double) total; + Serial.printf("\rOTA Update: %3.0f%%", ratio * 100); + + 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([]() { + Serial.println("\nOTA Success!\n"); + display.clear(); + display.loop(); + }); + ArduinoOTA.onError([](int error) { + Serial.println("\nOTA Failure!\n"); + display.clear(); + display.loop(); + }); + ArduinoOTA.begin(); + yield(); +} + +void wifi_loop() { + ArduinoOTA.handle(); + bool hasIp = (uint32_t) WiFi.localIP() != 0; + if (!connected) { + if (hasIp) { + connected = true; + Serial.printf("WiFi connected: %s\n", WiFi.localIP().toString().c_str()); + ntp_setup(); + } + } else { + if (!hasIp) { + connected = false; + Serial.println("WiFi disconnected!"); + } + } +} + +void ntp_setup() { + char calculatedGateway[16] = {0}; + calculateGateway(calculatedGateway, sizeof(calculatedGateway)); + sntp_set_time_sync_notification_cb(timeSyncCallback); + Serial.printf("configTime(%s / %s / %s)\n", WiFi.gatewayIP().toString().c_str(), calculatedGateway, "pool.ntp.org"); + configTime(3600, 3600, WiFi.gatewayIP().toString().c_str(), calculatedGateway, "pool.ntp.org"); + yield(); +} + +char *calculateGateway(char *calculatedGateway, size_t size) { + uint32_t local = ip2int(WiFi.localIP()); + uint32_t netmask = ip2int(WiFi.subnetMask()); + uint32_t gateway = local & netmask + 1; + snprintf( + calculatedGateway, + size, + "%u.%u.%u.%u", + (gateway >> 24) & 0xFF, + (gateway >> 16) & 0xFF, + (gateway >> 8) & 0xFF, + (gateway >> 0) & 0xFF + ); + return calculatedGateway; +} + +uint32_t ip2int(const IPAddress &ip) { + return ((ip[0] * 256 + ip[1]) * 256 + ip[2]) * 256 + ip[3]; +} + +void timeSyncCallback(struct timeval *tv) { + Serial.printf("timeSyncCallback: %ld\n", tv->tv_sec); +} diff --git a/src/wifi.h b/src/wifi.h new file mode 100644 index 0000000..90514cf --- /dev/null +++ b/src/wifi.h @@ -0,0 +1,8 @@ +#ifndef MEDIATABLE_WIFI_H +#define MEDIATABLE_WIFI_H + +void wifi_setup(); + +void wifi_loop(); + +#endif