Semi working profiles and longer macros

This commit is contained in:
Julian Appel 2026-04-13 21:42:02 +02:00
parent 7169d3bbba
commit 098a166a9f
9 changed files with 257 additions and 108 deletions

View file

@ -101,13 +101,16 @@ void CMainController::init_buttons()
bool valid = nvm_config_load(cfg);
(void)valid; // false = keine gültige Config → Defaults wurden bereits geladen
// Aktives Profil auswählen (load() sichert bereits 02 ab)
const SDeviceProfile& prof = cfg.profiles[cfg.active_profile];
// Encoder-SW-Buttons: nur SW-Aktion, kein LED (led_index = -1)
for (uint8_t enc = 0; enc < 4; enc++) {
m_buttons[enc].init(enc, -1, cfg.enc_actions[enc][ENC_ACTION_SW], RGB());
m_buttons[enc].init(enc, -1, prof.enc_actions[enc][ENC_ACTION_SW], RGB());
}
// MX-Buttons: LED-Index aus serpentiner Verdrahtung berechnen,
// Aktion + Base-Farbe + Animation aus NVM.
// Aktion + Base-Farbe + Animation aus aktivem Profil.
// mx_actions[0] ↔ key_id 5 (COL_1/ROW_0), mx_actions[19] ↔ key_id 24 (COL_4/ROW_4)
for (uint8_t key = 5; key < MATRIX_KEYS; key++) {
@ -115,11 +118,21 @@ void CMainController::init_buttons()
uint8_t row = key % MATRIX_ROWS;
int8_t led = static_cast<int8_t>(LED_INDEX(col, row));
uint8_t mx_idx = key - 5;
RGB base(cfg.led_r[mx_idx], cfg.led_g[mx_idx], cfg.led_b[mx_idx]);
m_buttons[key].init(key, led, cfg.mx_actions[mx_idx], base);
LEDAnim anim = static_cast<LEDAnim>(cfg.led_anim[mx_idx]);
uint16_t period = cfg.led_period_ms[mx_idx] > 0 ? cfg.led_period_ms[mx_idx] : 4000;
// Effektive Farbe = base × led_brightness × global_brightness / 255²
auto scale = [&](uint8_t val) -> uint8_t {
return (uint8_t)((uint32_t)val
* prof.led_brightness[mx_idx] / 255
* cfg.global_brightness / 255);
};
RGB base(scale(prof.led_r[mx_idx]),
scale(prof.led_g[mx_idx]),
scale(prof.led_b[mx_idx]));
m_buttons[key].init(key, led, prof.mx_actions[mx_idx], base);
LEDAnim anim = static_cast<LEDAnim>(prof.led_anim[mx_idx]);
uint16_t period = prof.led_period_ms[mx_idx] > 0 ? prof.led_period_ms[mx_idx] : 4000;
if (anim == LEDAnim::COLOR_CYCLE) {
// Phase gleichmäßig verteilen → stehender Regenbogen dreht sich
@ -133,8 +146,8 @@ void CMainController::init_buttons()
// Encoder CW/CCW-Aktionen separat merken Encoder haben kein CButton-Objekt
// da sie keine LED haben und kein Matrix-Key sind.
for (uint8_t enc = 0; enc < 4; enc++) {
m_enc_cw [enc] = cfg.enc_actions[enc][ENC_ACTION_CW];
m_enc_ccw[enc] = cfg.enc_actions[enc][ENC_ACTION_CCW];
m_enc_cw [enc] = prof.enc_actions[enc][ENC_ACTION_CW];
m_enc_ccw[enc] = prof.enc_actions[enc][ENC_ACTION_CCW];
}
}
@ -198,8 +211,8 @@ void CMainController::poll_vendor()
// 6 Nutzbytes ab Puffer-Offset (chunk_index × 6) eintragen
uint16_t offset = (uint16_t)pkt.key_id() * 6;
if (offset < sizeof(m_cfg_buf)) {
uint8_t count = (uint8_t)(sizeof(m_cfg_buf) - offset);
if (count > 6) count = 6;
uint16_t remaining = (uint16_t)(sizeof(m_cfg_buf) - offset);
uint8_t count = (uint8_t)(remaining > 6 ? 6 : remaining);
memcpy(m_cfg_buf + offset, &pkt.data[2], count);
}
}
@ -211,10 +224,10 @@ void CMainController::poll_vendor()
{
SDeviceConfig cfg;
nvm_config_load(cfg); // ungültige NVM → Defaults
const uint8_t* raw = reinterpret_cast<const uint8_t*>(&cfg);
const uint8_t sz = sizeof(SDeviceConfig); // 223
const uint8_t* raw = reinterpret_cast<const uint8_t*>(&cfg);
const uint16_t sz = sizeof(SDeviceConfig); // 740
const uint8_t payload = 6;
uint8_t chunks = (sz + payload - 1) / payload; // 38
uint8_t chunks = (uint8_t)((sz + payload - 1) / payload); // 124
usb_serial_send(USB_EVT_CONFIG_BEGIN, chunks);
@ -262,10 +275,10 @@ void CMainController::poll_vendor()
case USB_CMD_MACRO_DATA:
if (m_macro_receiving) {
uint16_t offset = (uint16_t)pkt.key_id() * 6;
uint16_t offset = (uint16_t)pkt.key_id() * 6;
if (offset < sizeof(m_macro_buf)) {
uint8_t count = (uint8_t)(sizeof(m_macro_buf) - offset);
if (count > 6) count = 6;
uint16_t remaining = (uint16_t)(sizeof(m_macro_buf) - offset);
uint8_t count = (uint8_t)(remaining > 6 ? 6 : remaining);
memcpy(m_macro_buf + offset, &pkt.data[2], count);
}
}
@ -283,10 +296,10 @@ void CMainController::poll_vendor()
// ── Makro-Dump anfordern ─────────────────────────────────────────
case USB_CMD_MACRO_READ:
{
const uint8_t* raw = reinterpret_cast<const uint8_t*>(&m_macros);
const uint16_t sz = sizeof(SMacroTable); // 256
const uint8_t* raw = reinterpret_cast<const uint8_t*>(&m_macros);
const uint16_t sz = sizeof(SMacroTable); // 512
const uint8_t payload = 6;
uint8_t chunks = (uint8_t)((sz + payload - 1) / payload); // 43
uint8_t chunks = (uint8_t)((sz + payload - 1) / payload); // 86
usb_serial_send(USB_EVT_MACRO_BEGIN, chunks);
@ -417,6 +430,20 @@ void CMainController::execute_action_down(SAction action, uint8_t key_id)
break;
}
case ActionType::PROFILE_SWITCH:
{
SDeviceConfig cfg;
nvm_config_load(cfg);
uint8_t target = static_cast<uint8_t>(action.data);
if (target == 0xFF)
target = (cfg.active_profile + 1) % 3; // Zyklus: 0→1→2→0
if (target > 2) break;
cfg.active_profile = target;
nvm_config_save(cfg);
init_buttons();
break;
}
case ActionType::NONE:
default:
break;