Release 9 — DMX & Professional Lighting¶
Theme: Releases 3–8 covered addressable LEDs end-to-end. Release 9 brings projectMM into stage-lighting territory: DMX512 input and output over RS-485, moving-head fixtures with pan/tilt/gobo/zoom channels, and a Channels UI for debugging unknown fixtures. By the end, a projectMM device can control a DMX moving head and render scrolling text or WLED-ported effects across any layout.
Release Overview¶
| Gap | Addressed by |
|---|---|
| No RS-485 driver; DMX hardware can't be driven at all | Sprint 1 |
| No DMX Out — projectMM can only drive pixels, not fixtures | Sprint 2 |
| No DMX In — can't receive from a DMX console | Sprints 3–4 |
| No per-channel visibility for debugging DMX fixtures | Sprint 5 |
| No notion of "control channel" (last-wins for pan/tilt/gobo/etc.) | Sprint 6 |
| No moving-head effects | Sprints 7–8 |
| No text rendering — can't show IP / clock / status on matrix | Sprint 9 |
| Several MoonLight-worthy effects still missing | Sprint 10 |
Sprint 1 — RS-485 Driver (MAX485 Half-Duplex)¶
Scope¶
Goal: a reusable RS-485 UART wrapper; both DMX and future Modbus/etc. will build on it.
Part A — Rs485Module. IoModule pin types: rs485_tx, rs485_rx, rs485_de (direction-enable). Initializes UART with MAX485 half-duplex flow control. Configurable baud (DMX uses 250 kbaud).
Part B — Raw write + read API. Other modules (DMX Out/In in Sprints 2–4) acquire the bus, write a frame, release. DE pin auto-toggled around writes.
Part C — Bus arbitration. Only one owner at a time; DMX Out and DMX In on the same bus would need separate UARTs (documented).
Definition of Done:
- Loopback test:
tx='A'; delay; rxreads'A'back on a bench-wired MAX485 - 250 kbaud sustained with no byte drop over 60 s
- Two-bus test: two RS-485 modules on separate UARTs coexist
Result¶
To be completed after implementation.
Retrospective¶
To be completed after implementation.
Sprint 2 — DMX Out (Channels 1–512)¶
Scope¶
Goal: send one DMX universe (512 channels) at the standard 44 Hz.
Part A — DmxOutputModule. Children of VirtualLayer OR direct channel writers. Controls: start_channel, channel_count, refresh_hz (cap 44).
Part B — Light-preset mapping. Same light-presets as R6 S10 (IRGB, CW/WW, CCT) now applicable to DMX fixtures — an IRGB fixture occupies 4 consecutive channels.
Part C — Universe guard. UI warns if two DmxOutputModules target the same start channel range.
Definition of Done:
- A DMX-controllable RGB fixture driven visually correct
- 512 channels written at 44 Hz, no timing violations per DMX spec
- Light-preset round-trip:
SolidEffect(red)onIRGBDMX fixture → intensity 255 + R=255 + G=0 + B=0
Result¶
To be completed after implementation.
Retrospective¶
To be completed after implementation.
Sprint 3 — DMX In: Direct Channel Buffer Mode¶
Scope¶
Goal: receive a DMX universe; expose the full 512-channel buffer to the runtime for arbitrary use.
Part A — DmxInputModule. Listens on its configured RS-485 bus; maintains uint8_t channels[512]. Exposes getChannel(ch).
Part B — Frame-rate counter. Display control showing incoming frame rate; warns if below 20 Hz.
Definition of Done:
- DMX console sending known test patterns updates
channels[] - Frame-rate counter reads ≈ 44 Hz with a standard console
- Break + MAB timing correct per DMX512 spec (measured with logic analyzer)
Result¶
To be completed after implementation.
Retrospective¶
To be completed after implementation.
Sprint 4 — DMX In: Lights-Control Mapping Mode¶
Scope¶
Goal: incoming DMX channels bind directly to control keys — a physical DMX console driving brightness, palette, speed without scripts.
Part A — Channel mapping table. Pairs (dmx_channel, module_id, control_key); UI for editing. Incoming value (0–255) writes to the control.
Part B — Range re-scaling. Map a DMX channel's 0–255 into the control's actual range — e.g. brightness (0–255) is identity, but a palette index (0–7) needs val / 32.
Part C — Mode switch. DmxInputModule has a mode control: buffer (Sprint 3 behavior) or controls (this sprint). Can be both simultaneously if two modules are configured on same bus.
Definition of Done:
- Assigning "channel 10 →
LightsControl.brightness" propagates console slider to actual brightness - 4 mapped channels verified with a real console
- Mode switch demoed: same DMX In can feed buffer for effects AND controls for config
Result¶
To be completed after implementation.
Retrospective¶
To be completed after implementation.
Sprint 5 — Channels Module UI¶
Scope¶
Goal: the per-channel diagnostic view MoonLight's Channels module provides.
Part A — ChannelsModule (read-only diagnostic). Displays 512 channels in a grid; hover shows the current 0–255 value. View selector: physical (what the driver is about to output), virtual (what a selected VirtualLayer has composed).
Part B — Universe selector. Multi-universe drivers (DDP, Art-Net with > 1 universe) can page per universe.
Part C — Group-to-max toggle. When debugging an unknown DMX fixture, a "set all channels of this light to 255" button helps reverse-engineer which channels do what.
Definition of Done:
- Channel grid shows live values; hover matches what the driver writes
- Universe switch correct for an Art-Net configuration with 3 universes
- Group-to-max toggles a fixture's channels to 255 for 5 seconds then restores
Result¶
To be completed after implementation.
Retrospective¶
To be completed after implementation.
Sprint 6 — Moving-Head Framework¶
Scope¶
Goal: fixtures that are not just color — they have pan, tilt, gobo, zoom. Control channels have last-wins semantics.
Part A — MovingHeadFixtureModule. Config: channel layout (pan_coarse, pan_fine, tilt_coarse, tilt_fine, gobo, zoom, strobe, dimmer, R, G, B, W). A fixture is a logical unit over N DMX channels.
Part B — Last-wins compositing. For control channels (pan/tilt/gobo/zoom/strobe/dimmer), the last layer to write wins — not additive. For color channels, additive still applies (matches MoonLight's decision).
Part C — Fixture presets. Preset JSON for common fixtures (generic 12-channel moving head + a couple of real-world fixtures — choose based on what we can test).
Definition of Done:
- A bench moving head addressable via pan/tilt
- Two layers targeting same fixture: layer 2 pan/tilt overrides layer 1 exactly
- Layer 1 RGB + layer 2 RGB add normally
Result¶
To be completed after implementation.
Retrospective¶
To be completed after implementation.
Sprint 7 — Moving-Head Effects: Troy1 Color + Move¶
Scope¶
Goal: first two moving-head effects, ported from MoonLight.
Part A — Troy1ColorEffect. Color cycles across the fixtures' color channels; tempo can be global BPM or an effect-level slider.
Part B — Troy1MoveEffect. Pan/tilt pattern across N fixtures — Lissajous / circle / figure-eight options.
Part C — Test fixture layout. Preset for a 4-fixture bar (common stage setup); effects render meaningfully across it.
Definition of Done:
Troy1ColorEffectrunning on 4 RGB fixtures produces coordinated color cyclingTroy1MoveEffectruns pan/tilt pattern visibly across 4 pan/tilt fixtures- Combined:
Troy1Coloron one layer +Troy1Moveon another layer both work (last-wins for movement, additive for color)
Result¶
To be completed after implementation.
Retrospective¶
To be completed after implementation.
Sprint 8 — Moving-Head Effects: Troy2, FreqColors, Wowi, Ambient¶
Scope¶
Goal: four more MoonLight moving-head effects — audio-reactive + ambient variants.
Part A — Troy2ColorEffect + Troy2MoveEffect. Richer Troy variants with more parameters.
Part B — FreqColorsEffect. Audio-reactive: fixture color follows dominant frequency band.
Part C — WowiMoveEffect. Sweeping choreographed motion — fixtures move in wave patterns triggered by audio magnitude.
Part D — AmbientMoveEffect. Slow, low-energy movement for background/atmosphere use.
Definition of Done:
- All 5 effects registered, each produces its expected behavior on the bench rig
- Audio-reactive variants respond to WLED-sync audio (doesn't need local mic on the fixture-driving device)
- At least one "performance" test: combined effect stack + real DMX console running simultaneously — no frame drops
Result¶
To be completed after implementation.
Retrospective¶
To be completed after implementation.
Sprint 9 — Scrolling Text Effect + Font Rendering¶
Scope¶
Goal: display IP address / time / FPS / uptime / client count / arbitrary text on a 2D layout.
Part A — FontModule. 5×7 pixel font table (ASCII subset). Exposes drawChar(x, y, c, color) + measureText(s). One font initially; extensible.
Part B — ScrollingTextEffect. Controls: text (free text), preset (dropdown: custom, ip, fps, time, uptime, clients, status), speed, color, direction. Preset auto-populates text each frame from the corresponding system source.
Part C — Layout sizing. Text renders correctly on panels of any size; for narrow panels (< font height), auto-scales or shows a warning.
Definition of Done:
- IP address scrolling across a 32×8 panel at a readable speed
preset=timeupdates every second;preset=fpsupdates live- Text renders correctly on 16-pixel-high panel and clearly on 8-pixel-high
Result¶
To be completed after implementation.
Retrospective¶
To be completed after implementation.
Sprint 10 — Additional WLED-Ported Effects¶
Scope¶
Goal: round out the effect library with the last set of high-value WLED ports.
Part A — PaintBrushEffect. 6D bass-driven paint-stroke effect from MoonModules.
Part B — BouncingBallsEffect. N balls bouncing within a 1D/2D volume; audio-reactive variant triggers new balls on beats.
Part C — FrequencySawsEffect. Audio-reactive saw-waves synced to bands.
Part D — RandomEffect + PraxisEffect. Two more MoonLight natives.
Part E — Effect gallery doc. Each effect with a one-sentence description + a GIF (or screenshot) on docs/modules/effects.md.
Definition of Done:
- All 5 effects registered
- Effect gallery page published
- Combined footprint delta < 30 KB flash
Result¶
To be completed after implementation.
Retrospective¶
To be completed after implementation.
Release 9 Backlog¶
- DMX merging (HTP/LTP strategies). HTP (highest-takes-precedence) and LTP (latest-takes-precedence) merge semantics. Pick up when two-console setups demand it.
- RDM (Remote Device Management). DMX-over-DMX device discovery. Significant work; pick up when a real fixture benefits from it.
- Full fixture library. Import OpenFixtureLibrary JSON. Pick up when fixture count on bench exceeds ~5.
- Multi-font support. Bigger/smaller fonts, proportional fonts. Pick up when text effect demand grows.
- Custom pixel-font editor. UI for drawing custom characters. Pick up when users request.