The problem, in PLN's words, asked three times: "why no button lights, still see
only A1 green? recover that asap i see no feedback anymore not even yellow
lifeline" — then "back from 'all yellow' to 'our coding, but touch-reactive and
persistent post touches'".
Three failures were stacked:
1. NOTHING PAINTED AT BOOT. The only LED painter lived in the Pulsar HUD
(lib/lcxl-leds.js), so the board was lit only if Pulsar was open, had activated
the package, and its frame pipeline worked — and #57 says its lastFrame dedupe
latches an early empty frame, so even with Pulsar open one bad first frame means
a permanently dark surface with no error anywhere.
2. FACTORY YELLOW WINNING — a real Midi-Through feedback loop echoing velocity 127
back as an LED colour byte, not a device default.
3. NO PERSISTENCE. The LEDs are write-only, there is NO readback, so software must
own the state and re-assert it. Nothing did.
Approach: tools/lcxl-leds.py, python3 stdlib only, standalone. It works with Pulsar
closed and is scriptable from gig-up. --map [TRACK] paints by ROLE derived from the
`^NN` bindings the file actually contains (dark = unbound on this track, which is
the biggest cognitive win); --map with no track paints the channel CONVENTION, so a
boot can never leave the board dark. --watch is the touch-reactive daemon: it keeps
a model of every control and repaints from that model, so persistence is the data
structure rather than a feature bolted on. --test walks every index so a dead LED
is visible. --dry-run prints hex and sends nothing.
It NEVER sends a CC. Not one, ever. SysEx out only; input is read-only via aseqdump
as a child process, which does not steal MIDI from SuperCollider. Sending CCs would
move live audio parameters, and CC 77-84 are MIDI-learned to Ardour track gains
(CC77 down = total silence).
Three things this cost, worth writing down:
* TRANSPORT. `amidi -p hw:2,0,0 -S ...` is what lit knob A1 by hand — but only
because nothing else held the raw device. On a LIVE rig the ALSA sequencer layer
owns the rawmidi substream and amidi dies with "cannot open port hw:2,0,0: Device
or resource busy". The tool that works on a cold rig failed on the only rig that
matters. Primary transport is now `aseqsend` to the LCXL's writable SEQUENCER
port, which coexists with SuperCollider; amidi stays as fallback.
* PARSING. Splitting the .tidal on blank lines is right in principle (that IS
Tidal's block separator) but stripping full-line `-- comments` first manufactures
blank lines that cut a dN block in half: on vague_de_crime that put 9/9 bindings
in the "fx" fallback because no segment head ever matched dN. Segment boundaries
are now original blank lines PLUS every dN line, comments stripped only for the
CC scan. Same track now reads rhythm=9, fx=6; gimme_acid 21 controls across
rhythm/bass/fx; perfect.tidal 25 across rhythm/bass/lead/fx.
* THE SEAM. The first --watch regexes assumed bare space-separated numbers and
would have matched NOTHING — a daemon that runs clean, logs nothing and paints
nothing. Pulled aseqdump's real format strings out of the binary ("Control change
%2d, controller %d, value %d") and verified the whole loop by putting a fake
aseqdump on PATH: 9/9 synthetic events decoded, coloured and sent, plus a
respawn-with-backoff when the child exited.
Also: the periodic re-assert runs on its own thread, not inside the read loop —
inside, it would only ever fire when an event arrived, i.e. never during the
silences when a device hiccup would actually go unnoticed.
Verified: hex reviewed byte-by-byte against the protocol, 40 index/value pairs in
one write, all bytes < 0x80; sends return rc=0 to the real device; --watch attaches
and survives; event decode unit-checked (CC13@64 -> green full, CC49@0 -> dark red
= LPF hard down, CC33@127 -> green flash, note 73 -> red flash). UNVERIFIED: what
the panel actually looks like — nobody has eyes on it. Absence of an error is not
evidence of a lit LED.
| Name |
Last commit
|
Last update |
|---|---|---|
| .gitea/workflows | Loading commit data... | |
| armada | Loading commit data... | |
| blocks | Loading commit data... | |
| blog | Loading commit data... | |
| copycat | Loading commit data... | |
| docs | Loading commit data... | |
| gifts | Loading commit data... | |
| lib-parvagues | Loading commit data... | |
| live | Loading commit data... | |
| output | Loading commit data... | |
| releases | Loading commit data... | |
| sandbox | Loading commit data... | |
| study | Loading commit data... | |
| test | Loading commit data... | |
| tools | Loading commit data... | |
| utils | Loading commit data... | |
| visuals/slop | Loading commit data... | |
| viz | Loading commit data... | |
| .gitignore | Loading commit data... | |
| BootTidal.hs | Loading commit data... | |
| BootTidal.hs.broken | Loading commit data... | |
| BootTidal.visuals.broken.hs | Loading commit data... | |
| CLAUDE.md | Loading commit data... | |
| FOH_MASTER.md | Loading commit data... | |
| LICENSE | Loading commit data... | |
| PatchBay_MultiChannel.xml | Loading commit data... | |
| PatchBay_Perf.xml | Loading commit data... | |
| PatchBay_Perf5.1.xml | Loading commit data... | |
| README.md | Loading commit data... | |
| RUNBOOK.md | Loading commit data... | |
| SHOPPING_LIST.md | Loading commit data... | |
| backlog.md | Loading commit data... | |
| bullet_train.tidal | Loading commit data... | |
| collide.sh | Loading commit data... | |
| debug.tidal | Loading commit data... | |
| didacticpatternvisualizer.pde | Loading commit data... | |
| gig-up.sh | Loading commit data... | |
| gpu-mode.sh | Loading commit data... | |
| hello.sc | Loading commit data... | |
| init_midi.sh | Loading commit data... | |
| intro.md | Loading commit data... | |
| library.txt | Loading commit data... | |
| link_jack.sh | Loading commit data... | |
| link_samples.sh | Loading commit data... | |
| link_samples_all.txt | Loading commit data... | |
| main_fairbanks.scd | Loading commit data... | |
| notes.md | Loading commit data... | |
| parvagues-sc.service | Loading commit data... | |
| perf-audio.sudoers | Loading commit data... | |
| perf-tray.py | Loading commit data... | |
| perf.sh | Loading commit data... | |
| samples.txt | Loading commit data... | |
| setlist_opal2026.txt | Loading commit data... | |
| start_and_midi.scd | Loading commit data... | |
| test.tidal | Loading commit data... |