# VersaMCU - Architekturuebersicht ## Zielplattform | Merkmal | Wert | |---|---| | MCU | ATSAMD21G17D, Cortex-M0+, 48 MHz | | Flash | 128 KB | | RAM | 16 KB | | FPU | keine, deshalb Integer-Arithmetik | | USB | HID Keyboard + Consumer + CDC Serial | | Toolchain | PlatformIO + Arduino Core | ## Setup und Loop ```text setup() macro_config_load() nvm_config_load() init_buttons() usb_hid_init() usb_serial_init() matrix_init(cb) encoder_init(cb) loop() matrix_scan() poll_vendor() processEvents() check_factory_reset() updateLEDs() ``` Die Reihenfolge ist absichtlich simpel: - Eingaben einsammeln - CDC-Kommandos vom Host verarbeiten - Event-Queue leeren - Sonderlogik fuer den Werksreset pruefen - LED-Frame nur bei Bedarf rendern ## Datenfluss ```text matrix_scan / encoder ISR -> EventQueue -> processEvents() -> execute_action_down / execute_action_up -> usb_hid_* -> usb_serial_send() fuer HOST_COMMAND CDC Serial -> poll_vendor() -> Config/Makros einlesen oder dumpen -> LED-Overrides setzen/loeschen LED-Render -> CButton.render_led() -> ws2812_set() -> ws2812_show() nur wenn dirty ``` ## Zentrale Komponenten | Datei | Aufgabe | |---|---| | `main.cpp` | startet den Controller | | `CMainController.*` | Orchestrator fuer Inputs, Actions, Serial, LEDs | | `CButton.*` | LED-Zustand, Animationen, Action-Referenz | | `CEventQueue.*` | ISR-sicherer Ringbuffer | | `config/nvm_config.*` | Config v3 laden, speichern, Defaults | | `config/macro_config.*` | Makros laden, speichern | | `hal/matrix.*` | 5x5-Matrixscan mit Debounce | | `hal/encoder.*` | Encoder-ISR und Drehrichtung | | `hal/usb_hid.*` | Keyboard- und Consumer-HID | | `hal/usb_serial.*` | CDC-Paketpfad | | `hal/ws2812.*` | WS2812-Treiber | ## Key-ID-Schema ```text 0..3 = Encoder-SW 4 = unbenutzt 5..24 = MX-Buttons ``` Die beiden Werksreset-Tasten sind: - `key_id 9` = unten links - `key_id 24` = unten rechts ## Werksreset im Ablauf Der Werksreset ist keine PC-Funktion, sondern Teil der Firmware: - sobald beide Reset-Tasten gleichzeitig gehalten werden, werden ihre normalen Actions unterdrueckt - falls bereits ein HID-Hold aktiv war, wird er sofort freigegeben - nach 5 Sekunden gemeinsamer Haltezeit wird Default-Config + leere Makro-Tabelle in NVM geschrieben - danach folgt ein kurzes rotes Feedback-Blinken ## Invarianten - kein Heap - keine Floats - `packed` fuer serielle und NVM-relevante Structs - NVM-Schreibpuffer muessen 4-Byte-aligned sein - `usb_serial_send()` sendet nur bei aktiver CDC-Verbindung