Compare commits

..
1 Commits
Author SHA1 Message Date
ash 31cd488488 Remove heartbeat on pixel 9 2026-06-30 03:30:15 +00:00
6 changed files with 48 additions and 58 deletions
+4
View File
@@ -11,6 +11,7 @@ public:
virtual void clear_all() = 0;
virtual void set_led_brightness(uint8_t brightness) = 0;
virtual void flash_activity() {}
virtual void flash_sysex() {}
virtual void update() {}
virtual uint8_t note_to_index(uint8_t note) {
@@ -35,6 +36,8 @@ private:
bool initialized;
uint32_t activity_off_time = 0;
uint8_t saved_r = 0, saved_g = 0, saved_b = 0;
uint8_t sysex_saved_r[10] = {0}, sysex_saved_g[10] = {0}, sysex_saved_b[10] = {0};
bool sysex_flash_active = false;
public:
DefaultLedStub();
@@ -43,6 +46,7 @@ public:
void clear_all() override;
void set_led_brightness(uint8_t brightness) override;
void flash_activity() override;
void flash_sysex() override;
void update() override;
void set_mux(PixelStompMux* mux);
-2
View File
@@ -21,5 +21,3 @@ monitor_speed = 115200
board_build.partitions = default_8MB.csv
board_build.arduino.memory_type = qio_opi
extra_scripts = pre:pre_build.py
-49
View File
@@ -1,49 +0,0 @@
import os
import fileinput
def patch_usb_ids():
# Find the core's pins_arduino.h for ESP32-S3 DevKitC-1
core_variants = os.path.expanduser("~/.platformio/packages/framework-arduinoespressif32/variants")
if not os.path.exists(core_variants):
# Try PlatformIO default location
core_variants = os.path.join(os.environ.get("PLATFORMIO_PACKAGES_DIR", ""), "framework-arduinoespressif32", "variants")
pins_file = os.path.join(core_variants, "esp32s3_devkitc", "pins_arduino.h")
if not os.path.exists(pins_file):
# Try alternative variant name
pins_file = os.path.join(core_variants, "esp32s3", "pins_arduino.h")
if os.path.exists(pins_file):
print(f"Patching {pins_file} with Launchpad X VID/PID")
# Read and replace
with open(pins_file, 'r') as f:
content = f.read()
# Replace USB_VID and USB_PID
content = content.replace(
'#define USB_VID 0x303a',
'#define USB_VID 0x1235'
)
content = content.replace(
'#define USB_PID 0x1001',
'#define USB_PID 0x0103'
)
# Add or replace manufacturer/product
if 'USB_MANUFACTURER' not in content:
content = content.replace(
'#define USB_PID 0x0103',
'#define USB_PID 0x0103\n#define USB_MANUFACTURER "JOC"\n#define USB_PRODUCT "JOC Midi"'
)
else:
content = content.replace('USB_MANUFACTURER "Novation"', 'USB_MANUFACTURER "JOC"')
content = content.replace('USB_PRODUCT "Launchpad X"', 'USB_PRODUCT "JOC Midi"')
with open(pins_file, 'w') as f:
f.write(content)
print("USB VID/PID patched successfully")
else:
print(f"WARNING: Could not find pins_arduino.h at {pins_file}")
patch_usb_ids()
+2
View File
@@ -47,6 +47,7 @@ void AppTask::process_midi_event(const MidiEvent& event) {
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();
if (event.type == MidiEvent::SYSEX) {
@@ -54,6 +55,7 @@ void AppTask::process_midi_event(const MidiEvent& event) {
uint8_t cin = event.channel;
uint8_t packet[3] = {event.data1, event.data2, 0};
process_sysex_packet(packet, cin);
led_driver->flash_sysex();
return;
}
+36 -1
View File
@@ -283,15 +283,50 @@ void DefaultLedStub::flash_activity() {
activity_off_time = now + 50;
}
void DefaultLedStub::flash_sysex() {
if (!initialized || !mux_ptr) return;
// Save all LED states
for (int i = 0; i < NUM_LEDS; i++) {
if (led_states[i].active) {
uint32_t color = launchpad_palette[led_states[i].velocity];
sysex_saved_r[i] = (color >> 16) & 0xFF;
sysex_saved_g[i] = (color >> 8) & 0xFF;
sysex_saved_b[i] = color & 0xFF;
} else {
sysex_saved_r[i] = 0;
sysex_saved_g[i] = 0;
sysex_saved_b[i] = 0;
}
}
// Flash ALL LEDs white
for (int i = 0; i < NUM_LEDS; i++) {
mux_ptr->set_led_color(i, 255, 255, 255);
}
mux_ptr->show();
activity_off_time = now + 200;
sysex_flash_active = true;
}
void DefaultLedStub::update() {
if (!initialized || !mux_ptr) return;
uint32_t now = millis();
// Turn off activity flash
// Turn off activity/SysEx flash
if (activity_off_time > 0 && now >= activity_off_time) {
if (sysex_flash_active) {
for (int i = 0; i < NUM_LEDS; i++) {
mux_ptr->set_led_color(i, sysex_saved_r[i], sysex_saved_g[i], sysex_saved_b[i]);
}
sysex_flash_active = false;
} else {
mux_ptr->set_led_color(0, saved_r, saved_g, saved_b);
}
mux_ptr->show();
activity_off_time = 0;
}
}
+5 -5
View File
@@ -13,11 +13,11 @@ UsbMidiTransport::~UsbMidiTransport() {
bool UsbMidiTransport::begin() {
Serial.println("[MIDI] Setting up USB MIDI device...");
// Use Launchpad X VID/PID (0x1235/0x0103) so Loopy Pro recognizes us
// but with our own name
TinyUSBDevice.setManufacturerDescriptor("JOC");
TinyUSBDevice.setProductDescriptor("JOC Midi");
TinyUSBDevice.setSerialDescriptor("JOCMIDI001");
// Novation Launchpad X identifiers so Loopy Pro recognizes us
TinyUSBDevice.setID(0x1235, 0x0103);
TinyUSBDevice.setManufacturerDescriptor("Novation");
TinyUSBDevice.setProductDescriptor("Launchpad X");
TinyUSBDevice.setSerialDescriptor("LPX00001");
TinyUSBDevice.begin(0);
if (!usb_midi.begin()) {