Initial commit: Phase 1 skeleton

This commit is contained in:
2026-06-23 08:55:42 +00:00
commit db4b63c755
8 changed files with 488 additions and 0 deletions
+110
View File
@@ -0,0 +1,110 @@
// 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;
}
}
}
+22
View File
@@ -0,0 +1,22 @@
// components/controller/app_task.h
#pragma once
#include <freertos/FreeRTOS.h>
#include <freertos/queue.h>
#include "hal/led_stub.h"
#include "hal/switch_stub.h"
// Application task parameters
struct AppTaskParams {
LedStub* led_driver;
SwitchStub* switch_driver;
QueueHandle_t midi_queue;
};
// Application task function
BaseType_t app_task(void* parameters);
// Application state management
void app_process_midi_event(const MidiEvent& event);
void app_process_switch_event(uint8_t switch_id, bool pressed);
void app_initialize_config();