128 lines
3.5 KiB
Markdown
128 lines
3.5 KiB
Markdown
# Aktions-Engine
|
|
|
|
Dateien:
|
|
|
|
- `config/action.h`
|
|
- `CMainController.h/.cpp`
|
|
- `CButton.h/.cpp`
|
|
|
|
## `SAction`
|
|
|
|
```cpp
|
|
struct __attribute__((packed)) SAction {
|
|
ActionType type;
|
|
uint16_t data;
|
|
};
|
|
```
|
|
|
|
Groesse: 3 Byte.
|
|
Das `packed` ist zwingend, weil Config v3 bytegenau zwischen Firmware und GUI uebereinstimmen muss.
|
|
|
|
## `ActionType`
|
|
|
|
| Typ | Bedeutung | `data` |
|
|
|---|---|---|
|
|
| `NONE` | keine Aktion | - |
|
|
| `HID_KEY` | Tastaturtaste ueber USB HID | low byte = keycode, high byte = modifier |
|
|
| `HID_CONSUMER` | Media/Consumer-HID | usage id |
|
|
| `HOST_COMMAND` | Event an die GUI | 16-Bit-Command-ID |
|
|
| `MACRO` | Makro aus `SMacroTable` | slot 0..31 |
|
|
| `PROFILE_SWITCH` | Profilwechsel | 0..2, `0x00FF` oder `0xFFFF` für nächstes Profil |
|
|
|
|
## Verhalten bei `KEY_DOWN`
|
|
|
|
| Typ | Effekt |
|
|
|---|---|
|
|
| `HID_KEY` | `usb_hid_send_key()` |
|
|
| `HID_CONSUMER` | `usb_hid_send_consumer()` |
|
|
| `HOST_COMMAND` | `USB_EVT_KEY_DOWN (0x81)` mit `key_id` und Command-ID senden |
|
|
| `MACRO` | komplette Sequenz sofort abspielen |
|
|
| `PROFILE_SWITCH` | Config aus NVM laden, Profil aendern, CRC neu berechnen, speichern, Buttons neu initialisieren |
|
|
| `NONE` | nichts |
|
|
|
|
## Verhalten bei `KEY_UP`
|
|
|
|
| Typ | Effekt |
|
|
|---|---|
|
|
| `HID_KEY` | `usb_hid_release_key()` |
|
|
| `HID_CONSUMER` | `usb_hid_release_consumer()` |
|
|
| `HOST_COMMAND` | `USB_EVT_KEY_UP (0x82)` mit `key_id` und Command-ID senden |
|
|
| `MACRO` | nichts |
|
|
| `PROFILE_SWITCH` | nichts |
|
|
| `NONE` | nichts |
|
|
|
|
## Hold- und Tap-Modell
|
|
|
|
- MX-Buttons und Encoder-SW benutzen fuer HID und Consumer das Hold-Modell.
|
|
- Encoder `CW` und `CCW` sind immer diskrete Tap-Events:
|
|
|
|
```text
|
|
down -> delay(10 ms) -> up
|
|
```
|
|
|
|
- Makros laufen komplett synchron in der Firmware.
|
|
|
|
Keyboard-Keys und Modifier werden im HID-HAL referenzgezählt. Bis zu sechs
|
|
unterschiedliche Keyboard-Usages können der Report gleichzeitig abbilden;
|
|
beim Loslassen einer Action bleiben die übrigen Holds aktiv.
|
|
|
|
Der Consumer-Descriptor kann jeweils nur ein Usage darstellen. Der HAL
|
|
verwaltet mehrere Holds und zeigt das zuletzt gedrückte aktive Usage; nach
|
|
dessen Release wird das zuvor aktive Usage wiederhergestellt.
|
|
|
|
## Host-Commands
|
|
|
|
Der aktuelle Code sendet für jede `HOST_COMMAND`-Action nur:
|
|
|
|
```text
|
|
Byte 0 = USB_EVT_KEY_DOWN (0x81) oder USB_EVT_KEY_UP (0x82)
|
|
Byte 1 = Matrix-Key-ID oder Encoder-ID
|
|
Byte 2 = Command-ID Low-Byte
|
|
Byte 3 = Command-ID High-Byte
|
|
```
|
|
|
|
Encoder-Host-Actions senden genau ein Richtungsereignis:
|
|
`ENC_CW (0x83)` beziehungsweise `ENC_CCW (0x84)`, ebenfalls mit Encoder-ID und
|
|
Command-ID. Die GUI erhält damit die konfigurierte Action direkt aus dem
|
|
Event und muss den aktiven Profilstand nicht rekonstruieren.
|
|
|
|
## Makro-Ausfuehrung
|
|
|
|
Bei `ActionType::MACRO` wird `action.data` als Slot interpretiert.
|
|
Die Firmware laeuft dann durch bis zu 8 Steps:
|
|
|
|
```text
|
|
step.keycode == 0 -> Ende
|
|
Key-Down
|
|
10 ms warten
|
|
Key-Up
|
|
20 ms warten
|
|
```
|
|
|
|
## Profilwechsel
|
|
|
|
`PROFILE_SWITCH` arbeitet direkt auf der gespeicherten Config:
|
|
|
|
1. Config aus NVM laden
|
|
2. `active_profile` aendern
|
|
3. CRC neu berechnen
|
|
4. wieder speichern
|
|
5. `init_buttons()`
|
|
|
|
Wichtig:
|
|
`active_profile` liegt im CRC-geschuetzten Bereich. Ohne neue CRC wuerde die Config beim naechsten Laden verworfen.
|
|
|
|
## Sonderfall Werksreset
|
|
|
|
Die Reset-Kombination uebersteuert das normale Action-System fuer genau zwei Tasten:
|
|
|
|
- `key_id 9`
|
|
- `key_id 24`
|
|
|
|
Sobald beide gleichzeitig gehalten werden:
|
|
|
|
- ihre normalen Actions werden nicht weiter ausgefuehrt
|
|
- eventuell bereits gestartete HID-Holds werden sofort freigegeben
|
|
- die LEDs der beiden Tasten leuchten rot
|
|
- nach 5 Sekunden wird `perform_factory_reset()` ausgefuehrt
|