- Add include/display_manager.h: DisplayManager class declaration - Two-zone layout: Zone 0 (top, laser time), Zone 1 (bottom, countdown/status) - showLaserTime(), showCountdown(), showIdle(), showStatus(), setBrightness() - rotateCCW() bitmap transformation for 90 deg physical module rotation - charBitmap() for 17-character set (0-9, space, dash, dot, special chars) - Add src/display_manager.cpp: full implementation - Double-init pattern for SPI power stability - showLaserTime() format: <10 -> ' x.x', <100 -> 'xx.x', <1000 -> ' xxx', else 'xxxx' - showCountdown() right-aligned 4-char format - All methods use writeZone() -> writeChar() -> rotateCCW() -> MD_MAX72XX - Add test_sketches/test_display_manager.cpp: 6-step verification test - allLedsOn/Off, showLaserTime (12 boundary values), showCountdown 5->0 - showIdle, showStatus (Err/AP/WiFi/oF), live simulation loop - Update platformio.ini: add test-display-mgr environment - Update src/main.cpp: integrate display.begin/showIdle/update - Update Implementation-Plan.md: mark Phase 4 tasks 4.1-4.3 complete Tested on hardware: all 6 test steps passed
98 lines
3.2 KiB
C++
98 lines
3.2 KiB
C++
#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.
|
||
//
|
||
// Zone-Aufteilung:
|
||
// Zone 0 (top): Module 0–3 → akkumulierte Laserzeit (Float, Minuten)
|
||
// Zone 1 (bottom): Module 4–7 → Countdown / Status
|
||
//
|
||
// Verwendung:
|
||
// display.begin(); // einmalig in setup()
|
||
// display.showLaserTime(42.5f);
|
||
// display.showCountdown(18);
|
||
// display.showIdle();
|
||
// 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 0–15
|
||
void setBrightness(uint8_t level);
|
||
|
||
// ---- Anzeige-Methoden ---------------------------------------------------
|
||
|
||
// Obere Zone: Laserzeit in Minuten
|
||
// < 10 → " x.x" z.B. " 9.5"
|
||
// < 100 → "xx.x" z.B. "42.5"
|
||
// < 1000 → " xxx" z.B. " 123"
|
||
// < 10000 → "xxxx" z.B. "1234"
|
||
// >= 10000 → "!!!!" (Überlauf)
|
||
void showLaserTime(float minutes);
|
||
|
||
// Untere Zone: Countdown-Sekunden (rechtsbündig)
|
||
// 0–999s werden dargestellt, > 999 → " !!!"
|
||
void showCountdown(int seconds);
|
||
|
||
// Untere Zone: Leerlauf-Anzeige (" --")
|
||
void showIdle();
|
||
|
||
// Untere Zone: Statustext (max. 4 Zeichen, wird abgeschnitten / aufgefüllt)
|
||
void showStatus(const char* msg);
|
||
|
||
// Beide Zonen löschen
|
||
void clear();
|
||
|
||
// Muss in loop() aufgerufen werden (reserviert für zukünftige Scroll-Animation)
|
||
void update() {}
|
||
|
||
// Alle LEDs ein / aus (Testfunktion)
|
||
void allLedsOn();
|
||
void allLedsOff();
|
||
|
||
// Debug-Ausgabe auf Serial
|
||
void printToSerial() const;
|
||
|
||
private:
|
||
MD_MAX72XX _mx;
|
||
|
||
// 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;
|