MQTT-Display-LaserCutter/include/display_manager.h
MaPaLo76 6c8be70eb9 fix(display): FR-014 MAX7219 Re-Init + redraw() nach Relais-Umschaltung (v1.5.2)
- DisplayManager::reinit() setzt nur Kontroll-Register (ohne clear())
- Neues State-Tracking: show*() speichert letzten Zustand intern
- Neues redraw(): zeichnet alle Zonen nach reinit() sofort neu
- LaserTracker::onSessionStart/onSessionEnd rufen display.reinit() auf
2026-03-06 21:48:14 +01:00

151 lines
5.5 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#pragma once
// =============================================================================
// display_manager.h Dot-Matrix-Display Ausgabe (8× GYMAX7219, 4×2 Layout)
// Projekt: MQTT-Display LaserCutter
//
// Implementierung mit rohem MD_MAX72XX (kein MD_Parola), damit die physische
// 90°-CW Verdrehung der Module per Software (rotateCCW) zuverlässig kompensiert
// werden kann ohne dass MD_Parola Zonenlogik interferiert.
//
// Modul-Aufteilung (oben links = Index 0):
// Modul 0 : WiFi-Fehler-Indikator (showWifiError)
// Modul 13 (oben) : Laserzeit in ganzen Minuten, 3 Stellen rechtsbündig
// Modul 4 : MQTT-Fehler-Indikator (showMqttError)
// Modul 57 (unten) : Countdown-Sekunden, 3 Stellen rechtsbündig / showIdle
//
// Verwendung:
// display.begin(); // einmalig in setup()
// display.showLaserTime(42.5f); // Modul 1-3
// display.showCountdown(18); // Modul 5-7
// display.showIdle(); // Modul 5-7
// display.showWifiError(true); // Modul 0
// display.showMqttError(true); // Modul 4
// display.update(); // in loop() aufrufen (Pflicht)
// =============================================================================
#include <Arduino.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
#include "config.h"
// ---------------------------------------------------------------------------
// Maximale Textlänge je Zone (= Anzahl Module pro Zone)
// ---------------------------------------------------------------------------
#define DISP_CHARS_PER_ZONE DISPLAY_MODULES_PER_ZONE // 4
class DisplayManager {
public:
DisplayManager();
// Initialisierung (einmalig in setup())
void begin();
// Helligkeit setzen 015
void setBrightness(uint8_t level);
// ---- Anzeige-Methoden ---------------------------------------------------
// Modul 13 (oben): Laserzeit in ganzen Minuten, 3 Stellen rechtsbündig
// 09 → " x" z.B. " 7"
// 1099 → " xx" z.B. " 42"
// 100999 → "xxx" z.B. "123"
// ≥ 1000 → "!!!" (Überlauf, wird laut Anforderung nie erreicht)
// Modul 0 bleibt unberührt.
void showLaserTime(float minutes);
// Modul 57 (unten): Countdown-Sekunden, 3 Stellen rechtsbündig
// 09 → " x"
// 1099 → " xx"
// 100999 → "xxx"
// ≥ 1000 → "!!!"
// Modul 4 bleibt unberührt.
void showCountdown(int seconds);
// Modul 57 (unten): Leerlauf-Anzeige (" --")
// Modul 4 bleibt unberührt.
void showIdle();
// Modul 57 (unten): Sekunden-Kreisanzeige (wie analoge Uhr)
// seconds = 060: Rand der 3 Module wird sekündlich befüllt
// 60 LEDs = Perimeter des 24×8-Feldes (24 oben + 6 rechts + 24 unten + 6 links)
// Richtung: Uhrzeigersinn, Start oben-links
// seconds = 0 → alle LEDs aus (= Idle)
// seconds ≥ 60 → alle 60 Rand-LEDs an
// Modul 4 bleibt unberührt.
void showSessionRing(int seconds);
// Modul 57 (unten): Statustext (max. 3 Zeichen, wird abgeschnitten / aufgefüllt)
// Modul 4 bleibt unberührt.
void showStatus(const char* msg);
// Modul 0 (oben links): WiFi-Fehler-Indikator
// error=true → 'W' Symbol
// error=false → leer
void showWifiError(bool error);
// Modul 4 (unten links): MQTT-Fehler-Indikator
// error=true → 'M' Symbol
// error=false → leer
void showMqttError(bool error);
// Beide Zonen löschen
void clear();
// MAX7219 neu initialisieren (einmaliges initMx, kein Delay)
// Aufrufen nach Relais-Umschaltung um durch EMV-Störungen korrumpierte
// MAX7219-Register (Decode-Mode, Scan-Limit) zurückzusetzen
void reinit();
// Muss in loop() aufgerufen werden (reserviert für zukünftige Scroll-Animation)
void update() {}
// Alle LEDs ein / aus (Testfunktion)
void allLedsOn();
void allLedsOff();
// Display ein-/ausschalten (SHUTDOWN-Modus des MAX7219)
// setEnabled(false) → alle LEDs aus (MAX7219 Shutdown)
// setEnabled(true) → normaler Betrieb
void setEnabled(bool enabled);
bool isEnabled() const { return _enabled; }
// Debug-Ausgabe auf Serial
void printToSerial() const;
private:
MD_MAX72XX _mx;
bool _enabled = true;
// ---- Letzter angezeigter Zustand (für redraw nach reinit) ----------------
enum class BottomMode : uint8_t { IDLE, COUNTDOWN, RING, STATUS };
float _lastLaserMinutes = 0.0f;
BottomMode _lastBottomMode = BottomMode::IDLE;
int _lastBottomValue = 0;
char _lastStatusMsg[4] = {' ', ' ', ' ', '\0'};
bool _lastWifiError = false;
bool _lastMqttError = false;
// Zeichnet den zuletzt gespeicherten Zustand neu auf die Hardware
void redraw();
// Schreibt genau DISP_CHARS_PER_ZONE Zeichen auf eine Zone
// zone 0 → Module 0..3 (oben)
// zone 1 → Module 4..7 (unten)
// str muss exakt DISP_CHARS_PER_ZONE Zeichen enthalten (kein Null-Terminator nötig)
void writeZone(uint8_t zone, const char* str);
// Schreibt ein Zeichen auf ein einzelnes Modul
void writeChar(uint8_t moduleIdx, char c);
// 90° CCW Rotation kompensiert physische 90° CW Verdrehung der Module
static void rotateCCW(const uint8_t src[8], uint8_t dst[8]);
// Gibt Zeiger auf 8-Byte-Bitmap für ASCII-Zeichen zurück
// Unterstützt: '0''9', ' ', '-', '.', '!', 'E', 'r', 'o', 'n', 'A', 'P'
static const uint8_t* charBitmap(char c);
};
// Globale Instanz
extern DisplayManager display;