Files
VersaMCU/src/CButton.h
T

132 lines
6.5 KiB
C++
Raw 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.
// 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 (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;
};