Skip to content

Commit 836b0d8

Browse files
committed
improve phy switching, fix collision issue when neogtiating on connection
schedule a negotiation 2 seconds after connection established.
1 parent 2523273 commit 836b0d8

File tree

2 files changed

+101
-33
lines changed

2 files changed

+101
-33
lines changed

libraries/Bluefruit52Lib/examples/Peripheral/image_eink_upload/image_eink_upload.ino

Lines changed: 46 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ uint32_t totalPixel = 0; // received pixel
6161
// pixel line buffer, should be large enough to hold an image width
6262
uint16_t pixel_buf[512];
6363

64+
// Use software timer to schedule bandwidth negotiation a few seconds after connection
65+
SoftwareTimer negoTimer;
66+
6467
// Statistics for speed testing
6568
uint32_t rxStartTime = 0;
6669
uint32_t rxLastTime = 0;
@@ -109,6 +112,9 @@ void setup()
109112

110113
bleuart.setRxOverflowCallback(bleuart_overflow_callback);
111114

115+
// one-shot (non-repeating) 2 seconds timer
116+
negoTimer.begin(2000, negotiate_bandwidth, NULL, false);
117+
112118
// Set up and start advertising
113119
startAdv();
114120

@@ -176,11 +182,15 @@ void bleuart_rx_callback(uint16_t conn_hdl)
176182

177183
totalPixel = 0;
178184

179-
Serial.printf("Image resolution: %dx%d with %d bit color\n", imageWidth, imageHeight, imageColorBit);
180-
181185
display.clearBuffer();
182186
display.fillScreen(EPD_WHITE);
183187
display.setCursor(0, 0);
188+
189+
// Print out the current connection info
190+
BLEConnection* conn = Bluefruit.Connection(conn_hdl);
191+
Serial.printf("Connection Info: PHY = %d Mbps, Conn Interval = %.2f ms, Data Length = %d, MTU = %d\n",
192+
conn->getPHY(), conn->getConnectionInterval()*1.25f, conn->getDataLength(), conn->getMtu());
193+
Serial.printf("Receving an %dx%d Image with %d bit color\n", imageWidth, imageHeight, imageColorBit);
184194
}
185195

186196
// Extract pixel data to buffer and draw image line by line
@@ -238,6 +248,7 @@ void bleuart_rx_callback(uint16_t conn_hdl)
238248
print_summary(totalPixel*(imageColorBit/8) + 8, rxLastTime-rxStartTime);
239249

240250
// Display on Eink, will probably take dozens of seconds
251+
Serial.println("Displaying image (~20 seconds) .....");
241252
display.display();
242253

243254
// reset and waiting for new image
@@ -249,24 +260,44 @@ void bleuart_rx_callback(uint16_t conn_hdl)
249260
}
250261
}
251262

252-
void connect_callback(uint16_t conn_handle)
263+
void negotiate_bandwidth(TimerHandle_t xTimer)
253264
{
254-
BLEConnection* conn = Bluefruit.Connection(conn_handle);
265+
(void) xTimer;
255266

256-
Serial.println("Connected");
267+
uint16_t conn_hdl = (uint16_t) ((uint32_t) negoTimer.getID());
268+
BLEConnection* conn = Bluefruit.Connection(conn_hdl);
257269

258-
// Requesting to Switching to 2MB PHY, larger data length and MTU
259-
// will increase the throughput on supported central. This should be already done
260-
// with latest Bluefruit app, but still put here for user reference
261-
conn->requestPHY();
262-
Serial.println("Switching PHY");
270+
// Switching from 1 Mb to 2 Mb PHY if needed
271+
if ( conn->connected() )
272+
{
273+
// Requesting to Switching to 2MB PHY, larger data length and bigger MTU
274+
// will increase the throughput on supported central. This should already
275+
// be done with latest Bluefruit app.
276+
//
277+
// However, some Android devices require 2Mb PHY switching must be initiated
278+
// from nRF side
279+
if ( conn->getPHY() == BLE_GAP_PHY_1MBPS )
280+
{
281+
Serial.println("Requesting PHY change from 1 Mb to 2Mb");
282+
conn->requestPHY();
263283

264-
conn->requestDataLengthUpdate();
265-
Serial.println("Updating Data Length");
284+
// Data Length and MTU should already be done by Bluefruit app
285+
// conn->requestDataLengthUpdate();
286+
// conn->requestMtuExchange(247);
287+
}
288+
}
289+
}
266290

267-
conn->requestMtuExchange(247);
268-
Serial.println("Exchanging MTU");
291+
void connect_callback(uint16_t conn_handle)
292+
{
293+
// Set connection handle as timer ID
294+
// Then schedule negotiation after a few seconds, we should not
295+
// negotiate here since it increases chance to conflict with other
296+
// on-going negotiation from central after connection
297+
negoTimer.setID((void*) conn_handle);
298+
negoTimer.start();
269299

300+
Serial.println("Connected");
270301
Serial.println("Ready to receive new image");
271302
}
272303

@@ -275,7 +306,7 @@ void print_summary(uint32_t count, uint32_t ms)
275306
float sec = ms / 1000.0F;
276307

277308
Serial.printf("Received %d bytes in %.2f seconds\n", count, sec);
278-
Serial.printf("Speed: %.2f KB/s for %dx%d Image\n", (count / 1024.0F) / sec, imageWidth, imageHeight);
309+
Serial.printf("Speed: %.2f KB/s\n\n", (count / 1024.0F) / sec);
279310
}
280311

281312
void bleuart_overflow_callback(uint16_t conn_hdl, uint16_t leftover)

libraries/Bluefruit52Lib/examples/Peripheral/image_upload/image_upload.ino

Lines changed: 55 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,9 @@ uint32_t totalPixel = 0; // received pixel
9696
// pixel line buffer, should be large enough to hold an image width
9797
uint16_t pixel_buf[512];
9898

99+
// Use software timer to schedule bandwidth negotiation a few seconds after connection
100+
SoftwareTimer negoTimer;
101+
99102
// Statistics for speed testing
100103
uint32_t rxStartTime = 0;
101104
uint32_t rxLastTime = 0;
@@ -153,6 +156,9 @@ void setup()
153156

154157
bleuart.setRxOverflowCallback(bleuart_overflow_callback);
155158

159+
// one-shot (non-repeating) 2 seconds timer
160+
negoTimer.begin(2000, negotiate_bandwidth, NULL, false);
161+
156162
// Set up and start advertising
157163
startAdv();
158164

@@ -220,12 +226,15 @@ void bleuart_rx_callback(uint16_t conn_hdl)
220226

221227
totalPixel = 0;
222228

223-
PRINT_INT(imageColorBit);
224-
PRINT_INT(imageWidth);
225-
PRINT_INT(imageHeight);
226-
227229
tft.fillScreen(COLOR_BLACK);
228230
tft.setCursor(0, 0);
231+
232+
// Print out the current connection info
233+
BLEConnection* conn = Bluefruit.Connection(conn_hdl);
234+
Serial.printf("Connection Info: PHY = %d Mbps, Conn Interval = %.2f ms, Data Length = %d, MTU = %d\n",
235+
conn->getPHY(), conn->getConnectionInterval()*1.25f, conn->getDataLength(), conn->getMtu());
236+
237+
Serial.printf("Receiving an %dx%d Image with %d-bit color\n", imageWidth, imageHeight, imageColorBit);
229238
}
230239

231240
// Extract pixel data to buffer and draw image line by line
@@ -270,31 +279,59 @@ void bleuart_rx_callback(uint16_t conn_hdl)
270279
}
271280
}
272281

273-
void connect_callback(uint16_t conn_handle)
282+
void negotiate_bandwidth(TimerHandle_t xTimer)
274283
{
275-
BLEConnection* conn = Bluefruit.Connection(conn_handle);
284+
(void) xTimer;
276285

277-
tft.println("Connected");
286+
uint16_t conn_hdl = (uint16_t) ((uint32_t) negoTimer.getID());
287+
BLEConnection* conn = Bluefruit.Connection(conn_hdl);
278288

279-
// Requesting to Switching to 2MB PHY, larger data length and MTU
280-
// will increase the throughput on supported central. This should be already done
281-
// with latest Bluefruit app, but still put here for user reference
282-
conn->requestPHY();
283-
tft.println("Switching PHY");
289+
// Switching from 1 Mb to 2 Mb PHY if needed
290+
if ( conn->connected() )
291+
{
292+
// Requesting to Switching to 2MB PHY, larger data length and bigger MTU
293+
// will increase the throughput on supported central. This should already
294+
// be done with latest Bluefruit app.
295+
//
296+
// However, some Android devices require 2Mb PHY switching must be initiated
297+
// from nRF side
298+
if ( conn->getPHY() == BLE_GAP_PHY_1MBPS )
299+
{
300+
Serial.println("Requesting PHY change from 1 Mb to 2Mb");
301+
conn->requestPHY();
284302

285-
conn->requestDataLengthUpdate();
286-
tft.println("Updating Data Length");
303+
// Data Length and MTU should already be done by Bluefruit app
304+
// conn->requestDataLengthUpdate();
305+
// conn->requestMtuExchange(247);
306+
}
307+
}
308+
}
287309

288-
conn->requestMtuExchange(247);
289-
tft.println("Exchanging MTU");
310+
void connect_callback(uint16_t conn_handle)
311+
{
312+
// Set connection handle as timer ID
313+
// Then schedule negotiation after a few seconds, we should not
314+
// negotiate here since it increases chance to conflict with other
315+
// on-going negotiation from central after connection
316+
negoTimer.setID((void*) conn_handle);
317+
negoTimer.start();
290318

319+
tft.println("Connected");
291320
tft.setTextColor(COLOR_GREEN);
292321
tft.println("Ready to receive new image");
293322
tft.setTextColor(COLOR_WHITE);
294323
}
295324

296325
void print_summary(uint32_t count, uint32_t ms)
297326
{
327+
float sec = ms / 1000.0F;
328+
329+
// Print to serial
330+
Serial.printf("Received %d bytes in %.2f seconds\n", count, sec);
331+
Serial.printf("Speed: %.2f KB/s\n\n", (count / 1024.0F) / sec);
332+
Serial.println("Ready to receive new image");
333+
334+
// Also print to TFT with color text
298335
tft.setCursor(0, imageHeight+5);
299336
tft.print("Received ");
300337

@@ -305,14 +342,14 @@ void print_summary(uint32_t count, uint32_t ms)
305342
tft.print(" bytes in ");
306343

307344
tft.setTextColor(COLOR_YELLOW);
308-
tft.print(ms / 1000.0F, 2);
345+
tft.print(sec, 2);
309346
tft.setTextColor(COLOR_WHITE);
310347

311348
tft.println(" seconds");
312349

313350
tft.print("Speed: ");
314351
tft.setTextColor(COLOR_YELLOW);
315-
tft.print( (count / 1000.0F) / (ms / 1000.0F), 2);
352+
tft.print( (count / 1024.0F) / sec, 2);
316353
tft.setTextColor(COLOR_WHITE);
317354
tft.print(" KB/s for ");
318355

0 commit comments

Comments
 (0)