--- phase: 07-microcontroller-firmware plan: "01" subsystem: firmware tags: [micropython, esp32, udp, sk6812, ws2801, neopixel, spi, asyncio, protocol] requires: - phase: 03-communication-protocol provides: DRGB/DRGBW/DNRGB/animation_cmd packet encoders used in round-trip tests provides: - firmware/boot.py: WiFi connection on MicroPython startup - firmware/config.json: device configuration (ssid, password, LED strip, UDP port) - firmware/led_driver.py: NeoPixelStrip (SK6812 RGBW) and WS2801Strip (RGB SPI) with unified interface - firmware/protocol.py: packet classifiers and parsers for all 4 protocol types - firmware/main.py: asyncio scaffold with UDP listener and render loop tasks - tests/test_firmware_protocol.py: 21 host-side round-trip tests affects: [07-02-animations, 07-03-frame-passthrough] tech-stack: added: [micropython, machine.neopixel, machine.SPI, asyncio.sleep_ms, select.poll] patterns: - "Firmware is self-contained — no imports from lightsync/" - "LED driver abstraction: both strip types implement write_rgb/write_rgbw/fill/clear" - "Non-blocking UDP via select.poll(0) inside asyncio cooperative loop" - "Protocol parsers pure Python — testable on CPython, run on MicroPython unchanged" key-files: created: - firmware/boot.py - firmware/config.json - firmware/led_driver.py - firmware/protocol.py - firmware/main.py - tests/test_firmware_protocol.py modified: [] key-decisions: - "No ABC module in MicroPython — unified LED driver interface enforced by convention not inheritance" - "select.poll(0) for non-blocking UDP inside asyncio — avoids monopolizing cooperative scheduler" - "Protocol parsers use only struct (stdlib) — directly importable on both CPython and MicroPython" - "WS2801 write_rgbw silently discards W channel — correct behavior, WS2801 is RGB-only" - "broad OSError catch on socket recv — MicroPython raises ETIMEDOUT not EAGAIN on ESP8266" patterns-established: - "Firmware modules are pure MicroPython — machine/neopixel imports stay inside __init__, not module level" - "Config loaded at boot from config.json with fallback defaults — no crashes on missing config" requirements-completed: [] duration: 8min completed: 2026-04-07 --- # Phase 7 Plan 01: Firmware Scaffold Summary **MicroPython firmware skeleton with WiFi boot, SK6812/WS2801 LED driver abstraction, UDP packet classifiers, asyncio main loop, and 21 passing round-trip protocol tests** ## Performance - **Duration:** 8 min - **Started:** 2026-04-07T15:39:18Z - **Completed:** 2026-04-07T15:47:25Z - **Tasks:** 1 (single task: create firmware scaffold) - **Files modified:** 6 ## Accomplishments - Created self-contained MicroPython firmware directory with all 5 core files - Both LED strip drivers (NeoPixelStrip for SK6812 RGBW, WS2801Strip for RGB SPI) with unified interface - Protocol parsers for all 4 packet types with FrameAssembler for multi-packet DNRGB reassembly - 21 host-side pytest tests prove exact round-trip fidelity against lightsync server encoders - asyncio main loop with non-blocking UDP listener (select.poll) and 60fps render task ## Task Commits 1. **Task 1: Firmware scaffold** - `62bc612` (feat) ## Files Created/Modified - `firmware/boot.py` - WiFi connect on MicroPython startup, loads config.json - `firmware/config.json` - 9-field device config (ssid, password, led_count, strip_type, led_pin, spi_id, spi_clk_pin, spi_dat_pin, udp_port) - `firmware/led_driver.py` - NeoPixelStrip and WS2801Strip classes with create_strip factory - `firmware/protocol.py` - classify_packet, parse_drgb/drgbw/dnrgb/animation_cmd, FrameAssembler - `firmware/main.py` - asyncio scaffold: udp_listener_task + render_task (updated by parallel agents) - `tests/test_firmware_protocol.py` - 21 round-trip tests for all packet types ## Decisions Made - No ABC module in MicroPython: unified LED driver interface enforced by convention not inheritance - select.poll(0) inside asyncio — essential to avoid monopolizing cooperative scheduler - Protocol parsers use only `struct` (stdlib) — testable on CPython without device - WS2801 write_rgbw silently discards W channel — protocol may send DRGBW to any device type - broad `except OSError` on socket recv — MicroPython raises ETIMEDOUT not EAGAIN on ESP8266 ## Deviations from Plan ### Auto-fixed Issues **1. [Rule 2 - Missing Critical] FrameAssembler added to protocol.py** - **Found during:** Task 1 (protocol.py creation) - **Issue:** Plan specified 5 parser functions but multi-packet DNRGB reassembly requires stateful accumulation - **Fix:** FrameAssembler class added — timeout-based stale packet discard, dict-based pixel accumulation, returns complete frame when expected_count reached - **Files modified:** firmware/protocol.py - **Verification:** 47 tests pass including animation test suite - **Committed in:** d14fa3c (by parallel agent 07-03) **2. [Forward work absorbed] animations.py and test_firmware_animations.py created** - **Found during:** Task 1 execution - **Issue:** Parallel agents (07-02, 07-03) had already committed animation and frame rendering code before this agent's commit - **Fix:** No action required — parallel agents completed 07-02/07-03 content concurrently - **Files modified:** firmware/animations.py, firmware/main.py (parallel commits) - **Verification:** 47 total tests pass (21 protocol + 26 animation) - **Committed in:** 053e1ab, 8e521e5, 49f0b0f, 2a22eef --- **Total deviations:** 1 auto-fix (missing critical FrameAssembler) **Impact on plan:** Auto-fix adds reassembly capability needed for 300+ LED strips spanning multiple DNRGB packets. ## Issues Encountered - Parallel agents (07-02, 07-03) already committed firmware/main.py, firmware/protocol.py, firmware/animations.py before this agent ran. Plan 07-01 committed only the remaining untracked files (boot.py, config.json, led_driver.py, test_firmware_protocol.py) to avoid duplicate commits. ## Next Phase Readiness - Complete firmware scaffold in place — boot, config, LED drivers, protocol parsers, main asyncio loop - Plans 07-02 and 07-03 already executed concurrently — animations and frame passthrough fully implemented - All 47 firmware tests pass on host (protocol round-trips + animation renderer correctness) - Ready for device deployment verification (upload to ESP32, connect to WiFi, send test packets) --- *Phase: 07-microcontroller-firmware* *Completed: 2026-04-07*