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
+96 -61
View File
@@ -1,92 +1,127 @@
# Serial-Protokoll (CDC USB)
**Dateien:** `hal/usb_serial.h`, `hal/usb_serial.cpp`
Dateien:
## Grundprinzip
- `hal/usb_serial.h`
- `hal/usb_serial.cpp`
- `CMainController.cpp`
Board erscheint unter Windows als CDC Serial-Port (kein Treiber nötig). Alle Pakete haben feste Größe von **8 Byte** kein Längen-Header, kein Framing, kein Escape.
## Paketformat
Alle Pakete sind exakt 8 Byte lang:
```text
Byte 0: command / event id
Byte 1: key_id oder chunk-index oder chunk-count
Byte 2: daten a
Byte 3: daten b
Byte 4: daten c
Byte 5..7: reserviert
```
Byte 0: Command / Event-ID
Byte 1: key_id (Button 024 oder Encoder 03) / Chunk-Index / Chunk-Count
Byte 2: r / Daten-Byte A
Byte 3: g / Daten-Byte B
Byte 4: b
Byte 57: reserviert (0x00)
```
Es gibt kein Framing und keinen Laengenheader.
## Richtungen
| Richtung | ID-Bereich | Verarbeitung |
| Richtung | IDs | Verarbeitung |
|---|---|---|
| PC Board (Commands) | 0x010x7F | `poll_vendor()` in CMainController |
| Board PC (Events) | 0x810xFF | `usb_serial_send()` in processEvents |
| PC -> Board | `0x01..0x7F` | `poll_vendor()` |
| Board -> PC | `0x81..0xFF` | `usb_serial_send()` |
## Command-Referenz (PC → Board)
## Commands
| ID | Name | Bedeutung |
| ID | Name | Zweck |
|---|---|---|
| `0x01` | SET_LED_OVERRIDE | key_id, r, g, b temporäre Override-Farbe setzen |
| `0x02` | CLEAR_LED_OVERRIDE | key_id Override löschen, zurück zu base |
| `0x03` | SET_LED_BASE | key_id, r, g, b base-Farbe dauerhaft ändern (kein NVM) |
| `0x05` | PING | Board antwortet sofort mit PONG (0x85) |
| `0x10` | CONFIG_BEGIN | Byte[1] = Chunk-Anzahl neuen Config-Empfang starten |
| `0x11` | CONFIG_DATA | Byte[1] = Chunk-Index, Byte[27] = 6 B Nutzdaten |
| `0x12` | CONFIG_COMMIT | CRC prüfen → NVM schreiben → Buttons neu laden → ACK/NACK |
| `0x13` | CONFIG_READ | Board sendet aktuelle NVM-Config zurück (BEGIN/DATA/END) |
| `0x20` | MACRO_BEGIN | Byte[1] = Chunk-Anzahl neuen Makro-Empfang starten |
| `0x21` | MACRO_DATA | Byte[1] = Chunk-Index, Byte[27] = 6 B Nutzdaten |
| `0x22` | MACRO_COMMIT | NVM schreiben → MACRO_ACK oder MACRO_NACK |
| `0x23` | MACRO_READ | Board sendet aktuelle Makro-Tabelle zurück |
| `0x01` | `SET_LED_OVERRIDE` | temporaere LED-Override setzen |
| `0x02` | `CLEAR_LED_OVERRIDE` | Override entfernen |
| `0x03` | `SET_LED_BASE` | Base-Farbe im RAM setzen |
| `0x05` | `PING` | Antwort: `PONG` |
| `0x10` | `CONFIG_BEGIN` | Config-Transfer starten |
| `0x11` | `CONFIG_DATA` | 6 Byte Config-Nutzdaten |
| `0x12` | `CONFIG_COMMIT` | Config pruefen und speichern |
| `0x13` | `CONFIG_READ` | Config-Dump an Host senden |
| `0x20` | `MACRO_BEGIN` | Makro-Transfer starten |
| `0x21` | `MACRO_DATA` | 6 Byte Makro-Nutzdaten |
| `0x22` | `MACRO_COMMIT` | Makros speichern |
| `0x23` | `MACRO_READ` | Makro-Dump an Host senden |
## Event-Referenz (Board → PC)
## Events
| ID | Name | Bedeutung |
| ID | Name | Zweck |
|---|---|---|
| `0x81` | KEY_DOWN | key_id HOST_COMMAND-Button gedrückt |
| `0x82` | KEY_UP | key_id (derzeit nicht gesendet) |
| `0x83` | ENC_CW | enc_id Encoder-Schritt CW (HOST_COMMAND) |
| `0x84` | ENC_CCW | enc_id Encoder-Schritt CCW (HOST_COMMAND) |
| `0x85` | PONG | Antwort auf PING |
| `0x90` | CONFIG_ACK | Config erfolgreich in NVM geschrieben |
| `0x91` | CONFIG_NACK | Config CRC/Magic ungültig oder NVM-Timeout nicht geschrieben |
| `0x92` | CONFIG_BEGIN | Byte[1] = Chunk-Anzahl (Config-Dump) |
| `0x93` | CONFIG_DATA | Byte[1] = Index, Byte[27] = 6 B (Config-Dump) |
| `0x94` | CONFIG_END | Config-Dump abgeschlossen |
| `0x95` | MACRO_ACK | Makro-Tabelle erfolgreich gespeichert |
| `0x96` | MACRO_BEGIN | Byte[1] = Chunk-Anzahl (Makro-Dump) |
| `0x97` | MACRO_DATA | Byte[1] = Index, Byte[27] = 6 B (Makro-Dump) |
| `0x98` | MACRO_END | Makro-Dump abgeschlossen |
| `0x99` | MACRO_NACK | Makro-Tabelle: NVM-Timeout nicht geschrieben |
| `0x81` | `KEY_DOWN` | Host-Command-Button gedrueckt |
| `0x82` | `KEY_UP` | Host-Command-Button losgelassen |
| `0x83` | `ENC_CW` | Encoder Host-Command im Uhrzeigersinn |
| `0x84` | `ENC_CCW` | Encoder Host-Command gegen Uhrzeigersinn |
| `0x85` | `PONG` | Antwort auf Ping |
| `0x90` | `CONFIG_ACK` | Config erfolgreich gespeichert |
| `0x91` | `CONFIG_NACK` | Config ungueltig oder NVM-Timeout |
| `0x92` | `CONFIG_BEGIN` | Config-Dump beginnt |
| `0x93` | `CONFIG_DATA` | 6 Byte Config-Dump |
| `0x94` | `CONFIG_END` | Config-Dump fertig |
| `0x95` | `MACRO_ACK` | Makros erfolgreich gespeichert |
| `0x96` | `MACRO_BEGIN` | Makro-Dump beginnt |
| `0x97` | `MACRO_DATA` | 6 Byte Makro-Dump |
| `0x98` | `MACRO_END` | Makro-Dump fertig |
| `0x99` | `MACRO_NACK` | Makro-Speichern fehlgeschlagen |
## Chunked Transfer
## Chunk-Zahlen
Config (740 B) und Makro-Tabelle (512 B) werden in 6-Byte-Chunks übertragen:
Aktuelle Blob-Groessen:
```
Config: ceil(740 / 6) = 124 Chunks
Makros: ceil(512 / 6) = 86 Chunks (letzter Chunk hat 2 Nutzbytes)
- Config: `740` Byte
- Makros: `512` Byte
Bei 6 Nutzbytes pro Paket ergibt das:
```text
Config: ceil(740 / 6) = 124 Chunks
Makros: ceil(512 / 6) = 86 Chunks
```
Ablauf (PC → Board):
```
BEGIN (chunk_count)
DATA chunk_0 (Bytes 05)
DATA chunk_1 (Bytes 611)
## Transferablauf
### PC -> Board
```text
BEGIN(chunk_count)
DATA 0
DATA 1
...
COMMIT
```
**CONFIG_COMMIT**: Board prüft Magic + Version + CRC. Bei Fehler → `CONFIG_NACK`. Bei NVM-Timeout während Erase/Write → `CONFIG_NACK`. Bei Erfolg → `CONFIG_ACK`.
### Board -> PC
**MACRO_COMMIT**: Kein CRC, Board schreibt direkt. Bei Erfolg → `MACRO_ACK`. Bei NVM-Timeout → `MACRO_NACK`.
```text
BEGIN(chunk_count)
DATA 0
DATA 1
...
END
```
### ACK-Synchronisation (GUI-Seite)
## Validierung
VersaGUI wartet nach COMMIT auf das ACK/NACK via `SemaphoreSlim` (Timeout 3 s). Erst nach Freigabe des Gates startet der nächste Transfer. Dies verhindert, dass Makro-Chunks gesendet werden während das Board noch den Config-NVM schreibt (~750 ms für 3 Rows).
`CONFIG_COMMIT` prueft:
- Magic
- Version
- CRC
Nur bei erfolgreicher Pruefung wird in NVM geschrieben.
`MACRO_COMMIT` schreibt ohne CRC direkt nach NVM und signalisiert nur Erfolg oder Fehler.
## Praktische Hinweise fuer die GUI
- nach `CONFIG_COMMIT` auf `CONFIG_ACK` oder `CONFIG_NACK` warten
- danach erst `MACRO_*` senden
- Dumps besser sequenziell lesen: zuerst Config, danach Makros
- `DtrEnable` muss aktiv sein, sonst verwirft das Board CDC-Ausgaben
## Implementierungsdetails
- **Ring-Buffer**: 256 Byte Eingangspuffer (= 32 vollständige Pakete) in `usb_serial.cpp`
- **DTR-Check**: `usb_serial_send()` sendet nur wenn `SerialUSB` aktiv ist (verhindert stilles Verwerfen wenn VersaGUI nicht verbunden)
- **SAMD21 CDC**: Nach SWD-Flash braucht Windows eine physische USB-Reinitialisierung (Kabel abziehen/stecken) damit der CDC-Port neu enumeriert
- RX-Ringbuffer: 256 Byte = 32 volle Pakete
- feste 8-Byte-Pakete vereinfachen Firmware und GUI
- nach einem reinen SWD-Reflash kann ein physischer USB-Reconnect noetig sein