Root cause: Arduino Core 3.x breaks cross-core NimBLE API calls.
Calling BLEMidiServer.controlChange() from loop() on Core 1 while
NimBLE host runs on Core 0 causes immediate crash.
Fix:
- Move ble_midi_transport.begin() to ble_init_task on Core 0
- All BLE MIDI sends use queue_cc() (cross-core safe flag setter)
- ble_midi_transport.update() processes queued sends on Core 0
- Pin NimBLE-Arduino to v1.4.3 (stable LTS for BLE MIDI)
- Keep CONFIG_BT_ENABLED out of sdkconfig.h (causes double-init)
Replace direct NimBLE-Arduino dependency with max22/ESP32-BLE-MIDI
wrapper library (v0.3.2). Rewrite ble_midi_transport to use
BLEMidiServer API instead of raw NimBLEDevice calls.
Removes patch_nimble_device() from pre_build.py — no longer needed
since BT controller init is managed by the library internally.
The library uses NimBLE v1.4.1 internally and configures advertising
without setScanResponse() or setName(), which may resolve the invisible
BLE advertising issue on ESP32-S3.
- variants/esp32s3/pins_arduino.h overrides USB_VID/USB_PID
- Included via -I in build_flags before core variant
- This should force USB descriptors at hardware level
- Set USB VID/PID via ESP32 core build flags (may work better than TinyUSB API)
- Heartbeat on LED 9 (amber pulse every 2s) confirms device is alive
- SysEx flashes ALL LEDs white for 200ms
- Regular MIDI flashes LED 0 white for 50ms
FastLED has better ESP32 support and handles timing/RMT properly.
- Use CRGB array instead of Adafruit_NeoPixel
- FastLED.show() is more reliable on ESP32-S3
- probe command now tests all LEDs at max brightness
PixelStomp MUX uses:
- WS2812C LEDs: one data line via DAT (GPIO 9), NeoPixel protocol
- 74HC165 shift register: LD/CLK/DI for reading 8 button states
Changes:
- Use Adafruit NeoPixel library for LED control
- Proper 74HC165 parallel-load shift-in for buttons
- 8 switches + 8 LEDs (was incorrectly 10)
- Diagnostic commands: dump, ledtest, red, green, blue, read
- Replace ESP-IDF structure with PlatformIO (platformio.ini)
- Move source files to src/ and include/
- Move libraries to lib/ directory
- Replace FreeRTOS with Arduino task/vTaskDelay
- Use Arduino MIDI library instead of raw TinyUSB
- Dual-core: MIDI on core 0, controller on core 1