This commit is contained in:
lathoub 2018-11-10 20:07:47 -05:00
parent c3f40ace79
commit 920fbe1644
3 changed files with 78 additions and 40 deletions

View File

@ -1,6 +1,3 @@
// Select your device
#define ESP32
#include "BleMidi.h" #include "BleMidi.h"
BLEMIDI_CREATE_INSTANCE(bm); BLEMIDI_CREATE_INSTANCE(bm);

View File

@ -14,9 +14,9 @@ class BleMidiInterface : public AbstractMidiInterface
{ {
protected: protected:
// ESP32 // ESP32
BLEServer *pServer; BLEServer * _server;
BLEAdvertising *pAdvertising; BLEAdvertising * _advertising;
BLECharacteristic *pCharacteristic; BLECharacteristic *_characteristic;
bool _connected; bool _connected;
@ -28,7 +28,7 @@ public:
void(*_disconnectedCallback)() = NULL; void(*_disconnectedCallback)() = NULL;
protected: protected:
void getMidiTimestamp (uint8_t *header, uint8_t *timestamp) inline static void getMidiTimestamp (uint8_t *header, uint8_t *timestamp)
{ {
/* /*
The first byte of all BLE packets must be a header byte. This is followed by timestamp bytes and MIDI messages. The first byte of all BLE packets must be a header byte. This is followed by timestamp bytes and MIDI messages.
@ -74,6 +74,9 @@ protected:
*timestamp = (currentTimeStamp & 0x7F) | 0x80; // 7 bits plus MSB *timestamp = (currentTimeStamp & 0x7F) | 0x80; // 7 bits plus MSB
} }
// serialize towards hardware
void serialize(DataByte b1) void serialize(DataByte b1)
{ {
getMidiTimestamp(&_midiPacket[0], &_midiPacket[1]); getMidiTimestamp(&_midiPacket[0], &_midiPacket[1]);
@ -82,8 +85,8 @@ protected:
// TODO: quid running status // TODO: quid running status
pCharacteristic->setValue(_midiPacket, 3); _characteristic->setValue(_midiPacket, 3);
pCharacteristic->notify(); _characteristic->notify();
}; };
void serialize(DataByte b1, DataByte b2) void serialize(DataByte b1, DataByte b2)
@ -95,8 +98,8 @@ protected:
// TODO: quid running status // TODO: quid running status
pCharacteristic->setValue(_midiPacket, 4); _characteristic->setValue(_midiPacket, 4);
pCharacteristic->notify(); _characteristic->notify();
}; };
void serialize(DataByte b1, DataByte b2, DataByte b3) void serialize(DataByte b1, DataByte b2, DataByte b3)
@ -109,8 +112,8 @@ protected:
// TODO: quid running status // TODO: quid running status
pCharacteristic->setValue(_midiPacket, 5); _characteristic->setValue(_midiPacket, 5);
pCharacteristic->notify(); _characteristic->notify();
}; };
@ -123,10 +126,17 @@ public:
{ {
} }
// TODO why must these functions be inline??
inline bool begin(const char* deviceName); inline bool begin(const char* deviceName);
inline void receive(uint8_t *buffer, uint8_t bufferSize); inline void run()
{
// n/a, data comes in async (see onWrite callbacks)
}
inline void receive(uint8_t *buffer, uint8_t bufferSize);
void onConnected(void(*fptr)()) { void onConnected(void(*fptr)()) {
_connected = true; _connected = true;
_connectedCallback = fptr; _connectedCallback = fptr;
@ -146,12 +156,12 @@ public:
protected: protected:
BleMidiInterface* _bleMidiInterface; BleMidiInterface* _bleMidiInterface;
void onConnect(BLEServer* pServer) { void onConnect(BLEServer* server) {
if (_bleMidiInterface->_connectedCallback) if (_bleMidiInterface->_connectedCallback)
_bleMidiInterface->_connectedCallback(); _bleMidiInterface->_connectedCallback();
}; };
void onDisconnect(BLEServer* pServer) { void onDisconnect(BLEServer* server) {
if (_bleMidiInterface->_disconnectedCallback) if (_bleMidiInterface->_disconnectedCallback)
_bleMidiInterface->_disconnectedCallback(); _bleMidiInterface->_disconnectedCallback();
} }
@ -162,11 +172,12 @@ public:
MyCharacteristicCallbacks(BleMidiInterface* bleMidiInterface) { MyCharacteristicCallbacks(BleMidiInterface* bleMidiInterface) {
_bleMidiInterface = bleMidiInterface; _bleMidiInterface = bleMidiInterface;
} }
protected: protected:
BleMidiInterface* _bleMidiInterface; BleMidiInterface* _bleMidiInterface;
void onWrite(BLECharacteristic *pCharacteristic) { void onWrite(BLECharacteristic * characteristic) {
std::string rxValue = pCharacteristic->getValue(); std::string rxValue = characteristic->getValue();
if (rxValue.length() > 0) { if (rxValue.length() > 0) {
_bleMidiInterface->receive((uint8_t *)(rxValue.c_str()), rxValue.length()); _bleMidiInterface->receive((uint8_t *)(rxValue.c_str()), rxValue.length());
} }
@ -177,23 +188,23 @@ bool BleMidiInterface::begin(const char* deviceName)
{ {
BLEDevice::init(deviceName); BLEDevice::init(deviceName);
pServer = BLEDevice::createServer(); _server = BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks(this)); _server->setCallbacks(new MyServerCallbacks(this));
// Create the BLE Service // Create the BLE Service
auto pService = pServer->createService(BLEUUID(SERVICE_UUID)); auto service = _server->createService(BLEUUID(SERVICE_UUID));
// Create a BLE Characteristic // Create a BLE Characteristic
pCharacteristic = pService->createCharacteristic( _characteristic = service->createCharacteristic(
BLEUUID(CHARACTERISTIC_UUID), BLEUUID(CHARACTERISTIC_UUID),
BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_WRITE |
BLECharacteristic::PROPERTY_NOTIFY | BLECharacteristic::PROPERTY_NOTIFY |
BLECharacteristic::PROPERTY_WRITE_NR BLECharacteristic::PROPERTY_WRITE_NR
); );
pCharacteristic->setCallbacks(new MyCharacteristicCallbacks(this)); _characteristic->setCallbacks(new MyCharacteristicCallbacks(this));
// Start the service // Start the service
pService->start(); service->start();
auto advertisementData = BLEAdvertisementData(); auto advertisementData = BLEAdvertisementData();
advertisementData.setFlags(0x04); advertisementData.setFlags(0x04);
@ -201,9 +212,9 @@ bool BleMidiInterface::begin(const char* deviceName)
advertisementData.setName(deviceName); advertisementData.setName(deviceName);
// Start advertising // Start advertising
pAdvertising = pServer->getAdvertising(); _advertising = _server->getAdvertising();
pAdvertising->setAdvertisementData(advertisementData); _advertising->setAdvertisementData(advertisementData);
pAdvertising->start(); _advertising->start();
return true; return true;
} }
@ -275,8 +286,8 @@ void BleMidiInterface::receive(uint8_t *buffer, uint8_t bufferSize)
// TODO: switch for type // TODO: switch for type
if (_noteOnCallback) if (_noteOnCallback) // if an attached function exisist, call it here
_noteOnCallback(0, 1, 2); _noteOnCallback(0, 1, 2);
// MIDI.send(command, buffer[lPtr + 1], buffer[lPtr + 2], channel); // MIDI.send(command, buffer[lPtr + 1], buffer[lPtr + 2], channel);
} else { } else {

View File

@ -71,6 +71,7 @@ typedef byte MIDI_PRESSURE;
enum MidiType : uint8_t enum MidiType : uint8_t
{ {
InvalidType = 0x00, ///< For notifying errors InvalidType = 0x00, ///< For notifying errors
NoteOff = 0x80, ///< Note Off NoteOff = 0x80, ///< Note Off
NoteOn = 0x90, ///< Note On NoteOn = 0x90, ///< Note On
AfterTouchPoly = 0xA0, ///< Polyphonic AfterTouch AfterTouchPoly = 0xA0, ///< Polyphonic AfterTouch
@ -78,13 +79,16 @@ enum MidiType : uint8_t
ProgramChange = 0xC0, ///< Program Change ProgramChange = 0xC0, ///< Program Change
AfterTouchChannel = 0xD0, ///< Channel (monophonic) AfterTouch AfterTouchChannel = 0xD0, ///< Channel (monophonic) AfterTouch
PitchBend = 0xE0, ///< Pitch Bend PitchBend = 0xE0, ///< Pitch Bend
SystemExclusive = 0xF0, ///< System Exclusive SystemExclusive = 0xF0, ///< System Exclusive
SystemExclusiveStart = SystemExclusive, SystemExclusiveStart = SystemExclusive,
SystemExclusiveEnd = 0xF7, ///< System Exclusive End SystemExclusiveEnd = 0xF7, ///< System Exclusive End
TimeCodeQuarterFrame = 0xF1, ///< System Common - MIDI Time Code Quarter Frame TimeCodeQuarterFrame = 0xF1, ///< System Common - MIDI Time Code Quarter Frame
SongPosition = 0xF2, ///< System Common - Song Position Pointer SongPosition = 0xF2, ///< System Common - Song Position Pointer
SongSelect = 0xF3, ///< System Common - Song Select SongSelect = 0xF3, ///< System Common - Song Select
TuneRequest = 0xF6, ///< System Common - Tune Request TuneRequest = 0xF6, ///< System Common - Tune Request
Clock = 0xF8, ///< System Real Time - Timing Clock Clock = 0xF8, ///< System Real Time - Timing Clock
Tick = 0xF9, ///< System Real Time - Tick Tick = 0xF9, ///< System Real Time - Tick
Start = 0xFA, ///< System Real Time - Start Start = 0xFA, ///< System Real Time - Start
@ -311,44 +315,61 @@ public:
send(MidiType::AfterTouchChannel, note, pressure, channel); send(MidiType::AfterTouchChannel, note, pressure, channel);
} }
void sendSysEx(const byte*, uint16_t inLength) { void sendSysEx(const byte*, uint16_t inLength) {
// TODO
} }
void sendTimeCodeQuarterFrame(DataByte typeNibble, DataByte valuesNibble) { void sendTimeCodeQuarterFrame(DataByte typeNibble, DataByte valuesNibble) {
// TODO f(typeNibble, valuesNibble);
send(MidiType::TimeCodeQuarterFrame);
} }
void sendTimeCodeQuarterFrame(DataByte data) { void sendTimeCodeQuarterFrame(DataByte data) {
send(MidiType::TimeCodeQuarterFrame, data);
} }
void sendSongPosition(unsigned short beats) { void sendSongPosition(unsigned short beats) {
send(MidiType::SongPosition, beats);
} }
void sendSongSelect(DataByte number) { void sendSongSelect(DataByte number) {
send(MidiType::SongSelect, number);
} }
void sendTuneRequest() { void sendTuneRequest() {
send(MidiType::TuneRequest);
} }
void sendActiveSensing() { void sendActiveSensing() {
} send(MidiType::ActiveSensing);
}
void sendStart() { void sendStart() {
send(MidiType::Start);
} }
void sendContinue() { void sendContinue() {
} send(MidiType::Continue);
}
void sendStop() { void sendStop() {
send(MidiType::Stop);
}
void sendClock() {
send(MidiType::Clock);
}
void sendTick() {
send(MidiType::Tick);
} }
void sendReset() { void sendReset() {
send(MidiType::SystemReset);
} }
void sendClock() {
}
void sendTick() {
}
//receiving //receiving
void setHandleNoteOn(void (*fptr)(byte channel, byte note, byte velocity)) { void setHandleNoteOn(void (*fptr)(byte channel, byte note, byte velocity)) {
@ -418,8 +439,10 @@ protected:
return; // Don't send anything return; // Don't send anything
} }
if (type <= MidiType::PitchBend) // Channel messages if (type <= MidiType::PitchBend)
{ {
// Channel messages
// Protection: remove MSBs on data // Protection: remove MSBs on data
data1 &= 0x7f; data1 &= 0x7f;
data2 &= 0x7f; data2 &= 0x7f;
@ -437,22 +460,29 @@ protected:
} }
else if (type >= MidiType::Clock && type <= MidiType::SystemReset) else if (type >= MidiType::Clock && type <= MidiType::SystemReset)
{ {
serialize(type); // System Real-time and 1 byte. send(type); // System Real-time and 1 byte.
} }
} }
// SystemCommon message // SystemCommon message
virtual void send(MidiType type, DataByte data1, DataByte data2) virtual void send(MidiType type, DataByte data1)
{ {
} }
// realTime // realTime messages
virtual void send(MidiType type) virtual void send(MidiType type)
{ {
} }
virtual bool begin(const char*) = 0;
virtual void run() = 0;
// serialize from the hardware
// serialize towards to hardware
virtual void serialize(DataByte) = 0; virtual void serialize(DataByte) = 0;
virtual void serialize(DataByte, DataByte) = 0; virtual void serialize(DataByte, DataByte) = 0;
virtual void serialize(DataByte, DataByte, DataByte) = 0; virtual void serialize(DataByte, DataByte, DataByte) = 0;