Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
31cd488488 |
@@ -11,6 +11,7 @@ public:
|
|||||||
virtual void clear_all() = 0;
|
virtual void clear_all() = 0;
|
||||||
virtual void set_led_brightness(uint8_t brightness) = 0;
|
virtual void set_led_brightness(uint8_t brightness) = 0;
|
||||||
virtual void flash_activity() {}
|
virtual void flash_activity() {}
|
||||||
|
virtual void flash_sysex() {}
|
||||||
virtual void update() {}
|
virtual void update() {}
|
||||||
|
|
||||||
virtual uint8_t note_to_index(uint8_t note) {
|
virtual uint8_t note_to_index(uint8_t note) {
|
||||||
@@ -35,6 +36,8 @@ private:
|
|||||||
bool initialized;
|
bool initialized;
|
||||||
uint32_t activity_off_time = 0;
|
uint32_t activity_off_time = 0;
|
||||||
uint8_t saved_r = 0, saved_g = 0, saved_b = 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:
|
public:
|
||||||
DefaultLedStub();
|
DefaultLedStub();
|
||||||
@@ -43,6 +46,7 @@ public:
|
|||||||
void clear_all() override;
|
void clear_all() override;
|
||||||
void set_led_brightness(uint8_t brightness) override;
|
void set_led_brightness(uint8_t brightness) override;
|
||||||
void flash_activity() override;
|
void flash_activity() override;
|
||||||
|
void flash_sysex() override;
|
||||||
void update() override;
|
void update() override;
|
||||||
|
|
||||||
void set_mux(PixelStompMux* mux);
|
void set_mux(PixelStompMux* mux);
|
||||||
|
|||||||
@@ -21,5 +21,3 @@ monitor_speed = 115200
|
|||||||
|
|
||||||
board_build.partitions = default_8MB.csv
|
board_build.partitions = default_8MB.csv
|
||||||
board_build.arduino.memory_type = qio_opi
|
board_build.arduino.memory_type = qio_opi
|
||||||
|
|
||||||
extra_scripts = pre:pre_build.py
|
|
||||||
|
|||||||
@@ -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()
|
|
||||||
@@ -47,6 +47,7 @@ void AppTask::process_midi_event(const MidiEvent& event) {
|
|||||||
event.type, event.channel, event.data1, event.data2);
|
event.type, event.channel, event.data1, event.data2);
|
||||||
|
|
||||||
// Flash LED 0 white briefly on ANY MIDI input - visual activity indicator
|
// Flash LED 0 white briefly on ANY MIDI input - visual activity indicator
|
||||||
|
// (visible without serial when connected to iPad)
|
||||||
led_driver->flash_activity();
|
led_driver->flash_activity();
|
||||||
|
|
||||||
if (event.type == MidiEvent::SYSEX) {
|
if (event.type == MidiEvent::SYSEX) {
|
||||||
@@ -54,6 +55,7 @@ void AppTask::process_midi_event(const MidiEvent& event) {
|
|||||||
uint8_t cin = event.channel;
|
uint8_t cin = event.channel;
|
||||||
uint8_t packet[3] = {event.data1, event.data2, 0};
|
uint8_t packet[3] = {event.data1, event.data2, 0};
|
||||||
process_sysex_packet(packet, cin);
|
process_sysex_packet(packet, cin);
|
||||||
|
led_driver->flash_sysex();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+36
-1
@@ -283,15 +283,50 @@ void DefaultLedStub::flash_activity() {
|
|||||||
activity_off_time = now + 50;
|
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() {
|
void DefaultLedStub::update() {
|
||||||
if (!initialized || !mux_ptr) return;
|
if (!initialized || !mux_ptr) return;
|
||||||
|
|
||||||
uint32_t now = millis();
|
uint32_t now = millis();
|
||||||
|
|
||||||
// Turn off activity flash
|
// Turn off activity/SysEx flash
|
||||||
if (activity_off_time > 0 && now >= activity_off_time) {
|
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();
|
mux_ptr->show();
|
||||||
activity_off_time = 0;
|
activity_off_time = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,11 +13,11 @@ UsbMidiTransport::~UsbMidiTransport() {
|
|||||||
bool UsbMidiTransport::begin() {
|
bool UsbMidiTransport::begin() {
|
||||||
Serial.println("[MIDI] Setting up USB MIDI device...");
|
Serial.println("[MIDI] Setting up USB MIDI device...");
|
||||||
|
|
||||||
// Use Launchpad X VID/PID (0x1235/0x0103) so Loopy Pro recognizes us
|
// Novation Launchpad X identifiers so Loopy Pro recognizes us
|
||||||
// but with our own name
|
TinyUSBDevice.setID(0x1235, 0x0103);
|
||||||
TinyUSBDevice.setManufacturerDescriptor("JOC");
|
TinyUSBDevice.setManufacturerDescriptor("Novation");
|
||||||
TinyUSBDevice.setProductDescriptor("JOC Midi");
|
TinyUSBDevice.setProductDescriptor("Launchpad X");
|
||||||
TinyUSBDevice.setSerialDescriptor("JOCMIDI001");
|
TinyUSBDevice.setSerialDescriptor("LPX00001");
|
||||||
TinyUSBDevice.begin(0);
|
TinyUSBDevice.begin(0);
|
||||||
|
|
||||||
if (!usb_midi.begin()) {
|
if (!usb_midi.begin()) {
|
||||||
|
|||||||
Reference in New Issue
Block a user