Control Surface main
MIDI Control Surface library for Arduino
Loading...
Searching...
No Matches
ESP32Backend.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <AH/Error/Error.hpp>
4
5#include "BLEAPI.hpp"
9
10#include <atomic>
11
12#ifndef ARDUINO
13#define ESP_LOGD(...) ((void)0)
14#define ESP_LOGE(...) ((void)0)
15#define ESP_LOGI(...) ((void)0)
16#endif
17
19
22template <class Impl>
23class ESP32BLEBackend : private ThreadedBLEMIDISender<ESP32BLEBackend<Impl>>,
24 private MIDIBLEInstance {
25 protected:
26 [[no_unique_address]] Impl impl;
28 friend Sender;
29 void sendData(BLEDataView data) {
30 auto chr = characteristic.load();
31 auto con = connection.load();
32 ESP_LOGD("CS-BLEMIDI", "conn=%d, char=%d", con.conn,
33 chr.characteristic);
34 if (chr.characteristic == 0xFFFF)
35 return;
36 impl.notify(con, chr, data);
37 }
38 std::atomic<BLEConnectionHandle> connection;
39 std::atomic<BLECharacteristicHandle> characteristic;
40
41 protected:
42 void handleConnect(BLEConnectionHandle conn_handle) override {
43 ESP_LOGD("CS-BLEMIDI", "conn=%d", conn_handle.conn);
44 this->connection.store(conn_handle);
45 }
47 [[maybe_unused]] BLEConnectionHandle conn_handle) override {
48 ESP_LOGD("CS-BLEMIDI", "conn=%d", conn_handle.conn);
49 this->connection.store({});
50 this->characteristic.store({});
51 }
52 void handleMTU([[maybe_unused]] BLEConnectionHandle conn_handle,
53 uint16_t mtu) override {
54 ESP_LOGD("CS-BLEMIDI", "conn=%d, mtu=%d", conn_handle.conn, mtu);
56 }
58 BLECharacteristicHandle char_handle,
59 bool notify) override {
60 ESP_LOGD("CS-BLEMIDI", "conn=%d, char=%d, notify=%d", conn_handle.conn,
61 char_handle.characteristic, +notify);
62 if (notify) {
63 this->connection.store(conn_handle);
64 this->characteristic.store(char_handle);
65 } else {
66 this->characteristic.store({});
67 }
68 }
69 void handleData([[maybe_unused]] BLEConnectionHandle conn_handle,
70 BLEDataGenerator &&data, BLEDataLifetime) override {
71 ESP_LOGD("CS-BLEMIDI", "conn=%d", conn_handle.conn);
72 BLEDataView packet = data();
73 if (!packet)
74 return;
75 if (!parser.pushPacket(packet)) {
76 ESP_LOGE("CS-BLEMIDI", "BLE packet dropped, size=%d",
77 packet.length);
78 return;
79 }
80 while (BLEDataView cont = data()) {
81 if (!parser.pushPacket(cont, BLEDataType::Continuation)) {
82 ESP_LOGE("CS-BLEMIDI", "BLE chunk dropped, size=%d",
83 cont.length);
84 return;
85 } else {
86 ESP_LOGI("CS-BLEMIDI", "added chunk, size=%d", cont.length);
87 }
88 }
89 }
90
91 private:
92 struct AtomicSize {
93#ifdef ESP32
94 constexpr static size_t alignment = 32; // default cache size
95#else
96 constexpr static size_t alignment = 64;
97#endif
98 AtomicSize(uint_fast16_t value) : value {value} {}
99 std::atomic_uint_fast16_t value;
100 uint_fast16_t load_acquire() const {
101 return value.load(std::memory_order_acquire);
102 }
103 void add_release(uint_fast16_t t) {
104 value.fetch_add(t, std::memory_order_release);
105 }
106 void sub_release(uint_fast16_t t) {
107 value.fetch_sub(t, std::memory_order_release);
108 }
109 };
112
113 public:
115 bool popMessage(IncomingMIDIMessage &incomingMessage) {
116 return parser.popMessage(incomingMessage);
117 }
118
119 public:
120 void begin(BLESettings ble_settings) {
121 impl.init(*this, ble_settings);
122 // Need larger stack than default, pin to non-Arduino core
123 ScopedThreadConfig sc {4096, 3, true, "CS-BLEMIDI", 0};
125 }
126 void end() {
127 FATAL_ERROR(F("ESP32BLEBackend::end not implemented"), 0x3278);
128 }
129 bool isConnected() const {
130 return connection.load(std::memory_order_relaxed).conn != 0xFFFF;
131 }
134 using Sender::getMinMTU;
136 using Sender::sendNow;
137 using Sender::setTimeout;
138};
139
Type definitions and callback interfaces for communication between the low-level BLE stacks and highe...
@ Continuation
Buffer contains a chunk of a BLE packet.
BLEDataLifetime
Should a buffer of BLEData be consumed immediately inside of the callback, or can we hold on to it an...
Definition BLEAPI.hpp:113
#define END_CS_NAMESPACE
#define BEGIN_CS_NAMESPACE
Callable that returns the next chunk of data from a BLE packet when called.
Definition BLEAPI.hpp:66
FIFO buffer that you can push BLE packets into, and pop MIDI messages out of.
ESP32 backend intended to be plugged into GenericBLEMIDI_Interface.
std::atomic< BLECharacteristicHandle > characteristic
void handleData(BLEConnectionHandle conn_handle, BLEDataGenerator &&data, BLEDataLifetime) override
Called by the BLE stack when the central writes data to the MIDI GATT characteristic.
void handleConnect(BLEConnectionHandle conn_handle) override
Called by the BLE stack when a connection is established.
void handleDisconnect(BLEConnectionHandle conn_handle) override
Called by the BLE stack when a connection is terminated.
void sendData(BLEDataView data)
BufferedBLEMIDIParser< 4096, AtomicSize > parser
Contains incoming BLE MIDI data to be parsed.
void begin(BLESettings ble_settings)
void handleMTU(BLEConnectionHandle conn_handle, uint16_t mtu) override
Called by the BLE stack when the maximum transmission unit for the connection changes.
bool isConnected() const
std::atomic< BLEConnectionHandle > connection
bool popMessage(IncomingMIDIMessage &incomingMessage)
void handleSubscribe(BLEConnectionHandle conn_handle, BLECharacteristicHandle char_handle, bool notify) override
Called by the BLE stack when the central subscribes to receive notifications for the MIDI GATT charac...
Defines the interface for callback functions registered by the low-level BLE code.
Definition BLEAPI.hpp:127
Class that manages a background thread that sends BLE packets asynchronously.
BLEMIDIPacketBuilder packet
View of the data to send.
uint16_t getMinMTU() const
Get the minimum MTU of all connected clients.
void setTimeout(std::chrono::milliseconds timeout)
Set the timeout, the number of milliseconds to buffer the outgoing MIDI messages.
void forceMinMTU(uint16_t mtu)
Force the MTU to an artificially small value (used for testing).
ProtectedBuilder acquirePacket()
Acquire exclusive access to the buffer to be sent by the timer.
void begin()
Start the background thread.
void releasePacketAndNotify(ProtectedBuilder &lck)
Release exclusive access to the buffer and notify the sender thread that data is available.
void updateMTU(uint16_t mtu)
Set the maximum transmission unit of the Bluetooth link.
void sendNow(ProtectedBuilder &lck)
Sends the data immediately without waiting for the timeout.
#define FATAL_ERROR(msg, errc)
Print the error message and error code, and stop the execution.
Definition Error.hpp:57
MIDI message variant type (with timestamp).
Represents a handle to a local GATT characteristic.
Definition BLEAPI.hpp:30
Represents a handle to the connection to another device.
Definition BLEAPI.hpp:19
Non-owning, std::span-style read-only view of BLE data.
Definition BLEAPI.hpp:42
Configuration options for the low-level BLE code.
Definition BLEAPI.hpp:150
void add_release(uint_fast16_t t)
void sub_release(uint_fast16_t t)
std::atomic_uint_fast16_t value
uint_fast16_t load_acquire() const
static constexpr size_t alignment
AtomicSize(uint_fast16_t value)