Compare commits
17
Commits
31cd488488
...
1c1fc4d372
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1c1fc4d372 | ||
|
|
ac83ba269f | ||
|
|
17c630f850 | ||
|
|
268b793d87 | ||
|
|
a281eaa46e | ||
|
|
6ccd28362f | ||
|
|
90bbfa7b84 | ||
|
|
a209b48720 | ||
|
|
c20f1dec2c | ||
|
|
c02121cd09 | ||
|
|
109106f1f1 | ||
|
|
75f583b3c4 | ||
|
|
fc9b7688c0 | ||
|
|
b380133b3e | ||
|
|
25713707aa | ||
|
|
7558082e7b | ||
|
|
dee60c7d27 |
@@ -11,7 +11,6 @@ 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) {
|
||||
@@ -36,10 +35,6 @@ 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;
|
||||
uint32_t heartbeat_time = 0;
|
||||
uint8_t heartbeat_phase = 0;
|
||||
|
||||
public:
|
||||
DefaultLedStub();
|
||||
@@ -48,7 +43,6 @@ 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);
|
||||
|
||||
@@ -21,3 +21,5 @@ monitor_speed = 115200
|
||||
|
||||
board_build.partitions = default_8MB.csv
|
||||
board_build.arduino.memory_type = qio_opi
|
||||
|
||||
extra_scripts = pre:pre_build.py
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
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()
|
||||
@@ -47,7 +47,6 @@ 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) {
|
||||
@@ -55,7 +54,6 @@ 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;
|
||||
}
|
||||
|
||||
|
||||
+2
-50
@@ -283,63 +283,15 @@ 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/SysEx flash
|
||||
// Turn off activity 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->set_led_color(0, saved_r, saved_g, saved_b);
|
||||
mux_ptr->show();
|
||||
activity_off_time = 0;
|
||||
}
|
||||
|
||||
// Heartbeat: pulse LED 9 slowly (amber)
|
||||
if (now - heartbeat_time > 2000 && !activity_off_time) {
|
||||
heartbeat_time = now;
|
||||
heartbeat_phase = 1;
|
||||
}
|
||||
if (heartbeat_phase && !activity_off_time) {
|
||||
uint8_t brightness = (heartbeat_phase < 100) ? (heartbeat_phase * 2) : (400 - heartbeat_phase * 2);
|
||||
if (!led_states[9].active) {
|
||||
mux_ptr->set_led_color(9, brightness, brightness / 4, 0);
|
||||
mux_ptr->show();
|
||||
}
|
||||
heartbeat_phase++;
|
||||
if (heartbeat_phase > 200) heartbeat_phase = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,11 +13,11 @@ UsbMidiTransport::~UsbMidiTransport() {
|
||||
bool UsbMidiTransport::begin() {
|
||||
Serial.println("[MIDI] Setting up USB MIDI device...");
|
||||
|
||||
// Novation Launchpad X identifiers so Loopy Pro recognizes us
|
||||
TinyUSBDevice.setID(0x1235, 0x0103);
|
||||
TinyUSBDevice.setManufacturerDescriptor("Novation");
|
||||
TinyUSBDevice.setProductDescriptor("Launchpad X");
|
||||
TinyUSBDevice.setSerialDescriptor("LPX00001");
|
||||
// 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");
|
||||
TinyUSBDevice.begin(0);
|
||||
|
||||
if (!usb_midi.begin()) {
|
||||
|
||||
Reference in New Issue
Block a user