renamed ESP32 -> MIDI_ESP32
This commit is contained in:
parent
533eab5204
commit
acd1d95001
|
|
@ -1,7 +1,8 @@
|
|||
#include <BLE-MIDI.h>
|
||||
#include <hardware/ESP32_NimBLE.h>
|
||||
//#include <hardware/ESP32.h>
|
||||
//#include <hardware/nRF52.h>
|
||||
#include <hardware/MIDI_ESP32_NimBLE.h>
|
||||
//#include <hardware/MIDI_ESP32.h>
|
||||
//#include <hardware/MIDI_nRF52.h>
|
||||
//#include <hardware/MIDI_ArduinoBLE.h>
|
||||
|
||||
BLEMIDI_CREATE_DEFAULT_INSTANCE()
|
||||
|
||||
|
|
@ -13,19 +14,21 @@ bool isConnected = false;
|
|||
// -----------------------------------------------------------------------------
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.begin(9600); // initialize serial communication
|
||||
while (!Serial);
|
||||
Serial.println("Booting");
|
||||
|
||||
|
||||
MIDI.begin();
|
||||
|
||||
Serial.println("booting!");
|
||||
|
||||
pinMode(LED_BUILTIN, OUTPUT);
|
||||
digitalWrite(LED_BUILTIN, LOW);
|
||||
|
||||
BLEMIDI.setHandleConnected(OnConnected);
|
||||
BLEMIDI.setHandleDisconnected(OnDisconnected);
|
||||
|
||||
MIDI.setHandleNoteOn(OnNoteOn);
|
||||
MIDI.setHandleNoteOff(OnNoteOff);
|
||||
|
||||
Serial.println(F("Ready"));
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
@ -39,8 +42,8 @@ void loop()
|
|||
{
|
||||
t0 = millis();
|
||||
|
||||
MIDI.sendNoteOn(60, 127, 1); // note 60, velocity 127 on channel 1
|
||||
MIDI.sendNoteOff(60, 0, 1);
|
||||
// MIDI.sendNoteOn (60, 100, 1); // note 60, velocity 127 on channel 1
|
||||
// MIDI.sendNoteOff(60, 0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -52,40 +55,30 @@ void loop()
|
|||
// Device connected
|
||||
// -----------------------------------------------------------------------------
|
||||
void OnConnected() {
|
||||
Serial.println(F("Connected"));
|
||||
isConnected = true;
|
||||
digitalWrite(LED_BUILTIN, HIGH);
|
||||
Serial.println("connected!");
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Device disconnected
|
||||
// -----------------------------------------------------------------------------
|
||||
void OnDisconnected() {
|
||||
Serial.println(F("Disconnected"));
|
||||
isConnected = false;
|
||||
digitalWrite(LED_BUILTIN, LOW);
|
||||
Serial.println("disconnected!");
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Received note on
|
||||
// -----------------------------------------------------------------------------
|
||||
void OnNoteOn(byte channel, byte note, byte velocity) {
|
||||
Serial.print(F("Incoming NoteOn from channel:"));
|
||||
Serial.print(channel);
|
||||
Serial.print(F(" note:"));
|
||||
Serial.print(note);
|
||||
Serial.print(F(" velocity:"));
|
||||
Serial.print(velocity);
|
||||
Serial.println();
|
||||
Serial.println("note on");
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Received note off
|
||||
// -----------------------------------------------------------------------------
|
||||
void OnNoteOff(byte channel, byte note, byte velocity) {
|
||||
Serial.print(F("Incoming NoteOff from channel:"));
|
||||
Serial.print(channel);
|
||||
Serial.print(F(" note:"));
|
||||
Serial.print(note);
|
||||
Serial.print(F(" velocity:"));
|
||||
Serial.print(velocity);
|
||||
Serial.println();
|
||||
Serial.println("note off");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,198 @@
|
|||
#pragma once
|
||||
|
||||
#include <ArduinoBLE.h>
|
||||
|
||||
BLEService midiService(SERVICE_UUID);
|
||||
BLEStringCharacteristic midiChar(CHARACTERISTIC_UUID, // standard 16-bit characteristic UUID
|
||||
BLERead | BLEWrite | BLENotify | BLEWriteWithoutResponse, 16); // remote clients will be able to get notifications if this characteristic changes
|
||||
|
||||
#define BLE_POLLING
|
||||
|
||||
BEGIN_BLEMIDI_NAMESPACE
|
||||
|
||||
class BLEMIDI
|
||||
{
|
||||
private:
|
||||
static BLEMIDITransport<class BLEMIDI>* _bleMidiTransport;
|
||||
static BLEDevice* _central;
|
||||
|
||||
// byte mRxBuffer[Settings::MaxBufferSize];
|
||||
|
||||
public:
|
||||
BLEMIDI()
|
||||
{
|
||||
}
|
||||
|
||||
bool begin(const char*, BLEMIDITransport<class BLEMIDI>*);
|
||||
|
||||
void write(uint8_t* buffer, size_t length)
|
||||
{
|
||||
// TODO: test length
|
||||
((BLECharacteristic)midiChar).writeValue(buffer, length);
|
||||
}
|
||||
|
||||
size_t available(uint8_t* buffer, const size_t index, const size_t max)
|
||||
{
|
||||
#ifdef BLE_POLLING
|
||||
poll();
|
||||
|
||||
if (midiChar.written()) {
|
||||
// auto buffer = midiChar.value();
|
||||
auto length = midiChar.valueLength();
|
||||
|
||||
if (length > 0) {
|
||||
// TODO: test length
|
||||
memcpy(buffer + index, midiChar.value().c_str(), length);
|
||||
return length;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef BLE_EVENTS
|
||||
/ BLE.poll();
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void read()
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
The general form of a MIDI message follows:
|
||||
n-byte MIDI Message
|
||||
Byte 0 MIDI message Status byte, Bit 7 is Set to 1.
|
||||
Bytes 1 to n-1 MIDI message Data bytes, if n > 1. Bit 7 is Set to 0
|
||||
There are two types of MIDI messages that can appear in a single packet: full MIDI messages and
|
||||
Running Status MIDI messages. Each is encoded differently.
|
||||
A full MIDI message is simply the MIDI message with the Status byte included.
|
||||
A Running Status MIDI message is a MIDI message with the Status byte omitted. Running Status
|
||||
MIDI messages may only be placed in the data stream if the following criteria are met:
|
||||
1. The original MIDI message is 2 bytes or greater and is not a System Common or System
|
||||
Real-Time message.
|
||||
2. The omitted Status byte matches the most recently preceding full MIDI message’s Status
|
||||
byte within the same BLE packet.
|
||||
In addition, the following rules apply with respect to Running Status:
|
||||
1. A Running Status MIDI message is allowed within the packet after at least one full MIDI
|
||||
message.
|
||||
2. Every MIDI Status byte must be preceded by a timestamp byte. Running Status MIDI
|
||||
messages may be preceded by a timestamp byte. If a Running Status MIDI message is not
|
||||
preceded by a timestamp byte, the timestamp byte of the most recently preceding message
|
||||
in the same packet is used.
|
||||
3. System Common and System Real-Time messages do not cancel Running Status if
|
||||
interspersed between Running Status MIDI messages. However, a timestamp byte must
|
||||
precede the Running Status MIDI message that follows.
|
||||
4. The end of a BLE packet does cancel Running Status.
|
||||
In the MIDI 1.0 protocol, System Real-Time messages can be sent at any time and may be
|
||||
inserted anywhere in a MIDI data stream, including between Status and Data bytes of any other
|
||||
MIDI messages. In the MIDI BLE protocol, the System Real-Time messages must be deinterleaved
|
||||
from other messages – except for System Exclusive messages.
|
||||
*/
|
||||
static void receive(const uint8_t* buffer, size_t length)
|
||||
{
|
||||
Serial.print("receive: ");
|
||||
for (int i = 0; i < length; i++) {
|
||||
Serial.print(" 0x");
|
||||
Serial.print(buffer[i], HEX);
|
||||
}
|
||||
Serial.println("");
|
||||
}
|
||||
|
||||
bool poll()
|
||||
{
|
||||
BLEDevice central = BLE.central();
|
||||
if (!central) {
|
||||
if (_central) {
|
||||
BLEMIDI::blePeripheralDisconnectHandler(*_central);
|
||||
_central = nullptr;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!central.connected()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (nullptr == _central) {
|
||||
BLEMIDI::blePeripheralConnectHandler(central);
|
||||
_central = ¢ral;
|
||||
}
|
||||
else {
|
||||
if (*_central != central) {
|
||||
BLEMIDI::blePeripheralDisconnectHandler(*_central);
|
||||
BLEMIDI::blePeripheralConnectHandler(central);
|
||||
_central = ¢ral;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void blePeripheralConnectHandler(BLEDevice central)
|
||||
{
|
||||
_central = ¢ral;
|
||||
if (_bleMidiTransport->_connectedCallback)
|
||||
_bleMidiTransport->_connectedCallback();
|
||||
}
|
||||
|
||||
static void blePeripheralDisconnectHandler(BLEDevice central)
|
||||
{
|
||||
if (_bleMidiTransport->_disconnectedCallback)
|
||||
_bleMidiTransport->_disconnectedCallback();
|
||||
_central = nullptr;
|
||||
}
|
||||
|
||||
static void characteristicWritten(BLEDevice central, BLECharacteristic characteristic) {
|
||||
auto buffer = characteristic.value();
|
||||
auto length = characteristic.valueLength();
|
||||
|
||||
if (length > 0)
|
||||
receive(buffer, length);
|
||||
}
|
||||
};
|
||||
|
||||
BLEMIDITransport<class BLEMIDI>* BLEMIDI::_bleMidiTransport = nullptr;
|
||||
BLEDevice* BLEMIDI::_central = nullptr;
|
||||
|
||||
bool BLEMIDI::begin(const char* deviceName, BLEMIDITransport<class BLEMIDI>* bleMidiTransport)
|
||||
{
|
||||
_bleMidiTransport = bleMidiTransport;
|
||||
|
||||
if (!BLE.begin())
|
||||
return false;
|
||||
|
||||
BLE.setLocalName(deviceName);
|
||||
|
||||
BLE.setAdvertisedService(midiService);
|
||||
midiService.addCharacteristic(midiChar);
|
||||
BLE.addService(midiService);
|
||||
|
||||
#ifdef BLE_EVENTS
|
||||
// assign event handlers for connected, disconnected to peripheral
|
||||
BLE.setEventHandler(BLEConnected, BLEMIDI::blePeripheralConnectHandler);
|
||||
BLE.setEventHandler(BLEDisconnected, BLEMIDI::blePeripheralDisconnectHandler);
|
||||
|
||||
midiChar.setEventHandler(BLEWritten, characteristicWritten);
|
||||
#endif
|
||||
|
||||
/* Start advertising BLE. It will start continuously transmitting BLE
|
||||
advertising packets and will be visible to remote BLE central devices
|
||||
until it receives a new connection */
|
||||
|
||||
// start advertising
|
||||
BLE.advertise();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*! \brief Create an instance for nRF52 named <DeviceName>
|
||||
*/
|
||||
#define BLEMIDI_CREATE_INSTANCE(DeviceName, Name) \
|
||||
BLEMIDI_NAMESPACE::BLEMIDITransport<BLEMIDI_NAMESPACE::BLEMIDI> BLE##Name(DeviceName); \
|
||||
MIDI_NAMESPACE::MidiInterface<BLEMIDI_NAMESPACE::BLEMIDITransport<BLEMIDI_NAMESPACE::BLEMIDI>, MySettings> Name((BLEMIDI_NAMESPACE::BLEMIDITransport<BLEMIDI_NAMESPACE::BLEMIDI> &)BLE##Name);
|
||||
|
||||
/*! \brief Create a default instance for nRF52 named BLE-MIDI
|
||||
*/
|
||||
#define BLEMIDI_CREATE_DEFAULT_INSTANCE() \
|
||||
BLEMIDI_CREATE_INSTANCE("BLE-MIDI", MIDI)
|
||||
|
||||
END_BLEMIDI_NAMESPACE
|
||||
|
|
@ -8,24 +8,24 @@
|
|||
|
||||
BEGIN_BLEMIDI_NAMESPACE
|
||||
|
||||
class BLEMIDI_ESP32
|
||||
class BLEMIDI
|
||||
{
|
||||
private:
|
||||
BLEServer* _server = nullptr;
|
||||
BLEAdvertising* _advertising = nullptr;
|
||||
BLECharacteristic* _characteristic = nullptr;
|
||||
|
||||
BLEMIDITransport<class BLEMIDI_ESP32>* _bleMidiTransport = nullptr;
|
||||
BLEMIDITransport<class BLEMIDI>* _bleMidiTransport = nullptr;
|
||||
|
||||
protected:
|
||||
QueueHandle_t mRxQueue;
|
||||
|
||||
public:
|
||||
BLEMIDI_ESP32()
|
||||
BLEMIDI()
|
||||
{
|
||||
}
|
||||
|
||||
bool begin(const char*, BLEMIDITransport<class BLEMIDI_ESP32>*);
|
||||
bool begin(const char*, BLEMIDITransport<class BLEMIDI>*);
|
||||
|
||||
void write(uint8_t* buffer, size_t length)
|
||||
{
|
||||
|
|
@ -78,7 +78,7 @@ public:
|
|||
// 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 statement contains incrementing pointers and breaks when buffer size exceeded.
|
||||
while (true)
|
||||
{
|
||||
lastStatus = buffer[lPtr];
|
||||
|
|
@ -160,12 +160,12 @@ public:
|
|||
|
||||
class MyServerCallbacks: public BLEServerCallbacks {
|
||||
public:
|
||||
MyServerCallbacks(BLEMIDI_ESP32* bluetoothEsp32)
|
||||
MyServerCallbacks(BLEMIDI* bluetoothEsp32)
|
||||
: _bluetoothEsp32(bluetoothEsp32) {
|
||||
}
|
||||
|
||||
protected:
|
||||
BLEMIDI_ESP32* _bluetoothEsp32 = nullptr;
|
||||
BLEMIDI* _bluetoothEsp32 = nullptr;
|
||||
|
||||
void onConnect(BLEServer*) {
|
||||
if (_bluetoothEsp32)
|
||||
|
|
@ -180,12 +180,12 @@ protected:
|
|||
|
||||
class MyCharacteristicCallbacks: public BLECharacteristicCallbacks {
|
||||
public:
|
||||
MyCharacteristicCallbacks(BLEMIDI_ESP32* bluetoothEsp32)
|
||||
MyCharacteristicCallbacks(BLEMIDI* bluetoothEsp32)
|
||||
: _bluetoothEsp32(bluetoothEsp32 ) {
|
||||
}
|
||||
|
||||
protected:
|
||||
BLEMIDI_ESP32* _bluetoothEsp32 = nullptr;
|
||||
BLEMIDI* _bluetoothEsp32 = nullptr;
|
||||
|
||||
void onWrite(BLECharacteristic * characteristic) {
|
||||
std::string rxValue = characteristic->getValue();
|
||||
|
|
@ -195,7 +195,7 @@ protected:
|
|||
}
|
||||
};
|
||||
|
||||
bool BLEMIDI_ESP32::begin(const char* deviceName, BLEMIDITransport<class BLEMIDI_ESP32>* bleMidiTransport)
|
||||
bool BLEMIDI::begin(const char* deviceName, BLEMIDITransport<class BLEMIDI>* bleMidiTransport)
|
||||
{
|
||||
_bleMidiTransport = bleMidiTransport;
|
||||
|
||||
|
|
@ -242,8 +242,8 @@ bool BLEMIDI_ESP32::begin(const char* deviceName, BLEMIDITransport<class BLEMIDI
|
|||
/*! \brief Create an instance for ESP32 named <DeviceName>
|
||||
*/
|
||||
#define BLEMIDI_CREATE_INSTANCE(DeviceName, Name) \
|
||||
BLEMIDI_NAMESPACE::BLEMIDITransport<BLEMIDI_NAMESPACE::BLEMIDI_ESP32> BLE##Name(DeviceName); \
|
||||
MIDI_NAMESPACE::MidiInterface<BLEMIDI_NAMESPACE::BLEMIDITransport<BLEMIDI_NAMESPACE::BLEMIDI_ESP32>, MySettings> Name((BLEMIDI_NAMESPACE::BLEMIDITransport<BLEMIDI_NAMESPACE::BLEMIDI_ESP32> &)BLE##Name);
|
||||
BLEMIDI_NAMESPACE::BLEMIDITransport<BLEMIDI_NAMESPACE::BLEMIDI> BLE##Name(DeviceName); \
|
||||
MIDI_NAMESPACE::MidiInterface<BLEMIDI_NAMESPACE::BLEMIDITransport<BLEMIDI_NAMESPACE::BLEMIDI>, MySettings> Name((BLEMIDI_NAMESPACE::BLEMIDITransport<BLEMIDI_NAMESPACE::BLEMIDI> &)BLE##Name);
|
||||
|
||||
/*! \brief Create a default instance for ESP32 named BLE-MIDI
|
||||
*/
|
||||
|
|
@ -0,0 +1,267 @@
|
|||
#pragma once
|
||||
|
||||
// Headers for ESP32 NimBLE
|
||||
#include <NimBLEDevice.h>
|
||||
|
||||
BEGIN_BLEMIDI_NAMESPACE
|
||||
|
||||
class BLEMIDI
|
||||
{
|
||||
private:
|
||||
BLEServer* _server = nullptr;
|
||||
BLEAdvertising* _advertising = nullptr;
|
||||
BLECharacteristic* _characteristic = nullptr;
|
||||
|
||||
BLEMIDITransport<class BLEMIDI>* _bleMidiTransport = nullptr;
|
||||
|
||||
protected:
|
||||
QueueHandle_t mRxQueue;
|
||||
|
||||
public:
|
||||
BLEMIDI()
|
||||
{
|
||||
}
|
||||
|
||||
bool begin(const char*, BLEMIDITransport<class BLEMIDI>*);
|
||||
|
||||
void write(uint8_t* buffer, size_t length)
|
||||
{
|
||||
_characteristic->setValue(buffer, length);
|
||||
_characteristic->notify();
|
||||
}
|
||||
|
||||
size_t available(uint8_t* buffer, size_t index, const size_t max)
|
||||
{
|
||||
size_t length = uxQueueMessagesWaiting(mRxQueue);
|
||||
if (0 == length) return 0;
|
||||
|
||||
Serial.print("nimBLE available: ");
|
||||
|
||||
while (xQueueReceive(mRxQueue, buffer + index++, 0))
|
||||
{
|
||||
Serial.print(" 0x");
|
||||
Serial.print(buffer[index], HEX);
|
||||
index++;
|
||||
}
|
||||
Serial.println("");
|
||||
|
||||
if (length > 0)
|
||||
{
|
||||
Serial.print("index: ");
|
||||
Serial.println(length);
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
/*
|
||||
The general form of a MIDI message follows:
|
||||
n-byte MIDI Message
|
||||
Byte 0 MIDI message Status byte, Bit 7 is Set to 1.
|
||||
Bytes 1 to n-1 MIDI message Data bytes, if n > 1. Bit 7 is Set to 0
|
||||
There are two types of MIDI messages that can appear in a single packet: full MIDI messages and
|
||||
Running Status MIDI messages. Each is encoded differently.
|
||||
A full MIDI message is simply the MIDI message with the Status byte included.
|
||||
A Running Status MIDI message is a MIDI message with the Status byte omitted. Running Status
|
||||
MIDI messages may only be placed in the data stream if the following criteria are met:
|
||||
1. The original MIDI message is 2 bytes or greater and is not a System Common or System
|
||||
Real-Time message.
|
||||
2. The omitted Status byte matches the most recently preceding full MIDI message’s Status
|
||||
byte within the same BLE packet.
|
||||
In addition, the following rules apply with respect to Running Status:
|
||||
1. A Running Status MIDI message is allowed within the packet after at least one full MIDI
|
||||
message.
|
||||
2. Every MIDI Status byte must be preceded by a timestamp byte. Running Status MIDI
|
||||
messages may be preceded by a timestamp byte. If a Running Status MIDI message is not
|
||||
preceded by a timestamp byte, the timestamp byte of the most recently preceding message
|
||||
in the same packet is used.
|
||||
3. System Common and System Real-Time messages do not cancel Running Status if
|
||||
interspersed between Running Status MIDI messages. However, a timestamp byte must
|
||||
precede the Running Status MIDI message that follows.
|
||||
4. The end of a BLE packet does cancel Running Status.
|
||||
In the MIDI 1.0 protocol, System Real-Time messages can be sent at any time and may be
|
||||
inserted anywhere in a MIDI data stream, including between Status and Data bytes of any other
|
||||
MIDI messages. In the MIDI BLE protocol, the System Real-Time messages must be deinterleaved
|
||||
from other messages – except for System Exclusive messages.
|
||||
*/
|
||||
void receive(uint8_t* buffer, size_t length)
|
||||
{
|
||||
// Pointers used to search through payload.
|
||||
uint8_t lPtr = 0;
|
||||
uint8_t rPtr = 0;
|
||||
// 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(mRxQueue, &lastStatus, portMAX_DELAY);
|
||||
} else if( rPtr - lPtr < 2 ) {
|
||||
xQueueSend(mRxQueue, &lastStatus, portMAX_DELAY);
|
||||
xQueueSend(mRxQueue, &buffer[lPtr + 1], portMAX_DELAY);
|
||||
} else if( rPtr - lPtr < 3 ) {
|
||||
xQueueSend(mRxQueue, &lastStatus, portMAX_DELAY);
|
||||
xQueueSend(mRxQueue, &buffer[lPtr + 1], portMAX_DELAY);
|
||||
xQueueSend(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)
|
||||
{
|
||||
xQueueSend(mRxQueue, &lastStatus, portMAX_DELAY);
|
||||
xQueueSend(mRxQueue, &buffer[i + 1], portMAX_DELAY);
|
||||
xQueueSend(mRxQueue, &buffer[i + 2], portMAX_DELAY);
|
||||
}
|
||||
break;
|
||||
case 0xC0:
|
||||
case 0xD0:
|
||||
for (auto i = lPtr; i < rPtr; i = i + 1)
|
||||
{
|
||||
xQueueSend(mRxQueue, &lastStatus, portMAX_DELAY);
|
||||
xQueueSend(mRxQueue, &buffer[i + 1], portMAX_DELAY);
|
||||
}
|
||||
break;
|
||||
case 0xF0:
|
||||
xQueueSend(mRxQueue, &buffer[lPtr], portMAX_DELAY);
|
||||
for (auto i = lPtr; i < rPtr; i++)
|
||||
xQueueSend(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()
|
||||
{
|
||||
if (_bleMidiTransport->_connectedCallback)
|
||||
_bleMidiTransport->_connectedCallback();
|
||||
}
|
||||
|
||||
void disconnected()
|
||||
{
|
||||
if (_bleMidiTransport->_disconnectedCallback)
|
||||
_bleMidiTransport->_disconnectedCallback();
|
||||
}
|
||||
};
|
||||
|
||||
class MyServerCallbacks: public BLEServerCallbacks {
|
||||
public:
|
||||
MyServerCallbacks(BLEMIDI* bluetoothEsp32)
|
||||
: _bluetoothEsp32(bluetoothEsp32) {
|
||||
}
|
||||
|
||||
protected:
|
||||
BLEMIDI* _bluetoothEsp32 = nullptr;
|
||||
|
||||
void onConnect(BLEServer*) {
|
||||
if (_bluetoothEsp32)
|
||||
_bluetoothEsp32->connected();
|
||||
};
|
||||
|
||||
void onDisconnect(BLEServer*) {
|
||||
if (_bluetoothEsp32)
|
||||
_bluetoothEsp32->disconnected();
|
||||
}
|
||||
};
|
||||
|
||||
class MyCharacteristicCallbacks: public BLECharacteristicCallbacks {
|
||||
public:
|
||||
MyCharacteristicCallbacks(BLEMIDI* bluetoothEsp32)
|
||||
: _bluetoothEsp32(bluetoothEsp32 ) {
|
||||
}
|
||||
|
||||
protected:
|
||||
BLEMIDI* _bluetoothEsp32 = nullptr;
|
||||
|
||||
void onWrite(BLECharacteristic * characteristic) {
|
||||
std::string rxValue = characteristic->getValue();
|
||||
if (rxValue.length() > 0) {
|
||||
_bluetoothEsp32->receive((uint8_t *)(rxValue.c_str()), rxValue.length());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
bool BLEMIDI::begin(const char* deviceName, BLEMIDITransport<class BLEMIDI>* bleMidiTransport)
|
||||
{
|
||||
_bleMidiTransport = bleMidiTransport;
|
||||
|
||||
BLEDevice::init(deviceName);
|
||||
|
||||
// To communicate between the 2 cores.
|
||||
// Core_0 runs here, core_1 runs the BLE stack
|
||||
mRxQueue = xQueueCreate(64, sizeof(uint8_t)); // TODO Settings::MaxBufferSize
|
||||
|
||||
_server = BLEDevice::createServer();
|
||||
_server->setCallbacks(new MyServerCallbacks(this));
|
||||
|
||||
// Create the BLE Service
|
||||
auto service = _server->createService(BLEUUID(SERVICE_UUID));
|
||||
|
||||
// Create a BLE Characteristic
|
||||
_characteristic = service->createCharacteristic(
|
||||
BLEUUID(CHARACTERISTIC_UUID),
|
||||
NIMBLE_PROPERTY::READ |
|
||||
NIMBLE_PROPERTY::WRITE |
|
||||
NIMBLE_PROPERTY::NOTIFY |
|
||||
NIMBLE_PROPERTY::WRITE_NR
|
||||
);
|
||||
|
||||
_characteristic->setCallbacks(new MyCharacteristicCallbacks(this));
|
||||
// Start the service
|
||||
service->start();
|
||||
|
||||
auto advertisementData = BLEAdvertisementData();
|
||||
advertisementData.setFlags(0x04);
|
||||
advertisementData.setCompleteServices(BLEUUID(SERVICE_UUID));
|
||||
advertisementData.setName(deviceName);
|
||||
|
||||
// Start advertising
|
||||
_advertising = _server->getAdvertising();
|
||||
_advertising->setAdvertisementData(advertisementData);
|
||||
_advertising->start();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*! \brief Create an instance for ESP32 named <DeviceName>
|
||||
*/
|
||||
#define BLEMIDI_CREATE_INSTANCE(DeviceName, Name) \
|
||||
BLEMIDI_NAMESPACE::BLEMIDITransport<BLEMIDI_NAMESPACE::BLEMIDI> BLE##Name(DeviceName); \
|
||||
MIDI_NAMESPACE::MidiInterface<BLEMIDI_NAMESPACE::BLEMIDITransport<BLEMIDI_NAMESPACE::BLEMIDI>, MySettings> Name((BLEMIDI_NAMESPACE::BLEMIDITransport<BLEMIDI_NAMESPACE::BLEMIDI> &)BLE##Name);
|
||||
|
||||
/*! \brief Create a default instance for ESP32 named BLE-MIDI
|
||||
*/
|
||||
#define BLEMIDI_CREATE_DEFAULT_INSTANCE() \
|
||||
BLEMIDI_CREATE_INSTANCE("BLE-MIDI", MIDI)
|
||||
|
||||
END_BLEMIDI_NAMESPACE
|
||||
|
|
@ -6,18 +6,18 @@
|
|||
|
||||
BEGIN_BLEMIDI_NAMESPACE
|
||||
|
||||
class BLEMIDI_nRF52
|
||||
class BLEMIDI
|
||||
{
|
||||
private:
|
||||
|
||||
BLEMIDITransport<class BLEMIDI_nRF52>* _bleMidiTransport = nullptr;
|
||||
BLEMIDITransport<class BLEMIDI>* _bleMidiTransport = nullptr;
|
||||
|
||||
public:
|
||||
BLEMIDI_nRF52()
|
||||
BLEMIDI()
|
||||
{
|
||||
}
|
||||
|
||||
bool begin(const char*, BLEMIDITransport<class BLEMIDI_nRF52>*);
|
||||
bool begin(const char*, BLEMIDITransport<class BLEMIDI>*);
|
||||
|
||||
void write(uint8_t* buffer, size_t length)
|
||||
{
|
||||
|
|
@ -70,7 +70,7 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
bool BLEMIDI_nRF52::begin(const char* deviceName, BLEMIDITransport<class BLEMIDI_nRF52>* bleMidiTransport)
|
||||
bool BLEMIDI::begin(const char* deviceName, BLEMIDITransport<class BLEMIDI>* bleMidiTransport)
|
||||
{
|
||||
_bleMidiTransport = bleMidiTransport;
|
||||
|
||||
|
|
@ -125,8 +125,8 @@ bool BLEMIDI_nRF52::begin(const char* deviceName, BLEMIDITransport<class BLEMIDI
|
|||
/*! \brief Create an instance for nRF52 named <DeviceName>
|
||||
*/
|
||||
#define BLEMIDI_CREATE_INSTANCE(DeviceName, Name) \
|
||||
BLEMIDI_NAMESPACE::BLEMIDITransport<BLEMIDI_NAMESPACE::BLEMIDI_nRF52> BLE##Name(DeviceName); \
|
||||
MIDI_NAMESPACE::MidiInterface<BLEMIDI_NAMESPACE::BLEMIDITransport<BLEMIDI_NAMESPACE::BLEMIDI_nRF52>, MySettings> Name((BLEMIDI_NAMESPACE::BLEMIDITransport<BLEMIDI_NAMESPACE::BLEMIDI_nRF52> &)BLE##Name);
|
||||
BLEMIDI_NAMESPACE::BLEMIDITransport<BLEMIDI_NAMESPACE::BLEMIDI> BLE##Name(DeviceName); \
|
||||
MIDI_NAMESPACE::MidiInterface<BLEMIDI_NAMESPACE::BLEMIDITransport<BLEMIDI_NAMESPACE::BLEMIDI>, MySettings> Name((BLEMIDI_NAMESPACE::BLEMIDITransport<BLEMIDI_NAMESPACE::BLEMIDI> &)BLE##Name);
|
||||
|
||||
/*! \brief Create a default instance for nRF52 named BLE-MIDI
|
||||
*/
|
||||
Loading…
Reference in New Issue