Files
VersaMCU/doc/00_architecture.md
T

3.4 KiB
Raw Blame History

VersaMCU Architekturübersicht

Zielplattform

Merkmal Wert
MCU ATSAMD21G17D, Cortex-M0+, 48 MHz
Flash 128 KB
RAM 16 KB
FPU keine; LED-/Timingpfade verwenden Integer-Arithmetik
USB HID Keyboard + Consumer + CDC Serial
Toolchain PlatformIO + Arduino Core

Setup und Loop

Arduino setup()
  delay(500)
  ws2812_init()
  rotes Startsignal für 1 s
  CMainController::setup()
    macro_config_load()
    init_buttons() -> nvm_config_load()
    Queue-Bridge setzen
    usb_hid_init()
    usb_serial_init()
    matrix_init(cb)
    encoder_init(cb)

Arduino 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

Makros, Encoder-Taps, NVM-Schreiben sowie Start- und Reset-Feedback verwenden blockierende Delays. Währenddessen werden Matrix und CDC nicht bearbeitet.

Datenfluss

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.* fester Ringbuffer mit 16 nutzbaren Slots
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

Die drei Fader sind nur im Variant und in config/pins.h definiert. Es gibt aktuell keinen Fader-HAL und keine Verarbeitung im Controller.

Key-ID-Schema

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

  • Projektcode vermeidet dynamische Allokation
  • Integer-Arithmetik in zeitkritischen LED-/ISR-Pfaden
  • packed fuer serielle und NVM-relevante Structs
  • NVM-Schreibpuffer muessen 4-Byte-aligned sein
  • usb_serial_send() sendet nur bei aktiver CDC-Verbindung

Nebenläufigkeit

Encoder-Callbacks laufen im EIC-Interrupt, Matrixcallbacks im Loop. Beide schreiben in dieselbe CEventQueue; processEvents() liest im Loop. Der Matrixcallback maskiert Interrupts während seines Queue-Pushs, sodass Loop und ISR den Tail-Index nicht gleichzeitig ändern. Bei Überlauf werden Events weiterhin verworfen.