Fully working Delphi GUI
This commit is contained in:
@@ -1,14 +1,18 @@
|
||||
# VersaGUI
|
||||
|
||||
Windows-Tray-App zur Konfiguration und Steuerung des VersaPad v2.
|
||||
Geschrieben in **C# / .NET 7 / WinForms**.
|
||||
Windows-Tray-App zur Konfiguration des VersaPad v2.
|
||||
Geschrieben in C# mit WinForms.
|
||||
|
||||
Hinweis:
|
||||
Diese GUI ist weiterhin die Referenzimplementierung fuer Protokoll und Datenlayout.
|
||||
Parallel existiert mit `VersaGUIDelphi` ein Delphi/VCL-Port unter dem Namen `VersaGUI Delphi`.
|
||||
|
||||
## 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)
|
||||
- .NET SDK
|
||||
- geflashte `VersaMCU`-Firmware
|
||||
- Board per USB als CDC-Device verbunden
|
||||
|
||||
## Starten
|
||||
|
||||
@@ -16,194 +20,86 @@ Geschrieben in **C# / .NET 7 / WinForms**.
|
||||
dotnet run
|
||||
```
|
||||
|
||||
Oder als Release-Build:
|
||||
## Was die App macht
|
||||
|
||||
```bash
|
||||
dotnet publish -c Release -r win-x64 --self-contained
|
||||
- erkennt das Board automatisch per VID/PID
|
||||
- oeffnet den CDC-COM-Port mit aktivem DTR
|
||||
- liest beim Verbinden zuerst die Config und danach die Makros
|
||||
- zeigt MX-Buttons und Encoder-Aktionen an
|
||||
- schreibt Config und Makros getrennt, aber in einem UI-Vorgang auf das Board
|
||||
|
||||
## Aktueller Datenstand
|
||||
|
||||
### DeviceConfig
|
||||
|
||||
- Magic `0x56503203`
|
||||
- Version `3`
|
||||
- `740` Byte
|
||||
- 3 Profile
|
||||
- globale Helligkeit
|
||||
- per-LED-Helligkeit
|
||||
|
||||
### MacroTable
|
||||
|
||||
- 32 Slots
|
||||
- 8 Steps pro Slot
|
||||
- `512` Byte
|
||||
|
||||
## Uebertragungsformat
|
||||
|
||||
Es wird dasselbe 8-Byte-Protokoll wie in der Firmware verwendet.
|
||||
|
||||
Aktuelle Chunk-Zahlen:
|
||||
|
||||
- Config: `124`
|
||||
- Makros: `86`
|
||||
|
||||
Speicherablauf:
|
||||
|
||||
```text
|
||||
CONFIG_BEGIN
|
||||
CONFIG_DATA x124
|
||||
CONFIG_COMMIT
|
||||
wait for ACK/NACK
|
||||
|
||||
MACRO_BEGIN
|
||||
MACRO_DATA x86
|
||||
MACRO_COMMIT
|
||||
wait for ACK/NACK
|
||||
```
|
||||
|
||||
Die App erscheint als Icon in der Windows-Taskleiste (System Tray). Kein Hauptfenster.
|
||||
## GUI-Funktionen
|
||||
|
||||
## Bedienung
|
||||
- HID-Key-Zuweisung inklusive Modifier
|
||||
- Consumer-Keys
|
||||
- Host-Commands
|
||||
- Makros mit bis zu 8 Steps
|
||||
- Profilwechsel als ActionType
|
||||
- LED-Farbe, Animation und Periode pro MX-Button
|
||||
- JSON Import/Export
|
||||
|
||||
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
|
||||
## Projektstruktur
|
||||
|
||||
---
|
||||
|
||||
## Funktionsumfang (Anforderungskatalog)
|
||||
|
||||
### 1 Verbindung & Geräteerkennung
|
||||
|
||||
| # | Anforderung | Status |
|
||||
|---|-------------|--------|
|
||||
| 1.1 | App läuft als **Windows Tray-Anwendung** ohne sichtbares Hauptfenster | ✅ |
|
||||
| 1.2 | Automatische Board-Erkennung per **WMI / VID+PID** (`0x239A / 0x0042`) | ✅ |
|
||||
| 1.3 | **Automatischer Reconnect** alle 3 s; 5 s Backoff nach Verbindungsverlust | ✅ |
|
||||
| 1.4 | Verbindungsstatus im Tray-Icon (Symbol + Tooltip) sichtbar | ✅ |
|
||||
| 1.5 | Beim Verbinden wird die gespeicherte Config **automatisch vom Board gelesen** | ✅ |
|
||||
| 1.6 | Beim Verbinden wird die **Makro-Tabelle automatisch vom Board gelesen** | ✅ |
|
||||
|
||||
### 2 Tastenbelegung – HID Tastatur
|
||||
|
||||
| # | Anforderung | Status |
|
||||
|---|-------------|--------|
|
||||
| 2.1 | Taste durch **Drücken erfassen** (kein manuelles HID-ID-Eingeben) | ✅ |
|
||||
| 2.2 | Modifier-Kombination: **Strg / Shift / Alt / Win** einzeln oder kombiniert | ✅ |
|
||||
| 2.3 | **Pfeiltasten, Enter, Escape, F1–F12, Numpad** erfassbar | ✅ |
|
||||
| 2.4 | **Layout-unabhängige Erfassung** via PS/2-Scan-Code → HID-Usage; Ö/Ä/Ü auf QWERTZ korrekt | ✅ |
|
||||
| 2.5 | Taste-Name wird laut **aktivem Windows-Layout** angezeigt (`GetKeyNameText`) | ✅ |
|
||||
| 2.6 | Board führt Tastendruck als **USB-HID-Tastatureingabe** aus (funktioniert ohne laufende App) | ✅ |
|
||||
| 2.7 | **Hold-Semantik**: Taste bleibt gedrückt solange physisch gehalten (OS initiiert Repeat nach ~500ms) | ✅ |
|
||||
|
||||
### 3 Tastenbelegung – HID Consumer / Medientasten
|
||||
|
||||
| # | Anforderung | Status |
|
||||
|---|-------------|--------|
|
||||
| 3.1 | Auswahl per **Dropdown** mit Klartext-Namen | ✅ |
|
||||
| 3.2 | Unterstützte Aktionen: Play/Pause, Nächster/Vorheriger Titel, Stop, Lauter/Leiser, Mute, Taschenrechner, Browser Zurück/Vor | ✅ |
|
||||
| 3.3 | **Hold-Semantik**: Media-Control bleibt aktiv solange Taste gehalten wird (z.B. Lautstärke-Wiederholung) | ✅ |
|
||||
|
||||
### 4 Tastenbelegung – Makros
|
||||
|
||||
| # | Anforderung | Status |
|
||||
|---|-------------|--------|
|
||||
| 4.1 | Bis zu **4 Schritte** pro Makro (je 1 Taste + Modifier) | ✅ |
|
||||
| 4.2 | Jeder Schritt per **Taste drücken** erfassen, inkl. Sondertasten | ✅ |
|
||||
| 4.3 | Leere Schritte werden übersprungen (kürzere Makros möglich) | ✅ |
|
||||
| 4.4 | **32 Makro-Slots** – je ein Slot pro MX-Button (0–19) und Encoder-Aktion (20–31) | ✅ |
|
||||
| 4.5 | Makro-Tabelle wird **separat** vom Board gelesen und geschrieben (NVM Row 1) | ✅ |
|
||||
| 4.6 | Board führt Makro-Schritte mit 10 ms Key-Down + 20 ms Pause **ohne laufende App** aus | ✅ |
|
||||
|
||||
### 5 Encoder-Belegung
|
||||
|
||||
| # | Anforderung | Status |
|
||||
|---|-------------|--------|
|
||||
| 5.1 | **4 Encoder**, je 3 Aktionen: SW (Drücken), CW (Rechts), CCW (Links) | ✅ |
|
||||
| 5.2 | Gleiche Aktionstypen wie Tasten (HID Key, Consumer, Makro, Host Command) | ✅ |
|
||||
| 5.3 | **Encoder-SW**: Hold-Semantik wie normale Tasten (Taste bleibt gedrückt) | ✅ |
|
||||
| 5.4 | **Encoder-CW/CCW**: Tap-Modell (diskrete Ereignisse, atomare down+delay+up Sequenzen, kein Hold möglich) | ✅ |
|
||||
|
||||
### 6 LED-Konfiguration
|
||||
|
||||
| # | Anforderung | Status |
|
||||
|---|-------------|--------|
|
||||
| 6.1 | **Basis-LED-Farbe** pro MX-Button via Farbpicker (RGB) | ✅ |
|
||||
| 6.2 | **Animationsmodus** pro Button wählbar: Statisch, Blinken, Pulsieren, Regenbogen | ✅ |
|
||||
| 6.3 | **Animations-Tempo**: Schnell (0,5 s) / Mittel (1 s) / Langsam (2 s) / Sehr langsam (4 s) | ✅ |
|
||||
| 6.4 | Regenbogen-Modus: Board berechnet Hue-Sweep lokal, gleichmäßige Phasenverteilung | ✅ |
|
||||
| 6.5 | LED-Config und Aktionstyp im **gleichen Dialog** bearbeitbar | ✅ |
|
||||
|
||||
### 7 Konfiguration speichern & laden
|
||||
|
||||
| # | Anforderung | Status |
|
||||
|---|-------------|--------|
|
||||
| 7.1 | Config und Makros werden gleichzeitig per **„Auf Board speichern"** übertragen | ✅ |
|
||||
| 7.2 | Board validiert Config mit **CRC16-CCITT + Magic + Version**; NACK bei Fehler | ✅ |
|
||||
| 7.3 | Config bleibt nach Stromverlust im **NVM** erhalten (kein Flash-Verschleiß bei nur Lesen) | ✅ |
|
||||
| 7.4 | **JSON-Export** der gesamten Config (Aktionen + LED) in Datei | ✅ |
|
||||
| 7.5 | **JSON-Import** mit Versionscheck; ungültige Dateien werden abgelehnt | ✅ |
|
||||
|
||||
### 8 Verbindungsprotokoll
|
||||
|
||||
| # | Anforderung | Status |
|
||||
|---|-------------|--------|
|
||||
| 8.1 | **8-Byte-Festlängen-Pakete** über CDC Serial (kein Treiber nötig) | ✅ |
|
||||
| 8.2 | **Ping/Pong** zur manuellen Verbindungsdiagnose im Konfigurations-Fenster | ✅ |
|
||||
| 8.3 | Config-Transfer: BEGIN → n×DATA(6 Byte) → COMMIT → ACK/NACK | ✅ |
|
||||
| 8.4 | Makro-Transfer: gleiche Struktur, 43 Chunks à 6 Byte (256 Byte Tabelle) | ✅ |
|
||||
| 8.5 | Debug-Logging aller RX-Pakete in `%TEMP%\versapad_rx.txt` | ✅ |
|
||||
|
||||
### 9 Nicht implementiert / Roadmap
|
||||
|
||||
| # | Anforderung | Status |
|
||||
|---|-------------|--------|
|
||||
| 9.1 | **Host Command**: URL/Programm öffnen wenn Board-Taste gedrückt | 🔲 TODO |
|
||||
| 9.2 | Eigenes **Tray-Icon** (aktuell: Windows-Standard-Icon) | 🔲 TODO |
|
||||
| 9.3 | **Fader/Potentiometer**-Unterstützung (3× ADC-Achsen auf Board vorhanden) | 🔲 TODO |
|
||||
| 9.4 | **Profile**: mehrere Tastenbelegungen speichern und wechseln | 🔲 TODO |
|
||||
|
||||
---
|
||||
|
||||
## Projekt-Struktur
|
||||
|
||||
```
|
||||
```text
|
||||
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 / Makro / LED-Animation
|
||||
├── DeviceConfig.cs – C#-Spiegel von SDeviceConfig (223 B, Version 2) + MacroTable (256 B)
|
||||
├── ConfigJson.cs – JSON-Export/Import der DeviceConfig
|
||||
├── Protocol.cs – Protokoll-Konstanten (Commands + Events)
|
||||
└── SerialManager.cs – COM-Port-Erkennung, Read-Loop, Config + Makros senden/empfangen
|
||||
`-- src/
|
||||
|-- Program.cs
|
||||
|-- TrayApp.cs
|
||||
|-- SerialManager.cs
|
||||
|-- DeviceConfig.cs
|
||||
|-- ConfigForm.cs
|
||||
|-- ActionDialog.cs
|
||||
|-- ConfigJson.cs
|
||||
`-- Protocol.cs
|
||||
```
|
||||
|
||||
## Architektur
|
||||
## Grenzen / Status
|
||||
|
||||
```
|
||||
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
|
||||
```
|
||||
- Host-Commands sind protokollseitig vorhanden, aber appseitig noch nicht voll ausgebaut
|
||||
- die App ist Windows-only
|
||||
- fuer eine alternative GUI ist `VersaGUIDelphi` der aktuelle Delphi/VCL-Port
|
||||
|
||||
### SerialManager
|
||||
## Weiterfuehrende Doku
|
||||
|
||||
- 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 **223-Byte**-Puffer der `SDeviceConfig`-Struct (Version 2, little-endian, packed). `CRC16-CCITT` (Poly 0x1021, Init 0xFFFF) über Bytes 7–222 – identisch zur Firmware-Implementierung.
|
||||
|
||||
`MacroTable.ToBytes()` erzeugt **256 Byte** (32 Slots × 4 Steps × 2 Byte).
|
||||
|
||||
Config-Übertragung Board→PC (Lesen):
|
||||
```
|
||||
PC sendet: CMD_CONFIG_READ (0x13)
|
||||
Board sendet: EVT_CONFIG_BEGIN (Chunk-Anzahl = 38)
|
||||
EVT_CONFIG_DATA × 38 (je 6 Nutzbytes)
|
||||
EVT_CONFIG_END
|
||||
```
|
||||
|
||||
Config-Übertragung PC→Board (Schreiben):
|
||||
```
|
||||
PC sendet: CMD_CONFIG_BEGIN (0x10, Chunk-Anzahl)
|
||||
CMD_CONFIG_DATA × 38
|
||||
CMD_CONFIG_COMMIT (0x12)
|
||||
Board sendet: EVT_CONFIG_ACK (0x90) oder EVT_CONFIG_NACK (0x91)
|
||||
```
|
||||
|
||||
Makro-Übertragung (analog, separate Kommandos 0x20–0x23):
|
||||
```
|
||||
PC sendet: CMD_MACRO_BEGIN (0x20, Chunk-Anzahl = 43)
|
||||
CMD_MACRO_DATA × 43
|
||||
CMD_MACRO_COMMIT (0x22)
|
||||
Board sendet: EVT_MACRO_ACK (0x95)
|
||||
```
|
||||
|
||||
### Kommunikationsprotokoll
|
||||
|
||||
Das vollständige Protokoll (alle Command- und Event-IDs, NVM-Layout, Paketformat) ist in [VersaMCU/README.md](../VersaMCU/README.md#serial-protokoll-8-bytes-fixed) dokumentiert.
|
||||
|
||||
### 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 |
|
||||
- [doc/02_device_config.md](doc/02_device_config.md)
|
||||
- [../VersaMCU/doc/07_serial_protocol.md](../VersaMCU/doc/07_serial_protocol.md)
|
||||
|
||||
+89
-89
@@ -1,120 +1,120 @@
|
||||
# DeviceConfig & MacroTable
|
||||
# DeviceConfig und MacroTable
|
||||
|
||||
**Datei:** `DeviceConfig.cs`
|
||||
Datei:
|
||||
|
||||
## Überblick
|
||||
- `src/DeviceConfig.cs`
|
||||
|
||||
C#-Spiegel der Firmware-Structs. Muss byte-kompatibel mit `SDeviceConfig` (nvm_config.h) und `SMacroTable` (macro_config.h) sein.
|
||||
## Zweck
|
||||
|
||||
---
|
||||
Die C#-Klassen spiegeln das aktuelle Firmware-Layout bytegenau.
|
||||
Sie muessen deshalb synchron zu `VersaMCU/src/config/nvm_config.h` und `macro_config.h` bleiben.
|
||||
|
||||
## DeviceConfig
|
||||
|
||||
### Felder
|
||||
### Globaler Stand
|
||||
|
||||
| Feld | Typ | Inhalt |
|
||||
|---|---|---|
|
||||
| `ActiveProfileIndex` | `byte` | Aktives Profil (0–2) |
|
||||
| `GlobalBrightness` | `byte` | Globale LED-Helligkeit (0–255) |
|
||||
| `MxActions[20]` | `DeviceAction[]` | Aktionen für MX-Buttons 0–19 (aus aktivem Profil) |
|
||||
| `EncActions[4,3]` | `DeviceAction[,]` | Encoder [0–3][SW=0/CW=1/CCW=2] (aus aktivem Profil) |
|
||||
| `LedBase[20]` | `Color[]` | RGB-Basis-LED-Farbe je Button (aus aktivem Profil) |
|
||||
| `LedAnim[20]` | `LedAnimType[]` | Animation je Button (aus aktivem Profil) |
|
||||
| `LedPeriod[20]` | `ushort[]` | Animationsperiode in ms (aus aktivem Profil) |
|
||||
- Magic `0x56503203`
|
||||
- Version `3`
|
||||
- Groesse `740` Byte
|
||||
- 3 Profile
|
||||
|
||||
### Serialisierungs-Layout (ToBytes / FromBytes, 740 B)
|
||||
### Wichtige Felder
|
||||
|
||||
```
|
||||
Offset 0 4B Magic 0x56503203 (little-endian)
|
||||
Offset 4 1B Version = 3
|
||||
Offset 5 2B CRC16-CCITT über Bytes 7–739 (little-endian)
|
||||
Offset 7 1B active_profile (0–2)
|
||||
Offset 8 1B global_brightness
|
||||
Offset 9 4B enc_sensitivity[4]
|
||||
Offset 13 19B Reserve (_reserve)
|
||||
| Feld | Bedeutung |
|
||||
|---|---|
|
||||
| `ActiveProfileIndex` | aktives Profil 0..2 |
|
||||
| `GlobalBrightness` | globale LED-Helligkeit |
|
||||
| `Profiles[3]` | komplette Profil-Daten |
|
||||
|
||||
Profil 0 (Offset 32, 236 B):
|
||||
Offset 32 60B MxActions[20] je 3B: type(1) + data_lo(1) + data_hi(1)
|
||||
Offset 92 36B EncActions[4][3] je 3B
|
||||
Offset 128 20B LedBase[i].R
|
||||
Offset 148 20B LedBase[i].G
|
||||
Offset 168 20B LedBase[i].B
|
||||
Offset 188 20B LedBrightness[i]
|
||||
Offset 208 20B LedAnim[i] als byte
|
||||
Offset 228 40B LedPeriod[i] als uint16 little-endian
|
||||
Fuer die GUI gibt es zusaetzlich Komfortzugriffe auf das aktive Profil:
|
||||
|
||||
Profil 1 (Offset 268, 236 B): identisches Layout
|
||||
Profil 2 (Offset 504, 236 B): identisches Layout
|
||||
- `MxActions[20]`
|
||||
- `EncActions[4,3]`
|
||||
- `LedBase[20]`
|
||||
- `LedAnim[20]`
|
||||
- `LedPeriod[20]`
|
||||
|
||||
### Layout
|
||||
|
||||
```text
|
||||
Offset 0 4B magic
|
||||
Offset 4 1B version
|
||||
Offset 5 2B crc
|
||||
Offset 7 1B active_profile
|
||||
Offset 8 1B global_brightness
|
||||
Offset 9 4B enc_sensitivity[4]
|
||||
Offset 13 19B reserve
|
||||
Offset 32 profile 0
|
||||
Offset 268 profile 1
|
||||
Offset 504 profile 2
|
||||
```
|
||||
|
||||
### CRC16-CCITT
|
||||
Jedes Profil belegt 236 Byte:
|
||||
|
||||
Polynom `0x1021`, Init `0xFFFF`, über Bytes 7–739 (nach dem CRC-Feld selbst, einschließlich `active_profile`). Muss identisch mit Firmware-Implementierung sein. `DeviceConfig.Crc16()` ist statisch und direkt testbar.
|
||||
|
||||
### Defaults (entspricht Firmware-Defaults)
|
||||
|
||||
- Alle Aktionen: `None`
|
||||
- LEDs: warm-weiß (R=80, G=40, B=0), Helligkeit 255
|
||||
- Animation: `ColorCycle` (Regenbogen), Period 4000 ms
|
||||
- `active_profile = 0`, `global_brightness = 255`
|
||||
|
||||
---
|
||||
|
||||
## DeviceAction
|
||||
|
||||
```csharp
|
||||
public enum ActionType : byte {
|
||||
None=0, HidKey=1, HidConsumer=2, HostCommand=3, Macro=4, ProfileSwitch=5
|
||||
}
|
||||
|
||||
public class DeviceAction {
|
||||
public ActionType Type { get; set; }
|
||||
public ushort Data { get; set; }
|
||||
// HidKey: Low-Byte = HID Keycode, High-Byte = Modifier
|
||||
// HidConsumer: Consumer Usage ID
|
||||
// HostCommand: Command-ID
|
||||
// Macro: Slot-Index 0–31
|
||||
// ProfileSwitch: 0–2 = Ziel-Profil, 0xFFFF = nächstes Profil (Zyklus)
|
||||
}
|
||||
```text
|
||||
20 x mx_actions
|
||||
12 x enc_actions
|
||||
20 x led_r
|
||||
20 x led_g
|
||||
20 x led_b
|
||||
20 x led_brightness
|
||||
20 x led_anim
|
||||
20 x led_period_ms
|
||||
```
|
||||
|
||||
`DeviceAction.Display` gibt einen lesbaren String zurück (z.B. `"Strg+C"`, `"Play/Pause"`, `"→ Profil 2"`, `"→ Nächstes Profil"`).
|
||||
## CRC
|
||||
|
||||
---
|
||||
CRC16-CCITT:
|
||||
|
||||
- Polynom `0x1021`
|
||||
- Init `0xFFFF`
|
||||
- Bereich `7..739`
|
||||
|
||||
Die CRC muss exakt zur Firmware passen.
|
||||
|
||||
## Defaults
|
||||
|
||||
Firmware-Defaults:
|
||||
|
||||
- alle Actions `None`
|
||||
- `GlobalBrightness = 255`
|
||||
- `enc_sensitivity = 1`
|
||||
- Base-Farbe `R=80, G=40, B=0`
|
||||
- Animation `ColorCycle`
|
||||
- Periode `4000 ms`
|
||||
|
||||
Sichtbarer Effekt auf dem Board:
|
||||
|
||||
- alle MX-LEDs laufen im Regenbogenmodus
|
||||
|
||||
## MacroTable
|
||||
|
||||
```csharp
|
||||
public class MacroTable {
|
||||
public const int Slots = 32;
|
||||
public const int MaxSteps = 8;
|
||||
public MacroStep[,] Steps { get; } // [slot][step]
|
||||
}
|
||||
public class MacroStep {
|
||||
public byte Keycode { get; set; } // 0 = leer
|
||||
public byte Modifier { get; set; }
|
||||
}
|
||||
```
|
||||
### Stand
|
||||
|
||||
- 32 Slots
|
||||
- 8 Steps pro Slot
|
||||
- 512 Byte gesamt
|
||||
|
||||
### Slot-Konvention
|
||||
|
||||
| Slots | Verwendung |
|
||||
| Slots | Bedeutung |
|
||||
|---|---|
|
||||
| 0–19 | MX-Button `mxIdx` (`MacroTable.SlotForMx(mxIdx)`) |
|
||||
| 20–31 | Encoder: `20 + enc * 3 + actIdx` (`MacroTable.SlotForEncoder(enc, actIdx)`) |
|
||||
| `0..19` | MX-Buttons |
|
||||
| `20..31` | Encoder-Aktionen |
|
||||
|
||||
### Serialisierung (512 B)
|
||||
### Serialisierung
|
||||
|
||||
32 Slots × 8 Steps × 2 B = 512 B. Keycode zuerst, dann Modifier. Kein Magic/CRC (Board akzeptiert jeden Inhalt).
|
||||
Ein Step besteht aus:
|
||||
|
||||
---
|
||||
- `keycode`
|
||||
- `modifier`
|
||||
|
||||
## LedAnimType
|
||||
Es gibt kein Magic und keine CRC fuer die Makrotabelle.
|
||||
|
||||
```csharp
|
||||
public enum LedAnimType : byte {
|
||||
Static=0, Blink=1, Pulse=2, ColorCycle=5
|
||||
}
|
||||
```
|
||||
## Wichtig fuer Aenderungen
|
||||
|
||||
Werte entsprechen `LEDAnim` in der Firmware. `FADE_IN` (3) und `FADE_OUT` (4) existieren in der Firmware aber nicht in der GUI (nicht konfigurierbar).
|
||||
Wenn sich Firmware-Layout, Magic, Version, Profilzahl oder Makrogroesse aendern, muessen mindestens diese Stellen zusammen angepasst werden:
|
||||
|
||||
- `VersaMCU`
|
||||
- `VersaGUI`
|
||||
- `VersaGUIDelphi`
|
||||
|
||||
+15
-19
@@ -1,25 +1,21 @@
|
||||
# VersaGUI – Dokumentations-Index
|
||||
# VersaGUI - Dokumentationsindex
|
||||
|
||||
Jede Datei deckt eine GUI-Komponente ab. Für Claude: die relevante(n) Dateien zu Beginn einer Aufgabe lesen statt die gesamten Quelldateien zu scannen.
|
||||
Die Dateien hier beschreiben die aktuelle C#-Referenz-GUI fuer Config v3 und 32x8 Makros.
|
||||
|
||||
| Datei | Inhalt |
|
||||
|---|---|
|
||||
| [00_architecture.md](00_architecture.md) | Threading-Modell, Datenfluss, Verbindungslebenszyklus, globale Constraints (DTR, IOException, Packed-Layout) |
|
||||
| [01_serial_manager.md](01_serial_manager.md) | WMI-Erkennung, TryConnect, ReadLoop, Sende-Methoden, Reconnect-Backoff |
|
||||
| [02_device_config.md](02_device_config.md) | DeviceConfig + MacroTable: Felder, Byte-Layout (223/256 B), CRC16, LedAnimType |
|
||||
| [03_tray_app.md](03_tray_app.md) | ApplicationContext, Tray-Icon, Board-Event-Routing, Config/Makro-Dump-Empfang, TODOs |
|
||||
| [04_config_form.md](04_config_form.md) | Grid-Layout, mx_idx-Formel, RefreshMxButton, OnSave (Task.Run), Import/Export |
|
||||
| [05_action_dialog.md](05_action_dialog.md) | Panels je Typ, ProcessCmdKey-Capture, layout-unabhängiger Scan-Code-Lookup, Consumer-Liste |
|
||||
| [06_config_json.md](06_config_json.md) | JSON-Format, Serialize/Deserialize, Einschränkungen |
|
||||
| [00_architecture.md](00_architecture.md) | Threading-Modell, Datenfluss, Verbindungslebenszyklus |
|
||||
| [01_serial_manager.md](01_serial_manager.md) | Port-Erkennung, Connect, ReadLoop, Sende-Pfad |
|
||||
| [02_device_config.md](02_device_config.md) | `DeviceConfig`, `MacroTable`, aktuelles Byte-Layout, CRC |
|
||||
| [03_tray_app.md](03_tray_app.md) | TrayApp, Packet-Routing, Dump-Empfang, UI-Zustand |
|
||||
| [04_config_form.md](04_config_form.md) | Grid, Speichern, Import/Export |
|
||||
| [05_action_dialog.md](05_action_dialog.md) | Key-Capture, Action-Auswahl, LED-Einstellungen |
|
||||
| [06_config_json.md](06_config_json.md) | JSON-Format und Grenzen |
|
||||
|
||||
## Schnell-Referenz: Was steht wo?
|
||||
## Schnellreferenz
|
||||
|
||||
- **DtrEnable-Problem** → [00_architecture.md](00_architecture.md), [01_serial_manager.md](01_serial_manager.md)
|
||||
- **IOException ≠ Disconnect (.NET 7)** → [00_architecture.md](00_architecture.md), [01_serial_manager.md](01_serial_manager.md)
|
||||
- **Byte-Layout der 223-Byte-Config** → [02_device_config.md](02_device_config.md)
|
||||
- **Warum ProcessCmdKey statt OnKeyDown?** → [05_action_dialog.md](05_action_dialog.md)
|
||||
- **Warum Scan-Codes statt VK-Codes (Umlaut-Problem)?** → [05_action_dialog.md](05_action_dialog.md)
|
||||
- **mx_idx ↔ key_id-Umrechnung** → [04_config_form.md](04_config_form.md)
|
||||
- **Makro-Slot-Konvention** → [02_device_config.md](02_device_config.md)
|
||||
- **HOST_COMMAND noch nicht implementiert** → [03_tray_app.md](03_tray_app.md)
|
||||
- **Task.Run beim Speichern** → [04_config_form.md](04_config_form.md)
|
||||
- aktuelles Config-Layout `740` Byte -> [02_device_config.md](02_device_config.md)
|
||||
- aktuelle Makrotabelle `512` Byte -> [02_device_config.md](02_device_config.md)
|
||||
- DTR und Connect-Pfad -> [00_architecture.md](00_architecture.md), [01_serial_manager.md](01_serial_manager.md)
|
||||
- Makro-Slot-Konvention -> [02_device_config.md](02_device_config.md)
|
||||
- Host-Command-Status -> [03_tray_app.md](03_tray_app.md)
|
||||
|
||||
Reference in New Issue
Block a user