// CButton.h // Bildet eine einzelne Taste (MX-Button oder Encoder-SW) vollständig ab: // - Zugehöriger WS2812-LED-Index (oder -1 wenn keine LED) // - Konfigurierte Aktion (HID_KEY, HID_CONSUMER, HOST_COMMAND, NONE) // - 2-Layer-LED-Modell: base (Idle-Farbe) + override (temporär, z.B. Benachrichtigung) // - LED-Animationen: STATIC, BLINK, PULSE, FADE_IN, FADE_OUT, COLOR_CYCLE, COLOR_FADE // // LED-Rendering: // Aktive Farbe = override wenn gesetzt, sonst base. // Helligkeits-Animationen (BLINK, PULSE, FADE_*) modulieren die Helligkeit der aktiven Farbe. // Farb-Animationen (COLOR_CYCLE, COLOR_FADE) berechnen die Farbe selbst (ignorieren base/override). // render_led() gibt true zurück solange eine Animation läuft oder dirty gesetzt ist – // CMainController::updateLEDs() ruft dann ws2812_show() auf. // // Aktionsausführung: // on_press() / on_release() sind Hooks für zukünftige Button-Logik. // Die eigentliche Aktion wird vom CMainController via action() ausgeführt. #pragma once #include #include "config/action.h" // ── Farb-Struct ─────────────────────────────────────────────────────────────── struct RGB { uint8_t r, g, b; RGB() : r(0), g(0), b(0) {} RGB(uint8_t r, uint8_t g, uint8_t b) : r(r), g(g), b(b) {} }; // ── LED-Animationen ─────────────────────────────────────────────────────────── // // Helligkeits-Animationen (BLINK, PULSE, FADE_*): // Modulieren die Helligkeit der aktiven Farbe (base oder override). // BLINK und PULSE laufen endlos bis clear_anim() aufgerufen wird. // FADE_IN und FADE_OUT sind einmalig – nach Ablauf zurück zu STATIC. // FADE_OUT: nach Abschluss leuchtet die LED nicht (base wird auf schwarz gesetzt). // // Farb-Animationen (COLOR_CYCLE, COLOR_FADE): // Berechnen die Farbe selbst – base/override werden ignoriert, aber nicht verändert. // COLOR_CYCLE läuft endlos; COLOR_FADE ist einmalig (base wird auf Zielfarbe gesetzt). // Für COLOR_FADE: set_color_fade(to, period_ms) statt set_anim() verwenden. enum class LEDAnim : uint8_t { STATIC = 0, // Sofort, keine Animation (Standardzustand) BLINK, // Binäres An/Aus – period_ms = Halbperiode (An-Zeit = Aus-Zeit) PULSE, // Lineares Fade-In/Fade-Out in Schleife – period_ms = Vollperiode FADE_IN, // Einmalig: schwarz → volle Helligkeit über period_ms FADE_OUT, // Einmalig: volle Helligkeit → schwarz über period_ms COLOR_CYCLE, // Endloser Hue-Sweep (Regenbogen) – period_ms = eine volle Runde COLOR_FADE, // Einmalig: Crossfade von Startfarbe → Zielfarbe über period_ms }; // ── CButton ─────────────────────────────────────────────────────────────────── class CButton { public: CButton(); // Initialisierung (ersetzt Konstruktor-Parameter). void init(uint8_t key_id, int8_t led_index, SAction action, RGB base = RGB()); // ── LED Layer 1: base ───────────────────────────────────────────────────── // Idle-Farbe, aus NVM geladen oder von Windows-App gesetzt. void set_base(RGB color); // ── LED Layer 2: override ───────────────────────────────────────────────── // Temporärer Override, überschreibt base solange aktiv. // Typisch: Windows-App signalisiert Benachrichtigung. void set_override(RGB color); void clear_override(); // Zurück zu base // ── LED-Animation ───────────────────────────────────────────────────────── // set_anim(): für STATIC, BLINK, PULSE, FADE_IN, FADE_OUT, COLOR_CYCLE. // period_ms: Halbperiode (BLINK), Vollperiode (PULSE/COLOR_CYCLE), Dauer (FADE_*). // phase_offset_ms: Zeitversatz in die Vergangenheit – verschiebt den Startpunkt der // Animation. Nützlich für COLOR_CYCLE um LEDs versetzt starten zu // lassen (Regenbogen-Wellen-Effekt über mehrere Buttons). void set_anim(LEDAnim anim, uint16_t period_ms = 500, uint16_t phase_offset_ms = 0); // Crossfade von der aktuell aktiven Farbe zur Zielfarbe. // Nach Abschluss wird base auf die Zielfarbe gesetzt → LED bleibt in Zielfarbe. void set_color_fade(RGB to, uint16_t period_ms = 500); void clear_anim(); // Zurück zu STATIC, Helligkeit sofort wieder voll // ── Rendering ───────────────────────────────────────────────────────────── // Schreibt aktuelle Farbe (mit Animations-Skalierung) in den WS2812-Buffer. // Gibt true zurück wenn ws2812_show() nötig ist: // - dirty-Flag gesetzt (Farbe hat sich geändert), oder // - Animation läuft (jeder Frame braucht einen neuen ws2812_set-Aufruf) bool render_led(); uint8_t key_id() const { return m_key_id; } bool has_led() const { return m_led_index >= 0; } SAction action() const { return m_action; } private: uint8_t m_key_id; int8_t m_led_index; SAction m_action; // LED-Zustand RGB m_base; RGB m_override; bool m_override_active; bool m_dirty; // true = render_led() muss ws2812_set() aufrufen // Animations-Zustand LEDAnim m_anim; uint16_t m_anim_period_ms; uint32_t m_anim_start_ms; RGB m_anim_from; // COLOR_FADE: Startfarbe (Snapshot bei set_color_fade()) RGB m_anim_to; // COLOR_FADE: Zielfarbe // Helfer: Helligkeits-Skalierungsfaktor (0–255) für BLINK/PULSE/FADE_*. // Aktualisiert m_anim bei Abschluss von FADE_IN/FADE_OUT. uint8_t compute_scale(); // Helfer: finale RGB-Farbe für alle Animationstypen. // Ruft compute_scale() für Helligkeits-Animationen auf; // berechnet Farbe direkt für COLOR_CYCLE und COLOR_FADE. RGB compute_rgb(); // true wenn die Animation noch läuft (BLINK/PULSE/COLOR_CYCLE immer, FADE* bis Ablauf) bool is_animating() const; };