From 500720dadfe7827220caa85905ea34404f86686e Mon Sep 17 00:00:00 2001 From: Ashley Strahle Date: Thu, 25 Jun 2026 06:43:00 +0000 Subject: [PATCH] Add visual MIDI activity indicator Flash LED 0 white for 30ms on any MIDI input. Visible without serial - helps diagnose whether MIDI is arriving when connected to iPad with Loopy Pro. --- include/led_stub.h | 6 ++++++ src/app_task.cpp | 4 ++++ src/led_stub.cpp | 36 ++++++++++++++++++++++++++++++++++++ src/main.cpp | 1 + 4 files changed, 47 insertions(+) diff --git a/include/led_stub.h b/include/led_stub.h index 4488bca..5537f37 100644 --- a/include/led_stub.h +++ b/include/led_stub.h @@ -10,6 +10,8 @@ public: virtual void set_led_state(uint8_t note, uint8_t channel, uint8_t velocity) = 0; virtual void clear_all() = 0; virtual void set_led_brightness(uint8_t brightness) = 0; + virtual void flash_activity() {} + virtual void update() {} virtual uint8_t note_to_index(uint8_t note) { return note; @@ -31,6 +33,8 @@ private: static const uint8_t NUM_LEDS = 10; LedState led_states[NUM_LEDS]; bool initialized; + uint32_t activity_off_time = 0; + uint8_t saved_r = 0, saved_g = 0, saved_b = 0; public: DefaultLedStub(); @@ -38,6 +42,8 @@ public: void set_led_state(uint8_t note, uint8_t channel, uint8_t velocity) override; void clear_all() override; void set_led_brightness(uint8_t brightness) override; + void flash_activity() override; + void update() override; void set_mux(PixelStompMux* mux); }; diff --git a/src/app_task.cpp b/src/app_task.cpp index 5398efb..b87c448 100644 --- a/src/app_task.cpp +++ b/src/app_task.cpp @@ -45,6 +45,10 @@ void AppTask::update() { void AppTask::process_midi_event(const MidiEvent& event) { Serial.printf("[APP] MIDI IN: Type=%d Ch=%d Data1=%d Data2=%d\n", event.type, event.channel, event.data1, event.data2); + + // Flash LED 0 white briefly on ANY MIDI input - visual activity indicator + // (visible without serial when connected to iPad) + led_driver->flash_activity(); uint8_t led_index = 0xFF; uint8_t midi_channel = event.channel; diff --git a/src/led_stub.cpp b/src/led_stub.cpp index 0640d16..c64b955 100644 --- a/src/led_stub.cpp +++ b/src/led_stub.cpp @@ -258,3 +258,39 @@ void DefaultLedStub::set_led_brightness(uint8_t brightness) { mux_ptr->set_led_brightness(brightness); mux_ptr->show(); } + +void DefaultLedStub::flash_activity() { + if (!initialized || !mux_ptr) return; + + uint32_t now = millis(); + + // Save current LED 0 color if we just started flashing + if (now >= activity_off_time) { + saved_r = 0; + saved_g = 0; + saved_b = 0; + if (led_states[0].active) { + uint32_t color = launchpad_palette[led_states[0].velocity]; + saved_r = (color >> 16) & 0xFF; + saved_g = (color >> 8) & 0xFF; + saved_b = color & 0xFF; + } + } + + // Flash LED 0 white + mux_ptr->set_led_color(0, 255, 255, 255); + mux_ptr->show(); + activity_off_time = now + 30; +} + +void DefaultLedStub::update() { + if (!initialized || !mux_ptr) return; + + // Turn off activity flash after 30ms + uint32_t now = millis(); + if (activity_off_time > 0 && now >= activity_off_time) { + mux_ptr->set_led_color(0, saved_r, saved_g, saved_b); + mux_ptr->show(); + activity_off_time = 0; + } +} diff --git a/src/main.cpp b/src/main.cpp index 3e83f94..76fe3de 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -367,6 +367,7 @@ void setup() { } void loop() { + led_driver.update(); controller.update(); if (Serial.available()) {