// components/controller/app_task.cpp #include "controller/app_task.h" #include "midi/midi_transport.h" #include "esp_log.h" static const char* TAG = "app_task"; // Simple pad mapping table (Phase 1 - modifiable) struct PadMapping { uint8_t physical_switch; // 0-9 uint8_t midi_channel; // 1-3 uint8_t midi_note; // Note number (configurable) uint8_t led_index; // LED index (0-9) }; static PadMapping pad_mapping[] = { {0, 1, 0, 0}, // Switch 0 -> Channel 1, Note 0, LED 0 {1, 1, 1, 1}, // Switch 1 -> Channel 1, Note 1, LED 1 {2, 1, 2, 2}, // Switch 2 -> Channel 1, Note 2, LED 2 {3, 1, 3, 3}, // Switch 3 -> Channel 1, Note 3, LED 3 {4, 1, 4, 4}, // Switch 4 -> Channel 1, Note 4, LED 4 {5, 1, 5, 5}, // Switch 5 -> Channel 1, Note 5, LED 5 {6, 1, 6, 6}, // Switch 6 -> Channel 1, Note 6, LED 6 {7, 1, 7, 7}, // Switch 7 -> Channel 1, Note 7, LED 7 {8, 1, 8, 8}, // Switch 8 -> Channel 1, Note 8, LED 8 {9, 1, 9, 9}, // Switch 9 -> Channel 1, Note 9, LED 9 }; static const uint8_t NUM_PADS = sizeof(pad_mapping) / sizeof(pad_mapping[0]); BaseType_t app_task(void* parameters) { AppTaskParams* params = (AppTaskParams*)parameters; ESP_LOGI(TAG, "Controller task started"); while (true) { // Check for MIDI events MidiEvent midi_event; if (xQueueReceive(params->midi_queue, &midi_event, 0) == pdPASS) { app_process_midi_event(midi_event, params->led_driver); } // Check for switch events (Phase 1 stub) for (uint8_t i = 0; i < NUM_PADS; i++) { bool is_pressed = params->switch_driver->is_pressed(i); static bool last_state[10] = {false}; if (is_pressed && !last_state[i]) { // Switch press detected app_process_switch_event(i, true); last_state[i] = true; } else if (!is_pressed && last_state[i]) { // Switch release detected app_process_switch_event(i, false); last_state[i] = false; } } vTaskDelay(pdMS_TO_TICKS(10)); // 10ms task period } } void app_process_midi_event(const MidiEvent& event, LedStub* led_driver) { // Convert MIDI event to LED command // This is where we map MIDI to LED state uint8_t led_index = -1; uint8_t midi_channel = event.channel; uint8_t midi_note = event.data1; uint8_t midi_velocity = event.data2; // Find matching LED index from pad mapping for (uint8_t i = 0; i < NUM_PADS; i++) { if (pad_mapping[i].midi_channel == midi_channel && pad_mapping[i].midi_note == midi_note) { led_index = pad_mapping[i].led_index; break; } } if (led_index != 255) { // Trigger LED state change led_driver->set_led_state( pad_mapping[led_index].midi_note, pad_mapping[led_index].midi_channel, event.type == MidiEvent::NOTE_ON ? midi_velocity : 0 ); ESP_LOGI(TAG, "MIDI PROCESSED: Channel %d Note %d Velocity %d -> LED %d", midi_channel, midi_note, midi_velocity, led_index); } } void app_process_switch_event(uint8_t switch_id, bool pressed) { // Convert switch event to MIDI event MidiEvent midi_event; // Find mapping for this switch for (uint8_t i = 0; i < NUM_PADS; i++) { if (pad_mapping[i].physical_switch == switch_id) { midi_event.channel = pad_mapping[i].midi_channel; midi_event.data1 = pad_mapping[i].midi_note; midi_event.data2 = pressed ? 127 : 0; // Full velocity for press midi_event.type = pressed ? MidiEvent::NOTE_ON : MidiEvent::NOTE_OFF; ESP_LOGI(TAG, "SWITCH EVENT: Switch %d -> Channel %d Note %d Velocity %d", switch_id, midi_event.channel, midi_event.data1, midi_event.data2); break; } } }