Rewrote the AI slop

This commit is contained in:
2026-05-28 21:40:57 +03:00
parent 68ee8c210b
commit a08228265d
6 changed files with 71 additions and 225 deletions
+10 -12
View File
@@ -4,28 +4,26 @@
#include <Arduino.h>
#include <U8g2lib.h>
#include "screens.h"
struct Screen
{
void (*draw)(U8G2 &u8g2);
};
class Carousel {
class Carousel
{
public:
Carousel(Screen *screens, size_t screenCount);
void begin(unsigned long now);
void update(unsigned long now);
void next(unsigned long now);
void render(U8X8 &display) const;
void draw(U8G2 &u8g2);
bool consumeDirty();
void nextScreen();
void update(unsigned long now);
private:
Screen *screens_;
size_t screenCount_;
size_t currentIndex_;
unsigned long nextAutoAdvanceAt_;
unsigned long manualModeUntil_;
unsigned long nextUpdate_;
bool dirty_;
void scheduleNextAdvance(unsigned long now);
void drawIndicators(U8X8 &display) const;
};
#endif
-22
View File
@@ -1,22 +0,0 @@
#ifndef DISPLAY_CONFIG_H
#define DISPLAY_CONFIG_H
#include <Arduino.h>
namespace display_config {
constexpr uint8_t kNextButtonPin = A4;
constexpr unsigned long kAutoAdvanceIntervalMs = 10000;
constexpr unsigned long kManualHoldIntervalMs = 60000;
constexpr unsigned long kButtonDebounceMs = 150;
constexpr unsigned long kDebugLogIntervalMs = 500;
constexpr uint8_t kDisplayColumns = 16;
constexpr uint8_t kDisplayRows = 8;
constexpr uint8_t kIndicatorRow = 7;
constexpr uint8_t kIndicatorSpacing = 2;
} // namespace display_config
#endif
-16
View File
@@ -1,16 +0,0 @@
#ifndef SCREENS_H
#define SCREENS_H
#include <U8g2lib.h>
struct Screen {
const char *title;
void (*render)(U8X8 &display);
};
void renderTimeScreen(U8X8 &display);
void renderWeatherScreen(U8X8 &display);
void renderTemperatureScreen(U8X8 &display);
void renderHumidityScreen(U8X8 &display);
#endif
+22 -90
View File
@@ -1,104 +1,36 @@
#include "carousel.h"
#include "display_config.h"
const unsigned long pageInterval = 5000;
Carousel::Carousel(Screen *screens, size_t screenCount)
: screens_(screens),
screenCount_(screenCount),
dirty_(true),
currentIndex_(0),
nextAutoAdvanceAt_(0),
manualModeUntil_(0),
dirty_(true) {}
nextUpdate_(pageInterval) {}
void Carousel::begin(unsigned long now) {
currentIndex_ = 0;
manualModeUntil_ = 0;
void Carousel::draw(U8G2 &u8g2)
{
screens_[currentIndex_].draw(u8g2);
dirty_ = false;
}
bool Carousel::consumeDirty()
{
bool d = dirty_;
dirty_ = false;
return d;
}
void Carousel::nextScreen()
{
currentIndex_ = (currentIndex_ + 1) % screenCount_;
dirty_ = true;
scheduleNextAdvance(now);
Serial.print("carousel: begin index=");
Serial.print(currentIndex_);
Serial.print(" nextAutoAdvanceAt=");
Serial.println(nextAutoAdvanceAt_);
nextUpdate_ += pageInterval;
}
void Carousel::update(unsigned long now) {
if (screenCount_ == 0) {
return;
}
if (manualModeUntil_ != 0 && now < manualModeUntil_) {
return;
}
if (now >= nextAutoAdvanceAt_) {
currentIndex_ = (currentIndex_ + 1) % screenCount_;
dirty_ = true;
scheduleNextAdvance(now);
Serial.print("carousel: auto advance index=");
Serial.print(currentIndex_);
Serial.print(" now=");
Serial.print(now);
Serial.print(" nextAutoAdvanceAt=");
Serial.println(nextAutoAdvanceAt_);
if (now > nextUpdate_) {
nextScreen();
}
}
void Carousel::next(unsigned long now) {
if (screenCount_ == 0) {
return;
}
currentIndex_ = (currentIndex_ + 1) % screenCount_;
manualModeUntil_ = now + display_config::kManualHoldIntervalMs;
dirty_ = true;
scheduleNextAdvance(manualModeUntil_);
Serial.print("carousel: manual advance index=");
Serial.print(currentIndex_);
Serial.print(" now=");
Serial.print(now);
Serial.print(" manualModeUntil=");
Serial.print(manualModeUntil_);
Serial.print(" nextAutoAdvanceAt=");
Serial.println(nextAutoAdvanceAt_);
}
void Carousel::render(U8X8 &display) const {
if (screenCount_ == 0) {
return;
}
screens_[currentIndex_].render(display);
drawIndicators(display);
}
bool Carousel::consumeDirty() {
const bool wasDirty = dirty_;
dirty_ = false;
return wasDirty;
}
void Carousel::scheduleNextAdvance(unsigned long now) {
nextAutoAdvanceAt_ = now + display_config::kAutoAdvanceIntervalMs;
}
void Carousel::drawIndicators(U8X8 &display) const {
char indicatorLine[display_config::kDisplayColumns + 1];
for (uint8_t i = 0; i < display_config::kDisplayColumns; ++i) {
indicatorLine[i] = ' ';
}
indicatorLine[display_config::kDisplayColumns] = '\0';
const int totalWidth =
static_cast<int>((screenCount_ - 1) * display_config::kIndicatorSpacing) + 1;
const int startX = (display_config::kDisplayColumns - totalWidth) / 2;
for (size_t i = 0; i < screenCount_; ++i) {
const int x = startX + static_cast<int>(i * display_config::kIndicatorSpacing);
if (x >= 0 && x < display_config::kDisplayColumns) {
indicatorLine[x] = (i == currentIndex_) ? '*' : 'o';
}
}
display.drawString(0, display_config::kIndicatorRow, indicatorLine);
}
+34 -46
View File
@@ -3,66 +3,54 @@
#include <Wire.h>
#include "carousel.h"
#include "display_config.h"
#include "screens.h"
// SH1106 128x64 OLED over hardware I2C, rotated 180 degrees for flipped mounting.
U8X8_SH1106_128X64_NONAME_HW_I2C display(U8X8_PIN_NONE, SCL, SDA);
U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R2, U8X8_PIN_NONE);
int lastButtonState = LOW;
uint8_t buttonOne = A3;
int number = 0;
bool dirty = true;
void drawScreen1(U8G2 &u8g2) {
u8g2.setFont(u8g2_font_ncenB14_tr);
u8g2.drawStr(0, 20, "Screen 1");
}
void drawScreen2(U8G2 &u8g2) {
u8g2.setFont(u8g2_font_ncenB14_tr);
u8g2.drawStr(0, 40, "Screen 2");
}
Screen screens[] = {
{"Local Time", renderTimeScreen},
{"Forecast", renderWeatherScreen},
{"Temperature", renderTemperatureScreen},
{"Humidity", renderHumidityScreen},
{ drawScreen1 },
{ drawScreen2 }
};
Carousel carousel(screens, sizeof(screens) / sizeof(screens[0]));
unsigned long lastButtonPressAt = 0;
int lastNextButtonState = LOW;
void setup() {
Serial.begin(115200);
pinMode(display_config::kNextButtonPin, INPUT);
pinMode(buttonOne, INPUT);
display.begin();
display.setFlipMode(1);
display.setFont(u8x8_font_chroma48medium8_r);
display.clearDisplay();
carousel.begin(millis());
Serial.println("setup: display initialized");
Serial.print("setup: next button pin=");
Serial.println(display_config::kNextButtonPin);
u8g2.begin();
u8g2.clearBuffer();
u8g2.sendBuffer();
}
void loop(){
const unsigned long now = millis();
const int nextButtonState = digitalRead(display_config::kNextButtonPin);
if (nextButtonState != lastNextButtonState) {
Serial.print("button: state changed to ");
Serial.print(nextButtonState);
Serial.print(" at ");
Serial.println(now);
}
if (lastNextButtonState == HIGH && nextButtonState == LOW &&
now - lastButtonPressAt >= display_config::kButtonDebounceMs) {
Serial.print("button: press detected at ");
Serial.println(now);
carousel.next(now);
lastButtonPressAt = now;
}
lastNextButtonState = nextButtonState;
carousel.update(now);
const int currentButtonState = digitalRead(buttonOne);
if (lastButtonState == LOW && currentButtonState == HIGH) {
number += 10;
carousel.nextScreen();
}
lastButtonState = currentButtonState;
if (carousel.consumeDirty()) {
Serial.print("display: redraw at ");
Serial.println(now);
carousel.render(display);
u8g2.clearBuffer();
carousel.draw(u8g2);
u8g2.sendBuffer();
}
delay(100);
delay(50);
}
-34
View File
@@ -1,34 +0,0 @@
#include "screens.h"
namespace {
void clearContentRows(U8X8 &display) {
for (uint8_t row = 0; row < 7; ++row) {
display.clearLine(row);
}
}
void drawScreenFrame(U8X8 &display, const char *title, const char *value) {
clearContentRows(display);
display.drawString(0, 0, title);
display.drawString(0, 2, "--------------");
display.drawString(0, 4, value);
}
} // namespace
void renderTimeScreen(U8X8 &display) {
drawScreenFrame(display, "Local Time", "12:34");
}
void renderWeatherScreen(U8X8 &display) {
drawScreenFrame(display, "Forecast", "Sunny");
}
void renderTemperatureScreen(U8X8 &display) {
drawScreenFrame(display, "Temperature", "21.5 C");
}
void renderHumidityScreen(U8X8 &display) {
drawScreenFrame(display, "Humidity", "45 %");
}