diff --git a/include/ble_midi_transport.h b/include/ble_midi_transport.h index 105ca63..eedd1c4 100644 --- a/include/ble_midi_transport.h +++ b/include/ble_midi_transport.h @@ -20,6 +20,8 @@ public: bool is_connected(); + void queue_cc(uint8_t channel, uint8_t cc, uint8_t value); + private: static void on_control_change(uint8_t channel, uint8_t controller, uint8_t value, uint16_t timestamp); static void on_note_on(uint8_t channel, uint8_t note, uint8_t velocity, uint16_t timestamp); @@ -30,4 +32,9 @@ private: std::function receive_callback; bool initialized; bool client_connected; + + uint8_t queued_channel; + uint8_t queued_cc; + uint8_t queued_value; + bool queued; }; diff --git a/platformio.ini b/platformio.ini index a9fe930..23a202c 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,6 +9,7 @@ lib_deps = adafruit/Adafruit TinyUSB Library@3.1.0 fastled/FastLED@^3.9.0 max22/ESP32-BLE-MIDI@^0.3.2 + h2zero/NimBLE-Arduino@^1.4.3 build_unflags = -DARDUINO_USB_MODE=1 diff --git a/pre_build.py b/pre_build.py index 01b6bdf..2a8e9b6 100644 --- a/pre_build.py +++ b/pre_build.py @@ -70,10 +70,6 @@ def patch_sdkconfig_bt(): content = f.read() defines = { - # Do NOT set CONFIG_BT_ENABLED here — forces Arduino framework - # to pre-init BT controller at startup, which conflicts with - # TinyUSB on ESP32-S3 (causes reboot on USB MIDI send). - # NimBLEDevice::init() handles its own init. "CONFIG_BTDM_CTRL_MODE_BLE_ONLY": 1, "CONFIG_BT_NIMBLE_MAX_CONNECTIONS": 1, "CONFIG_BT_NIMBLE_TASK_STACK_SIZE": 6144, diff --git a/src/app_task.cpp b/src/app_task.cpp index cc3d152..937a9be 100644 --- a/src/app_task.cpp +++ b/src/app_task.cpp @@ -54,7 +54,7 @@ void AppTask::update() { pending_cc = false; delay(1); usb_midi->send_cc(pending_channel, pending_cc_num, pending_value); - if (ble_midi) ble_midi->send_cc(pending_channel, pending_cc_num, pending_value); + if (ble_midi) ble_midi->queue_cc(pending_channel, pending_cc_num, pending_value); } } diff --git a/src/ble_midi_transport.cpp b/src/ble_midi_transport.cpp index 9db54f8..7b8d515 100644 --- a/src/ble_midi_transport.cpp +++ b/src/ble_midi_transport.cpp @@ -4,7 +4,7 @@ static BleMidiTransport* instance = nullptr; -BleMidiTransport::BleMidiTransport() : initialized(false), client_connected(false) { +BleMidiTransport::BleMidiTransport() : initialized(false), client_connected(false), queued(false) { instance = this; } @@ -70,24 +70,34 @@ bool BleMidiTransport::begin() { void BleMidiTransport::update() { client_connected = BLEMidiServer.isConnected(); + + if (queued) { + queued = false; + BLEMidiServer.controlChange(queued_channel, queued_cc, queued_value); + } } void BleMidiTransport::on_midi_receive(std::function callback) { receive_callback = callback; } +void BleMidiTransport::queue_cc(uint8_t channel, uint8_t cc, uint8_t value) { + queued_channel = channel; + queued_cc = cc; + queued_value = value; + queued = true; +} + void BleMidiTransport::send_note_on(uint8_t channel, uint8_t note, uint8_t velocity) { - BLEMidiServer.noteOn(channel, note, velocity); - Serial.printf("[BLE OUT] Ch:%d NOTE_ON:%d:%d\n", channel, note, velocity); + queue_cc(channel, note, velocity); } void BleMidiTransport::send_note_off(uint8_t channel, uint8_t note, uint8_t velocity) { - BLEMidiServer.noteOff(channel, note, velocity); - Serial.printf("[BLE OUT] Ch:%d NOTE_OFF:%d:%d\n", channel, note, velocity); + queue_cc(channel, note, velocity); } void BleMidiTransport::send_cc(uint8_t channel, uint8_t cc, uint8_t value) { - BLEMidiServer.controlChange(channel, cc, value); + queue_cc(channel, cc, value); } bool BleMidiTransport::is_connected() { diff --git a/src/main.cpp b/src/main.cpp index 4aee710..6818fb9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -23,6 +23,13 @@ AppTask controller(&led_driver, &switch_driver, &midi_transport, &ble_midi_trans TaskHandle_t midi_task_handle = NULL; +void ble_init_task(void* parameter) { + Serial.println("[TASK] BLE init task started on core 0"); + ble_midi_transport.begin(); + Serial.println("[TASK] BLE init complete, deleting task"); + vTaskDelete(NULL); +} + void midi_task(void* parameter) { Serial.println("[TASK] MIDI task started on core 0"); @@ -346,16 +353,23 @@ void setup() { switch_driver.set_mux(&mux); switch_driver.begin(); - Serial.println("[INIT] Initializing BLE MIDI..."); - delay(1000); - ble_midi_transport.begin(); - Serial.println("[INIT] Initializing USB MIDI..."); midi_transport.begin(); delay(500); Serial.println("[INIT] Registering MIDI callbacks..."); controller.begin(); + + Serial.println("[INIT] Starting BLE init on core 0..."); + xTaskCreatePinnedToCore( + ble_init_task, + "ble_init", + 8192, + NULL, + 3, + NULL, + 0 + ); xTaskCreatePinnedToCore( midi_task,