Initial commit

This commit is contained in:
2026-03-29 14:47:13 +02:00
commit b49984b9c0
32 changed files with 2394 additions and 0 deletions
+136
View File
@@ -0,0 +1,136 @@
// 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).
// led_index = -1 → kein LED (Encoder-SW-Buttons).
void init(uint8_t key_id, int8_t led_index, SAction action, RGB base = RGB());
// Hooks für Tastendruck/-loslassen.
// Reserviert für zukünftige Logik (Hold-Aktionen, Toggle-Modus, …).
void on_press();
void on_release();
// ── 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 (0255) 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;
};