better BLE MIDI parser (incl SysEx)

This commit is contained in:
lathoub 2020-03-09 22:52:10 +01:00
parent f78f5a8f9c
commit 42cd91d79b
3 changed files with 72 additions and 20 deletions

View File

@ -45,6 +45,8 @@ public:
{ {
mBleClass.begin(mDeviceName, this); mBleClass.begin(mDeviceName, this);
// To communicate between the 2 cores.
// Core_0 runs here, core_1 runs the BLE stack
mRxQueue = xQueueCreate(Settings::MaxBufferSize, sizeof(uint8_t)); mRxQueue = xQueueCreate(Settings::MaxBufferSize, sizeof(uint8_t));
} }
@ -101,18 +103,6 @@ public:
return mRxIndex; return mRxIndex;
} }
private:
void reverse(byte arr[], int n)
{
for (int low = 0, high = n - 1; low < high; low++, high--)
{
int temp = arr[low];
arr[low] = arr[high];
arr[high] = temp;
}
}
public: public:
QueueHandle_t mRxQueue; QueueHandle_t mRxQueue;

View File

@ -27,12 +27,12 @@ MIDI_NAMESPACE::MidiInterface<BLEMIDI_t> MIDI((BLEMIDI_t &)Name);
/*! \brief Create an instance for ESP32 named <DeviceName> /*! \brief Create an instance for ESP32 named <DeviceName>
*/ */
#define BLEMIDI_CREATE_ESP32_INSTANCE(DeviceName) \ #define BLEMIDI_CREATE_ESP32_INSTANCE(DeviceName) \
BLEMIDI_CREATE_INSTANCE(BLEMIDI_NAMESPACE::BLEMIDI_ESP32, DeviceName, bm); BLEMIDI_CREATE_INSTANCE(BLEMIDI_NAMESPACE::BLEMIDI_ESP32, DeviceName, bm);
/*! \brief Create a default instance for ESP32 named BLE-MIDI /*! \brief Create a default instance for ESP32 named BLE-MIDI
*/ */
#define BLEMIDI_CREATE_DEFAULT_ESP32_INSTANCE() \ #define BLEMIDI_CREATE_DEFAULT_ESP32_INSTANCE() \
BLEMIDI_CREATE_ESP32_INSTANCE("BLE-MIDI") BLEMIDI_CREATE_ESP32_INSTANCE("BLE-MIDI")
END_BLEMIDI_NAMESPACE END_BLEMIDI_NAMESPACE

View File

@ -24,18 +24,80 @@ public:
bool begin(const char*, BLEMIDI<class BLEMIDI_ESP32>*); bool begin(const char*, BLEMIDI<class BLEMIDI_ESP32>*);
void write(uint8_t* data, uint8_t length) void write(uint8_t* buffer, size_t length)
{ {
_characteristic->setValue(data, length); _characteristic->setValue(buffer, length);
_characteristic->notify(); _characteristic->notify();
} }
void receive(uint8_t* buffer, size_t length) void receive(uint8_t* buffer, size_t length)
{ {
// Post the items to the back of the queue // Pointers used to search through payload.
// (drop the first 2 items) uint8_t lPtr = 0;
for (size_t i = 2; i < length; i++) uint8_t rPtr = 0;
xQueueSend(_bleMidiTransport->mRxQueue, &buffer[i], portMAX_DELAY); // lastStatus used to capture runningStatus
uint8_t lastStatus;
// Decode first packet -- SHALL be "Full MIDI message"
lPtr = 2; //Start at first MIDI status -- SHALL be "MIDI status"
//While statement contains incrementing pointers and breaks when buffer size exceeded.
while (true)
{
lastStatus = buffer[lPtr];
if( (buffer[lPtr] < 0x80))
return; // Status message not present, bail
// Point to next non-data byte
rPtr = lPtr;
while( (buffer[rPtr + 1] < 0x80) && (rPtr < (length - 1)) )
rPtr++;
if (buffer[rPtr + 1] == 0xF7) rPtr++;
// look at l and r pointers and decode by size.
if( rPtr - lPtr < 1 ) {
// Time code or system
xQueueSend(_bleMidiTransport->mRxQueue, &buffer[lPtr], portMAX_DELAY);
} else if( rPtr - lPtr < 2 ) {
xQueueSend(_bleMidiTransport->mRxQueue, &buffer[lPtr], portMAX_DELAY);
xQueueSend(_bleMidiTransport->mRxQueue, &buffer[lPtr + 1], portMAX_DELAY);
} else if( rPtr - lPtr < 3 ) {
xQueueSend(_bleMidiTransport->mRxQueue, &buffer[lPtr], portMAX_DELAY);
xQueueSend(_bleMidiTransport->mRxQueue, &buffer[lPtr + 1], portMAX_DELAY);
xQueueSend(_bleMidiTransport->mRxQueue, &buffer[lPtr + 2], portMAX_DELAY);
} else {
// Too much data
// If not System Common or System Real-Time, send it as running status
switch(buffer[lPtr] & 0xF0)
{
case 0x80:
case 0x90:
case 0xA0:
case 0xB0:
case 0xE0:
// for (auto i = lPtr; i < rPtr; i = i + 2)
// transmitMIDIonDIN( lastStatus, buffer[i + 1], buffer[i + 2] );
break;
case 0xC0:
case 0xD0:
// for (auto i = lPtr; i < rPtr; i = i + 1)
// transmitMIDIonDIN( lastStatus, buffer[i + 1], 0 );
break;
case 0xF0:
xQueueSend(_bleMidiTransport->mRxQueue, &buffer[lPtr], portMAX_DELAY);
for (auto i = lPtr; i < rPtr; i++)
xQueueSend(_bleMidiTransport->mRxQueue, &buffer[i + 1], portMAX_DELAY);
break;
default:
break;
}
}
// Point to next status
lPtr = rPtr + 2;
if(lPtr >= length)
return; //end of packet
}
} }
void connected() void connected()