67 lines
2.3 KiB
Markdown
67 lines
2.3 KiB
Markdown
# Makro-System
|
||
|
||
**Dateien:** `config/macro_config.h`, `config/macro_config.cpp`, `CMainController.cpp`
|
||
|
||
## Datenstruktur
|
||
|
||
```cpp
|
||
struct __attribute__((packed)) SMacroStep {
|
||
uint8_t keycode; // HID Keyboard Usage (0x00 = leer → Step überspringen)
|
||
uint8_t modifier; // HID Modifier: Ctrl=0x01, Shift=0x02, Alt=0x04, GUI=0x08
|
||
};
|
||
|
||
#define MACRO_SLOTS 32
|
||
#define MACRO_MAX_STEPS 8
|
||
|
||
struct __attribute__((packed)) SMacroTable {
|
||
SMacroStep steps[MACRO_SLOTS][MACRO_MAX_STEPS]; // 32 × 8 × 2 = 512 Byte
|
||
};
|
||
```
|
||
|
||
Beide Structs sind `packed` (kein Padding). `sizeof(SMacroTable) == 512 == zwei NVM-Rows`.
|
||
|
||
## NVM-Speicherort
|
||
|
||
| Row | Adresse | Inhalt |
|
||
|---|---|---|
|
||
| Macro Row 0 | `0x1FB00` | SMacroTable Bytes 0–255 |
|
||
| Macro Row 1 | `0x1FC00` | SMacroTable Bytes 256–511 |
|
||
|
||
Beide Rows sind im Linkerscript reserviert. Gelöschter Flash (`0xFF`-Bytes) → `macro_config_load()` gibt `false` zurück → leere Tabelle (alle Keycodes 0).
|
||
|
||
## Slot-Zuweisung (Konvention, Board speichert blind)
|
||
|
||
| Slots | Verwendung |
|
||
|---|---|
|
||
| 0–19 | MX-Button `mx_idx` (entspricht key_id − 5) |
|
||
| 20–31 | Encoder-Aktionen (`enc * 3 + act_idx`, 0=SW / 1=CW / 2=CCW) |
|
||
|
||
## Laden und Speichern
|
||
|
||
**Laden** (`macro_config_load`):
|
||
- `memcpy` direkt aus Flash-Adresse in RAM-Struct
|
||
- Kein Magic/CRC — leere Tabelle (alle 0xFF) ist ein akzeptabler Zustand
|
||
|
||
**Speichern** (`macro_config_save`) — gibt `bool` zurück:
|
||
- SMacroTable in `uint8_t aligned_buf[512] __attribute__((aligned(4)))` kopieren (Pflicht!)
|
||
- `NVMCTRL->CTRLB.bit.MANW = 1` (manueller Schreib-Modus)
|
||
- Beide Rows löschen (`nvm_erase_row`) — bei NVM-Timeout: `return false`
|
||
- 8 Pages à 64 Byte schreiben (`nvm_write_page`) — bei NVM-Timeout: `return false`
|
||
- `return true`
|
||
|
||
> **Warum aligned_buf?** `nvm_write_page` castet den Pointer zu `volatile uint32_t*`. Wenn `&tbl` nicht 4-Byte-aligned ist (möglich bei packed struct), entsteht ein HardFault auf Cortex-M0+ (kein unaligned 32-Bit-Zugriff auf Peripherie-Adressen).
|
||
|
||
## Ausführung (in execute_action_down, ActionType::MACRO)
|
||
|
||
```
|
||
slot = action.data (0–31)
|
||
für Step 0–7:
|
||
if step.keycode == 0: abbrechen
|
||
HID Key-Down (keycode, modifier)
|
||
delay(10 ms)
|
||
HID Key-Up
|
||
delay(20 ms)
|
||
```
|
||
|
||
Die Makro-Tabelle liegt nach `setup()` im RAM (`m_macros` in CMainController). Kein NVM-Zugriff während der Ausführung.
|