- Detect 0xF8 in midi_transport.cpp (runs on Core 0)
- Every 24th tick = beat, flash pixel 6 white
- Instant-on, quadratic fade over 80ms, restore to dim
- All FastLED calls stay on Core 0, no cross-core conflict
- New MidiClock module: tracks 24 PPQN clock ticks, computes beat phase
and smooth sine pulse from incoming MIDI Clock (0xF8)
- midi_transport: detect CIN=0xF real-time packets, route 0xF8 to
MidiClock::tick(), 0xFA/FB to start(), 0xFC to stop()
- led_stub update(): every 20ms, modulates active LED brightness
using pulse curve (50%-100%), pixel 6 always throbs when clock
is running even if no loops active
- Aligned set_led_state() all paths to use pad_base_colors
- Removed dead activity flash code
Latency sources fixed:
- debounce 50ms -> 5ms (switch_stub.cpp:15)
- Removed [MIDI OUT] Serial.printf from send_cc() (midi_transport.cpp:93-98)
- Removed [APP] Switch pressed/released prints from update() (app_task.cpp:39,43)
- Removed [APP] Switch -> CC print from process_switch_event() (app_task.cpp:140-143)
- loop() delay 10ms -> 1ms (main.cpp:390)
Serial output at 115200 baud was taking 2-5ms per printf call
in the critical button-to-MIDI path, adding 7-15ms+ total latency
per button press. All removed from hot path.
- Removed flash_sysex/flash_all/flash_one (conflicted with heartbeat)
- Simplified flash_activity: LED 0 white 50ms, restores properly
- Heartbeat only on LED 9 when no activity
- USB renamed: Manufacturer=JOC, Product=JOC Midi
- Interface 1 (DAW): Button presses -> Loopy Pro
- Interface 2 (MIDI): SysEx + LED control <- Loopy Pro
- Both interfaces polled in update()
- Sends on DAW interface (like real Launchpad X)
Change USB device descriptor to VID 0x1235 PID 0x0103
so Loopy Pro recognizes the device as a Launchpad X
and sends LED control MIDI in Launchpad mode.
- Remove TinyUSBDevice.begin() conflict with Arduino core
- Switch stub now reads GPIO with debounce (pins 1-10)
- LED stub now drives GPIO pins (pins 11-20) with startup animation
- All pins printed to console on init