83 lines
2.9 KiB
Markdown
83 lines
2.9 KiB
Markdown
# Aktions-Engine
|
||
|
||
**Dateien:** `config/action.h`, `CButton.h/.cpp`, `CMainController.cpp` (`processEvents`, `execute_action_down`, `execute_action_up`)
|
||
|
||
## SAction-Struct
|
||
|
||
```cpp
|
||
struct __attribute__((packed)) SAction {
|
||
ActionType type; // 1 Byte
|
||
uint16_t data; // 2 Bytes (Keycode, Consumer-Code, Command-ID oder Slot-Index)
|
||
};
|
||
// Gesamt: 3 Bytes (packed! ohne packed wären es 4 durch Alignment)
|
||
```
|
||
|
||
`packed` ist zwingend damit `sizeof(SDeviceConfig) == 223` mit der C#-Serialisierung in VersaGUI übereinstimmt.
|
||
|
||
## ActionType
|
||
|
||
| Typ | Bedeutung | data-Inhalt |
|
||
|---|---|---|
|
||
| `NONE` | Keine Aktion | — |
|
||
| `HID_KEY` | Tastendruck via USB HID Keyboard | Low-Byte = HID Keycode, High-Byte = Modifier |
|
||
| `HID_CONSUMER` | Consumer Control (Volume, Media, …) | Consumer Usage ID |
|
||
| `HOST_COMMAND` | Event an VersaGUI senden, App führt aus | Command-ID (frei definiert) |
|
||
| `MACRO` | Makro-Sequenz aus NVM-Tabelle | Slot-Index 0–31 |
|
||
|
||
## execute_action_down() — Taste gedrückt (Hold-Start)
|
||
|
||
| ActionType | Verhalten |
|
||
|---|---|
|
||
| `HID_KEY` | `usb_hid_send_key(keycode, modifier)` — Taste bleibt gedrückt bis `execute_action_up()` |
|
||
| `HID_CONSUMER` | `usb_hid_send_consumer(usage_id)` — bleibt aktiv bis `execute_action_up()` |
|
||
| `HOST_COMMAND` | `usb_serial_send(USB_EVT_KEY_DOWN, key_id)` |
|
||
| `MACRO` | Volle Sequenz ausführen (Steps[slot], keycode==0 = Ende, delay 10+20 ms) |
|
||
| `NONE` | nop |
|
||
|
||
## execute_action_up() — Taste losgelassen (Hold-Ende)
|
||
|
||
| ActionType | Verhalten |
|
||
|---|---|
|
||
| `HID_KEY` | `usb_hid_release_key()` |
|
||
| `HID_CONSUMER` | `usb_hid_release_consumer()` |
|
||
| `HOST_COMMAND` | — (optional: könnte `USB_EVT_KEY_UP` senden) |
|
||
| `MACRO`/`NONE` | nop |
|
||
|
||
## Hold-Modell (HID-Keys und Consumer Controls)
|
||
|
||
Normale Tasten- und Media-Aktionen folgen dem **Hold-Modell**:
|
||
|
||
```
|
||
KEY_DOWN-Event vom Board → execute_action_down() → HID Key-Down senden
|
||
[Taste bleibt physisch gedrückt...]
|
||
KEY_UP-Event vom Board → execute_action_up() → HID Key-Up senden
|
||
```
|
||
|
||
Das OS erkennt die gedrückte Taste und startet sein eigenes Key-Repeat nach ~500 ms — wie auf einer normalen Tastatur.
|
||
|
||
## Tap-Modell (Encoder CW/CCW)
|
||
|
||
Encoder-Bewegungen sind diskret (kein Halten möglich) und verwenden das **Tap-Modell**:
|
||
|
||
```
|
||
ENC_CW/ENC_CCW-Event → execute_action_down() + delay(10) + execute_action_up()
|
||
```
|
||
|
||
(Atomare Sequenz für jeden Encoder-Schritt.)
|
||
|
||
## Work-Loop-Reihenfolge
|
||
|
||
```cpp
|
||
void work() {
|
||
matrix_scan(); // → Events in Queue (KEY_DOWN, KEY_UP, ENC_CW, ENC_CCW)
|
||
poll_vendor(); // Serial-Pakete verarbeiten (PC↔Board Kommandos)
|
||
processEvents(); // → execute_action_down/up() aufrufen
|
||
updateLEDs(); // Dirty-LEDs aktualisieren
|
||
}
|
||
```
|
||
|
||
**processEvents() verarbeitet:**
|
||
- `KEY_DOWN` → `execute_action_down()`
|
||
- `KEY_UP` → `execute_action_up()`
|
||
- `ENC_CW` / `ENC_CCW` → `execute_action_down()` + `delay(10)` + `execute_action_up()`
|