Skip to content

Commit 6263bcc

Browse files
committed
Extended timeouts, txStandBy changes
- For use in noisy or low signal scenarios - Allows user specified timeout period of extended duration - Modified txStandBy() and writeBlocking() functions to rely on a user defined timeout period, automatic retries and payload reUse
1 parent 0ddec52 commit 6263bcc

File tree

6 files changed

+363
-316
lines changed

6 files changed

+363
-316
lines changed

RF24.cpp

+25-18
Original file line numberDiff line numberDiff line change
@@ -471,25 +471,27 @@ bool RF24::write( const void* buf, uint8_t len )
471471
/****************************************************************************/
472472

473473
//For general use, the interrupt flags are not important to clear
474-
bool RF24::writeBlocking( const void* buf, uint8_t len )
474+
bool RF24::writeBlocking( const void* buf, uint8_t len, unsigned long timeout )
475475
{
476476
//Block until the FIFO is NOT full.
477477
//Keep track of the MAX retries and set auto-retry if seeing failures
478478
//This way the FIFO will fill up and allow blocking until packets go through
479479
//The radio will auto-clear everything in the FIFO as long as CE remains high
480480

481+
unsigned long timer = millis(); //Get the time that the payload transmission started
481482

482483
while ( (read_register(FIFO_STATUS) & _BV(FIFO_FULL))){ //Blocking only if FIFO is full. This will loop and block until TX is successful
483484

484-
if( get_status() & _BV(MAX_RT)){
485-
reUseTX(); //Set re-transmit
485+
if( get_status() & _BV(MAX_RT)){ //If MAX Retries have been reached
486+
reUseTX(); //Set re-transmit and clear the MAX_RT interrupt flag
486487
}
487-
488+
if(millis() - timer > timeout){ return 0; } //If this payload has exceeded the user-defined timeout, exit and return 0
488489
}
489-
//Start Writing
490-
startFastWrite(buf,len);
491490

492-
return 1;
491+
//Start Writing
492+
startFastWrite(buf,len); //Write the payload if a buffer is clear
493+
494+
return 1; //Return 1 to indicate successful transmission
493495
}
494496

495497

@@ -504,7 +506,6 @@ void RF24::reUseTX(){
504506

505507
/****************************************************************************/
506508

507-
//This is for when every bit of data is important
508509
bool RF24::writeFast( const void* buf, uint8_t len )
509510
{
510511
//Block until the FIFO is NOT full.
@@ -516,9 +517,7 @@ bool RF24::writeFast( const void* buf, uint8_t len )
516517
while ( (read_register(FIFO_STATUS) & _BV(FIFO_FULL))){ //Blocking only if FIFO is full. This will loop and block until TX is successful
517518

518519
if( get_status() & _BV(MAX_RT)){
519-
write_register(STATUS,_BV(MAX_RT) ); //Clear max retry flag
520520
reUseTX(); //Set re-transmit
521-
delayMicroseconds(15); //CE needs to stay high for 10us, for TX_REUSE to engage
522521
return 0; //Return 0. The previous payload has been retransmitted
523522
//From the user perspective, if you get a 0, just keep trying to send the same payload
524523
}
@@ -565,23 +564,31 @@ void RF24::startWrite( const void* buf, uint8_t len )
565564
}
566565

567566
bool RF24::txStandBy(){
568-
txStandBy(0);
567+
while( ! (read_register(FIFO_STATUS) & _BV(TX_EMPTY)) ){
568+
if( get_status() & _BV(MAX_RT)){
569+
write_register(STATUS,_BV(MAX_RT) );
570+
flush_tx(); //Non blocking, flush the data
571+
ce(LOW); //Set STANDBY-I mode
572+
return 0;
573+
}
574+
}
575+
576+
ce(LOW); //Set STANDBY-I mode
577+
return 1;
569578
}
570579

571-
bool RF24::txStandBy(bool block){
580+
bool RF24::txStandBy(unsigned long timeout){
581+
582+
unsigned long start = millis();
572583

573584
while( ! (read_register(FIFO_STATUS) & _BV(TX_EMPTY)) ){
574585
if( get_status() & _BV(MAX_RT)){
575586
write_register(STATUS,_BV(MAX_RT) );
576-
if(block){
587+
if(timeout > 0){
577588
ce(LOW); //Set re-transmit
578589
ce(HIGH);
579-
delayMicroseconds(15);
590+
if(millis() - start > timeout){ ce(LOW); flush_tx(); return 0; }
580591

581-
}else{
582-
flush_tx(); //Non blocking, flush the data
583-
ce(LOW); //Set STANDBY-I mode
584-
return 0;
585592
}
586593
}
587594
}

RF24.h

+104-62
Original file line numberDiff line numberDiff line change
@@ -152,13 +152,6 @@ class RF24
152152
*/
153153
uint8_t flush_rx(void);
154154

155-
/**
156-
* Empty the transmit buffer
157-
*
158-
* @return Current value of status register
159-
*/
160-
uint8_t flush_tx(void);
161-
162155
/**
163156
* Retrieve the current status of the chip
164157
*
@@ -270,7 +263,7 @@ class RF24
270263
void stopListening(void);
271264

272265
/**
273-
* @note Optimization: Improved performance and reliability
266+
* @note Optimization: Improved performance slightly
274267
* Write to the open writing pipe
275268
*
276269
* Be sure to call openWritingPipe() first to set the destination
@@ -293,56 +286,57 @@ class RF24
293286
bool write( const void* buf, uint8_t len );
294287

295288
/**
296-
* @note Optimization: New Command
297-
* Write to the open writing pipe filling up the FIFO buffers
298-
*
299-
* Be sure to call openWritingPipe() first to set the destination
300-
* of where to write to.
301-
*
289+
* @note Optimization: New Command *
302290
* This will not block until the 3 FIFO buffers are filled with data.
303291
* Once the FIFOs are full, writeFast will simply wait for success or
304292
* timeout, and return 1 or 0 respectively. From a user perspective, just
305293
* keep trying to send the same data. The library will keep auto retrying
306294
* the current payload using the built in functionality.
307295
*
308-
* The maximum size of data written is the fixed payload size, see
309-
* getPayloadSize(). However, you can write less, and the remainder
310-
* will just be filled with zeroes.
311-
*
312296
* ONLY max retry interrupt flags will be cleared when writeFast is called
313297
*
298+
* @code
299+
* Example (Partial blocking):
300+
*
301+
* radio.writeFast(&buf,32); // Writes 1 payload to the buffers
302+
* txStandBy(); // Returns 0 if failed. 1 if success. Blocks only until MAX_RT timeout or success. Data flushed on fail.
303+
* @endcode
304+
*
305+
* @see txStandBy()
306+
* @see write()
307+
* @see writeBlocking()
308+
*
314309
* @param buf Pointer to the data to be sent
315310
* @param len Number of bytes to be sent
316311
* @return True if the payload was delivered successfully false if not
317312
*/
318313
bool writeFast( const void* buf, uint8_t len );
319314

320-
/**
321-
* @note Optimization: New Command
322-
* Write to the open writing pipe
323-
*
324-
* Be sure to call openWritingPipe() first to set the destination
325-
* of where to write to.
326-
*
327-
* This will not block until the 3 FIFO buffers are filled with data or
328-
* a timeout is detected. If so the library will auto retry until a new
329-
* payload is written or the TX buffers are flushed. Interrupts can be
330-
* used to control the timeout period.
331-
*
332-
* This will never return a 0. It will not return until a packet is
333-
* loaded successfully into the FIFO and TX is complete.
334-
*
335-
* The maximum size of data written is the fixed payload size, see
336-
* getPayloadSize(). However, you can write less, and the remainder
337-
* will just be filled with zeroes.
338-
*
339-
* ONLY max retry interrupt flags will be cleared when writeBlocking is called
340-
*
341-
* @param buf Pointer to the data to be sent
342-
* @param len Number of bytes to be sent
343-
* @return True if the payload was delivered successfully false if not
344-
*/
345-
bool writeBlocking( const void* buf, uint8_t len );
315+
/**
316+
* @note Optimization: New Command
317+
* This function extends the auto-retry mechanism to any specified duration.
318+
* It will not block until the 3 FIFO buffers are filled with data.
319+
* If so the library will auto retry until a new payload is written
320+
* or the user specified timeout period is reached.
321+
*
322+
* ONLY max retry interrupt flags will be cleared when writeBlocking is called
323+
* @code
324+
* Example (Full blocking):
325+
*
326+
* radio.writeBlocking(&buf,32,1000); //Writes 1 payload to the buffers with extended timeout of 1 second
327+
* txStandBy(1000); //Returns 0 if failed after timeout period. 1 if success.
328+
* //Blocks only until user timeout or success. Data flushed on fail.
329+
* @endcode
330+
* @see txStandBy()
331+
* @see write()
332+
* @see writeFast()
333+
*
334+
* @param buf Pointer to the data to be sent
335+
* @param len Number of bytes to be sent
336+
* @param timeout User defined timeout in milliseconds.
337+
* @return True if the payload was delivered successfully false if not
338+
*/
339+
bool writeBlocking( const void* buf, uint8_t len, uint32_t timeout );
346340

347341
/**
348342
* @note Optimization: New Command
@@ -355,29 +349,42 @@ class RF24
355349
* the manufacturer to drop the radio out of TX or STANDBY-II mode if there is
356350
* time enough between sends for the FIFOs to empty.
357351
*
358-
* @note This does NOT need to be called when using per-payload noACK commands,
359-
* or when using the regular write command since it is only capable of single
360-
* payload transmission..
361-
* Per the datasheet, the radio will automatically engage STANDBY-I mode when
362-
* using the W_TX_PAYLOAD_NOACK command.
352+
* Relies on built-in auto retry functionality.
363353
*
364354
* @code
365-
* Example:
355+
* Example (Partial blocking):
356+
*
366357
* radio.writeFast(&buf,32);
367358
* radio.writeFast(&buf,32);
368359
* radio.writeFast(&buf,32); //Fills the FIFO buffers up
369-
* bool ok = txStandBy(0); //Returns 0 if failed. 1 if success.
370-
* //Blocks only until timeout or success. Data flushed on fail.
360+
* bool ok = txStandBy(); //Returns 0 if failed. 1 if success.
361+
* //Blocks only until MAX_RT timeout or success. Data flushed on fail.
362+
* @endcode
363+
* @see txStandBy(unsigned long timeout)
364+
* @return True if transmission is successful
371365
*
372-
* Using txStandBy(1) will not return until the data is transmitted. It will never return 0.
366+
*/
367+
bool txStandBy();
368+
369+
/**
370+
* @note Optimization: New Command
373371
*
372+
* This function allows extended blocking and auto-retries per a user defined timeout
373+
* @code
374+
* Fully Blocking Example:
375+
*
376+
* radio.writeFast(&buf,32);
377+
* radio.writeFast(&buf,32);
378+
* radio.writeFast(&buf,32); //Fills the FIFO buffers up
379+
* bool ok = txStandBy(1000); //Returns 0 if failed after 1 second of retries. 1 if success.
380+
* //Blocks only until user defined timeout or success. Data flushed on fail.
374381
* @endcode
375382
*
383+
* @param timeout Number of milliseconds to retry failed payloads
376384
* @return True if transmission is successful
377385
*
378386
*/
379-
bool txStandBy();
380-
bool txStandBy(bool block);
387+
bool txStandBy(unsigned long timeout);
381388

382389
/**
383390
* Non-blocking write to the open writing pipe used for buffered writes
@@ -386,7 +393,9 @@ class RF24
386393
* will remain in TX or STANDBY-II Mode until a txStandBy() command is issued.
387394
* This allows the chip to be used to its full potential in TX mode.
388395
*
396+
* @see write()
389397
* @see writeFast()
398+
* @see startWrite()
390399
* @see writeBlocking()
391400
*
392401
* @param buf Pointer to the data to be sent
@@ -401,9 +410,14 @@ class RF24
401410
* @note Optimization: The available functino now checks the FIFO
402411
* buffers directly for data instead of relying of interrupt flags.
403412
*
404-
* @note: Interrupt flags will not be cleared until a payload is
413+
* @note Interrupt flags will not be cleared until a payload is
405414
* actually read from the FIFO
406415
*
416+
* @see txStandBy()
417+
* @see startWrite()
418+
* @see write()
419+
* @see writeFast()
420+
*
407421
* @return True if there is a payload available, false if none is
408422
*/
409423
bool available(void);
@@ -422,7 +436,7 @@ class RF24
422436
*
423437
* @param buf Pointer to a buffer where the data should be written
424438
* @param len Maximum number of bytes to read into the buffer
425-
* @return No return value. Use available.
439+
* @return No return value. Use available().
426440
*/
427441
void read( void* buf, uint8_t len );
428442

@@ -526,7 +540,7 @@ class RF24
526540
* For dynamic payloads, this pulls the size of the payload off
527541
* the chip
528542
*
529-
* Optimization: Corrupt packets are now detected and flushed per the
543+
* @note Optimization: Corrupt packets are now detected and flushed per the
530544
* manufacturer.
531545
*
532546
* @return Payload length of last-received dynamic payload
@@ -663,7 +677,7 @@ class RF24
663677
* To return to normal power mode, either write() some data or
664678
* startListening, or powerUp().
665679
*
666-
* Optimization: The radio will never enter power down unless instructed
680+
* @note Optimization: The radio will never enter power down unless instructed
667681
* by the MCU via this command.
668682
*/
669683
void powerDown(void);
@@ -681,10 +695,12 @@ class RF24
681695
* Just like write(), but it returns immediately. To find out what happened
682696
* to the send, catch the IRQ and then call whatHappened().
683697
*
684-
* @note Optimization: This function again behaves as it did previously.
685-
* startFastWrite() has been moved to an internal function
698+
* @note Optimization: This function again behaves as it did previously for backwards-compatibility.
699+
* with user code. The library uses startFastWrite() internally.
700+
* This is mainly used for single-payload transactions.
686701
*
687702
* @see write()
703+
* @see writeFast()
688704
* @see startFastWrite()
689705
* @see whatHappened()
690706
*
@@ -708,6 +724,8 @@ class RF24
708724
*
709725
* @note This is to be used AFTER auto-retry fails if wanting to resend
710726
* using the built-in payload reuse features.
727+
* After issuing reUseTX(), it will keep reending the same payload forever or until
728+
* a payload is written to the FIFO, or a flush_tx command is given.
711729
*/
712730
void reUseTX();
713731

@@ -735,7 +753,7 @@ class RF24
735753
*
736754
* @note Optimization: Calling this function NO LONGER clears the interrupt
737755
* flag. The new functionality checks the RX FIFO buffer for an ACK payload
738-
* instead of relying on interrupt flags.
756+
* instead of relying on interrupt flags.Reading the payload will clear the flags.
739757
*
740758
* @return True if an ack payload is available.
741759
*/
@@ -766,6 +784,13 @@ class RF24
766784
*/
767785
void whatHappened(bool& tx_ok,bool& tx_fail,bool& rx_ready);
768786

787+
/**
788+
* Empty the transmit buffer
789+
*
790+
* @return Current value of status register
791+
*/
792+
uint8_t flush_tx(void);
793+
769794
/**
770795
* Test whether there was a carrier on the line for the
771796
* previous listening period.
@@ -797,6 +822,11 @@ class RF24
797822
*/
798823
bool isValid() { return ce_pin != 0xff && csn_pin != 0xff; }
799824

825+
/**
826+
* @see txStandBy()
827+
*/
828+
bool txStandBy(bool block);
829+
800830
/**@}*/
801831
};
802832

@@ -824,6 +854,18 @@ class RF24
824854
* with the receiver displaying the payload count. (32Byte Payloads)
825855
*/
826856

857+
/**
858+
* @example TransferTimeouts.ino
859+
* Updated: TMRh20
860+
* This example demonstrates the use of and extended timeout period and
861+
* auto-retries/auto-reUse to increase reliability in noisy or low signal scenarios.
862+
*
863+
* Write this sketch to two different nodes. Put one of the nodes into 'transmit'
864+
* mode by connecting with the serial monitor and sending a 'T'. The data
865+
* transfer will begin, with the receiver displaying the payload count and the
866+
* data transfer rate.
867+
*/
868+
827869
/**
828870
* @example nordic_fob.pde
829871
*

0 commit comments

Comments
 (0)