VersaMCU/doc/06_nvm_config.md

131 lines
5.1 KiB
Markdown
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.

# NVM-Konfiguration
**Dateien:** `config/nvm_config.h`, `config/nvm_config.cpp`
## Flash-Layout
| Row | Adresse | Größe | Inhalt |
|---|---|---|---|
| Row 0 | `0x1FE00` | 256 B | SDeviceConfig (223 B genutzt, 33 B Padding) |
| Row 1 | `0x1FF00` | 256 B | SMacroTable (256 B, komplett genutzt) |
Beide Rows sind im Linkerscript vom Code-Bereich ausgeschlossen.
## SDeviceConfig Byte-Layout (223 Byte, packed)
| Offset | Größe | Feld |
|---|---|---|
| 0 | 4 | `magic` = `0x56503202` ('VP2\x02') |
| 4 | 1 | `version` = 2 |
| 5 | 2 | `crc` CRC16-CCITT über Bytes 7222 |
| 7 | 60 | `mx_actions[20]` 20 × 3 B SAction |
| 67 | 36 | `enc_actions[4][3]` 12 × 3 B SAction |
| 103 | 20 | `led_r[20]` |
| 123 | 20 | `led_g[20]` |
| 143 | 20 | `led_b[20]` |
| 163 | 20 | `led_anim[20]` LEDAnim-Typ als uint8_t |
| 183 | 40 | `led_period_ms[20]` uint16_t, little-endian |
| **223** | — | Ende des genutzten Bereichs |
`__attribute__((packed))` ist zwingend. Ohne packed wäre SAction 4 B statt 3 B (Alignment-Padding), was `sizeof(SDeviceConfig)` um 32 B vergrößert und die C#-Deserialisierung in VersaGUI zerstört.
## CRC16-CCITT
- Polynom: `0x1021`, Init: `0xFFFF`
- Berechnet über Bytes 7248 (ab `mx_actions`, nach dem `crc`-Feld selbst)
- Sichert Datenintegrität nach NVM-Schreiben und bei Versionswechsel
## Lese-Logik
```
memcpy aus Flash-Adresse 0x1FE00
if magic != 0x56503202: Defaults laden, return false
if version != 2: Defaults laden, return false
if crc != crc(cfg): Defaults laden, return false
return true
```
Kein Absturz bei ungültiger Config Defaults greifen immer.
## Defaults
- Alle Aktionen: `NONE`
- LEDs: warm-weiß (R=80, G=40, B=0)
- Animation: `COLOR_CYCLE` (Typ 5), Period 4000 ms
## Schreib-Logik (NVM-Mechanik)
SAMD21 NVM: Row = 256 B = 4 Pages à 64 B. Schreiben erfordert:
1. `NVMCTRL->CTRLB.bit.MANW = 1` (manueller Schreib-Modus, kein Auto-Write)
2. Row löschen (`NVMCTRL_CTRLA_CMD_ER`)
3. Page-Buffer löschen (`NVMCTRL_CTRLA_CMD_PBC`)
4. 64 B als `uint32_t*` in Page-Buffer schreiben
5. Page programmieren (`NVMCTRL_CTRLA_CMD_WP`)
6. Schritte 35 viermal (für alle 4 Pages)
> `NVMCTRL->ADDR.reg = addr / 2` NVMCTRL erwartet Wort-Adresse (16-Bit-Worte), nicht Byte-Adresse.
> **Aligned-Buffer-Pflicht**: `nvm_write_page` castet `data` zu `const uint32_t*`. Der Puffer muss `__attribute__((aligned(4)))` sein. Packed Structs sind nicht garantiert aligned → immer via lokalen `uint8_t buf[256] __attribute__((aligned(4)))` + `memcpy` übergeben.
---
## Geplante Erweiterung: NVM v3
### Motivation
Das bisherige Layout (2 Rows, 512 B) stößt an mehrere Grenzen:
- **Makro-Steps zu kurz** — 4 Steps reichen für komplexe Shortcuts (z.B. Excel-Ribbon-Navigation: Alt → Buchstabe → Buchstabe → ...) nicht aus. Ziel: 8 Steps.
- **Keine Profile** — Eine einzige Config erlaubt keine Umschaltung zwischen Layouts (z.B. Coding vs. Tabellenkalkulation). Ziel: 3 unabhängige Profile.
- **Keine Helligkeitssteuerung** — Weder global noch pro LED einstellbar. Beide Ebenen sollen konfigurierbar werden.
- **Encoder-Sensitivity** — Schrittweite pro Encoder soll konfigurierbar sein.
Das bisherige Layout hat außerdem Config und Macros in denselben Adressbereich gemischt (`0x1FE00` Config, `0x1FF00` Macros). Das neue Layout trennt beide Bereiche sauber.
### Neues Flash-Layout (5 Rows, 0x1FB000x1FFFF)
| Row | Adresse | Größe | Inhalt |
|---|---|---|---|
| Macro Row 0 | `0x1FB00` | 256 B | SMacroTable (Bytes 0255) |
| Macro Row 1 | `0x1FC00` | 256 B | SMacroTable (Bytes 256511) |
| Config Row 0 | `0x1FD00` | 256 B | Globaler Header + Profil 0 (Bytes 0255) |
| Config Row 1 | `0x1FE00` | 256 B | Profil 0 (Rest) + Profil 1 (Bytes 256511) |
| Config Row 2 | `0x1FF00` | 256 B | Profil 1 (Rest) + Profil 2 + Reserve (Bytes 512767) |
Macros und Config liegen in vollständig getrennten, jeweils zusammenhängenden Row-Blöcken.
### Config-Inhalt (768 B, davon 740 B genutzt, 28 B Reserve)
**Globaler Header (32 B, Offset 0):**
| Offset | Größe | Feld |
|---|---|---|
| 0 | 4 | `magic` = `0x56503203` ('VP2\x03') |
| 4 | 1 | `version` = 3 |
| 5 | 2 | `crc` CRC16-CCITT über alle Nutzdaten (ab Byte 7) |
| 7 | 1 | `active_profile` (02) |
| 8 | 1 | `global_brightness` (0255) |
| 9 | 4 | `enc_sensitivity[4]` (1 B pro Encoder) |
| 13 | 19 | Reserve |
**Pro Profil (236 B, Offset `32 + idx × 236`):**
| Offset | Größe | Feld |
|---|---|---|
| 0 | 60 | `mx_actions[20]` 20 × 3 B SAction |
| 60 | 36 | `enc_actions[4][3]` 12 × 3 B SAction |
| 96 | 20 | `led_r[20]` |
| 116 | 20 | `led_g[20]` |
| 136 | 20 | `led_b[20]` |
| 156 | 20 | `led_brightness[20]` ← neu |
| 176 | 20 | `led_anim[20]` |
| 196 | 40 | `led_period_ms[20]` |
### Makro-Tabelle (512 B)
32 Slots × **8 Steps** × 2 B = 512 B. Gegenüber v2 doppelt so viele Steps (4 → 8), Slot-Anzahl und Struktur bleiben gleich. Siehe [04_macro_system.md](04_macro_system.md).
### Migration von v2
Beim Laden: wenn `magic` oder `version` nicht zu v3 passen, werden Defaults geladen (kein Migrations-Pfad von v2 → v3, da das Layout inkompatibel ist). Eine einmalige Neukonfiguration nach dem Firmware-Update ist nötig.