Fully working Delphi GUI

This commit is contained in:
2026-04-19 11:59:32 +02:00
parent 24fe162833
commit aa6b7a8ec9
3 changed files with 184 additions and 292 deletions
+89 -89
View File
@@ -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 (02) |
| `GlobalBrightness` | `byte` | Globale LED-Helligkeit (0255) |
| `MxActions[20]` | `DeviceAction[]` | Aktionen für MX-Buttons 019 (aus aktivem Profil) |
| `EncActions[4,3]` | `DeviceAction[,]` | Encoder [03][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 7739 (little-endian)
Offset 7 1B active_profile (02)
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 7739 (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 031
// ProfileSwitch: 02 = 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 |
|---|---|
| 019 | MX-Button `mxIdx` (`MacroTable.SlotForMx(mxIdx)`) |
| 2031 | 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
View File
@@ -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)