Added config, added factory reset functionality
This commit is contained in:
+139
-4
@@ -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(¯os, 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).
|
||||
|
||||
@@ -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();
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user