Skip to content

Commit b1784ed

Browse files
committed
Make remote ad hoc protocol work over BLE
1 parent 4ee9dfb commit b1784ed

File tree

7 files changed

+134
-34
lines changed

7 files changed

+134
-34
lines changed

ats-mini/Ble.cpp

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
#include "Common.h"
22
#include "Themes.h"
3+
#include "Remote.h"
34
#include "Ble.h"
45

5-
NordicUART BLESerial = NordicUART(RECEIVER_NAME);
6-
76
//
87
// Get current connection status
98
// (-1 - not connected, 0 - disabled, 1 - connected)
@@ -31,15 +30,21 @@ void bleInit(uint8_t bleMode)
3130
BLESerial.start();
3231
}
3332

34-
int bleDoCommand(uint8_t bleMode)
33+
int bleDoCommand(Stream* stream, RemoteState* state, uint8_t bleMode)
3534
{
3635
if(bleMode == BLE_OFF) return 0;
3736

3837
if (BLEDevice::getServer()->getConnectedCount() > 0) {
39-
if (BLESerial.available()) {
40-
char bleChar = BLESerial.read();
41-
BLESerial.write(bleChar);
42-
}
38+
if (BLESerial.available())
39+
return remoteDoCommand(stream, state, BLESerial.read());
4340
}
4441
return 0;
4542
}
43+
44+
void remoteBLETickTime(Stream* stream, RemoteState* state, uint8_t bleMode)
45+
{
46+
if(bleMode == BLE_OFF) return;
47+
48+
if (BLEDevice::getServer()->getConnectedCount() > 0)
49+
remoteTickTime(stream, state);
50+
}

ats-mini/Ble.h

Lines changed: 96 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@
77
#include <BLE2902.h>
88
#include <semaphore>
99

10+
#include "Remote.h"
11+
1012
#define NORDIC_UART_SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9E"
1113
#define NORDIC_UART_CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
1214
#define NORDIC_UART_CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"
1315

14-
class NordicUART : public BLEServerCallbacks, public BLECharacteristicCallbacks {
16+
class NordicUART : public Stream, public BLEServerCallbacks, public BLECharacteristicCallbacks {
1517
private:
1618
// BLE components
1719
BLEServer* pServer;
@@ -53,7 +55,7 @@ class NordicUART : public BLEServerCallbacks, public BLECharacteristicCallbacks
5355
pServer->getAdvertising()->addServiceUUID(NORDIC_UART_SERVICE_UUID);
5456
pService = pServer->createService(NORDIC_UART_SERVICE_UUID);
5557
pTxCharacteristic = pService->createCharacteristic(NORDIC_UART_CHARACTERISTIC_UUID_TX, BLECharacteristic::PROPERTY_NOTIFY);
56-
pTxCharacteristic->setCallbacks(this); // onSubscribe
58+
pTxCharacteristic->setCallbacks(this); // onSubscribe/onStatus
5759
pRxCharacteristic = pService->createCharacteristic(NORDIC_UART_CHARACTERISTIC_UUID_RX, BLECharacteristic::PROPERTY_WRITE);
5860
pRxCharacteristic->setCallbacks(this); // onWrite
5961
pService->start();
@@ -109,11 +111,26 @@ class NordicUART : public BLEServerCallbacks, public BLECharacteristicCallbacks
109111
}
110112
}
111113

114+
void onStatus(BLECharacteristic *pCharacteristic, Status s, uint32_t code)
115+
{
116+
// if(code) Serial.println(code);
117+
}
118+
112119
int available()
113120
{
114121
return unreadByteCount;
115122
}
116123

124+
int peek()
125+
{
126+
if (unreadByteCount > 0)
127+
{
128+
size_t index = incomingPacket.length() - unreadByteCount;
129+
return incomingPacket[index];
130+
}
131+
return -1;
132+
}
133+
117134
int read()
118135
{
119136
if (unreadByteCount > 0)
@@ -128,22 +145,90 @@ class NordicUART : public BLEServerCallbacks, public BLECharacteristicCallbacks
128145
return -1;
129146
}
130147

131-
size_t write(uint8_t *data, size_t size)
148+
// It is hard to achieve max throughput witout using delays...
149+
//
150+
// https://github.com/nkolban/esp32-snippets/issues/773
151+
// https://github.com/espressif/arduino-esp32/issues/8413
152+
// https://github.com/espressif/esp-idf/issues/9097
153+
// https://github.com/espressif/esp-idf/issues/16889
154+
// https://github.com/espressif/esp-nimble/issues/75
155+
// https://github.com/espressif/esp-nimble/issues/106
156+
// https://github.com/h2zero/esp-nimble-cpp/issues/347
157+
size_t write(const uint8_t *data, size_t size)
132158
{
133-
if (pTxCharacteristic)
134-
{
135-
pTxCharacteristic->setValue(data, size);
136-
pTxCharacteristic->notify();
137-
return size;
138-
}
139-
else
159+
if (pTxCharacteristic)
160+
{
161+
// Data is sent in chunks of MTU size to avoid data loss
162+
// as each chunk is notified separately
163+
size_t chunkSize = BLEDevice::getMTU();
164+
size_t remainingByteCount = size;
165+
while (remainingByteCount >= chunkSize)
166+
{
167+
delay(20);
168+
pTxCharacteristic->setValue(data, chunkSize);
169+
pTxCharacteristic->notify();
170+
data += chunkSize;
171+
remainingByteCount -= chunkSize;
172+
}
173+
if (remainingByteCount > 0)
174+
{
175+
delay(20);
176+
pTxCharacteristic->setValue(data, remainingByteCount);
177+
pTxCharacteristic->notify();
178+
}
179+
return size;
180+
}
181+
else
140182
return 0;
141183
}
142184

143185
size_t write(uint8_t byte)
144186
{
145187
return write(&byte, 1);
146-
};
188+
}
189+
190+
size_t print(std::string str)
191+
{
192+
return write((const uint8_t *)str.data(), str.length());
193+
}
194+
195+
size_t printf(const char *format, ...)
196+
{
197+
char dummy;
198+
va_list args;
199+
va_start(args, format);
200+
int requiredSize = vsnprintf(&dummy, 1, format, args);
201+
va_end(args);
202+
if (requiredSize == 0)
203+
{
204+
return write((uint8_t *)&dummy, 1);
205+
}
206+
else if (requiredSize > 0)
207+
{
208+
char *buffer = (char *)malloc(requiredSize + 1);
209+
if (buffer)
210+
{
211+
va_start(args, format);
212+
int result = vsnprintf(buffer, requiredSize + 1, format, args);
213+
va_end(args);
214+
if ((result >= 0) && (result <= requiredSize))
215+
{
216+
size_t writtenBytesCount = write((uint8_t *)buffer, result + 1);
217+
free(buffer);
218+
return writtenBytesCount;
219+
}
220+
free(buffer);
221+
}
222+
}
223+
return 0;
224+
}
147225
};
148226

227+
void bleInit(uint8_t bleMode);
228+
void bleStop();
229+
int8_t getBleStatus();
230+
void remoteBLETickTime(Stream* stream, RemoteState* state, uint8_t bleMode);
231+
int bleDoCommand(Stream* stream, RemoteState* state, uint8_t bleMode);
232+
extern NordicUART BLESerial;
233+
149234
#endif

ats-mini/Common.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -206,12 +206,6 @@ bool ntpSyncTime();
206206
void netRequestConnect();
207207
void netTickTime();
208208

209-
// Ble.cpp
210-
int bleDoCommand(uint8_t bleModeIdx);
211-
void bleInit(uint8_t bleMode);
212-
void bleStop();
213-
int8_t getBleStatus();
214-
215209
// Remote.c
216210
#define REMOTE_CHANGED 1
217211
#define REMOTE_CLICK 2

ats-mini/Draw.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "Storage.h"
44
#include "Utils.h"
55
#include "Menu.h"
6+
#include "Ble.h"
67
#include "Draw.h"
78

89
//

ats-mini/Menu.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22
#include "Common.h"
33
#include "Themes.h"
44
#include "Utils.h"
5-
#include "Menu.h"
65
#include "Draw.h"
76
#include "EIBI.h"
7+
#include "Ble.h"
8+
#include "Menu.h"
89

910
//
1011
// Bands Menu
@@ -121,9 +122,9 @@ static const char *menu[] =
121122
#define MENU_SLEEP 9
122123
#define MENU_SLEEPMODE 10
123124
#define MENU_LOADEIBI 11
124-
#define MENU_BLEMODE 14
125-
#define MENU_WIFIMODE 12
126-
#define MENU_ABOUT 13
125+
#define MENU_BLEMODE 12
126+
#define MENU_WIFIMODE 13
127+
#define MENU_ABOUT 14
127128

128129

129130
int8_t settingsIdx = MENU_BRIGHTNESS;
@@ -142,7 +143,7 @@ static const char *settings[] =
142143
"Sleep",
143144
"Sleep Mode",
144145
"Load EiBi",
145-
// "Bluetooth",
146+
"Bluetooth",
146147
"Wi-Fi",
147148
"About",
148149
};
@@ -249,7 +250,7 @@ static const char *uiLayoutDesc[] =
249250

250251
uint8_t bleModeIdx = BLE_OFF;
251252
static const char *bleModeDesc[] =
252-
{ "Off", "DummyEcho" };
253+
{ "Off", "Ad hoc" };
253254

254255
int getTotalBleModes() { return(ITEM_COUNT(bleModeDesc)); }
255256

ats-mini/Remote.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
#ifndef REMOTE_H
2+
#define REMOTE_H
3+
14
typedef struct {
25
uint32_t remoteTimer = millis();
36
uint8_t remoteSeqnum = 0;
@@ -6,3 +9,5 @@ typedef struct {
69

710
void remoteTickTime(Stream* stream, RemoteState* state);
811
int remoteDoCommand(Stream* stream, RemoteState* state, char key);
12+
13+
#endif

ats-mini/ats-mini.ino

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,14 @@
1313
#include "Utils.h"
1414
#include "EIBI.h"
1515
#include "Remote.h"
16+
#include "Ble.h"
1617

1718
// SI473/5 and UI
1819
#define MIN_ELAPSED_TIME 5 // 300
1920
#define MIN_ELAPSED_RSSI_TIME 200 // RSSI check uses IN_ELAPSED_RSSI_TIME * 6 = 1.2s
2021
#define ELAPSED_COMMAND 10000 // time to turn off the last command controlled by encoder. Time to goes back to the VFO control // G8PTN: Increased time and corrected comment
2122
#define DEFAULT_VOLUME 35 // change it for your favorite sound volume
2223
#define DEFAULT_SLEEP 0 // Default sleep interval, range = 0 (off) to 255 in steps of 5
23-
#define STRENGTH_CHECK_TIME 1500 // Not used
2424
#define RDS_CHECK_TIME 250 // Increased from 90
2525
#define SEEK_TIMEOUT 600000 // Max seek timeout (ms)
2626
#define NTP_CHECK_TIME 60000 // NTP time refresh period (ms)
@@ -93,6 +93,7 @@ uint8_t snr = 0;
9393
// Remotes
9494
//
9595
RemoteState remoteSerialState;
96+
RemoteState remoteBLEState;
9697

9798
//
9899
// Devices
@@ -102,7 +103,7 @@ ButtonTracker pb1 = ButtonTracker();
102103
TFT_eSPI tft = TFT_eSPI();
103104
TFT_eSprite spr = TFT_eSprite(&tft);
104105
SI4735_fixed rx;
105-
106+
NordicUART BLESerial = NordicUART(RECEIVER_NAME);
106107

107108
//
108109
// Hardware initialization and setup
@@ -752,8 +753,9 @@ void loop()
752753

753754
ButtonTracker::State pb1st = pb1.update(digitalRead(ENCODER_PUSH_BUTTON) == LOW);
754755

755-
// Periodically print status to serial
756+
// Periodically print status to remote interfaces
756757
remoteTickTime(&Serial, &remoteSerialState);
758+
remoteBLETickTime(&BLESerial, &remoteBLEState, bleModeIdx);
757759

758760
// if(encCount && getCpuFrequencyMhz()!=240) setCpuFrequencyMhz(240);
759761

@@ -769,7 +771,14 @@ void loop()
769771
if(revent & REMOTE_PREFS) prefsRequestSave(SAVE_ALL);
770772
}
771773

772-
int ble_event = bleDoCommand(bleModeIdx);
774+
// Receive and execute BLE command
775+
int ble_event = bleDoCommand(&BLESerial, &remoteBLEState, bleModeIdx);
776+
needRedraw |= !!(ble_event & REMOTE_CHANGED);
777+
pb1st.wasClicked |= !!(ble_event & REMOTE_CLICK);
778+
int direction = ble_event >> REMOTE_DIRECTION;
779+
encCount = direction? direction : encCount;
780+
encCountAccel = direction? direction : encCountAccel;
781+
if(ble_event & REMOTE_PREFS) prefsRequestSave(SAVE_ALL);
773782

774783
// Block encoder rotation when in the locked sleep mode
775784
if(encCount && sleepOn() && sleepModeIdx==SLEEP_LOCKED) encCount = encCountAccel = 0;

0 commit comments

Comments
 (0)