1414
1515 - handlePinMode calls Firmata::setPinMode
1616
17- Last updated October 16th, 2016
17+ Last updated March 16th, 2020
1818*/
1919
2020#include " SerialFirmata.h"
2121
22+ // The RX and TX hardware FIFOs of the ESP8266 hold 128 bytes that can be
23+ // extended using interrupt handlers. The Arduino constants are not available
24+ // for the ESP8266 platform.
25+ #if !defined(SERIAL_RX_BUFFER_SIZE) && defined(UART_TX_FIFO_SIZE)
26+ #define SERIAL_RX_BUFFER_SIZE UART_TX_FIFO_SIZE
27+ #endif
28+
29+
2230SerialFirmata::SerialFirmata ()
2331{
2432#if defined(SoftwareSerial_h)
@@ -29,6 +37,12 @@ SerialFirmata::SerialFirmata()
2937#endif
3038
3139 serialIndex = -1 ;
40+
41+ #if defined(FIRMATA_SERIAL_RX_DELAY)
42+ for (byte i = 0 ; i < SERIAL_READ_ARR_LEN; i++) {
43+ maxRxDelay[i] = FIRMATA_SERIAL_RX_DELAY; // @todo provide setter
44+ }
45+ #endif
3246}
3347
3448boolean SerialFirmata::handlePinMode (byte pin, int mode)
@@ -56,13 +70,17 @@ boolean SerialFirmata::handleSysex(byte command, byte argc, byte *argv)
5670 Stream *serialPort;
5771 byte mode = argv[0 ] & SERIAL_MODE_MASK;
5872 byte portId = argv[0 ] & SERIAL_PORT_ID_MASK;
73+ if (portId >= SERIAL_READ_ARR_LEN) return false ;
5974
6075 switch (mode) {
6176 case SERIAL_CONFIG:
6277 {
6378 long baud = (long )argv[1 ] | ((long )argv[2 ] << 7 ) | ((long )argv[3 ] << 14 );
6479 serial_pins pins;
65-
80+ #if defined(FIRMATA_SERIAL_RX_DELAY)
81+ lastBytesAvailable[portId] = 0 ;
82+ lastBytesReceived[portId] = 0 ;
83+ #endif
6684 if (portId < 8 ) {
6785 serialPort = getPortFromId (portId);
6886 if (serialPort != NULL ) {
@@ -229,6 +247,10 @@ void SerialFirmata::reset()
229247 serialIndex = -1 ;
230248 for (byte i = 0 ; i < SERIAL_READ_ARR_LEN; i++) {
231249 serialBytesToRead[i] = 0 ;
250+ #if defined(FIRMATA_SERIAL_RX_DELAY)
251+ lastBytesAvailable[i] = 0 ;
252+ lastBytesReceived[i] = 0 ;
253+ #endif
232254 }
233255}
234256
@@ -302,6 +324,10 @@ void SerialFirmata::checkSerial()
302324
303325 if (serialIndex > -1 ) {
304326
327+ #if defined(FIRMATA_SERIAL_RX_DELAY)
328+ unsigned long currentMillis = millis ();
329+ #endif
330+
305331 // loop through all reporting (READ_CONTINUOUS) serial ports
306332 for (byte i = 0 ; i < serialIndex + 1 ; i++) {
307333 portId = reportSerial[i];
@@ -316,27 +342,53 @@ void SerialFirmata::checkSerial()
316342 continue ;
317343 }
318344#endif
319- if (serialPort->available () > 0 ) {
320- Firmata.write (START_SYSEX);
321- Firmata.write (SERIAL_MESSAGE);
322- Firmata.write (SERIAL_REPLY | portId);
323-
324- if (bytesToRead == 0 || (serialPort->available () <= bytesToRead)) {
325- numBytesToRead = serialPort->available ();
345+ int bytesAvailable = serialPort->available ();
346+ if (bytesAvailable > 0 ) {
347+ #if defined(FIRMATA_SERIAL_RX_DELAY)
348+ if (bytesAvailable > lastBytesAvailable[portId]) {
349+ lastBytesReceived[portId] = currentMillis;
350+ }
351+ lastBytesAvailable[portId] = bytesAvailable;
352+ #endif
353+ if (bytesToRead <= 0 || (bytesAvailable <= bytesToRead)) {
354+ numBytesToRead = bytesAvailable;
326355 } else {
327356 numBytesToRead = bytesToRead;
328357 }
329-
358+ #if defined(FIRMATA_SERIAL_RX_DELAY)
359+ if (maxRxDelay[portId] >= 0 && numBytesToRead > 0 ) {
360+ // read and send immediately only if
361+ // - expected bytes are unknown and the receive buffer has reached 50 %
362+ // - expected bytes are available
363+ // - maxRxDelay has expired since last receive (or time counter wrap)
364+ if (!((bytesToRead <= 0 && bytesAvailable >= SERIAL_RX_BUFFER_SIZE/2 )
365+ || (bytesToRead > 0 && bytesAvailable >= bytesToRead)
366+ || (maxRxDelay[portId] > 0 && (currentMillis < lastBytesReceived[portId] || (currentMillis - lastBytesReceived[portId]) >= maxRxDelay[portId])))) {
367+ // delay
368+ numBytesToRead = 0 ;
369+ }
370+ }
371+ #endif
330372 // relay serial data to the serial device
331- while (numBytesToRead > 0 ) {
332- serialData = serialPort->read ();
333- Firmata.write (serialData & 0x7F );
334- Firmata.write ((serialData >> 7 ) & 0x7F );
335- numBytesToRead--;
373+ if (numBytesToRead > 0 ) {
374+ #if defined(FIRMATA_SERIAL_RX_DELAY)
375+ lastBytesAvailable[portId] -= numBytesToRead;
376+ #endif
377+ Firmata.write (START_SYSEX);
378+ Firmata.write (SERIAL_MESSAGE);
379+ Firmata.write (SERIAL_REPLY | portId);
380+
381+ // relay serial data to the serial device
382+ while (numBytesToRead > 0 ) {
383+ serialData = serialPort->read ();
384+ Firmata.write (serialData & 0x7F );
385+ Firmata.write ((serialData >> 7 ) & 0x7F );
386+ numBytesToRead--;
387+ }
388+
389+ Firmata.write (END_SYSEX);
336390 }
337- Firmata.write (END_SYSEX);
338391 }
339-
340392 }
341393 }
342394}
0 commit comments