#include "app_task.h" #include AppTask::AppTask(LedStub* led, SwitchStub* sw, UsbMidiTransport* midi) : led_driver(led), switch_driver(sw), midi_transport(midi) { // Default pad mapping for (uint8_t i = 0; i < NUM_PADS; i++) { pad_mapping[i].physical_switch = i; pad_mapping[i].midi_channel = 1; pad_mapping[i].midi_note = i; pad_mapping[i].led_index = i; last_switch_state[i] = false; } } void AppTask::begin() { Serial.println("[APP] Controller task started"); // Register MIDI callback midi_transport->on_midi_receive([this](const MidiEvent& event) { process_midi_event(event); }); } void AppTask::update() { // Poll switches for (uint8_t i = 0; i < NUM_PADS; i++) { bool is_pressed = switch_driver->is_pressed(i); if (is_pressed && !last_switch_state[i]) { process_switch_event(i, true); last_switch_state[i] = true; } else if (!is_pressed && last_switch_state[i]) { process_switch_event(i, false); last_switch_state[i] = false; } } } void AppTask::process_midi_event(const MidiEvent& event) { uint8_t led_index = 0xFF; 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 < NUM_PADS) { 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 ); Serial.printf("[APP] MIDI -> LED: Ch%d Note%d Vel%d -> LED%d\n", midi_channel, midi_note, midi_velocity, led_index); } } void AppTask::process_switch_event(uint8_t switch_id, bool pressed) { // Find mapping for this switch for (uint8_t i = 0; i < NUM_PADS; i++) { if (pad_mapping[i].physical_switch == switch_id) { uint8_t channel = pad_mapping[i].midi_channel; uint8_t note = pad_mapping[i].midi_note; uint8_t velocity = pressed ? 127 : 0; if (pressed) { midi_transport->send_note_on(channel, note, velocity); } else { midi_transport->send_note_off(channel, note, velocity); } Serial.printf("[APP] Switch %d -> Ch%d Note%d Vel%d (%s)\n", switch_id, channel, note, velocity, pressed ? "PRESS" : "RELEASE"); break; } } }