#pragma once #include #include "action.h" // ── NVM-Config-Layout (768 Bytes, ab 0x1FD00) ──────────────────────────────── // // Row 0 (0x1FD00, 256B): Globaler Header (32B) + Profil 0 (236B) + Padding (−12B → überläuft in Row 1) // Row 1 (0x1FE00, 256B): Profil 0 Rest + Profil 1 (Teil) // Row 2 (0x1FF00, 256B): Profil 1 Rest + Profil 2 + Reserve (28B) // // Profil-Offsets (ab Byte 0 des Config-Blobs): // Header: Bytes 0– 31 (32B) // Profil 0: Bytes 32–267 (236B) // Profil 1: Bytes 268–503 (236B) // Profil 2: Bytes 504–739 (236B) // Reserve: Bytes 740–767 (28B) // // Alle 3 Rows werden immer gemeinsam gelöscht und neu geschrieben. #define NVM_CONFIG_MAGIC 0x56503203UL // 'VP2\x03' – Version 3 #define NVM_CONFIG_VERSION 3 // Encoder-Aktions-Indizes (in SDeviceProfile.enc_actions[]) // Reihenfolge: [enc][0]=SW, [enc][1]=CW, [enc][2]=CCW #define ENC_ACTION_SW 0 #define ENC_ACTION_CW 1 #define ENC_ACTION_CCW 2 // ── Pro-Profil-Daten (236 Bytes) ───────────────────────────────────────────── struct __attribute__((packed)) SDeviceProfile { SAction mx_actions[20]; // 60B – MX-Buttons 0–19 SAction enc_actions[4][3]; // 36B – [Encoder 0–3][SW/CW/CCW] uint8_t led_r[20]; // 20B uint8_t led_g[20]; // 20B uint8_t led_b[20]; // 20B uint8_t led_brightness[20]; // 20B – per-LED Helligkeit (0–255, Default 255) uint8_t led_anim[20]; // 20B – LEDAnim-Typ (0=STATIC … 5=COLOR_CYCLE) uint16_t led_period_ms[20]; // 40B – Animationsperiode in ms // Gesamt: 236B }; // ── Globale Config (740 Bytes) ──────────────────────────────────────────────── struct __attribute__((packed)) SDeviceConfig { // Globaler Header (32B) uint32_t magic; // 4B uint8_t version; // 1B uint16_t crc; // 2B – CRC16-CCITT über Bytes 7–739 uint8_t active_profile; // 1B – aktives Profil (0–2) uint8_t global_brightness; // 1B – globale LED-Helligkeit (0–255) uint8_t enc_sensitivity[4]; // 4B – Schrittweite pro Encoder (reserviert, Default 1) uint8_t _reserve[19]; // 19B – Platz für spätere globale Felder // Profile (3 × 236B = 708B) SDeviceProfile profiles[3]; // Gesamt: 32 + 708 = 740B }; static_assert(sizeof(SAction) == 3, "SAction binary layout changed"); static_assert(sizeof(SDeviceProfile) == 236, "SDeviceProfile binary layout changed"); static_assert(sizeof(SDeviceConfig) == 740, "SDeviceConfig binary layout changed"); // Standardwerte wenn keine gültige Config im NVM void nvm_config_defaults(SDeviceConfig& cfg); // Vollständige Prüfung des persistenten/seriellen Binärvertrags inklusive CRC, // Enum-Bereichen, Action-Nutzdaten und animationsspezifischen Mindestwerten. bool nvm_config_validate(const SDeviceConfig& cfg); // Config aus NVM lesen. Gibt false zurück wenn Magic/CRC/Version ungültig → Defaults geladen. bool nvm_config_load(SDeviceConfig& cfg); // Config in NVM schreiben (CRC wird intern neu berechnet; löscht 3 Rows, // schreibt 12 Pages). // Gibt false zurück wenn eine NVM-Operation nicht rechtzeitig fertig wird (Board hängt nicht). bool nvm_config_save(const SDeviceConfig& cfg); // CRC16 über die Nutzdaten der Config (Bytes 7–739, nach dem crc-Feld) uint16_t nvm_config_crc(const SDeviceConfig& cfg);