2026-03-29 14:47:13 +02:00
2026-03-31 21:46:20 +02:00
2026-03-31 21:46:20 +02:00
2026-03-29 14:47:13 +02:00
2026-03-29 14:47:13 +02:00
2026-03-29 14:47:13 +02:00
2026-03-31 22:05:59 +02:00
2026-03-29 14:47:13 +02:00

VersaMCU

Firmware für das VersaPad v2 Macro-Pad. Läuft auf einem ATSAMD21G17D (Cortex-M0+), entwickelt mit PlatformIO + Arduino-Framework.

Hardware

Eigenschaft Detail
MCU ATSAMD21G17D (Cortex-M0+, 128 KB Flash, 16 KB RAM)
Taktfrequenz 48 MHz (DFLL, intern kein externer 32 kHz-Quarz)
Framework Arduino SAMD Core 1.8.14, PlatformIO
Programmer Atmel-ICE via SWD (kein Bootloader)

Button-Matrix

  • 5×5-Matrix (COL_04 × ROW_04) = 25 logische Keys
  • 20 Cherry MX Switches (COL_14 × ROW_04), je eine WS2812-LED
  • 4 Encoder-SW-Buttons (COL_0 × ROW_03), keine LEDs
  • COL_0 × ROW_4 = nicht belegt
  • Dioden: D4148 je Taste, Anode an Switch, Kathode an ROW → Ghost-Key-freies Scannen
  • Scan-Richtung: ROW wird OUTPUT LOW getrieben, COL-Leitungen haben 10 kΩ-Pullup nach 3V3 (werden gelesen)

Rotary Encoder

  • 4× Encoder (ENC0 = USB-nah, ENC3 = USB-fern)
  • Alle A/B-Leitungen auf EIC (PA16PA23), Quadratur-Dekodierung via ISR + 4-State-Lookup
  • Jeder Encoder hat drei Aktionen: CW, CCW, SW (alle aus NVM konfigurierbar)

LEDs (WS2812)

  • 20× WS2812B, serpentinen-verdrahtet (Reihe 0: L→R, Reihe 1: R→L, …)
  • Datenleitung: PB22 (D18), bit-bang via Adafruit NeoPixel Library
  • LED_INDEX-Formel: row * 4 + ((row & 1) ? (4 - col) : (col - 1))
  • Pegelproblematik: WS2812 sind 5V-Devices (HIGH-Schwelle ~3,5 V), SAMD21 liefert 3,3 V ohne Level-Shifter. LED 0 empfängt einen marginal gültigen Pegel; ab LED 1 regeneriert jede LED intern auf 5 V → alle weiteren problemlos. Fix nächste PCB-Revision: Level-Shifter oder Diode in der VDD-Leitung.

Fader (ADC)

  • 3× Linearpotentiometer: PA02 (A0), PA03 (A1, auch VREFA), PB08 (A2)
  • Noch nicht implementiert (siehe Roadmap)

Voraussetzungen

  • PlatformIO (CLI oder VS Code Extension)
  • Atmel-ICE Debugger/Programmer (SWD-Verbindung zur PCB)
  • OpenOCD wird von PlatformIO automatisch installiert

Flashen

pio run --target upload

Der Upload läuft via OpenOCD über SWD. Kein Bootloader nötig der Chip wird direkt programmiert.


Funktionsumfang (Anforderungskatalog)

1 Hardware-Plattform

# Anforderung Status
1.1 Ziel-MCU: ATSAMD21G17D (Cortex-M0+, 48 MHz, 128 KB Flash, 16 KB RAM)
1.2 Framework: Arduino + PlatformIO, kein Bootloader (Direktflash via SWD/Atmel-ICE)
1.3 USB-Enumeration ohne externen Quarz (-DCRYSTALLESS, DFLL48M nutzt USB-SOF als Referenz)
1.4 Benutzerdefiniertes Board-Profil (versapad_nobl.json) mit korrekten Flash/RAM-Limits

2 Tasten-Matrix

# Anforderung Status
2.1 5×5-Matrix-Scan (25 Keys, davon 20 MX-Buttons + 4 Encoder-SW + 1 NC)
2.2 10 ms Software-Debounce pro Taste (Flanken-Erkennung)
2.3 KEY_DOWN- und KEY_UP-Events werden in die Event-Queue geschrieben
2.4 Matrix-Scan im Loop-Kontext (kein ISR, kein Heap)

3 Encoder

# Anforderung Status
3.1 4 Quadratur-Encoder (A/B-Phasen per EIC-Interrupt)
3.2 Richtungserkennung: CW / CCW via 2-Bit-Greycode-Auswertung
3.3 Encoder-Events im ISR-Kontext direkt in Event-Queue (interrupt-sicher, kein Heap)
3.4 Encoder-SW-Tasten über Matrix-Scan (gleicher Pfad wie MX-Buttons)

4 Aktions-Engine

# Anforderung Status
4.1 ActionType NONE: kein HID-Event beim Drücken
4.2 ActionType HID_KEY: USB-HID-Tastendruck (Keycode + Modifier-Byte)
4.3 ActionType HID_CONSUMER: USB Consumer Control (Play/Pause, Lautstärke …)
4.4 ActionType HOST_COMMAND: Event-ID an VersaGUI senden, App führt aus
4.5 ActionType MACRO: Sequenz aus bis zu 4 HID-Key-Schritten aus NVM-Tabelle abspielen
4.6 Jede Aktion ausführbar ohne laufende VersaGUI (lokal per HID/Makro)
4.7 Hold-Modell für HID_KEY / HID_CONSUMER: KEY_DOWN → Key-Down senden, KEY_UP → Key-Up senden (OS-Repeat ab ~500ms)
4.8 Tap-Modell für Encoder CW/CCW: atomare down+delay(10)+up Sequenz (diskrete Events, kein Hold möglich)

5 Makro-System

# Anforderung Status
5.1 32 Makro-Slots, je 4 Steps (Keycode + Modifier-Byte) = 256 Byte gesamt
5.2 Steps mit keycode = 0 werden übersprungen (variable Makrolänge 14)
5.3 Timing: 10 ms Key-Down-Dauer + 20 ms Pause zwischen Steps
5.4 Makro-Tabelle in separater NVM-Row (Row 1, 0x1FF00, 256 Byte)
5.5 Makro-Tabelle wird beim Start aus NVM geladen; gelöschter Flash (0xFF) → leere Tabelle

6 LED-System (WS2812)

# Anforderung Status
6.1 20 WS2812-LEDs, serpentiner Verdrahtung; Adafruit-NeoPixel bit-bang Treiber
6.2 2-Schicht-Modell pro Button: base (Idle) + override (temporär von GUI)
6.3 STATIC: feste Farbe aus NVM
6.4 BLINK: binäres An/Aus mit konfigurierbarer Halbperiode
6.5 PULSE: lineares Helligkeitsdreieck (0→255→0), kein Float
6.6 COLOR_CYCLE (Regenbogen): Hue-Sweep über 6 Segmente, ignoriert base/override
6.7 COLOR_FADE: einmaliger RGB-Crossfade zu Zielfarbe
6.8 Phasenversatz beim Start: Regenbogen-LEDs sind gleichmäßig über die Periode verteilt
6.9 ws2812_show() nur bei dirty-Flag aufgerufen (~600 µs Blockzeit vermieden)
6.10 Alle Animationen in Integer-Arithmetik (kein FPU auf M0+)

7 Konfigurations-Speicherung (NVM)

# Anforderung Status
7.1 Config-Layout Version 2, 223 Byte packed, mit Magic 0x56503202 + CRC16-CCITT
7.2 Config gespeichert in NVM Row 0 (0x1FE00, 256 Byte, via Linkerscript reserviert)
7.3 Makro-Tabelle in NVM Row 1 (0x1FF00, 256 Byte)
7.4 NVM-Schreiben: Row löschen + 4 Pages à 64 Byte manuell schreiben (MANW=1)
7.5 Bei ungültigem Magic / falscher Version / CRC-Fehler → Defaults laden (kein Crash)
7.6 Defaults: alle Aktionen NONE, LEDs warm-weiß, Animation Regenbogen 4 s

8 Serial-Kommunikation mit VersaGUI

# Anforderung Status
8.1 CDC Serial (USB), kein Treiber nötig; 8-Byte-Festlängen-Pakete
8.2 Ring-Buffer (256 Byte = 32 Pakete) für eingehende Bytes; kein Datenverlust bei Burst
8.3 Ping / Pong (0x05 / 0x85) zur Verbindungsdiagnose
8.4 Config-Transfer PC→Board: BEGIN(0x10) → 38×DATA(0x11) → COMMIT(0x12) → ACK/NACK
8.5 Config-Dump Board→PC: auf READ(0x13) → BEGIN(0x92) → 38×DATA(0x93) → END(0x94)
8.6 Makro-Transfer PC→Board: BEGIN(0x20) → 43×DATA(0x21) → COMMIT(0x22) → ACK(0x95)
8.7 Makro-Dump Board→PC: auf READ(0x23) → BEGIN(0x96) → 43×DATA(0x97) → END(0x98)
8.8 Config-COMMIT validiert Magic + Version + CRC; bei Fehler NACK ohne NVM-Schreiben
8.9 Alle Sende-Pakete nur wenn SerialUSB aktiv (DTR-Check verhindert stilles Verwerfen)

9 Nicht implementiert / Roadmap

# Anforderung Status
9.1 Fader/Potentiometer: 3× ADC-Kanäle auf Board vorhanden, HAL nicht implementiert 🔲 TODO
9.2 HOST_COMMAND-Payload: Board sendet Command-ID, App-Seite führt aus (halbfertig) 🔲 TODO
9.3 FADE_IN / FADE_OUT per GUI konfigurierbar (Firmware vorhanden, kein GUI-Eintrag) 🔲 TODO

Projekt-Struktur

VersaMCU/
├── platformio.ini           Build- und Upload-Konfiguration
├── upload_openocd.py        Benutzerdefiniertes Upload-Script (OpenOCD)
├── boards/
│   ├── versapad.json        Board-Definition mit Bootloader
│   └── versapad_nobl.json   Board-Definition ohne Bootloader (aktiv)
├── variants/versapad/
│   ├── variant.h/.cpp       Pin-Mapping für den SAMD21G17D
│   └── linker_scripts/      Linkerscript (kein Bootloader, NVM-Reservierung)
└── src/
    ├── main.cpp                    Arduino setup()/loop()
    ├── CMainController.h/.cpp      Zentraler Orchestrator
    ├── CButton.h/.cpp              Button-Modell: LED-Schichten, Action, Animationen
    ├── CEventQueue.h/.cpp          Ring-Buffer FIFO (16 Slots, kein Heap)
    ├── SEvent.h                    Event-Typen (KEY_DOWN/UP, ENC_CW/CCW)
    ├── config/
    │   ├── pins.h                  Pin-Nummern (Arduino-Nummern aus variant.h)
    │   ├── action.h                ActionType-Enum + SAction-Struct (packed)
    │   └── nvm_config.h/.cpp       NVM-Config: Laden, Speichern, CRC16, Defaults
    └── hal/
        ├── matrix.h/.cpp           5×5-Matrix-Scan, 10 ms Debounce
        ├── encoder.h/.cpp          Quadratur-Dekodierung via EIC-Interrupts
        ├── ws2812.h/.cpp           WS2812-LED-Treiber (Adafruit NeoPixel, bit-bang)
        ├── usb_hid.h/.cpp          HID Keyboard + Consumer Control
        └── usb_serial.h/.cpp       CDC Serial bidirektional, 8-Byte-Pakete

Architektur

Schichten

┌────────────────────────────────────────────────┐
│  main.cpp                                      │
│  CMainController (setup / work)                │
├────────────────────────────────────────────────┤
│  Modell                                        │
│  CButton (LED 2-Layer, Action, dirty-Flag)     │
│  CEventQueue (Ring-Buffer FIFO, 16 Slots)      │
├────────────────────────────────────────────────┤
│  HAL                                           │
│  hal/matrix     5×5-Scan, 10 ms Debounce     │
│  hal/encoder    Quadratur via EIC-ISR         │
│  hal/ws2812     Adafruit NeoPixel bit-bang    │
│  hal/usb_hid    HID Keyboard + Consumer       │
│  hal/usb_serial CDC Serial bidirektional      │
├────────────────────────────────────────────────┤
│  Config                                        │
│  config/pins.h        Pin-Mapping             │
│  config/action.h      ActionType + SAction    │
│  config/nvm_config    Flash R/W, CRC16        │
└────────────────────────────────────────────────┘

Datenfluss

HAL (matrix_scan, Encoder-ISR)
  └─► matrix_cb / encoder_cb
        └─► CEventQueue.push()
              └─► CMainController.processEvents()
                    ├─► CButton.on_press() / on_release()
                    ├─► execute_action()  →  usb_hid_send_key / send_consumer
                    └─► usb_serial_send() (nur bei HOST_COMMAND)

SerialUSB (PC → Board, 8-Byte-Pakete)
  └─► CMainController.poll_vendor()
        └─► CButton.set_override() / set_base() / clear_override()

CMainController.updateLEDs()
  └─► CButton.render_led()  →  ws2812_set()
        └─► ws2812_show() (nur wenn dirty)

Loop-Ablauf

loop()
  ├── matrix_scan()    → matrix_cb()    → CEventQueue.push()
  │   (Encoder-ISRs laufen asynchron)  → CEventQueue.push()
  ├── poll_vendor()    → Serial-Pakete von VersaGUI verarbeiten
  ├── processEvents()  → Queue leeren, Aktionen ausführen
  └── updateLEDs()     → Dirty-CButtons → WS2812-Buffer → show()

CButton LED-Schichten

Jeder MX-Button hat zwei LED-Schichten:

  • base: Konfigurierte Idle-Farbe (aus NVM)
  • override: Temporär von VersaGUI gesetzt (Benachrichtigungen etc.)

Aktive Farbe = override wenn aktiv, sonst base. clear_override() kehrt sofort zu base zurück.

LED-Animationen

Animationen modulieren die Helligkeit oder Farbe der aktiven Schicht (base oder override). Alle Berechnungen in Integer-Arithmetik (Cortex-M0+ hat keine FPU).

Animation Typ Verhalten period_ms-Semantik
STATIC Feste Helligkeit (Standardzustand)
BLINK Helligkeit Binäres An/Aus, endlos Halbperiode (An = Aus)
PULSE Helligkeit Lineares Dreieck 0→255→0, endlos Vollperiode
FADE_IN Helligkeit Einmalig: schwarz → voll, dann STATIC Dauer
FADE_OUT Helligkeit Einmalig: voll → schwarz, dann STATIC + base=schwarz Dauer
COLOR_CYCLE Farbe Hue-Sweep Regenbogen, endlos, ignoriert base/override Eine volle Runde
COLOR_FADE Farbe Einmalig: Crossfade akt. Farbe → Zielfarbe, dann STATIC + base=Ziel Dauer

API:

set_anim(LEDAnim, period_ms, phase_offset_ms = 0)
// Für alle Typen außer COLOR_FADE.
// phase_offset_ms verschiebt den Startpunkt in die Vergangenheit →
// mehrere LEDs versetzt starten (z. B. Regenbogen-Welle).

set_color_fade(RGB to, period_ms)
// Startet COLOR_FADE von aktueller Farbe zu `to`.

clear_anim()
// Sofort zurück zu STATIC (volle Helligkeit).

render_led()
// Gibt true zurück solange dirty oder Animation läuft → ws2812_show() nötig.

Idle-Zustand: Alle 20 MX-LEDs laufen mit COLOR_CYCLE (4 s/Runde, 40 % Helligkeit). Der Phasenversatz ist gleichmäßig über alle 20 LEDs verteilt, sodass immer ein vollständiger Regenbogen auf dem Pad liegt.

Warum Bit-Bang statt DMA?

WS2812-DMA auf dem SAMD21 würde einen SERCOM im SPI-Modus bei exakt 2,4 MHz benötigen, wobei jedes WS2812-Bit als 3 SPI-Bits kodiert wird (110 = 1, 100 = 0). Das erfordert einen zusätzlichen Puffer von 20 LEDs × 24 Bit × 3 = 1440 Byte — mehr als 8 % des gesamten RAM — plus DMAC-Konfiguration und Transfer-Ende-Erkennung.

ws2812_show() blockiert ~600 µs mit gesperrten Interrupts, wird aber nur bei gesetztem dirty-Flag aufgerufen. Bei 20 ms Loop-Rate entspricht das 3 % der Loop-Zeit. Encoder-Impulse, die in dieses Fenster fallen, werden maximal um eine Loop-Iteration verzögert; bei typischen Drehgeschwindigkeiten (< 20 Rastschritte/s, Impulsabstand > 50 ms) ist das Risiko eines verlorenen Impulses praktisch null.

Ergebnis: Bit-Bang via Adafruit NeoPixel reicht für 20 LEDs vollständig aus, belegt keinen SERCOM und keinen zusätzlichen RAM.

Warum keine Adafruit-Animationsfunktionen?

Die Adafruit-NeoPixel-Library stellt ausschließlich den LED-Treiber bereit (setPixelColor, show, fill, clear). Animations-Logik (Blinken, Pulsieren, Farbverläufe) ist nicht enthalten und muss in jedem Fall selbst implementiert werden. Darüber hinaus:

  • Adafruit_NeoPixel::ColorHSV() verwendet intern float-Operationen für die HSV→RGB-Konvertierung. Der Cortex-M0+ hat keine FPU; float wird per Software emuliert (~1020× langsamer). hue_to_rgb() in CButton.cpp erreicht dasselbe Ergebnis mit reiner Integer-Arithmetik (6 lineare Segmente à 43 Hue-Einheiten).
  • Das 2-Schicht-Modell (base + override) und die dirty-Flag-gesteuerte Render-Pipeline sind projektspezifische Logik ohne Entsprechung in der Library.

Idle-Zustand: Alle 20 MX-LEDs zeigen einen rotierenden Regenbogen (COLOR_CYCLE, 4 s/Runde, 40 % Helligkeit, gleichmäßig phasenverschoben).

Serial-Protokoll (8 Bytes, fixed)

Byte 0: Command/Event-ID
Byte 1: key_id (Button 024 oder Encoder 03)
Byte 2: r / Daten-Byte A
Byte 3: g / Daten-Byte B
Byte 4: b
Byte 57: reserviert (0x00)
ID Richtung Bedeutung
0x01 PC→Board LED-Override setzen
0x02 PC→Board LED-Override löschen
0x03 PC→Board LED-Base setzen
0x05 PC→Board Ping
0x10 PC→Board Config-Begin (Chunks-Anzahl)
0x11 PC→Board Config-Data (Chunk-Index + 6B Nutzdaten)
0x12 PC→Board Config-Commit (CRC prüfen + NVM schreiben)
0x13 PC→Board Config-Read (Board sendet NVM-Config zurück)
0x81 Board→PC KEY_DOWN
0x82 Board→PC KEY_UP
0x83 Board→PC ENC_CW
0x84 Board→PC ENC_CCW
0x85 Board→PC Pong
0x90 Board→PC Config-ACK
0x91 Board→PC Config-NACK
0x20 PC→Board Makro-Begin (Chunk-Anzahl = 43)
0x21 PC→Board Makro-Data (Chunk-Index + 6B Nutzdaten)
0x22 PC→Board Makro-Commit (in NVM schreiben)
0x23 PC→Board Makro-Read (Board sendet Tabelle zurück)
0x90 Board→PC Config-ACK
0x91 Board→PC Config-NACK (CRC/Magic/Version ungültig)
0x92 Board→PC Config-Begin (Dump-Start, Chunks-Anzahl)
0x93 Board→PC Config-Data (Chunk-Index + 6B)
0x94 Board→PC Config-End
0x95 Board→PC Makro-ACK
0x96 Board→PC Makro-Begin (Dump-Start)
0x97 Board→PC Makro-Data (Chunk-Index + 6B)
0x98 Board→PC Makro-End

NVM-Config-Layout (Version 2, 223 Bytes, packed)

Offset   0   4B  Magic   0x56503202
Offset   4   1B  Version 2
Offset   5   2B  CRC16-CCITT (über Bytes 7222)
Offset   7  60B  mx_actions[20]      je 3B: type(1B) + data(2B)
Offset  67  36B  enc_actions[4][3]   je 3B
Offset 103  20B  led_r[20]
Offset 123  20B  led_g[20]
Offset 143  20B  led_b[20]
Offset 163  20B  led_anim[20]        LEDAnim-Typ (uint8_t)
Offset 183  40B  led_period_ms[20]   Animationsperiode in ms (uint16_t, LE)

NVM Row 0 (0x1FE00, 256 Byte): Config (223B genutzt, 33B Padding) NVM Row 1 (0x1FF00, 256 Byte): Makro-Tabelle (32 Slots × 4 Steps × 2B) Via Linkerscript reserviert. Bei ungültigem Magic/Version/CRC werden Defaults geladen.

Bekannte Fallstricke

Problem Lösung
Kaltstart hängt (XOSC32KRDY) -DCRYSTALLESS in build_flags pflicht
Adafruit NeoPixel ZeroDMA inkompatibel Standard bit-bang Library verwenden
WS2812 Pegel 3.3V statt 5V LED 0 marginal OK, ab LED 1 selbst-regenerierend. Fix nächste PCB-Rev: Level-Shifter
ws2812_show() blockiert ~600 µs Dirty-Flag-Pattern: nur aufrufen wenn nötig, nie aus ISR
SAction muss __attribute__((packed)) haben Ohne packed: 4B statt 3B → CRC-Mismatch beim Config-Laden
Windows HID-Descriptor-Cache Bei PID-Änderung Board neu einstecken
SERCOM5 CTRLB.RXEN Sync-Bug while(SYNCBUSY.bit.CTRLB) hängt vor ENABLE → nur relevant bei manueller SERCOM5-Konfiguration; nicht im Normalbetrieb
PluggableUSBModule nicht nutzbar USB_SendControl / USB_RecvControl nicht verlinkt in dieser Core-Version → CDC Serial statt Vendor HID für PC-Kommunikation verwenden
HID-Descriptor vor USB-Enumeration registrieren Registrierung via globalem Konstruktor (läuft vor main()), nicht in setup()

Next-Generation Hardware MCU-Empfehlung

Warum der SAMD21G17D an seine Grenzen stößt

Einschränkung Auswirkung auf geplante Features
128 KB Flash Mehrere Profile + lange Makros + OLED-Fonts füllen den Speicher vollständig
16 KB RAM OLED-Framebuffer (128×64 px = 1 KB) + Profil-Puffer + Makro-Tabellen + Stack = kaum Luft
Kein FPU LED-Animationen erfordern Integer-Arithmetik-Workarounds; aufwändigere Effekte unwirtschaftlich
Kein Ethernet-MAC Ethernet nur via langsamen SPI-Chip möglich
Kein USB High-Speed CDC bleibt auf 12 Mbit/s (Full Speed); für schnelle Konfigurationsübertragungen ausreichend, aber kein Spielraum
WS2812 bit-bang blockiert 600 µs Mit mehr LEDs oder höherer Auflösung kritisch; kein DMA ohne SERCOM-Umbau

Empfehlung: Microchip SAME54P20A

Primäre Empfehlung selber Hersteller, gleicher Toolchain-Stack, deutlich mehr Reserven.

Merkmal SAMD21G17D (aktuell) SAME54P20A (empfohlen)
Kern Cortex-M0+, 48 MHz Cortex-M4F, 120 MHz
FPU ✓ (single-precision)
Flash 128 KB 1 MB
RAM 16 KB 256 KB
USB Full Speed (12 Mbit/s) Full Speed + optionaler HS-PHY
Ethernet MAC ✓ (IEEE 802.3, braucht ext. PHY)
DMA 12 Kanäle 32 Kanäle
SERCOM 6 8
NVM (intern) 128 KB 1 MB (kein ext. Flash nötig)
Preis (LCSC ca.) ~2 € ~810 €

Warum SAME54?

  • Direkter Upgrade-Pfad: Arduino-Framework, PlatformIO, gleiche HAL-Konzepte
  • Ethernet-MAC integriert → nur externer PHY nötig (z.B. KSZ8081 oder LAN8720A, ~12 €)
  • 1 MB Flash reicht für viele Profile, lange Makros und OLED-Font-Tabellen ohne externen Flash
  • 256 KB RAM: OLED-Framebuffer, Profil-Puffer und komplexe Makro-Engines kein Problem
  • FPU: sauberere LED-Animationen, kein Integer-Workaround mehr nötig
  • DMA: WS2812 via SERCOM-SPI + DMA möglich → kein Bit-Bang, keine Interrupt-Sperre

Alternative: Raspberry Pi RP2350

Falls Ethernet nicht zwingend auf dem MCU selbst integriert sein muss (z.B. W5500 via SPI):

Merkmal RP2350
Kern Dual Cortex-M33 oder RISC-V, 150 MHz
FPU
RAM 520 KB SRAM
Flash Kein interner; ext. QSPI (typ. 216 MB)
USB Full Speed (Device + Host)
Ethernet MAC ✗ (W5500 via SPI, ~3 €)
PIO 3 × 4 PIO-Blöcke → WS2812 hardwareseitig ohne CPU
Preis ~1,50 €

Vorteil: PIO-Blöcke übernehmen WS2812-Timing hardwareseitig (kein bit-bang, kein DMA-Setup). Sehr viel RAM für komplexe Logik. Günstiger als SAME54.

Nachteil: Kein integrierter Ethernet-MAC. W5500 übernimmt TCP/IP-Stack per SPI (ausreichend für einfaches HTTP/Telnet-Protokoll), ist aber kein vollwertiger Network-Stack.


System-Architektur für PoE-Betrieb

PoE erfordert unabhängig vom MCU zusätzliche Hardware:

RJ45-Buchse (mit integrierten Magnetics)
  └─► PoE-PD-Controller  (z.B. TPS2372-4, AG9800)
        ├─► DC/DC-Wandler  → 3.3V / 5V Versorgung des Boards
        └─► Ethernet-Signal → MCU-Ethernet-MAC → ext. PHY (LAN8720A / KSZ8081)

Der PoE-PD-Controller ist zwingend: Er verhandelt mit dem PoE-Switch (IEEE 802.3af/at), isoliert galvanisch und liefert geregelte Spannung. Typische PoE-Leistungsklasse 0 (15,4 W) reicht für MCU + LEDs + Display mehrfach aus.

Empfohlene ICs:

Funktion IC Preis ca.
PoE PD Controller AG9800 oder TPS2372-4 13 €
Ethernet PHY LAN8720A oder KSZ8081 12 €
QSPI-Flash (falls RP2350) W25Q128 (16 MB) ~0,80 €
OLED Controller SSD1306 (128×64, I2C/SPI) im Modul enthalten

Empfehlung nach Szenario

Szenario Empfehlung
Voller Feature-Umfang (Ethernet-MAC, PoE, Profile, OLED) SAME54P20A + LAN8720A + PoE-PD
Maximale RAM/Flash-Reserve, WS2812 ohne CPU-Last RP2350 + W5500 + PoE-PD
Minimaler Footprint, kein Ethernet RP2040 (günstiger als RP2350, 264 KB RAM reicht für OLED + Profile)

Für VersaPad v3 mit allen genannten Features ist der SAME54P20A die solideste Wahl: gleicher Hersteller, etablierter Toolchain, integrierter Ethernet-MAC, und der Firmware-Code von v2 (HAL-Struktur, Event-Queue, CButton-Modell) ist weitgehend übertragbar.

Description
No description provided
Readme 214 KiB
Languages
C++ 76.3%
C 23%
Python 0.7%