VersaMCU/doc/07_serial_protocol.md

93 lines
4.0 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.

# Serial-Protokoll (CDC USB)
**Dateien:** `hal/usb_serial.h`, `hal/usb_serial.cpp`
## Grundprinzip
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.
```
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)
```
## Richtungen
| Richtung | ID-Bereich | Verarbeitung |
|---|---|---|
| PC → Board (Commands) | 0x010x7F | `poll_vendor()` in CMainController |
| Board → PC (Events) | 0x810xFF | `usb_serial_send()` in processEvents |
## Command-Referenz (PC → Board)
| ID | Name | Bedeutung |
|---|---|---|
| `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 |
## Event-Referenz (Board → PC)
| ID | Name | Bedeutung |
|---|---|---|
| `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 |
## Chunked Transfer
Config (740 B) und Makro-Tabelle (512 B) werden in 6-Byte-Chunks übertragen:
```
Config: ceil(740 / 6) = 124 Chunks
Makros: ceil(512 / 6) = 86 Chunks (letzter Chunk hat 2 Nutzbytes)
```
Ablauf (PC → Board):
```
BEGIN (chunk_count)
DATA chunk_0 (Bytes 05)
DATA chunk_1 (Bytes 611)
...
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`.
**MACRO_COMMIT**: Kein CRC, Board schreibt direkt. Bei Erfolg → `MACRO_ACK`. Bei NVM-Timeout → `MACRO_NACK`.
### ACK-Synchronisation (GUI-Seite)
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).
## 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