5252#define COLOR_BLACK 0x0000
5353#define COLOR_YELLOW 0xFFE0
5454#define COLOR_GREEN 0x07E0
55+ #define COLOR_RED 0xF800
5556
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 );
5861
5962/* The Image Transfer module sends the image of your choice to Bluefruit LE over UART.
6063 * Each image sent begins with
@@ -71,14 +74,15 @@ uint16_t imageHeight = 0;
7174
7275uint32_t totalPixel = 0 ; // received pixel
7376
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 ];
7779
7880// Statistics for speed testing
7981uint32_t rxStartTime = 0 ;
8082uint32_t rxLastTime = 0 ;
8183
84+ // for print out message to TFT once
85+ bool bleuart_overflowed = false ;
8286
8387void setup ()
8488{
@@ -104,6 +108,7 @@ void setup()
104108 // Configure and Start BLE Uart Service
105109 bleuart.begin ();
106110 bleuart.setRxCallback (bleuart_rx_callback);
111+ bleuart.setRxOverflowCallback (bleuart_overflow_callback);
107112
108113 // Set up and start advertising
109114 startAdv ();
@@ -142,60 +147,70 @@ void startAdv(void)
142147
143148void loop ()
144149{
145- if ( !Bluefruit.connected () ) return ;
146- if ( !bleuart.notifyEnabled () ) return ;
147- if ( !bleuart.available () ) return ;
150+ // nothing to do
151+ }
148152
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 ) )
151164 {
152- uint8_t crc = bleuart. read ();
153- // do checksum later
165+ // take note of time of first packet
166+ rxStartTime = millis ();
154167
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 ;
157171
158- // reset and waiting for new image
159- totalPixel = imageWidth = imageHeight = 0 ;
160- }
172+ if ( !bleuart.available () ) return ;
161173
162- // extract pixel data and display on TFT
163- uint16_t pixelNum = bleuart.available () / 3 ;
174+ imageWidth = bleuart. read16 ();
175+ imageHeight = bleuart.read16 () ;
164176
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 ;
169178
170- // Chop pixel number to multiple of image width
171- pixelNum = (pixelNum / imageWidth) * imageWidth ;
179+ PRINT_INT (imageWidth);
180+ PRINT_INT (imageHeight) ;
172181
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 )
176188 {
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++;
178195
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+ }
183201 }
184- #endif
185202
186- if ( pixelNum )
203+ // all pixel data is received
204+ if ( totalPixel == imageWidth*imageHeight )
187205 {
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
193208
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);
196211
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 ;
199214 }
200215}
201216
@@ -247,36 +262,28 @@ void print_speed(uint32_t count, uint32_t ms)
247262 tft.setTextColor (COLOR_WHITE);
248263}
249264
250- void bleuart_rx_callback (uint16_t conn_hdl)
265+ void bleuart_overflow_callback (uint16_t conn_hdl, uint16_t leftover )
251266{
252- (void ) conn_hdl;
253-
254- rxLastTime = millis ();
267+ Serial.println (" BLEUART rx buffer OVERFLOWED!" );
268+ Serial.println (" Please increase buffer size for bleuart" );
255269
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 )
258272 {
259- rxStartTime = millis ( );
273+ tft. setCursor ( 0 , imageHeight+ 5 );
260274
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!" );
264277
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" );
275280 }
281+
282+ bleuart_overflowed = true ;
276283}
277284
278285/* *
279- * Callback invoked when a connection is dropped
286+ * invoked when a connection is dropped
280287 * @param conn_handle connection where this event happens
281288 * @param reason is a BLE_HCI_STATUS_CODE which can be found in ble_hci.h
282289 */
@@ -289,6 +296,7 @@ void disconnect_callback(uint16_t conn_handle, uint8_t reason)
289296 tft.println (" Advertising ..." );
290297
291298 totalPixel = imageWidth = imageHeight = 0 ;
299+ bleuart_overflowed = false ;
292300
293301 bleuart.flush ();
294302}
0 commit comments