diff --git a/MidiDriver.cpp b/MidiDriver.cpp index 8605eec..d614f9e 100644 --- a/MidiDriver.cpp +++ b/MidiDriver.cpp @@ -2,19 +2,83 @@ // MIDI UART Pins (GP0/GP1) #define PIN_MIDI_TX 0 +#define PIN_MIDI_RX 1 MidiDriver midi; -MidiDriver::MidiDriver() { +MidiDriver::MidiDriver() : lastInputNote(-1), lastInputVelocity(0), _runningStatus(0), _byteIndex(0), _data1(0), _data2(0) { } void MidiDriver::begin() { mutex_init(&_mutex); Serial1.setTX(PIN_MIDI_TX); + Serial1.setRX(PIN_MIDI_RX); Serial1.begin(31250); Serial.println(F("MIDI Serial initialized on GP0/GP1")); } +void MidiDriver::update() { + while (Serial1.available()) { + uint8_t b = Serial1.read(); + Serial1.write(b); // Soft THRU: Merge input with output + + // Realtime messages don't affect running status + if (b >= 0xF8) continue; + + if (b >= 0x80) { + _runningStatus = b; + _byteIndex = 0; + } else if (_runningStatus) { + if (_byteIndex == 0) { + _data1 = b; + _byteIndex++; + + // Handle 2-byte messages (Program Change 0xC0, Channel Pressure 0xD0) + uint8_t type = _runningStatus & 0xF0; + if (type == 0xC0 || type == 0xD0) { + _byteIndex = 0; // Message complete + } + } else if (_byteIndex == 1) { + _data2 = b; + _byteIndex = 0; // Message complete + + uint8_t channel = (_runningStatus & 0x0F) + 1; + uint8_t type = _runningStatus & 0xF0; + if (type == 0x90) { + if (_data2 > 0) { + // Serial.print(F("Note On CH")); + // Serial.print(channel); + // Serial.print(F(": ")); + // Serial.print(_data1); + // Serial.print(F(" Vel: ")); + // Serial.println(_data2); + lastInputNote = _data1; + lastInputVelocity = _data2; + } else { + // Serial.print(F("Note Off CH")); + // Serial.print(channel); + // Serial.print(F(": ")); + // Serial.println(_data1); + if (lastInputNote == _data1) { + lastInputNote = -1; // Note On vel 0 is Note Off + lastInputVelocity = 0; + } + } + } else if (type == 0x80) { + // Serial.print(F("Note Off CH")); + // Serial.print(channel); + // Serial.print(F(": ")); + // Serial.println(_data1); + if (lastInputNote == _data1) { + lastInputNote = -1; + lastInputVelocity = 0; + } + } + } + } + } +} + void MidiDriver::lock() { mutex_enter_blocking(&_mutex); } diff --git a/MidiDriver.h b/MidiDriver.h index 4fb1673..afa1c9f 100644 --- a/MidiDriver.h +++ b/MidiDriver.h @@ -8,6 +8,10 @@ class MidiDriver { public: MidiDriver(); void begin(); + void update(); + + volatile int lastInputNote; + volatile int lastInputVelocity; void sendNoteOn(uint8_t note, uint8_t velocity, uint8_t channel); void sendNoteOff(uint8_t note, uint8_t channel); @@ -19,6 +23,10 @@ public: private: mutex_t _mutex; + uint8_t _runningStatus; + uint8_t _byteIndex; + uint8_t _data1; + uint8_t _data2; }; extern MidiDriver midi; diff --git a/PlaybackThread.cpp b/PlaybackThread.cpp index 29f278c..b1150ef 100644 --- a/PlaybackThread.cpp +++ b/PlaybackThread.cpp @@ -129,6 +129,7 @@ static void handlePlayback() { } void loopPlayback() { + midi.update(); if (needsPanic) { for (int i=0; i