Skip to content

Commit b208773

Browse files
committed
added multiple peripheral example sketch bleuart_multi.ino
1 parent d17d13f commit b208773

File tree

7 files changed

+208
-62
lines changed

7 files changed

+208
-62
lines changed

changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
- Added ARDUINO_NRF52832_FEATHER for feather 832, ARDUINO_NRF52840_FEATHER for feather 840, ARDUINO_NRF52_FEATHER for both
1111
- Fixed an memory leak with LFS, also extend to allow it to be used with SPI flash on other boards. Thanks @jeremypoulter
1212
- Seperate OTA DFU service from Bluefruit.begin(), sketch must explicit add it if needed.
13+
- Added multiple peripheral-role connections support, example sketch is at `examples/Peripherals/bleuart_multi`
1314
- Introduce BLEPeriph class (Bluefruit.Periph) to mange peripheral role's connection
1415
- setConnInterval(), setConnIntervalMS(), setConnSupervisionTimeout(), setConnSupervisionTimeoutMS()
1516
- setConnectCallback(), setDisconnectCallback()

libraries/Bluefruit52Lib/examples/Peripheral/StandardFirmataBLE/StandardFirmataBLE.ino

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -869,13 +869,8 @@ void startAdv(void)
869869
*============================================================================*/
870870
void loop()
871871
{
872-
// Skip if not connected and bleuart notification is enabled
873-
if ( !(Bluefruit.connected() && bleuart.notifyEnabled()) )
874-
{
875-
// go to low power mode since there is nothing to do
876-
waitForEvent();
877-
return;
878-
}
872+
// Skip if not connected and bleuart notification is not enabled
873+
if ( !(Bluefruit.connected() && bleuart.notifyEnabled()) ) return;
879874

880875
byte pin, analogPin;
881876

libraries/Bluefruit52Lib/examples/Peripheral/bleuart/bleuart.ino

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,9 +115,6 @@ void loop()
115115
ch = (uint8_t) bleuart.read();
116116
Serial.write(ch);
117117
}
118-
119-
// Request CPU to enter low-power mode until an event/interrupt occurs
120-
waitForEvent();
121118
}
122119

123120
// callback invoked when central connects
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
/*********************************************************************
2+
This is an example for our nRF52 based Bluefruit LE modules
3+
4+
Pick one up today in the adafruit shop!
5+
6+
Adafruit invests time and resources providing this open source code,
7+
please support Adafruit and open-source hardware by purchasing
8+
products from Adafruit!
9+
10+
MIT license, check LICENSE for more information
11+
All text above, and the splash screen below must be included in
12+
any redistribution
13+
*********************************************************************/
14+
#include <bluefruit.h>
15+
16+
#define MAX_PRPH_CONNECTION 2
17+
uint8_t connection_count = 0;
18+
19+
// BLE Service
20+
BLEDfu bledfu; // OTA DFU service
21+
BLEDis bledis; // device information
22+
BLEUart bleuart; // uart over ble
23+
24+
void setup()
25+
{
26+
Serial.begin(115200);
27+
while ( !Serial ) delay(10); // for nrf52840 with native usb
28+
29+
Serial.println("Bluefruit52 BLEUART Example");
30+
Serial.println("---------------------------\n");
31+
32+
// Setup the BLE LED to be enabled on CONNECT
33+
// Note: This is actually the default behaviour, but provided
34+
// here in case you want to control this LED manually via PIN 19
35+
Bluefruit.autoConnLed(true);
36+
37+
// Initialize Bluefruit with max concurrent connections as Peripheral = 2, Central = 0
38+
Bluefruit.begin(MAX_PRPH_CONNECTION, 0);
39+
// Set max power. Accepted values are: -40, -30, -20, -16, -12, -8, -4, 0, 4
40+
Bluefruit.setTxPower(4);
41+
Bluefruit.setName("Bluefruit52");
42+
Bluefruit.Periph.setConnectCallback(connect_callback);
43+
Bluefruit.Periph.setDisconnectCallback(disconnect_callback);
44+
45+
// To be consistent OTA DFU should be added first if it exists
46+
bledfu.begin();
47+
48+
// Configure and Start Device Information Service
49+
bledis.setManufacturer("Adafruit Industries");
50+
bledis.setModel("Bluefruit Feather52");
51+
bledis.begin();
52+
53+
// Configure and Start BLE Uart Service
54+
bleuart.begin();
55+
56+
// Set up and start advertising
57+
startAdv();
58+
59+
Serial.println("Please use Adafruit's Bluefruit LE app to connect in UART mode");
60+
Serial.println("Once connected, enter character(s) that you wish to send");
61+
}
62+
63+
void startAdv(void)
64+
{
65+
// Advertising packet
66+
Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
67+
Bluefruit.Advertising.addTxPower();
68+
69+
// Include bleuart 128-bit uuid
70+
Bluefruit.Advertising.addService(bleuart);
71+
72+
// Secondary Scan Response packet (optional)
73+
// Since there is no room for 'Name' in Advertising packet
74+
Bluefruit.ScanResponse.addName();
75+
76+
/* Start Advertising
77+
* - Enable auto advertising if disconnected
78+
* - Interval: fast mode = 20 ms, slow mode = 152.5 ms
79+
* - Timeout for fast mode is 30 seconds
80+
* - Start(timeout) with timeout = 0 will advertise forever (until connected)
81+
*
82+
* For recommended advertising interval
83+
* https://developer.apple.com/library/content/qa/qa1931/_index.html
84+
*/
85+
Bluefruit.Advertising.restartOnDisconnect(true);
86+
Bluefruit.Advertising.setInterval(32, 244); // in unit of 0.625 ms
87+
Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
88+
Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds
89+
}
90+
91+
92+
// print a string to Serial Uart and all connected BLE Uart
93+
void printAll(uint8_t* buf, int count)
94+
{
95+
Serial.write(buf, count);
96+
97+
// Send to all connected centrals
98+
for (uint8_t conn_hdl=0; conn_hdl < MAX_PRPH_CONNECTION; conn_hdl++)
99+
{
100+
bleuart.write(conn_hdl, buf, count);
101+
}
102+
}
103+
104+
void loop()
105+
{
106+
uint8_t buf[64];
107+
int count;
108+
109+
// Forward data from HW Serial to BLEUART
110+
while (Serial.available())
111+
{
112+
// Delay to wait for enough input
113+
delay(2);
114+
count = Serial.readBytes(buf, sizeof(buf));
115+
116+
printAll(buf, count);
117+
}
118+
119+
// Forward from BLEUART to HW Serial
120+
while ( bleuart.available() )
121+
{
122+
count = bleuart.read(buf, sizeof(buf));
123+
124+
printAll(buf, count);
125+
}
126+
}
127+
128+
// callback invoked when central connects
129+
void connect_callback(uint16_t conn_handle)
130+
{
131+
// Get the reference to current connection
132+
BLEConnection* connection = Bluefruit.Connection(conn_handle);
133+
134+
char central_name[32] = { 0 };
135+
connection->getPeerName(central_name, sizeof(central_name));
136+
137+
Serial.print("Connected to ");
138+
Serial.println(central_name);
139+
140+
connection_count++;
141+
Serial.print("Connection count: ");
142+
Serial.println(connection_count);
143+
144+
// Keep advertising if not reaching max
145+
if (connection_count < MAX_PRPH_CONNECTION)
146+
{
147+
Serial.println("Keep advertising");
148+
Bluefruit.Advertising.start(0);
149+
}
150+
}
151+
152+
/**
153+
* Callback invoked when a connection is dropped
154+
* @param conn_handle connection where this event happens
155+
* @param reason is a BLE_HCI_STATUS_CODE which can be found in ble_hci.h
156+
*/
157+
void disconnect_callback(uint16_t conn_handle, uint8_t reason)
158+
{
159+
(void) conn_handle;
160+
(void) reason;
161+
162+
Serial.println();
163+
Serial.println("Disconnected");
164+
165+
connection_count--;
166+
}

libraries/Bluefruit52Lib/examples/Peripheral/hid_keyboard/hid_keyboard.ino

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,9 +120,6 @@ void loop()
120120
// Delay a bit after a report
121121
delay(5);
122122
}
123-
124-
// Request CPU to enter low-power mode until an event/interrupt occurs
125-
waitForEvent();
126123
}
127124

128125
/**

libraries/Bluefruit52Lib/src/BLEGatt.cpp

Lines changed: 37 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -85,72 +85,64 @@ void BLEGatt::_eventHandler(ble_evt_t* evt)
8585
BLEConnection* conn = Bluefruit.Connection(evt_conn_hdl);
8686

8787
/*------------- Server service -------------*/
88-
// TODO multiple peripherals
89-
// if ( evt_conn_hdl == Bluefruit.connHandle() )
88+
if ( evt_id == BLE_GAP_EVT_DISCONNECTED || evt_id == BLE_GAP_EVT_CONNECTED )
9089
{
91-
if ( evt_id == BLE_GAP_EVT_DISCONNECTED || evt_id == BLE_GAP_EVT_CONNECTED )
90+
for(uint8_t i=0; i<_server.svc_count; i++)
9291
{
93-
for(uint8_t i=0; i<_server.svc_count; i++)
92+
if ( evt_id == BLE_GAP_EVT_DISCONNECTED )
9493
{
95-
if ( evt_id == BLE_GAP_EVT_DISCONNECTED )
96-
{
97-
_server.svc_list[i]->svc_disconnect_hdl(evt_conn_hdl);
98-
}else
99-
{
100-
_server.svc_list[i]->svc_connect_hdl(evt_conn_hdl);
101-
}
94+
_server.svc_list[i]->svc_disconnect_hdl(evt_conn_hdl);
95+
}else
96+
{
97+
_server.svc_list[i]->svc_connect_hdl(evt_conn_hdl);
10298
}
10399
}
104100
}
105101

106102
/*------------- Server Characteristics -------------*/
107-
// TODO multiple prph connection
108-
if ( evt_conn_hdl == Bluefruit.connHandle() )
103+
for(uint8_t i=0; i<_server.chr_count; i++)
109104
{
110-
for(uint8_t i=0; i<_server.chr_count; i++)
111-
{
112-
BLECharacteristic* chr = _server.chr_list[i];
113-
uint16_t req_handle = BLE_GATT_HANDLE_INVALID;
105+
BLECharacteristic* chr = _server.chr_list[i];
106+
uint16_t req_handle = BLE_GATT_HANDLE_INVALID;
114107

115-
// BLE_GATTS_OP_EXEC_WRITE_REQ_NOW has no handle, uuid only command op
116-
bool exec_write_now = false;
108+
// BLE_GATTS_OP_EXEC_WRITE_REQ_NOW has no handle, uuid only command op
109+
bool exec_write_now = false;
117110

118-
switch (evt_id)
111+
switch (evt_id)
112+
{
113+
case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST:
119114
{
120-
case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST:
121-
{
122-
// Handle has the same offset for read & write request
123-
req_handle = evt->evt.gatts_evt.params.authorize_request.request.read.handle;
115+
// Handle has the same offset for read & write request
116+
req_handle = evt->evt.gatts_evt.params.authorize_request.request.read.handle;
124117

125-
if ( evt->evt.gatts_evt.params.authorize_request.type == BLE_GATTS_AUTHORIZE_TYPE_WRITE )
118+
if ( evt->evt.gatts_evt.params.authorize_request.type == BLE_GATTS_AUTHORIZE_TYPE_WRITE )
119+
{
120+
ble_gatts_evt_write_t * wr_req = &evt->evt.gatts_evt.params.authorize_request.request.write;
121+
if ( wr_req->op == BLE_GATTS_OP_EXEC_WRITE_REQ_NOW )
126122
{
127-
ble_gatts_evt_write_t * wr_req = &evt->evt.gatts_evt.params.authorize_request.request.write;
128-
if ( wr_req->op == BLE_GATTS_OP_EXEC_WRITE_REQ_NOW )
129-
{
130-
exec_write_now = true;
131-
}
123+
exec_write_now = true;
132124
}
133125
}
134-
break;
126+
}
127+
break;
135128

136-
case BLE_GATTS_EVT_WRITE:
137-
req_handle = evt->evt.gatts_evt.params.write.handle;
129+
case BLE_GATTS_EVT_WRITE:
130+
req_handle = evt->evt.gatts_evt.params.write.handle;
138131
break;
139132

140-
default: break;
141-
}
133+
default: break;
134+
}
142135

143-
// invoke characteristic handler if matched
144-
if ( exec_write_now ||
145-
((req_handle != BLE_GATT_HANDLE_INVALID) && (req_handle == chr->handles().value_handle || req_handle == chr->handles().cccd_handle)) )
146-
{
147-
chr->_eventHandler(evt);
136+
// invoke characteristic handler if matched
137+
if ( exec_write_now ||
138+
((req_handle != BLE_GATT_HANDLE_INVALID) && (req_handle == chr->handles().value_handle || req_handle == chr->handles().cccd_handle)) )
139+
{
140+
chr->_eventHandler(evt);
148141

149-
// Save CCCD if paired
150-
if ( conn->paired() && (evt_id == BLE_GATTS_EVT_WRITE) && (req_handle == chr->handles().cccd_handle) )
151-
{
152-
conn->storeCccd();
153-
}
142+
// Save CCCD if paired
143+
if ( conn->paired() && (evt_id == BLE_GATTS_EVT_WRITE) && (req_handle == chr->handles().cccd_handle) )
144+
{
145+
conn->storeCccd();
154146
}
155147
}
156148
}

libraries/Bluefruit52Lib/src/bluefruit.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -463,9 +463,7 @@ bool AdafruitBluefruit::begin(uint8_t prph_count, uint8_t central_count)
463463
TaskHandle_t soc_task_hdl;
464464
xTaskCreate( adafruit_soc_task, "SOC", CFG_SOC_TASK_STACKSIZE, NULL, TASK_PRIO_HIGH, &soc_task_hdl);
465465

466-
// Interrupt priority has already been set by the stack.
467-
// NVIC_SetPriority(SD_EVT_IRQn, 6);
468-
NVIC_EnableIRQ(SD_EVT_IRQn);
466+
NVIC_EnableIRQ(SD_EVT_IRQn); // enable SD interrupt
469467

470468
// Create Timer for led advertising blinky
471469
_led_blink_th = xTimerCreate(NULL, ms2tick(CFG_ADV_BLINKY_INTERVAL/2), true, NULL, bluefruit_blinky_cb);
@@ -509,7 +507,7 @@ bool AdafruitBluefruit::setAddr (ble_gap_addr_t* gap_addr)
509507
void AdafruitBluefruit::setName (char const * str)
510508
{
511509
ble_gap_conn_sec_mode_t sec_mode = BLE_SECMODE_OPEN;
512-
sd_ble_gap_device_name_set(&sec_mode, (uint8_t const *) str, strlen(str));
510+
sd_ble_gap_device_name_set(&sec_mode, (uint8_t const *) str, strlen(str));
513511
}
514512

515513
uint8_t AdafruitBluefruit::getName(char* name, uint16_t bufsize)

0 commit comments

Comments
 (0)