SineEffectModule¶
A multi-type effect producer. Switches between a 3D sine-wave pattern and a 3D ripples effect via a runtime type selector. Writes colored RGB values into an EffectsLayer each loop(). Introduced in Release 1, Sprint 4; refactored in Release 1, Sprint 5; extended with the waveform selector in Release 7, Sprint 9; dynamic type selector added in Release 8, Sprint 1.
What it does¶
A type dropdown selects the active effect. Only the parameters relevant to the selected type are shown in the UI; the rest are hidden until needed.
Type 0: Sine¶
Fills a 3D pixel grid with a colored waveform. Each color channel responds to a different spatial axis:
R = amplitude × wave(frequency × (x + tick))
G = amplitude × wave(frequency × (y + tick) + 2π/3)
B = amplitude × wave(frequency × (z + tick) + 4π/3)
waveform selects the wave shape: sine, square, triangle, or sawtooth.
Type 1: Ripples¶
Radial wave from the centre of the XZ floor. One pixel column per (x, z) position is lit at a height determined by a sine phase driven by distance and time:
y = h/2 × (1 + sin(dist/ripple_interval + time))
Colour cycles through a hue wheel over time.
Controls¶
Common¶
| Parameter | Type | Default | Description |
|---|---|---|---|
type |
select | 0 (sine) | Effect variant. Switches the visible control set at runtime. |
enabled |
toggle | true | When false, loop() is skipped. |
Sine controls (type = 0)¶
| Parameter | Default | Description |
|---|---|---|
frequency |
1 | Spatial + temporal wave frequency (1-20). |
amplitude |
255 | Output amplitude (0-255, DMX-aligned). |
waveform |
0 (sine) | Wave shape: sine, square, triangle, sawtooth. |
Ripples controls (type = 1)¶
| Parameter | Default | Description |
|---|---|---|
speed |
50 | Animation speed (0 = stopped, 99 = fast). |
interval |
128 | Wavefront spacing (1 = tight, 254 = wide). |
Parameter values are preserved when switching between types: setting frequency to 15, switching to Ripples and back restores frequency = 15.
Dynamic controls¶
SineEffectModule overrides rebuildControls() and onUpdate(). When type changes, onUpdate("type") calls rebuildControls(), which calls clearControls() (saving current non-system values to the pending stash) and re-registers only the controls for the new type. The UI receives an early WebSocket push so the control card updates without waiting for the next 200 ms cycle.
Platform notes¶
Uses sinf() and sqrtf(). The module owns no pixel memory — allocation is in EffectsLayer. On ESP32, both functions use the hardware FPU.
Test coverage¶
→ Sine Effect — deterministic output, zero residue after teardown, checksum propagation through layers.
→ Controls and KV — type selector schema (4 controls in Sine mode), type switch to Ripples, frequency preserved across round-trip.
Also covered in Health Checks (healthReport format, checksum consistency).