eeprom config

This commit is contained in:
Patrick Haßel 2023-01-02 17:17:07 +01:00
parent 88ee6fa91c
commit 8483963b92
6 changed files with 186 additions and 41 deletions

83
src/config.cpp Normal file
View File

@ -0,0 +1,83 @@
#include <EEPROM.h>
#include "config.h"
uint32_t calculateChecksum(Config *ptr);
void config_defaults();
bool validateChecksum(uint32_t checksumEEPROM, Config &tmp);
Config config;
bool dirty = false;
unsigned long lastDirtyMillis = 0;
void config_setup() {
if (!config_load()) {
config_defaults();
}
}
void config_set_dirty() {
dirty = true;
lastDirtyMillis = millis();
}
void config_loop() {
if (!dirty) {
return;
}
if (millis() - lastDirtyMillis <= 30000) {
return;
}
dirty = false;
uint32_t checksum = calculateChecksum(&config);
EEPROM.begin(512);
EEPROM.writeBytes(0, &config, sizeof(Config));
EEPROM.writeUInt(sizeof(Config), checksum);
EEPROM.end();
Serial.printf("Config saved to EEPROM.\n");
}
bool config_load() {
Config tmp{};
EEPROM.begin(512);
EEPROM.readBytes(0, &tmp, sizeof(Config));
uint32_t checksum = EEPROM.readUInt(sizeof(Config));
EEPROM.end();
bool success = validateChecksum(checksum, tmp);
if (success) {
memcpy(&config, &tmp, sizeof(Config));
Serial.printf("Config loaded from EEPROM.\n");
} else {
Serial.printf("Failed to load config from EEPROM.\n");
}
return success;
}
bool validateChecksum(uint32_t checksumEEPROM, Config &tmp) {
uint32_t calculated = calculateChecksum(&tmp);
return checksumEEPROM == calculated;
}
void config_defaults() {
config.mode = GAME_OF_LIFE_GRAYSCALE;
config.speed = 1.0;
config.brightness = 16;
Serial.printf("Config DEFAULTS loaded.\n");
}
uint32_t calculateChecksum(Config *ptr) {
uint32_t checksum = 0;
for (auto *b = (uint8_t *) ptr; b < (uint8_t *) ptr + sizeof(Config); b++) {
checksum += *b;
}
return checksum;
}

22
src/config.h Normal file
View File

@ -0,0 +1,22 @@
#ifndef MEDIATABLE_CONFIG_H
#define MEDIATABLE_CONFIG_H
#include "mode/Mode.h"
struct Config {
ModeId mode;
double speed;
uint8_t brightness;
};
extern Config config;
void config_setup();
void config_loop();
bool config_load();
void config_set_dirty();
#endif

View File

@ -121,7 +121,7 @@ public:
} }
void setBrightness(int brightness) { void setBrightness(int brightness) {
leds.setBrightness(min(255, max(0, brightness))); leds.setBrightness(max(0, min(brightness, 255)));
} }
int getBrightness() { int getBrightness() {

View File

@ -6,6 +6,7 @@
#include "display/Display.h" #include "display/Display.h"
#include <WebServer.h> #include <WebServer.h>
#include <esp_sntp.h> #include <esp_sntp.h>
#include <EEPROM.h>
#include "mode/GameOfLife/GameOfLife.h" #include "mode/GameOfLife/GameOfLife.h"
#include "mode/Pong/Pong.h" #include "mode/Pong/Pong.h"
@ -13,34 +14,18 @@
#include "mode/SpaceInvaders/SpaceInvaders.h" #include "mode/SpaceInvaders/SpaceInvaders.h"
#include "mode/NewYear/NewYear.h" #include "mode/NewYear/NewYear.h"
#include "mode/Border/Border.h" #include "mode/Border/Border.h"
#include "config.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,
};
WebServer server(80); WebServer server(80);
Display display(32, 8); Display display(32, 8);
ModeId newModeId = NEW_YEAR;
ModeId currentModeId = NONE; ModeId currentModeId = NONE;
microseconds_t lastMicros = 0; microseconds_t lastMicros = 0;
ModeBase *mode = nullptr; ModeBase *mode = nullptr;
double speed = 1.0;
bool connected = false; bool connected = false;
void mode_check(); void mode_check();
@ -51,9 +36,9 @@ void unloadOldMode();
void loadNewMode(); void loadNewMode();
void setBrightness(int value); void setBrightness(int brightness);
void setSpeed(double value); void setSpeed(double speed);
void serial_read(); void serial_read();
@ -63,6 +48,8 @@ void ntp_setup();
uint32_t ip2int(const IPAddress &ip); uint32_t ip2int(const IPAddress &ip);
void setMode(ModeId value);
void web_index() { void web_index() {
server.setContentLength(CONTENT_LENGTH_UNKNOWN); server.setContentLength(CONTENT_LENGTH_UNKNOWN);
server.send(200, "text/html", ""); server.send(200, "text/html", "");
@ -77,6 +64,7 @@ void web_index() {
server.sendContent("<a href='/mode?mode=8'>SPACE_INVADERS</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("<a href='/mode?mode=9'>NEW_YEAR</a><br>");
server.sendContent("Helligkeit: <a href='/brighter'>+</a> / <a href='/darker'>-</a><br>"); server.sendContent("Helligkeit: <a href='/brighter'>+</a> / <a href='/darker'>-</a><br>");
server.sendContent("Geschwindigkeit: <a href='/faster'>+</a> / <a href='/slower'>-</a><br>");
server.client().flush(); server.client().flush();
} }
@ -90,11 +78,19 @@ void web_setMode() {
server.send(400, "text/plain", "'mode' not a number"); server.send(400, "text/plain", "'mode' not a number");
return; return;
} }
newModeId = (ModeId) value; setMode((ModeId) value);
server.sendHeader("location", "/"); server.sendHeader("location", "/");
server.send(301, "text/plain", "ok"); server.send(301, "text/plain", "ok");
} }
void setMode(ModeId value) {
if (config.mode == value) {
return;
}
config.mode = value;
config_set_dirty();
}
void web_brighter() { void web_brighter() {
setBrightness(display.getBrightness() + 10); setBrightness(display.getBrightness() + 10);
server.sendHeader("location", "/"); server.sendHeader("location", "/");
@ -107,6 +103,18 @@ void web_darker() {
server.send(301, "text/plain", "ok"); 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");
}
void setup() { void setup() {
delay(500); delay(500);
Serial.begin(115200); Serial.begin(115200);
@ -142,8 +150,11 @@ void setup() {
ArduinoOTA.begin(); ArduinoOTA.begin();
yield(); yield();
config_setup();
display.setup(); display.setup();
yield(); yield();
display.setBrightness(config.brightness);
server.on("", web_index); server.on("", web_index);
server.on("/", web_index); server.on("/", web_index);
@ -153,15 +164,20 @@ void setup() {
server.on("/brighter/", web_brighter); server.on("/brighter/", web_brighter);
server.on("/darker", web_darker); server.on("/darker", web_darker);
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(); server.begin();
} }
void loop() { void loop() {
yield(); yield();
ArduinoOTA.handle(); ArduinoOTA.handle();
server.handleClient();
wifi_loop();
serial_read(); serial_read();
server.handleClient();
config_loop();
wifi_loop();
mode_check(); mode_check();
display.loop(); display.loop();
mode_step(); mode_step();
@ -225,7 +241,7 @@ void serial_read() {
case '7': case '7':
case '8': case '8':
case '9': case '9':
newModeId = (ModeId) (input - '0'); setMode((ModeId) (input - '0'));
break; break;
case '+': case '+':
setBrightness(display.getBrightness() + 10); setBrightness(display.getBrightness() + 10);
@ -234,10 +250,10 @@ void serial_read() {
setBrightness(max(1, display.getBrightness() - 10)); setBrightness(max(1, display.getBrightness() - 10));
break; break;
case ',': case ',':
setSpeed(speed / 1.1); setSpeed(config.speed / 1.1);
break; break;
case '.': case '.':
setSpeed(speed * 1.1); setSpeed(config.speed * 1.1);
break; break;
default: default:
Serial.printf("Unknown command: %c\n", input); Serial.printf("Unknown command: %c\n", input);
@ -246,18 +262,29 @@ void serial_read() {
} }
} }
void setBrightness(int value) { void setBrightness(int brightness) {
display.setBrightness(value); brightness = max(0, min(brightness, 255));
Serial.printf("Setting brightness to %5.1f%%\n", value / 2.55); 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 value) { void setSpeed(double speed) {
speed = value; speed = min(max(0.01, speed), 10000.0);
Serial.printf("Setting speed to %6.2fx\n", value); if (config.speed == speed) {
return;
}
config.speed = speed;
config_set_dirty();
Serial.printf("Setting speed to %6.2fx\n", config.speed);
} }
void mode_check() { void mode_check() {
if (currentModeId != newModeId) { if (currentModeId != config.mode) {
unloadOldMode(); unloadOldMode();
loadNewMode(); loadNewMode();
} }
@ -272,11 +299,9 @@ void unloadOldMode() {
} }
void loadNewMode() { void loadNewMode() {
currentModeId = newModeId; currentModeId = config.mode;
lastMicros = 0; lastMicros = 0;
switch (currentModeId) { switch (currentModeId) {
case NONE:
break;
case BORDER: case BORDER:
mode = new Border(&display); mode = new Border(&display);
break; break;
@ -304,6 +329,9 @@ void loadNewMode() {
case NEW_YEAR: case NEW_YEAR:
mode = new NewYear(&display); mode = new NewYear(&display);
break; break;
default:
Serial.print("No mode loaded.\n");
break;
} }
Serial.printf("Mode: %s\n", mode == nullptr ? "None" : mode->getName()); Serial.printf("Mode: %s\n", mode == nullptr ? "None" : mode->getName());
} }
@ -313,7 +341,7 @@ void mode_step() {
return; return;
} }
auto currentMicros = (int64_t) micros(); auto currentMicros = (int64_t) micros();
microseconds_t dt = (microseconds_t) min(1000000.0, max(1.0, (double) (currentMicros - lastMicros) * speed)); microseconds_t dt = (microseconds_t) min(1000000.0, max(1.0, (double) (currentMicros - lastMicros) * config.speed));
lastMicros = currentMicros; lastMicros = currentMicros;
mode->step(dt); mode->step(dt);
} }

View File

@ -8,6 +8,19 @@
#include "Timer.h" #include "Timer.h"
#include "ModeBase.h" #include "ModeBase.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,
};
template<typename T> template<typename T>
class Mode : public ModeBase { class Mode : public ModeBase {

View File

@ -36,7 +36,6 @@ class NewYear : public Mode<NewYear> {
display->clear(); display->clear();
if (!ok) { if (!ok) {
drawNoTime(); drawNoTime();
drawSubSecondsBar(info.tm_sec);
} else if (info.tm_mon == 1 && info.tm_mday == 1 && info.tm_hour == 0) { } else if (info.tm_mon == 1 && info.tm_mday == 1 && info.tm_hour == 0) {
drawYear(counter, info.tm_year + 1900); drawYear(counter, info.tm_year + 1900);
drawFirework(timer->interval); drawFirework(timer->interval);