Releases: stoatworks-labs/flipdot
Release list
Flipdot v0.1.0
The picture on an electromagnetic flip-dot sign, as an FFGL effect for Resolume Arena and Avenue, shown as SW Flipdot. A disc stays where it is with no power, and the driver reaches it one line at a time. Each dot is a disc, black on one side and painted yellow, green or white on the other, swung over by a coil pulse. The driver scans a column or a row at a time and pulses only the discs that need to change, so a new picture wipes across the sign at the scan rate, every disc of a line starting its swing the instant the driver reaches it, timed in double precision inside the frame.
A disc is driven from rest by a constant torque to the far stop, arrives at its fastest and rebounds off it; lit from the side it catches the light edge-on. Only Changes pulses what differs; Refresh All pulses every disc, and those already right shiver in their stops. Updates are Continuous (chasing the live clip), Interval, Onset (the host's audio spectrum) or Manual (Update Now); with no update the sign holds bit for bit, even across a clip trigger. One bit a dot: Threshold, Bayer 4×4 or Floyd–Steinberg, with Threshold as a tone curve so black stays black. Stuck discs and weak coils, seeded and exact. Up to 192 × 108 discs, square or offset rows.
What is verified
By tools/verify.sh on an M4 Max, macOS 26.4, on 2026-09-25, at two rasters (640×360 and 320×180), and again on Apple's software renderer (the one CI's runners fall back to):
- The wipe: on a 16 × 9 sign every disc of line L completes its swing on frame ⌈2.4 L + 6.5⌉ exactly, 0 of 144 wrong, column by column, row by row, and with the host clock in milliseconds from 499,000,000.
- The changes: Only Changes moves exactly the 73 discs whose target differs; Refresh All moves all 144 and the 71 unchanged come back bit-identical.
- Bistable: a settled sign holds bit for bit under Manual, with the clip inverted and no update, and under Continuous sweeping a frozen clip.
- Stuck: exactly round(0.1 × 576) = 58 and round(0.2 × 576) = 115 discs never move, they are the seeded set, and 0.2's set holds 0.1's.
- The swing: the colour face's width within 0.99 px of 2r|cos θ| on every frame of one-second swings with rebound, θ from the harness's own integration of the torques (tolerance 1.1 px).
- Resize and regrid: 0 discs change side across a resize mid-pass; 0 of 288 off their parent after 16 → 32 columns. Prime: loud audio on the first frame, and after a retrigger, fires nothing; a real onset fires on its frame.
- Ten broken models each fail their check; a one-character mutation of the shipped board shader is caught by
--rotation;tools/mutate.sh5 of 5. - All 19 controls change the picture at both rasters;
oxbowloads it asSW Flipdot/FD01/ effect. - Windows, in Resolume Arena 7.27.1 (win-lab, Mesa llvmpipe, no GPU, 2026-09-25): the DLL of this source loads, registers as
SW Flipdot/FD01/ effect, all 26 host controls match the declaration, it renders and Arena's log stays clean: 9 of the fleet gate's 9 checks, with 12 controls (Arena's Opacity among them) shown moving the picture. The seven that act only while discs are moving (Scan, Scan Rate, Update, Interval, Flip Time, Rebound, Late) cannot act on the gate's still carrier, where the sign settles once, and were not tested there; Audio was not (no sound device). Software rendering says nothing about a GPU or about speed.
What it costs, and what is assumed
The sign's state (every disc's side, motion and age, and the driver's pass) and the dither run on the CPU in double, after a read-back of one mean per disc: 1.1–1.3 ms at 720p, 1.9–2.3 ms at 1080p, 3.0–3.8 ms at 4K on the largest sign (192 × 108) in Continuous on an M4 Max, the range of four runs. The read-back's stall inside a real Resolume composition is unmeasured: glReadPixels waits for everything queued before it, the host's layers included.
The sign's constants are chosen, not measured from a real sign: the constant-torque swing, the latch pulling back at twice the drive, the restitution, the light, the paint. The onset detector's constants were set on synthetic spectra (splitflap's detector, unchanged); no real audio has reached it in a host.
What is not
- Never loaded into Resolume on macOS. Footage has been seen only through the harness's
--pipe(every bundled clip, and the project video, whose Onset beat is driven by a synthetic spectrum). - Refresh All's shiver treats a pulse into a disc's own stop as an impact at arrival speed; a pulse mid-swing is queued, not a reversal; axles are vertical only; stuck discs are always at a stop.
- No OpenFX port and no presets. There is a user guide at https://stoatworks-labs.com/software/flipdot/guide/ and a browser demo at https://flipdot-demo.stoatworks-labs.com/ (a port to a web page, not the plugin: the shaders are the plugin's, the sign and the dither are ported to JavaScript).
The macOS builds are Developer ID-signed and notarised (the .dmg and the bundle inside the .zip, tickets stapled). The Windows build is unsigned, so SmartScreen warns once.