LCOV - code coverage report
Current view: top level - src/MIDI_Interfaces - BluetoothMIDI_Interface.hpp (source / functions) Hit Total Coverage
Test: 19d2efc7037c2e176feca44750a12594c76f466f Lines: 28 108 25.9 %
Date: 2019-11-24 14:50:27 Functions: 6 22 27.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : #pragma once
       2             : 
       3             : #include "BLEMIDI.hpp"
       4             : #include "SerialMIDI_Interface.hpp"
       5             : 
       6             : #include <Helpers/Error.hpp>
       7             : 
       8             : BEGIN_CS_NAMESPACE
       9             : 
      10             : /**
      11             :  * @brief   Bluetooth Low Energy MIDI Interface for the ESP32.
      12             :  * 
      13             :  * @ingroup MIDIInterfaces
      14             :  */
      15          10 : class BluetoothMIDI_Interface : public Parsing_MIDI_Interface,
      16             :                                 public BLEServerCallbacks,
      17             :                                 public BLECharacteristicCallbacks {
      18             : 
      19             :     // BLE Callbacks
      20             : 
      21           0 :     void onConnect(UNUSED_PARAM BLEServer *pServer) override {
      22           0 :         DEBUGFN("Connected");
      23           0 :         connected++;
      24           0 :     };
      25           0 :     void onDisconnect(UNUSED_PARAM BLEServer *pServer) override {
      26           0 :         DEBUGFN("Disonnected");
      27           0 :         if (!connected) {
      28           0 :             ERROR(F("Error: disconnect event, but was not connected"), 0x7788);
      29           0 :             return;
      30             :         }
      31           0 :         connected--;
      32           0 :     }
      33             : 
      34           0 :     void onRead(BLECharacteristic *pCharacteristic) override {
      35           0 :         DEBUGFN("Read");
      36           0 :         pCharacteristic->setValue(nullptr, 0);
      37           0 :     }
      38           0 :     void onWrite(BLECharacteristic *pCharacteristic) override {
      39           0 :         DEBUGFN("Write: ");
      40           0 :         std::string value = pCharacteristic->getValue();
      41           0 :         const uint8_t *const data =
      42           0 :             reinterpret_cast<const uint8_t *>(value.data());
      43           0 :         size_t len = value.size();
      44           0 :         for (size_t i = 0; i < len; i++) {
      45           0 :             Serial.print(data[i], HEX);
      46           0 :             Serial.print(' ');
      47           0 :         }
      48           0 :         Serial.println();
      49           0 :         parse(data, len);
      50           0 :     }
      51             : 
      52             :     constexpr static unsigned long MAX_MESSAGE_TIME = 10000; // microseconds
      53             : 
      54          10 :     unsigned long startTime = 0;
      55             : 
      56             :     constexpr static size_t BUFFER_LENGTH = 1024;
      57             : 
      58       10240 :     uint8_t buffer[BUFFER_LENGTH] = {};
      59          10 :     size_t index = 0;
      60             : 
      61             :     SerialMIDI_Parser parser;
      62             : 
      63             :     BLEMIDI bleMidi;
      64             : 
      65          10 :     uint8_t connected = 0;
      66             : 
      67           0 :     bool hasSpaceFor(size_t bytes) { return index + bytes < BUFFER_LENGTH; }
      68             : 
      69             :   public:
      70          20 :     BluetoothMIDI_Interface() : Parsing_MIDI_Interface(parser) {}
      71             : 
      72          10 :     void begin() override { bleMidi.begin(this, this); }
      73             : 
      74           0 :     void publish() {
      75           0 :         if (index == 0)
      76           0 :             return;
      77           0 :         if (!connected) {
      78           0 :             DEBUGFN("No connected BLE clients");
      79           0 :             return;
      80             :         }
      81           0 :         bleMidi.notifyValue(buffer, index);
      82           0 :         index = 0;
      83           0 :     }
      84             : 
      85           0 :     MIDI_read_t read() override {
      86           0 :         update();          // TODO
      87           0 :         return NO_MESSAGE; // TODO
      88             :     }
      89             : 
      90             :     template <size_t N>
      91           0 :     void addToBuffer(const uint8_t (&data)[N]) {
      92           0 :         addToBuffer(&data[0], N);
      93           0 :     }
      94             : 
      95           0 :     void addToBuffer(const uint8_t *data, size_t len) {
      96           0 :         bool first = index == 0;
      97           0 :         if (!hasSpaceFor(len + 1 + first)) { // TODO
      98           0 :             DEBUGFN("Buffer full");
      99           0 :             publish();
     100           0 :             if (!hasSpaceFor(len + 1 + first)) { // TODO
     101           0 :                 DEBUGFN("Message is larger than buffer");
     102           0 :                 return;
     103             :             }
     104           0 :         }
     105             : 
     106           0 :         if (first)
     107           0 :             startTime = micros();
     108             : 
     109           0 :         if (first)
     110           0 :             buffer[index++] = 0x80; // header / timestamp msb
     111           0 :         buffer[index++] = 0x80;     // timestamp lsb
     112           0 :         memcpy(&buffer[index], data, len);
     113           0 :         index += len;
     114             : 
     115           0 :         update();
     116           0 :     }
     117             : 
     118           0 :     void update() override {
     119           0 :         if (micros() - startTime >= MAX_MESSAGE_TIME)
     120           0 :             publish();
     121           0 :     }
     122             : 
     123           0 :     void sendImpl(uint8_t m, uint8_t c, uint8_t d1, uint8_t d2,
     124             :                   uint8_t cn) override {
     125             :         (void)cn;
     126           0 :         uint8_t msg[3] = {uint8_t(m | c), d1, d2};
     127           0 :         addToBuffer(msg);
     128           0 :     }
     129           0 :     void sendImpl(uint8_t m, uint8_t c, uint8_t d1, uint8_t cn) override {
     130             :         (void)cn;
     131           0 :         uint8_t msg[2] = {uint8_t(m | c), d1};
     132           0 :         addToBuffer(msg);
     133           0 :     }
     134             : 
     135           0 :     void sendImpl(const uint8_t *data, size_t length, uint8_t cn) override {
     136             :         (void)data;
     137             :         (void)length;
     138             :         (void)cn; // TODO
     139           0 :     }
     140             : 
     141           0 :     void sendImpl(uint8_t rt, uint8_t cn) override {
     142             :         (void)rt;
     143             :         (void)cn; // TODO
     144           0 :     }
     145             : 
     146          10 :     void parse(const uint8_t *const data, const size_t len) {
     147          10 :         if (len <= 1)
     148           0 :             return;
     149          10 :         if (MIDI_Parser::isData(data[0]))
     150           0 :             return;
     151          10 :         if (MIDI_Parser::isData(data[1]))
     152           1 :             parse(data[1]);
     153          10 :         bool prevWasTimestamp = true;
     154          84 :         for (const uint8_t *d = data + 2; d < data + len; d++) {
     155          74 :             if (MIDI_Parser::isData(*d)) {
     156          39 :                 parse(*d);
     157          39 :                 prevWasTimestamp = false;
     158          39 :             } else {
     159          35 :                 if (prevWasTimestamp)
     160          21 :                     parse(*d);
     161          35 :                 prevWasTimestamp = !prevWasTimestamp;
     162             :             }
     163          74 :         }
     164          10 :     }
     165             : 
     166          61 :     void parse(uint8_t data) {
     167          61 :         MIDI_read_t event = parser.parse(data);
     168          61 :         dispatchMIDIEvent(event);
     169          61 :     }
     170             : 
     171          10 :     BLEMIDI &getBLEMIDI() { return bleMidi; }
     172             : };
     173             : 
     174             : END_CS_NAMESPACE

Generated by: LCOV version 1.14-5-g4ff2ed6