52
52
#define COLOR_BLACK 0x0000
53
53
#define COLOR_YELLOW 0xFFE0
54
54
#define COLOR_GREEN 0x07E0
55
+ #define COLOR_RED 0xF800
55
56
56
- // Uart over BLE with large buffer to hold image data
57
- BLEUart bleuart (1024 *10 );
57
+ // Declaring Uart over BLE with large buffer to hold image data
58
+ // Depending on the Image Resolution and Transfer Mode especially without response
59
+ // or Interleaved with high ratio. You may need to increase this buffer size
60
+ BLEUart bleuart (10 *1024 );
58
61
59
62
/* The Image Transfer module sends the image of your choice to Bluefruit LE over UART.
60
63
* Each image sent begins with
@@ -71,14 +74,15 @@ uint16_t imageHeight = 0;
71
74
72
75
uint32_t totalPixel = 0 ; // received pixel
73
76
74
- // color buf must be large enough to consume incoming data fast enough
75
- // otherwise bleuart fifo could be overflow and start dropping data
76
- uint16_t color_buf[2048 ];
77
+ // pixel line buffer, should be large enough to hold an image width
78
+ uint16_t pixel_buf[512 ];
77
79
78
80
// Statistics for speed testing
79
81
uint32_t rxStartTime = 0 ;
80
82
uint32_t rxLastTime = 0 ;
81
83
84
+ // for print out message to TFT once
85
+ bool bleuart_overflowed = false ;
82
86
83
87
void setup ()
84
88
{
@@ -104,6 +108,7 @@ void setup()
104
108
// Configure and Start BLE Uart Service
105
109
bleuart.begin ();
106
110
bleuart.setRxCallback (bleuart_rx_callback);
111
+ bleuart.setRxOverflowCallback (bleuart_overflow_callback);
107
112
108
113
// Set up and start advertising
109
114
startAdv ();
@@ -142,60 +147,70 @@ void startAdv(void)
142
147
143
148
void loop ()
144
149
{
145
- if ( !Bluefruit.connected () ) return ;
146
- if ( !bleuart.notifyEnabled () ) return ;
147
- if ( !bleuart.available () ) return ;
150
+ // nothing to do
151
+ }
148
152
149
- // all pixel data is received
150
- if ( (totalPixel != 0 ) && (totalPixel == imageWidth*imageHeight) )
153
+ // Invoked when receiving data from bleuart
154
+ // Pull data from bleuart fifo & draw image as soon as possible,
155
+ // Otherwise bleuart fifo can be overflowed
156
+ void bleuart_rx_callback (uint16_t conn_hdl)
157
+ {
158
+ (void ) conn_hdl;
159
+
160
+ rxLastTime = millis ();
161
+
162
+ // Received new Image
163
+ if ( (imageWidth == 0 ) && (imageHeight == 0 ) )
151
164
{
152
- uint8_t crc = bleuart. read ();
153
- // do checksum later
165
+ // take note of time of first packet
166
+ rxStartTime = millis ();
154
167
155
- // print speed summary
156
- print_speed (totalPixel*3 + 7 , rxLastTime-rxStartTime);
168
+ // Skip all data until '!I' is found
169
+ while ( bleuart.available () && bleuart.read () != ' !' ) { }
170
+ if (bleuart.read () != ' I' ) return ;
157
171
158
- // reset and waiting for new image
159
- totalPixel = imageWidth = imageHeight = 0 ;
160
- }
172
+ if ( !bleuart.available () ) return ;
161
173
162
- // extract pixel data and display on TFT
163
- uint16_t pixelNum = bleuart.available () / 3 ;
174
+ imageWidth = bleuart. read16 ();
175
+ imageHeight = bleuart.read16 () ;
164
176
165
- // Draw multiple lines of image each time i.e pixelNum = n*imageWidth
166
- // pixelNum is capped at color_buf size (512 pixel)
167
- // the rest will be drawn in the next invocation of loop().
168
- pixelNum = min (pixelNum, sizeof (color_buf)/2 );
177
+ totalPixel = 0 ;
169
178
170
- // Chop pixel number to multiple of image width
171
- pixelNum = (pixelNum / imageWidth) * imageWidth ;
179
+ PRINT_INT (imageWidth);
180
+ PRINT_INT (imageHeight) ;
172
181
173
- #if 0
174
- static uint32_t last_available = 0;
175
- if ( last_available != bleuart.available() )
182
+ tft.fillScreen (COLOR_BLACK);
183
+ tft.setCursor (0 , 0 );
184
+ }
185
+
186
+ // Extract pixel data to buffer and draw image line by line
187
+ while ( bleuart.available () >= 3 )
176
188
{
177
- last_available = bleuart.available();
189
+ uint8_t rgb[3 ];
190
+ bleuart.read (rgb, 3 );
191
+
192
+ pixel_buf[totalPixel % imageWidth] = ((rgb[0 ] & 0xF8 ) << 8 ) | ((rgb[1 ] & 0xFC ) << 3 ) | (rgb[2 ] >> 3 );
193
+
194
+ totalPixel++;
178
195
179
- PRINT_INT(totalPixel);
180
- PRINT_INT(last_available);
181
- PRINT_INT(pixelNum);
182
- Serial.println();
196
+ // enough to draw an image line
197
+ if ( (totalPixel % imageWidth) == 0 )
198
+ {
199
+ tft.drawRGBBitmap (0 , totalPixel/imageWidth, pixel_buf, imageWidth, 1 );
200
+ }
183
201
}
184
- #endif
185
202
186
- if ( pixelNum )
203
+ // all pixel data is received
204
+ if ( totalPixel == imageWidth*imageHeight )
187
205
{
188
- for ( uint16_t i=0 ; i < pixelNum; i++)
189
- {
190
- uint8_t red = bleuart.read ();
191
- uint8_t green = bleuart.read ();
192
- uint8_t blue = bleuart.read ();
206
+ uint8_t crc = bleuart.read ();
207
+ // do checksum later
193
208
194
- color_buf[i] = ((red & 0xF8 ) << 8 ) | ((green & 0xFC ) << 3 ) | ( blue >> 3 );
195
- }
209
+ // print speed summary
210
+ print_speed (totalPixel* 3 + 7 , rxLastTime-rxStartTime);
196
211
197
- tft. drawRGBBitmap ( 0 , totalPixel/imageWidth, color_buf, imageWidth, pixelNum/imageWidth);
198
- totalPixel += pixelNum ;
212
+ // reset and waiting for new image
213
+ totalPixel = imageWidth = imageHeight = 0 ;
199
214
}
200
215
}
201
216
@@ -247,36 +262,28 @@ void print_speed(uint32_t count, uint32_t ms)
247
262
tft.setTextColor (COLOR_WHITE);
248
263
}
249
264
250
- void bleuart_rx_callback (uint16_t conn_hdl)
265
+ void bleuart_overflow_callback (uint16_t conn_hdl, uint16_t leftover )
251
266
{
252
- (void ) conn_hdl;
253
-
254
- rxLastTime = millis ();
267
+ Serial.println (" BLEUART rx buffer OVERFLOWED!" );
268
+ Serial.println (" Please increase buffer size for bleuart" );
255
269
256
- // Received new Image
257
- if ( (imageWidth == 0 ) && (imageHeight == 0 ) )
270
+ // only print the first time this occur, need disconnect to reset
271
+ if (!bleuart_overflowed )
258
272
{
259
- rxStartTime = millis ( );
273
+ tft. setCursor ( 0 , imageHeight+ 5 );
260
274
261
- // Skip all data until '!I' is found
262
- while ( bleuart.available () && bleuart.read () != ' !' ) { }
263
- if (bleuart.read () != ' I' ) return ;
275
+ tft.setTextColor (COLOR_RED);
276
+ tft.println (" BLEUART rx buffer OVERFLOWED!" );
264
277
265
- if ( !bleuart.available () ) return ;
266
-
267
- imageWidth = bleuart.read16 ();
268
- imageHeight = bleuart.read16 ();
269
-
270
- PRINT_INT (imageWidth);
271
- PRINT_INT (imageHeight);
272
-
273
- tft.fillScreen (COLOR_BLACK);
274
- tft.setCursor (0 , 0 );
278
+ tft.setTextColor (COLOR_WHITE);
279
+ tft.print (" Please increase buffer size for bleuart" );
275
280
}
281
+
282
+ bleuart_overflowed = true ;
276
283
}
277
284
278
285
/* *
279
- * Callback invoked when a connection is dropped
286
+ * invoked when a connection is dropped
280
287
* @param conn_handle connection where this event happens
281
288
* @param reason is a BLE_HCI_STATUS_CODE which can be found in ble_hci.h
282
289
*/
@@ -289,6 +296,7 @@ void disconnect_callback(uint16_t conn_handle, uint8_t reason)
289
296
tft.println (" Advertising ..." );
290
297
291
298
totalPixel = imageWidth = imageHeight = 0 ;
299
+ bleuart_overflowed = false ;
292
300
293
301
bleuart.flush ();
294
302
}
0 commit comments