Update BLEMIDI_ArduinoBLE.h

added :     _midiChar.writeValue((uint8_t)0);

otherwise the device will disconnect immediately
This commit is contained in:
lathoub 2022-06-04 22:34:11 +02:00
parent 8c605fea37
commit edd2f21a39
1 changed files with 100 additions and 95 deletions

View File

@ -7,53 +7,49 @@
BEGIN_BLEMIDI_NAMESPACE BEGIN_BLEMIDI_NAMESPACE
BLEService midiService(SERVICE_UUID); template <typename T, short rawSize>
class Fifo
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
template<typename T, short rawSize>
class Fifo {
public: public:
const size_t size; //speculative feature, in case it's needed const size_t size; // speculative feature, in case it's needed
Fifo(): size(rawSize) Fifo() : size(rawSize)
{ {
flush(); flush();
} }
T dequeue() T dequeue()
{ {
numberOfElements--; numberOfElements--;
nextOut %= size; nextOut %= size;
return raw[ nextOut++]; return raw[nextOut++];
}; };
bool enqueue( T element ) bool enqueue(T element)
{ {
if ( count() >= rawSize ) if (count() >= rawSize)
return false; return false;
numberOfElements++; numberOfElements++;
nextIn %= size; nextIn %= size;
raw[nextIn] = element; raw[nextIn] = element;
nextIn++; //advance to next index nextIn++; // advance to next index
return true; return true;
}; };
T peek() const T peek() const
{ {
return raw[ nextOut % size]; return raw[nextOut % size];
} }
void flush() void flush()
{ {
nextIn = nextOut = numberOfElements = 0; nextIn = nextOut = numberOfElements = 0;
} }
// how many elements are currently in the FIFO? // how many elements are currently in the FIFO?
size_t count() { return numberOfElements; } size_t count() { return numberOfElements; }
private: private:
size_t numberOfElements; size_t numberOfElements;
@ -65,56 +61,58 @@ private:
template <class _Settings> template <class _Settings>
class BLEMIDI_ArduinoBLE class BLEMIDI_ArduinoBLE
{ {
private: private:
BLEMIDI_Transport<class BLEMIDI_ArduinoBLE<_Settings>, _Settings>* _bleMidiTransport; BLEMIDI_Transport<class BLEMIDI_ArduinoBLE<_Settings>, _Settings> *_bleMidiTransport;
BLEDevice* _central; BLEDevice *_central;
BLEService _midiService;
BLECharacteristic _midiChar;
Fifo<byte, _Settings::MaxBufferSize> mRxBuffer; Fifo<byte, _Settings::MaxBufferSize> mRxBuffer;
public: public:
BLEMIDI_ArduinoBLE() BLEMIDI_ArduinoBLE() : _midiService(SERVICE_UUID),
{ _midiChar(CHARACTERISTIC_UUID, BLERead | BLEWrite | BLENotify | BLEWriteWithoutResponse, _Settings::MaxBufferSize)
}
bool begin(const char*, BLEMIDI_Transport<class BLEMIDI_ArduinoBLE<_Settings>, _Settings>*);
void end()
{ {
} }
void write(uint8_t* buffer, size_t length) bool begin(const char *, BLEMIDI_Transport<class BLEMIDI_ArduinoBLE<_Settings>, _Settings> *);
{
// TODO: test length
((BLECharacteristic)midiChar).writeValue(buffer, length);
}
bool available(byte* pvBuffer)
{
#ifdef BLE_POLLING
if (mRxBuffer.count() > 0) { void end()
{
}
void write(uint8_t *buffer, size_t length)
{
if (length > 0)
((BLECharacteristic)_midiChar).writeValue(buffer, length);
}
bool available(byte *pvBuffer)
{
#ifdef BLE_POLLING
if (mRxBuffer.count() > 0)
{
*pvBuffer = mRxBuffer.dequeue(); *pvBuffer = mRxBuffer.dequeue();
return true; return true;
} }
poll(); poll();
if (midiChar.written()) {
// auto buffer = midiChar.value();
auto length = midiChar.valueLength();
if (length > 0) { if (_midiChar.written())
auto buffer = midiChar.value().c_str(); {
_bleMidiTransport->receive((byte*)buffer, length); auto length = _midiChar.valueLength();
if (length > 0)
{
auto buffer = _midiChar.value();
_bleMidiTransport->receive((byte *)buffer, length);
} }
} }
return false; return false;
#endif #endif
#ifdef BLE_EVENTS #ifdef BLE_EVENTS
BLE.poll(); BLE.poll();
return false; return false;
#endif #endif
} }
@ -125,59 +123,64 @@ public:
} }
protected: protected:
void receive(const unsigned char* buffer, size_t length) void receive(const unsigned char *buffer, size_t length)
{ {
// forward the buffer so it can be parsed if (length > 0)
_bleMidiTransport->receive((uint8_t*)buffer, length); _bleMidiTransport->receive((uint8_t *)buffer, length);
} }
bool poll() bool poll()
{ {
BLEDevice central = BLE.central(); BLEDevice central = BLE.central();
if (!central) { if (!central)
if (_central) { {
if (_central)
{
BLEMIDI_ArduinoBLE::blePeripheralDisconnectHandler(*_central); BLEMIDI_ArduinoBLE::blePeripheralDisconnectHandler(*_central);
_central = nullptr; _central = nullptr;
} }
return false; return false;
} }
if (!central.connected()) { if (!central.connected())
return false; return false;
}
if (nullptr == _central) { if (nullptr == _central)
{
BLEMIDI_ArduinoBLE::blePeripheralConnectHandler(central); BLEMIDI_ArduinoBLE::blePeripheralConnectHandler(central);
_central = &central; _central = &central;
} }
else { else
if (*_central != central) { {
if (*_central != central)
{
BLEMIDI_ArduinoBLE::blePeripheralDisconnectHandler(*_central); BLEMIDI_ArduinoBLE::blePeripheralDisconnectHandler(*_central);
BLEMIDI_ArduinoBLE::blePeripheralConnectHandler(central); BLEMIDI_ArduinoBLE::blePeripheralConnectHandler(central);
_central = &central; _central = &central;
} }
} }
return true; return true;
} }
void blePeripheralConnectHandler(BLEDevice central) void blePeripheralConnectHandler(BLEDevice central)
{ {
_central = &central; _central = &central;
if (_bleMidiTransport->_connectedCallback) if (_bleMidiTransport->_connectedCallback)
_bleMidiTransport->_connectedCallback(); _bleMidiTransport->_connectedCallback();
} }
void blePeripheralDisconnectHandler(BLEDevice central) void blePeripheralDisconnectHandler(BLEDevice central)
{ {
if (_bleMidiTransport->_disconnectedCallback) if (_bleMidiTransport->_disconnectedCallback)
_bleMidiTransport->_disconnectedCallback(); _bleMidiTransport->_disconnectedCallback();
_central = nullptr; _central = nullptr;
} }
void characteristicWritten(BLEDevice central, BLECharacteristic characteristic) { void characteristicWritten(BLEDevice central, BLECharacteristic characteristic)
{
auto buffer = characteristic.value(); auto buffer = characteristic.value();
auto length = characteristic.valueLength(); auto length = characteristic.valueLength();
@ -187,50 +190,52 @@ protected:
}; };
template <class _Settings> template <class _Settings>
bool BLEMIDI_ArduinoBLE<_Settings>::begin(const char* deviceName, BLEMIDI_Transport<class BLEMIDI_ArduinoBLE<_Settings>, _Settings>* bleMidiTransport) bool BLEMIDI_ArduinoBLE<_Settings>::begin(const char *deviceName, BLEMIDI_Transport<class BLEMIDI_ArduinoBLE<_Settings>, _Settings> *bleMidiTransport)
{ {
_bleMidiTransport = bleMidiTransport; _bleMidiTransport = bleMidiTransport;
// initialize the Bluetooth® Low Energy hardware // initialize the Bluetooth® Low Energy hardware
if (!BLE.begin()) if (!BLE.begin())
return false; return false;
BLE.setLocalName(deviceName); BLE.setLocalName(deviceName);
BLE.setAdvertisedService(midiService); BLE.setAdvertisedService(_midiService);
midiService.addCharacteristic(midiChar); _midiService.addCharacteristic(_midiChar);
BLE.addService(midiService); BLE.addService(_midiService);
// set the initial value for the characeristic:
// (when not set, the device will disconnect after 0.5 seconds)
_midiChar.writeValue((uint8_t)0);
#ifdef BLE_EVENTS #ifdef BLE_EVENTS
// assign event handlers for connected, disconnected to peripheral // assign event handlers for connected, disconnected to peripheral
BLE.setEventHandler(BLEConnected, BLEMIDI_ArduinoBLE::blePeripheralConnectHandler); BLE.setEventHandler(BLEConnected, BLEMIDI_ArduinoBLE::blePeripheralConnectHandler);
BLE.setEventHandler(BLEDisconnected, BLEMIDI_ArduinoBLE::blePeripheralDisconnectHandler); BLE.setEventHandler(BLEDisconnected, BLEMIDI_ArduinoBLE::blePeripheralDisconnectHandler);
midiChar.setEventHandler(BLEWritten, characteristicWritten); _midiChar.setEventHandler(BLEWritten, characteristicWritten);
#endif #endif
/* Start advertising BLE. It will start continuously transmitting BLE /* Start advertising BLE. It will start continuously transmitting BLE
advertising packets and will be visible to remote BLE central devices advertising packets and will be visible to remote BLE central devices
until it receives a new connection */ until it receives a new connection */
// start advertising
BLE.advertise(); BLE.advertise();
return true; return true;
} }
/*! \brief Create an instance for ArduinoBLE <DeviceName> /*! \brief Create an instance for ArduinoBLE <DeviceName>
*/ */
#define BLEMIDI_CREATE_CUSTOM_INSTANCE(DeviceName, Name, _Settings) \ #define BLEMIDI_CREATE_CUSTOM_INSTANCE(DeviceName, Name, _Settings) \
BLEMIDI_NAMESPACE::BLEMIDI_Transport<BLEMIDI_NAMESPACE::BLEMIDI_ArduinoBLE<_Settings>, _Settings> BLE##Name(DeviceName); \ BLEMIDI_NAMESPACE::BLEMIDI_Transport<BLEMIDI_NAMESPACE::BLEMIDI_ArduinoBLE<_Settings>, _Settings> BLE##Name(DeviceName); \
MIDI_NAMESPACE::MidiInterface<BLEMIDI_NAMESPACE::BLEMIDI_Transport<BLEMIDI_NAMESPACE::BLEMIDI_ArduinoBLE<_Settings>, _Settings>, BLEMIDI_NAMESPACE::MySettings> Name((BLEMIDI_NAMESPACE::BLEMIDI_Transport<BLEMIDI_NAMESPACE::BLEMIDI_ArduinoBLE<_Settings>, _Settings> &)BLE##Name); MIDI_NAMESPACE::MidiInterface<BLEMIDI_NAMESPACE::BLEMIDI_Transport<BLEMIDI_NAMESPACE::BLEMIDI_ArduinoBLE<_Settings>, _Settings>, BLEMIDI_NAMESPACE::MySettings> Name((BLEMIDI_NAMESPACE::BLEMIDI_Transport<BLEMIDI_NAMESPACE::BLEMIDI_ArduinoBLE<_Settings>, _Settings> &)BLE##Name);
/*! \brief Create an instance for ArduinoBLE <DeviceName> /*! \brief Create an instance for ArduinoBLE <DeviceName>
*/ */
#define BLEMIDI_CREATE_INSTANCE(DeviceName, Name) \ #define BLEMIDI_CREATE_INSTANCE(DeviceName, Name) \
BLEMIDI_CREATE_CUSTOM_INSTANCE (DeviceName, Name, BLEMIDI_NAMESPACE::DefaultSettings) BLEMIDI_CREATE_CUSTOM_INSTANCE(DeviceName, Name, BLEMIDI_NAMESPACE::DefaultSettings)
/*! \brief Create a default instance for ArduinoBLE named BLE-MIDI /*! \brief Create a default instance for ArduinoBLE named BLE-MIDI
*/ */
#define BLEMIDI_CREATE_DEFAULT_INSTANCE() \ #define BLEMIDI_CREATE_DEFAULT_INSTANCE() \
BLEMIDI_CREATE_INSTANCE("BLE-MIDI", MIDI) BLEMIDI_CREATE_INSTANCE("BLE-MIDI", MIDI)