Initial commit

This commit is contained in:
2026-03-29 14:42:20 +02:00
commit 747bec985d
10 changed files with 1618 additions and 0 deletions
+98
View File
@@ -0,0 +1,98 @@
# VersaGUI
Windows-Tray-App zur Konfiguration und Steuerung des VersaPad v2.
Geschrieben in **C# / .NET 7 / WinForms**.
## Voraussetzungen
- Windows 10/11
- [.NET 7 SDK](https://dotnet.microsoft.com/download/dotnet/7.0) (zum Bauen)
- VersaMCU-Firmware auf dem Board geflasht
- Board per USB verbunden (erscheint als CDC COM-Port, kein Treiber nötig)
## Starten
```bash
dotnet run
```
Oder als Release-Build:
```bash
dotnet publish -c Release -r win-x64 --self-contained
```
Die App erscheint als Icon in der Windows-Taskleiste (System Tray). Kein Hauptfenster.
## Bedienung
1. **Board verbinden** App erkennt das Board automatisch per VID/PID (`0x239A / 0x0042`) via WMI
2. **Rechtsklick** auf das Tray-Icon → **Konfiguration...**
3. Taste/Encoder anklicken → Aktion auswählen:
- **HID Tastatur**: Großen Button klicken, dann gewünschte Taste drücken (Strg+C, F5, …)
- **HID Consumer**: Dropdown Play/Pause, Lautstärke, etc.
- **Host Command**: Numerische Command-ID (zukünftig: URL/Programm)
- **LED-Farbe**: Farbpicker für die Idle-LED des Buttons
4. **Auf Board speichern** überträgt Config in den NVM des Boards
5. Beim nächsten Verbinden wird die Config automatisch vom Board geladen
## Projekt-Struktur
```
VersaGUI/
├── VersaGUI.csproj .NET 7 WinForms Projekt
├── Program.cs Einstiegspunkt, startet TrayApp
├── TrayApp.cs ApplicationContext: Tray-Icon, Menü, Paket-Routing
├── ConfigForm.cs Konfigurations-Fenster (4×5 Grid + Encoder-Panel)
├── ActionDialog.cs Dialog: Taste erfassen / Consumer auswählen / Host-Command
├── DeviceConfig.cs C#-Spiegel von SDeviceConfig (163B Serialisierung, CRC16)
├── Protocol.cs Protokoll-Konstanten (Commands + Events)
└── SerialManager.cs COM-Port-Erkennung, Read-Loop, Config senden/empfangen
```
## Architektur
```
TrayApp
├── SerialManager Hintergrund-Thread: COM-Port-Verbindung + Leseloop
│ ├── Connected-Event → Config vom Board anfordern (CMD_CONFIG_READ)
│ └── PacketReceived → TrayApp.OnPacket()
├── DeviceConfig In-Memory-Modell der Board-Config
└── ConfigForm (optional) Öffnet sich auf Benutzeranfrage
└── ActionDialog Modaler Dialog pro Taste/Encoder
```
### SerialManager
- Erkennt das Board per **WMI** (`Win32_PnPEntity`, VID/PID-Filter) → COM-Port-Name
- Lese-Loop im Hintergrund-Thread: sammelt 8-Byte-Pakete, feuert `PacketReceived`-Event auf dem UI-Thread
- **Reconnect-Timer**: versucht alle 3 Sekunden neu zu verbinden; nach Disconnect 5 Sekunden Backoff
- Wichtig: `DtrEnable = true` muss **vor** `Open()` gesetzt werden der SAMD21 prüft die DTR-Leitung in `if (!SerialUSB)` und verwirft sonst alle ausgehenden Pakete
### DeviceConfig / Serialisierung
`DeviceConfig.ToBytes()` erzeugt den exakt 163-Byte-Puffer der `SDeviceConfig`-Struct in der Firmware entspricht (little-endian, packed). `CRC16-CCITT` (Poly 0x1021, Init 0xFFFF) über Bytes 7162 identisch zur Firmware-Implementierung.
Config-Übertragung Board→PC (Lesen):
```
PC sendet: CMD_CONFIG_READ (0x13)
Board sendet: EVT_CONFIG_BEGIN (Chunk-Anzahl)
EVT_CONFIG_DATA × 28 (je 6 Nutzbytes)
EVT_CONFIG_END
```
Config-Übertragung PC→Board (Schreiben):
```
PC sendet: CMD_CONFIG_BEGIN (Chunk-Anzahl)
CMD_CONFIG_DATA × 28
CMD_CONFIG_COMMIT
Board sendet: EVT_CONFIG_ACK oder EVT_CONFIG_NACK
```
### Bekannte .NET-Eigenheiten
| Problem | Lösung |
|---|---|
| `.NET 7 SerialPort.ReadByte()` wirft `IOException` statt `TimeoutException` auf Timeout | `catch (IOException)` → nur als Fehler behandeln wenn Port nicht mehr offen ist |
| `DtrEnable = false` (Standard) → Board sendet nichts | `DtrEnable = true` im SerialPort-Konstruktor setzen, **vor** `Open()` |
| DTR-Zustandswechsel nach `Open()` löst CDC-Disconnect auf dem Board aus | DTR vor `Open()` setzen → kein Zustandswechsel |