david
8e82286287
synth-diagnostic starts pipeline services, cleans up on failure
...
- run-tests.sh: starts pipeline services, runs test-unit.py,
stops services on failure, leaves running on success
- synth-diagnostic is the single gate for pipeline startup
- deploy: stop pipeline → restart prometheus → start synth-diagnostic
(synth-diagnostic starts pipeline on success)
2026-06-24 02:49:58 -07:00
david
b445c272fb
add boot-time synth-diagnostic.service
...
- synth-diagnostic.service: runs test-unit.py before pipeline services
- Type=oneshot, After=prometheus-exporter, Before=pipeline services
- Pipeline services: After=synth-diagnostic
- deploy: restart prometheus-exporter → start synth-diagnostic → restart pipeline
- install.sh: includes synth-diagnostic in SERVICES array
2026-06-24 02:48:40 -07:00
david
2e10839fc9
add diagnostic dashboard served from prometheus-exporter
...
- dashboard.html: standalone HTML, fetches :9090/metrics, auto-refresh
- Exporter serves dashboard at /dashboard and /dashboard.html
- Cards: Pipeline, Audio, Mixer, MIDI Bridge, LED Viz
- Live gauges, counters, service status dots, last-activity timestamps
2026-06-24 02:43:31 -07:00
david
74e0d3fa03
fix: use threading.Lock() instead of object() for _stats_lock
2026-06-24 02:42:06 -07:00
david
f673da4b3b
merge midi metrics into prometheus-exporter
...
midi-bridge: removed HTTP server on :9091, now writes /tmp/midi-stats.json
prometheus-exporter: reads /tmp/midi-stats.json, exposes all metrics on :9090/metrics
Single scrape endpoint for all pipeline components
2026-06-24 02:41:27 -07:00
david
7706517b88
fix: initialize stats_last_write inside main() to avoid UnboundLocalError
2026-06-24 02:39:37 -07:00
david
ad55dbc5e0
add viz diagnostic metrics to prometheus-exporter
...
- Viz writes stats to /tmp/viz-stats.json (frames_sent, frames_dropped, queue_depth)
- Exporter reads viz-stats.json and exposes:
- viz_frames_sent_total (counter)
- viz_frames_dropped_total (counter)
- viz_pending_queue (gauge)
- viz_queue_full (gauge)
2026-06-24 02:38:51 -07:00
david
5c95aa6cd0
viz: proper POLLOUT queue to prevent frame drops
...
- FrameQueue (max 5) buffers frames when router is slow
- POLLOUT drains pending_frames queue
- No silent drops — full queue increments counter
- Router always registered POLLIN| POLLOUT
- Frame interval 30ms (33 FPS)
2026-06-24 02:37:46 -07:00
david
272a13f8d9
viz: increase FPS to 30, drain UDP aggressively
...
- Poll timeout capped at 10ms for responsiveness
- Drain all pending UDP data before parsing
- Auto-reconnect router on error
- FPS 15 -> 30
2026-06-24 02:33:17 -07:00
david
caef6f04c8
midi-bridge: add prometheus metrics on :9091/metrics
...
- midi_messages_total: all MIDI messages
- midi_notes_on/off_total: note-on/off counts
- midi_last_status/note/velocity: last message tokens
- midi_last_time_unix: epoch of last message
- Removed MIDI counters from prometheus-exporter (bridge owns them)
2026-06-24 02:25:31 -07:00
david
163ad4145b
add prometheus exporter + test suite
...
- prometheus-exporter.py: stdlib-only HTTP metrics on :9090/metrics
- Exposes: ALSA status, hw_ptr rate, service health, mixer controls
- MIDI counters: notes_on, notes_off, errors
- test-unit.py: 10-test suite covering full MIDI→Pd→Audio pipeline
- test-tone.pd, test-midi-log.pd: minimal debug patches
- systemd service for exporter
- install.sh/deploy updated to include exporter
2026-06-24 02:22:05 -07:00
david
3cc497f632
refactor: 3-module pd architecture + viz non-blocking fix
...
- midi-in.pd: netreceive -> route -> unpack -> pitch/velocity outlets
- audio-out.pd: inlet~ -> dac~ abstraction
- synth.pd: consumer patch wiring midi-in -> voice -> audio-out
- led-matrix-viz.py: router socket non-blocking, registered with poller
- pd.rego: skip outlet/abstraction false positives in validation
2026-06-24 02:08:57 -07:00
david
242c74236f
systemd services: midi-bridge, pd-synth-onboard, led-matrix-viz + install script
2026-06-24 01:36:36 -07:00
david
f919af3d8b
midi-bridge: normalize all MIDI channels to channel 1
2026-06-24 00:50:39 -07:00
david
ed8cb7ca5a
working synth: two detuned oscs, env~, lop~ (no slider for now)
2026-06-24 00:45:37 -07:00
david
ccc40e4314
rebuild synth.pd from working components
2026-06-23 22:17:02 -07:00
david
e098f32a32
fix synth: envelope driven by velocity not pitch, louder gain
2026-06-23 21:58:10 -07:00
david
7e8848d23c
justfile: git-based deploy, streamlined recipes
2026-06-23 21:29:16 -07:00
david
d239d58c44
onboard audio: JMISC HPH wiring, UCM fix, update scripts for git deploy
2026-06-23 21:25:51 -07:00
david
a135dc4452
controller.pd: add MIDI passthrough for MPK Mini → board
...
Added notein→pack→noteout and ctlin→ctlout chains that forward all
incoming MIDI from the MPK Mini to the board's MIDI port. This means
physical keys/knobs now work alongside the GUI click buttons.
2026-06-23 14:44:05 -07:00
david
334e934dd7
stabilize systemd services: fix races, masked flooding, dependencies
...
- pd-synth: add After=usb-gadget-audio.service midi-bridge.service (was Wants= only, race)
- usb-gadget-audio: add Restart=on-failure After=sysinit.target
- pd-synth-i2s: fix Wants=configure-usb-audio.service → usb-gadget-audio.service
- detect-usb-role.sh: hardcode gadget role (all 4 detection methods always fail, skip 2s sleep)
- arduino-router-serial: masked on board (flooded 2173× restarts looking for nonexistent /dev/ttyGS0)
2026-06-23 14:31:11 -07:00
david
f1b65eb4d9
fix led-matrix-viz: use select.poll() instead of settimeout, fix hang
...
The O_NONBLOCK flag set by setblocking(False) was not cleared by
settimeout(n) on this CPython/kernel combo, causing recvfrom to never
return data. Switched to explicit select.poll() with frame-interval
based timeout — simpler, more portable, and avoids the O_NONBLOCK trap.
Also fixes midi-bridge: add time.sleep(0.01) in no-data paths to
prevent 100% CPU spin from spurious POLLIN on f_midi rawmidi.
2026-06-23 00:34:33 -07:00
david
dbd7c2cece
auto-detect MIDI device, drop ALSA sequencer dependency, MPK Mini simulator
...
midi-bridge.py:
- Auto-detect rawmidi device (gadget f_midi > env override > fallback)
- Reconnect on ENODEV (device hotplug)
- No longer needs MIDI_BRIDGE_DEV env var in common cases
start-synth.sh:
- Remove all -alsamidi/-midiadddev flags (kernel lacks CONFIG_SND_SEQUENCER)
- MIDI handled entirely by midi-bridge.service → UDP → netreceive
- Host mode: same approach, no ALSA sequencer needed
mpk-mini-sim.pd:
- New MPK Mini Mk II simulator (25 keys, 8 pads, 8 CC knobs)
- Proper Pd #X obj format for all objects (bng, hsl, t, del, netsend, loadbang)
- UDP output to board:8081, matching midi-bridge format
system: enable usb-gadget-audio.service at boot, load dwc3 module at boot
2026-06-22 23:10:38 -07:00
david
8cd796e3dd
Initial commit: Arduino Uno Q USB Audio Synth project
...
- USB gadget (UAC1 + MIDI) with boot persistence
- USB host mode with auto-detection
- Pure Data synth patch with ALSA + UDP netreceive MIDI input
- MIDI rawmidi-to-UDP bridge (midi-bridge.py)
- LED matrix visualization (led-matrix-viz.py via arduino-router RPC)
- MCU sketch for LED matrix control (Arduino_RouterBridge + ArduinoGraphics)
- Conftest/OPA Rego policy validation suite for .pd files
- gen_synth_pd.py: programmatic .pd file generator
- System services: midi-bridge, led-matrix-viz, pd-synth-auto, usb-role-detect
- Justfile with deploy, enable, diagnostic recipes
- Diagnostic script (diag.sh)
2026-06-22 22:46:36 -07:00