Files
VersaMCU/doc/07_serial_protocol.md
T

150 lines
4.6 KiB
Markdown

# Serial-Protokoll (CDC USB)
Dateien:
- `hal/usb_serial.h`
- `hal/usb_serial.cpp`
- `CMainController.cpp`
## 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..7: kommandospezifische Daten
```
LED-Kommandos verwenden Byte 2..4 für RGB. Config- und Makro-DATA-Pakete
verwenden alle sechs Bytes 2..7 als Nutzlast. Einfache Events aus
`usb_serial_send()` nutzen höchstens Byte 2..3 und füllen den Rest mit null.
Es gibt kein Framing, keinen Längenheader und keine Prüfsumme auf Paketebene.
## Richtungen
| Richtung | IDs | Verarbeitung |
|---|---|---|
| PC -> Board | `0x01..0x7F` | `poll_vendor()` |
| Board -> PC | `0x81..0xFF` | `usb_serial_send()` |
## Commands
| ID | Name | Zweck |
|---|---|---|
| `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 |
## Events
| ID | Name | Zweck |
|---|---|---|
| `0x81` | `KEY_DOWN` | wird für jede aktuelle Host-Action gesendet |
| `0x82` | `KEY_UP` | definiert, aktuell nicht gesendet |
| `0x83` | `ENC_CW` | definiert, aktuell nicht gesendet |
| `0x84` | `ENC_CCW` | definiert, aktuell nicht gesendet |
| `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 |
Bei `ActionType::HOST_COMMAND` enthält Byte 1 die Matrix-Key-ID oder die
Encoder-ID. `SAction.data` wird nicht übertragen. Auch CW- und CCW-Actions
senden aktuell `0x81`; die Drehrichtung ist im Paket nicht enthalten.
## Chunk-Zahlen
Aktuelle Blob-Groessen:
- 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
```
Wichtig fuer Implementierungen: Der Byte-Offset eines Chunks muss mindestens 16 Bit breit sein. Bei der Config liegt der Offset ab Chunk 43 ueber 255 Byte; ein 8-Bit-Offset wuerde ueberlaufen und spaetere Profilbereiche falsch dumpen.
## Transferablauf
### PC -> Board
```text
BEGIN(chunk_count)
DATA 0
DATA 1
...
COMMIT
```
### Board -> PC
```text
BEGIN(chunk_count)
DATA 0
DATA 1
...
END
```
## Validierung
`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.
Die in `BEGIN` angekündigte Chunkzahl wird zwar gespeichert, aber beim Commit
nicht ausgewertet. Die Firmware verfolgt nicht, welche Chunkindizes tatsächlich
eingetroffen sind. Doppelte, fehlende und ungeordnete Chunks werden deshalb
nicht als solche erkannt. Bei Configdaten schlägt ein unvollständiger Transfer
typischerweise an der CRC fehl; bei Makrodaten kann ein unvollständiger
Null-gefüllter Puffer gespeichert werden.
Die Configvalidierung prüft keine Feldwerte oder Enum-Bereiche. Insbesondere
müssen Hostimplementierungen gültige Profilindizes, Actiontypen, LED-Enums und
Animationsperioden liefern.
## 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
- ausschließlich vollständige 8-Byte-Pakete schreiben; schon ein verlorenes
Byte verschiebt die Paketgrenzen für alle folgenden Daten
- Encoder-Host-Actions derzeit nicht anhand von `0x83/0x84` erwarten
## Implementierungsdetails
- RX-Ringbuffer: 256 Byte = 32 volle Pakete; er ist ein laufender
Zwischenpuffer und fasst keinen kompletten Configtransfer
- feste 8-Byte-Pakete vereinfachen Firmware und GUI
- nach einem reinen SWD-Reflash kann ein physischer USB-Reconnect noetig sein