132 lines
6.5 KiB
C++
132 lines
6.5 KiB
C++
// 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 <stdint.h>
|
||
#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;
|
||
};
|