diff --git a/src/app_task.cpp b/src/app_task.cpp index c7c7096..5398efb 100644 --- a/src/app_task.cpp +++ b/src/app_task.cpp @@ -56,25 +56,23 @@ void AppTask::process_midi_event(const MidiEvent& event) { // Notes 36-45 (C2-A2) map to pads 0-9 // Velocity 1-127 = color palette index if (event.type == MidiEvent::NOTE_ON || event.type == MidiEvent::NOTE_OFF) { - // Only handle channels 1-3 (Launchpad channels) if (midi_channel >= 1 && midi_channel <= 3) { for (uint8_t i = 0; i < NUM_PADS; i++) { - if (pad_mapping[i].midi_channel == midi_channel && - pad_mapping[i].midi_note == midi_note) { + if (pad_mapping[i].midi_note == midi_note) { led_index = pad_mapping[i].led_index; break; } } - + if (led_index < NUM_PADS) { uint8_t color_vel = (event.type == MidiEvent::NOTE_ON) ? midi_velocity : 0; - + led_driver->set_led_state( - pad_mapping[led_index].midi_note, - pad_mapping[led_index].midi_channel, + midi_note, + midi_channel, color_vel ); - + Serial.printf("[APP] NOTE -> LED: Ch%d Note%d Vel%d -> LED%d\n", midi_channel, midi_note, color_vel, led_index); } else { diff --git a/src/led_stub.cpp b/src/led_stub.cpp index 4059fbc..0640d16 100644 --- a/src/led_stub.cpp +++ b/src/led_stub.cpp @@ -4,41 +4,138 @@ static PixelStompMux* mux_ptr = nullptr; -// Launchpad X color palette (velocity 0-127 mapped to colors) +// Launchpad colour palette - velocity 0-127 maps to specific colours +// Key breakpoints: 0=Off, 5=Red, 13=Orange, 21=Yellow, 37=Green, 45=Cyan, 53=Blue, 81=Purple +// Values between are linear RGB gradients; 82-127 fade purple to black static const uint32_t launchpad_palette[128] = { - 0x000000, // 0: off - 0xFF0000, 0xFF0000, 0xFF0000, 0xFF0000, // 1-4: Red - 0xFF0000, 0xFF0000, 0xFF0000, 0xFF0000, // 5-8: Red - 0xFF0000, 0xFF0000, 0xFF0000, 0xFF0000, // 9-12: Red - 0xFF0000, 0xFF0000, 0xFF0000, 0xFF0000, // 13-16: Red - 0xFF6600, 0xFF6600, 0xFF6600, 0xFF6600, // 17-20: Amber - 0xFF6600, 0xFF6600, 0xFF6600, 0xFF6600, // 21-24: Amber - 0xFF6600, 0xFF6600, 0xFF6600, 0xFF6600, // 25-28: Amber - 0xFF6600, 0xFF6600, 0xFF6600, 0xFF6600, // 29-32: Amber - 0xFFFF00, 0xFFFF00, 0xFFFF00, 0xFFFF00, // 33-36: Yellow - 0xFFFF00, 0xFFFF00, 0xFFFF00, 0xFFFF00, // 37-40: Yellow - 0xFFFF00, 0xFFFF00, 0xFFFF00, 0xFFFF00, // 41-44: Yellow - 0xFFFF00, 0xFFFF00, 0xFFFF00, 0xFFFF00, // 45-48: Yellow - 0x00FF00, 0x00FF00, 0x00FF00, 0x00FF00, // 49-52: Green - 0x00FF00, 0x00FF00, 0x00FF00, 0x00FF00, // 53-56: Green - 0x00FF00, 0x00FF00, 0x00FF00, 0x00FF00, // 57-60: Green - 0x00FF00, 0x00FF00, 0x00FF00, 0x00FF00, // 61-64: Green - 0x00FF66, 0x00FF66, 0x00FF66, 0x00FF66, // 65-68: Mint - 0x00FF66, 0x00FF66, 0x00FF66, 0x00FF66, // 69-72: Mint - 0x00FF66, 0x00FF66, 0x00FF66, 0x00FF66, // 73-76: Mint - 0x00FF66, 0x00FF66, 0x00FF66, 0x00FF66, // 77-80: Mint - 0x00FFFF, 0x00FFFF, 0x00FFFF, 0x00FFFF, // 81-84: Light Blue - 0x00FFFF, 0x00FFFF, 0x00FFFF, 0x00FFFF, // 85-88: Light Blue - 0x00FFFF, 0x00FFFF, 0x00FFFF, 0x00FFFF, // 89-92: Light Blue - 0x00FFFF, 0x00FFFF, 0x00FFFF, 0x00FFFF, // 93-96: Light Blue - 0x0000FF, 0x0000FF, 0x0000FF, 0x0000FF, // 97-100: Blue - 0x0000FF, 0x0000FF, 0x0000FF, 0x0000FF, // 101-104: Blue - 0x0000FF, 0x0000FF, 0x0000FF, 0x0000FF, // 105-108: Blue - 0x0000FF, 0x0000FF, 0x0000FF, 0x0000FF, // 109-112: Blue - 0x6600FF, 0x6600FF, 0x6600FF, 0x6600FF, // 113-116: Purple - 0x6600FF, 0x6600FF, 0x6600FF, 0x6600FF, // 117-120: Purple - 0x6600FF, 0x6600FF, 0x6600FF, 0x6600FF, // 121-124: Purple - 0x6600FF, 0x6600FF, 0x6600FF, // 125-127: Purple (3 entries) + 0x000000, // 0: Off + 0x330000, // 1 + 0x660000, // 2 + 0x990000, // 3 + 0xCC0000, // 4 + 0xFF0000, // 5: Red + 0xFF1500, // 6 + 0xFF2A00, // 7 + 0xFF4000, // 8 + 0xFF5500, // 9 + 0xFF6A00, // 10 + 0xFF8000, // 11 + 0xFF9500, // 12 + 0xFFAA00, // 13: Orange + 0xFFB500, // 14 + 0xFFC000, // 15 + 0xFFCB00, // 16 + 0xFFD600, // 17 + 0xFFE100, // 18 + 0xFFEC00, // 19 + 0xFFF700, // 20 + 0xFFFF00, // 21: Yellow + 0xEFFF00, // 22 + 0xDFFF00, // 23 + 0xCFFF00, // 24 + 0xBFFF00, // 25 + 0xAFFF00, // 26 + 0x9FFF00, // 27 + 0x8FFF00, // 28 + 0x7FFF00, // 29 + 0x6FFF00, // 30 + 0x5FFF00, // 31 + 0x4FFF00, // 32 + 0x3FFF00, // 33 + 0x2FFF00, // 34 + 0x1FFF00, // 35 + 0x0FFF00, // 36 + 0x00FF00, // 37: Green + 0x00FF20, // 38 + 0x00FF40, // 39 + 0x00FF60, // 40 + 0x00FF80, // 41 + 0x00FF9F, // 42 + 0x00FFBF, // 43 + 0x00FFDF, // 44 + 0x00FFFF, // 45: Cyan + 0x00DFFF, // 46 + 0x00BFFF, // 47 + 0x009FFF, // 48 + 0x007FFF, // 49 + 0x005FFF, // 50 + 0x003FFF, // 51 + 0x001FFF, // 52 + 0x0000FF, // 53: Blue + 0x0500FF, // 54 + 0x0B00FF, // 55 + 0x1000FF, // 56 + 0x1600FF, // 57 + 0x1B00FF, // 58 + 0x2100FF, // 59 + 0x2600FF, // 60 + 0x2B00FF, // 61 + 0x3100FF, // 62 + 0x3600FF, // 63 + 0x3C00FF, // 64 + 0x4100FF, // 65 + 0x4600FF, // 66 + 0x4C00FF, // 67 + 0x5100FF, // 68 + 0x5700FF, // 69 + 0x5C00FF, // 70 + 0x6200FF, // 71 + 0x6700FF, // 72 + 0x6D00FF, // 73 + 0x7200FF, // 74 + 0x7700FF, // 75 + 0x7D00FF, // 76 + 0x8200FF, // 77 + 0x8800FF, // 78 + 0x8D00FF, // 79 + 0x9300FF, // 80 + 0x9900FF, // 81: Purple + 0x9600F9, // 82 + 0x9300F4, // 83 + 0x8F00EE, // 84 + 0x8C00E8, // 85 + 0x8900E3, // 86 + 0x8500DD, // 87 + 0x8200D8, // 88 + 0x7F00D2, // 89 + 0x7B00CC, // 90 + 0x7800C7, // 91 + 0x7500C1, // 92 + 0x7100BC, // 93 + 0x6E00B6, // 94 + 0x6B00B0, // 95 + 0x6700AB, // 96 + 0x6400A5, // 97 + 0x61009F, // 98 + 0x5D009A, // 99 + 0x5A0094, // 100 + 0x57008E, // 101 + 0x530089, // 102 + 0x500083, // 103 + 0x4D007D, // 104 + 0x490078, // 105 + 0x460072, // 106 + 0x43006D, // 107 + 0x3F0067, // 108 + 0x3C0061, // 109 + 0x39005C, // 110 + 0x350056, // 111 + 0x320050, // 112 + 0x2F004B, // 113 + 0x2B0045, // 114 + 0x280040, // 115 + 0x25003A, // 116 + 0x210034, // 117 + 0x1E002F, // 118 + 0x1B0029, // 119 + 0x170023, // 120 + 0x14001E, // 121 + 0x110018, // 122 + 0x0D0013, // 123 + 0x0A000D, // 124 + 0x070008, // 125 + 0x030002, // 126 + 0x000000, // 127: Off }; static uint32_t velocity_to_color(uint8_t velocity) { @@ -107,7 +204,8 @@ void DefaultLedStub::set_led_state(uint8_t note, uint8_t channel, uint8_t veloci if (!initialized || !mux_ptr) return; for (int i = 0; i < NUM_LEDS; i++) { - if (led_states[i].active && led_states[i].note == note && led_states[i].channel == channel) { + if (led_states[i].active && led_states[i].note == note) { + led_states[i].channel = channel; led_states[i].velocity = velocity; led_states[i].timestamp = millis(); uint32_t color = velocity_to_color(velocity); @@ -121,7 +219,6 @@ void DefaultLedStub::set_led_state(uint8_t note, uint8_t channel, uint8_t veloci } } - // Find free slot for (int i = 0; i < NUM_LEDS; i++) { if (!led_states[i].active) { led_states[i].active = true;