Added config, added factory reset functionality

This commit is contained in:
2026-04-18 23:59:48 +02:00
parent 433d61c29f
commit 802ab858e1
9 changed files with 718 additions and 778 deletions
+139 -4
View File
@@ -33,6 +33,10 @@
#include "config/nvm_config.h"
#include "config/macro_config.h"
static constexpr uint8_t FACTORY_RESET_LEFT_KEY = 9;
static constexpr uint8_t FACTORY_RESET_RIGHT_KEY = 24;
static constexpr uint32_t FACTORY_RESET_HOLD_MS = 5000;
// ─── Static Bridge: HAL-Callbacks → EventQueue ───────────────────────────────
//
// matrix_init() und encoder_init() erwarten einfache Funktionszeiger (kein
@@ -72,6 +76,11 @@ CMainController::CMainController()
, m_cfg_receiving(false)
, m_macro_chunks_expected(0)
, m_macro_receiving(false)
, m_factory_left_held(false)
, m_factory_right_held(false)
, m_factory_reset_armed(false)
, m_factory_reset_done(false)
, m_factory_hold_started_ms(0)
{
memset(m_cfg_buf, 0, sizeof(m_cfg_buf));
memset(m_macro_buf, 0, sizeof(m_macro_buf));
@@ -158,6 +167,7 @@ void CMainController::work()
matrix_scan(); // 1. Matrix scannen → Debounce → matrix_cb() → Queue
poll_vendor(); // 2. Eingehende Serial-Pakete (PC→Board) verarbeiten
processEvents(); // 3. Queue leeren, Aktionen ausführen
check_factory_reset();// 4. Long-Press-Kombination für Werksreset prüfen
updateLEDs(); // 4. Geänderte LED-Zustände in WS2812-Buffer schreiben + show()
}
@@ -347,13 +357,22 @@ void CMainController::processEvents()
switch (ev.type) {
case EventType::KEY_DOWN:
if (ev.key_id < MATRIX_KEYS)
execute_action_down(m_buttons[ev.key_id].action(), ev.key_id);
if (ev.key_id < MATRIX_KEYS) {
update_factory_reset_hold(ev.key_id, true);
if (!(is_factory_reset_combo_active() && is_factory_reset_key(ev.key_id))) {
execute_action_down(m_buttons[ev.key_id].action(), ev.key_id);
}
}
break;
case EventType::KEY_UP:
if (ev.key_id < MATRIX_KEYS)
execute_action_up(m_buttons[ev.key_id].action(), ev.key_id);
if (ev.key_id < MATRIX_KEYS) {
bool suppress = is_factory_reset_combo_active() && is_factory_reset_key(ev.key_id);
update_factory_reset_hold(ev.key_id, false);
if (!suppress) {
execute_action_up(m_buttons[ev.key_id].action(), ev.key_id);
}
}
break;
case EventType::ENC_CW:
@@ -378,6 +397,122 @@ void CMainController::processEvents()
}
}
bool CMainController::is_factory_reset_key(uint8_t key_id) const
{
return key_id == FACTORY_RESET_LEFT_KEY || key_id == FACTORY_RESET_RIGHT_KEY;
}
bool CMainController::is_factory_reset_combo_active() const
{
return m_factory_left_held && m_factory_right_held;
}
void CMainController::update_factory_reset_led_feedback()
{
// Einzelne Reset-Taste gehalten: diese Taste rot hervorheben.
// Beide gehalten: beide Tasten rot hervorheben.
if (m_factory_left_held) {
m_buttons[FACTORY_RESET_LEFT_KEY].set_override(RGB(96, 0, 0));
} else {
m_buttons[FACTORY_RESET_LEFT_KEY].clear_override();
}
if (m_factory_right_held) {
m_buttons[FACTORY_RESET_RIGHT_KEY].set_override(RGB(96, 0, 0));
} else {
m_buttons[FACTORY_RESET_RIGHT_KEY].clear_override();
}
}
void CMainController::update_factory_reset_hold(uint8_t key_id, bool pressed)
{
if (key_id == FACTORY_RESET_LEFT_KEY) {
m_factory_left_held = pressed;
} else if (key_id == FACTORY_RESET_RIGHT_KEY) {
m_factory_right_held = pressed;
} else {
return;
}
update_factory_reset_led_feedback();
if (m_factory_left_held && m_factory_right_held) {
if (!m_factory_reset_armed) {
// Sobald beide Reset-Tasten gleichzeitig gehalten werden, sollen sie
// keine normale Aktion mehr auf dem Host auslösen. Falls die zuerst
// gedrückte Taste bereits ein HID-/Consumer-Hold gestartet hat,
// geben wir sie hier sofort wieder frei.
execute_action_up(m_buttons[FACTORY_RESET_LEFT_KEY].action(), FACTORY_RESET_LEFT_KEY);
execute_action_up(m_buttons[FACTORY_RESET_RIGHT_KEY].action(), FACTORY_RESET_RIGHT_KEY);
m_factory_reset_armed = true;
m_factory_reset_done = false;
m_factory_hold_started_ms = millis();
}
} else {
m_factory_reset_armed = false;
m_factory_reset_done = false;
m_factory_hold_started_ms = 0;
}
}
void CMainController::check_factory_reset()
{
if (!m_factory_reset_armed || m_factory_reset_done) return;
if (!(m_factory_left_held && m_factory_right_held)) return;
if ((millis() - m_factory_hold_started_ms) >= FACTORY_RESET_HOLD_MS) {
m_factory_reset_done = true;
perform_factory_reset();
}
}
void CMainController::perform_factory_reset()
{
SDeviceConfig cfg;
SMacroTable macros;
bool cfg_ok;
bool macro_ok;
nvm_config_defaults(cfg);
memset(&macros, 0, sizeof(macros));
cfg_ok = nvm_config_save(cfg);
macro_ok = macro_config_save(macros);
// Laufzeit-Zustand immer an die Defaults angleichen selbst wenn NVM gerade
// nicht geschrieben werden konnte, sieht das Gerät sofort wieder "frisch" aus.
m_macros = macros;
usb_hid_release_key();
usb_hid_release_consumer();
init_buttons();
show_factory_reset_feedback();
// Während die beiden Tasten weiter gehalten werden, keine erneuten Resets.
// Neue Arming-Phase erst nach vollständigem Loslassen beider Tasten.
if (!(cfg_ok && macro_ok)) {
// Keine Host-Meldung vorgesehen das Gerät bleibt aber betriebsfähig
// und kann über die GUI erneut konfiguriert werden.
}
}
void CMainController::show_factory_reset_feedback()
{
// Kurze rote Bestätigung ähnlich der Startsequenz, aber kompakter.
ws2812_fill(100, 0, 0);
ws2812_show();
delay(180);
ws2812_clear();
delay(90);
ws2812_fill(100, 0, 0);
ws2812_show();
delay(180);
ws2812_clear();
delay(60);
// Danach sofort die frisch geladenen Default-Animationen wieder anzeigen.
updateLEDs();
}
// ─── Aktions-Ausführung ───────────────────────────────────────────────────────
//
// execute_action_down(): Taste wird gedrückt (Hold-Start).
+17
View File
@@ -55,4 +55,21 @@ private:
// Geladene Makro-Tabelle (im RAM wird beim Start aus NVM geladen)
SMacroTable m_macros;
// Werksreset per Long-Press-Kombination:
// key_id 9 = unterster linker MX-Button (COL_1 / ROW_4)
// key_id 24 = unterster rechter MX-Button (COL_4 / ROW_4)
bool m_factory_left_held;
bool m_factory_right_held;
bool m_factory_reset_armed;
bool m_factory_reset_done;
uint32_t m_factory_hold_started_ms;
bool is_factory_reset_key(uint8_t key_id) const;
bool is_factory_reset_combo_active() const;
void update_factory_reset_led_feedback();
void update_factory_reset_hold(uint8_t key_id, bool pressed);
void check_factory_reset();
void perform_factory_reset();
void show_factory_reset_feedback();
};