Fix Launchpad mode MIDI receive and color palette

- Fixed note matching bug: removed channel check so notes 36-45 match
  across channels 1-3 (Launchpad static/flashing/pulsing)
- Simplified LED lookup to match by note only (channel stored for mode)
- Replaced sparse palette with proper RGB gradients between key
  breakpoints (Red, Orange, Yellow, Green, Cyan, Blue, Purple, Off)
This commit is contained in:
2026-06-25 06:31:16 +00:00
parent fee8ab5b94
commit 40dfe775ea
2 changed files with 139 additions and 44 deletions
+6 -8
View File
@@ -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 {
+133 -36
View File
@@ -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;