# 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 }; struct __attribute__((packed)) SMacroTable { SMacroStep steps[32][4]; // 32 Slots × 4 Steps × 2 Byte = 256 Byte }; ``` Beide Structs sind `packed` (kein Padding). `sizeof(SMacroTable) == 256 == eine NVM-Row`. ## NVM-Speicherort - **Row 1**: Adresse `0x1FF00`, 256 Byte - Vom Linkerscript reserviert (nicht überschreibbar durch Code) - 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 bei 0xFF ist akzeptabler Zustand) **Speichern** (`macro_config_save`): - SMacroTable in `uint8_t aligned_buf[256] __attribute__((aligned(4)))` kopieren (Pflicht!) - `NVMCTRL->CTRLB.bit.MANW = 1` (manueller Schreib-Modus) - Row 1 löschen (`nvm_erase_row`) - 4 Pages à 64 Byte schreiben (`nvm_write_page`) > **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, ActionType::MACRO) ``` slot = action.data (0–31) für Step 0–3: 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. --- ## Geplante Erweiterung: 8 Steps (NVM v3) ### Motivation 4 Steps reichen für einfache Shortcuts, aber nicht für Excel-Ribbon-Navigation oder andere Sequenzen mit 5+ Tasten. Mit dem NVM-v3-Umbau (siehe [06_nvm_config.md](06_nvm_config.md)) stehen zwei vollständige Rows für die Makro-Tabelle zur Verfügung. ### Neues Layout ```cpp #define MACRO_SLOTS 32 #define MACRO_MAX_STEPS 8 // war: 4 struct __attribute__((packed)) SMacroTable { SMacroStep steps[32][8]; // 32 × 8 × 2 = 512 Bytes = 2 NVM-Rows }; ``` ### Neuer NVM-Speicherort | Row | Adresse | Inhalt | |---|---|---| | Macro Row 0 | `0x1FB00` | SMacroTable Bytes 0–255 | | Macro Row 1 | `0x1FC00` | SMacroTable Bytes 256–511 | `macro_config_save` muss entsprechend beide Rows löschen und 8 Pages schreiben (statt bisher 4).