Commit 92a19af8 authored by TMRh20's avatar TMRh20

enableDynamicAck(), Single NOACK, default RT,

- Added new function: enableDynamicAck()  to enable single-write NOACK
payloads (merge closer with gcopeland fork)
- Added single NOACK writes for write(), writeFast(), startWrite() and
startFastWrite()
- powerUp() now checks to see if radio is powered on. No delay if
powered up.
- radio must still be powered up manually if powered down manually
- use setRetries function in begin()
- set CE low on powerDown
- updated readme
parent 07eb9f87
......@@ -2,20 +2,23 @@
Design Goals: This library is designed to be...
* More compliant with the manufacturer specified operation of the chip
* More compliant with the manufacturer specified operation of the chip, while allowing advanced users
* to work outside the reccommended operation.
* Utilize the capabilities of the radio to their full potential via Arduino
* More reliable and feature rich
* Easy for beginners to use
* Easy for beginners to use, with well documented examples and features
* Consumed with a public interface that's similiar to other Arduino standard libraries
* Built against the standard SPI library.
March 2014: Optimization begun
April 2014: Optimization nearing completion
* The library has been tweaked to allow full use of the FIFO buffers for maximum transfer speeds
* Changes to read() functionality have increased reliability and response
* Extended timeout periods have been added to aid in noisy or otherwise unreliable environments
* Delays have been removed where possible to ensure maximum efficiency
* Arduino Due fully supported with extended SPI functions
* More! See the links below and class documentation for more info.
April 2014: Official Release: Still some work to do, but most benefits have been realized
* The library has been tweaked to allow full use of the FIFO buffers for maximum transfer speeds
* Changes to read() and available () functionality have increased reliability and response
* Extended timeout periods have been added to aid in noisy or otherwise unreliable environments
* Delays have been removed where possible to ensure maximum efficiency
* Full Due support with extended SPI functions
* ATTiny 24/44/84 25/45/85 now supported.
* More! See the links below and class documentation for more info.
Please refer to:
......@@ -27,4 +30,11 @@ Please refer to:
This chip uses the SPI bus, plus two chip control pins. Remember that pin 10 must still remain an output, or
the SPI hardware will go into 'slave' mode.
Supported Boards:
* Uno, Nano, etc (328 based boards)
* Mega Types (2560, 1280, etc)
* ARM (Arduino Due) via extended SPI methods
* ATTiny 24/44/84 25/45/85
* See the [documentation](http://tmrh20.github.io/) for more info
\ No newline at end of file
......@@ -135,7 +135,7 @@ uint8_t RF24::write_register(uint8_t reg, uint8_t value)
/****************************************************************************/
uint8_t RF24::write_payload(const void* buf, uint8_t data_len)
uint8_t RF24::write_payload(const void* buf, uint8_t data_len, const uint8_t writeType)
{
uint8_t status;
const uint8_t* current = reinterpret_cast<const uint8_t*>(buf);
......@@ -147,7 +147,7 @@ uint8_t RF24::write_payload(const void* buf, uint8_t data_len)
#if defined (__arm__)
status = SPI.transfer(csn_pin, W_TX_PAYLOAD , SPI_CONTINUE);
status = SPI.transfer(csn_pin, writeType , SPI_CONTINUE);
if(blank_len){
while ( data_len--){
......@@ -160,14 +160,14 @@ uint8_t RF24::write_payload(const void* buf, uint8_t data_len)
}else{
while( --data_len ){
SPI.transfer(csn_pin,*current++, SPI_CONTINUE);
}
}
SPI.transfer(csn_pin,*current);
}
#else
csn(LOW);
status = SPI.transfer( W_TX_PAYLOAD );
status = SPI.transfer( writeType );
while ( data_len-- ) {
SPI.transfer(*current++);
}
......@@ -205,7 +205,7 @@ uint8_t RF24::read_payload(void* buf, uint8_t data_len)
}
while ( --blank_len ){
SPI.transfer(csn_pin,0xFF, SPI_CONTINUE);
}
}
SPI.transfer(csn_pin,0xFF);
}else{
while ( --data_len ){
......@@ -346,7 +346,7 @@ void RF24::print_address_register(const char* name, uint8_t reg, uint8_t qty)
/****************************************************************************/
RF24::RF24(uint8_t _cepin, uint8_t _cspin):
ce_pin(_cepin), csn_pin(_cspin), wide_band(true), p_variant(false),
ce_pin(_cepin), csn_pin(_cspin), wide_band(false), p_variant(false),
payload_size(32), ack_payload_available(false), dynamic_payloads_enabled(false),
pipe0_reading_address(0)
{
......@@ -466,8 +466,6 @@ void RF24::begin(void)
csn(HIGH);
#endif
// Must allow the radio time to settle else configuration bits will not necessarily stick.
// This is actually only required following power up but some settling time also appears to
// be required after resets too. For full coverage, we'll always assume the worst.
......@@ -479,7 +477,7 @@ void RF24::begin(void)
// Set 1500uS (minimum for 32B payload in ESB@250KBPS) timeouts, to make testing a little easier
// WARNING: If this is ever lowered, either 250KBS mode with AA is broken or maximum packet
// sizes must never be used. See documentation for a more complete explanation.
write_register(SETUP_RETR,(B0100 << ARD) | (B1111 << ARC));
setRetries(5,15);
// Restore our default PA level
setPALevel( RF24_PA_MAX ) ;
......@@ -516,9 +514,10 @@ void RF24::begin(void)
flush_rx();
flush_tx();
powerUp();
delay(5);
//Enable PTX, do not write CE high so radio will remain in standby I mode ( 130us max to transition to RX or TX instead of 1500us from powerUp )
powerUp(); //Power up by default when begin() is called
// Enable PTX, do not write CE high so radio will remain in standby I mode ( 130us max to transition to RX or TX instead of 1500us from powerUp )
// PTX should use only 22uA of power
write_register(CONFIG, ( read_register(CONFIG) ) & ~_BV(PRIM_RX) );
......@@ -528,7 +527,8 @@ void RF24::begin(void)
void RF24::startListening(void)
{
write_register(CONFIG, read_register(CONFIG) | _BV(PWR_UP) | _BV(PRIM_RX));
powerUp();
write_register(CONFIG, read_register(CONFIG) | _BV(PRIM_RX));
write_register(STATUS, _BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) );
// Restore the pipe0 adddress, if exists
......@@ -559,6 +559,7 @@ void RF24::stopListening(void)
void RF24::powerDown(void)
{
ce(LOW); // Guarantee CE is low on powerDown
write_register(CONFIG,read_register(CONFIG) & ~_BV(PWR_UP));
}
......@@ -567,17 +568,23 @@ void RF24::powerDown(void)
//Power up now. Radio will not power down unless instructed by MCU for config changes etc.
void RF24::powerUp(void)
{
write_register(CONFIG,read_register(CONFIG) | _BV(PWR_UP));
delay(5);
uint8_t cfg = read_register(CONFIG);
// if not powered up then power up and wait for the radio to initialize
if (!(cfg & _BV(PWR_UP))){
write_register(CONFIG,read_register(CONFIG) | _BV(PWR_UP));
delayMicroseconds(1500);
}
}
/******************************************************************/
//Similar to the previous write, clears the interrupt flags
bool RF24::write( const void* buf, uint8_t len )
bool RF24::write( const void* buf, uint8_t len, const bool multicast )
{
//Start Writing
startWrite(buf,len);
startWrite(buf,len,multicast);
//Wait until complete or failed
//ACK payloads that are handled improperly will cause this to hang
......@@ -595,6 +602,9 @@ bool RF24::write( const void* buf, uint8_t len )
return 1;
}
bool RF24::write( const void* buf, uint8_t len ){
write(buf,len,0);
}
/****************************************************************************/
//For general use, the interrupt flags are not important to clear
......@@ -617,7 +627,7 @@ bool RF24::writeBlocking( const void* buf, uint8_t len, uint32_t timeout )
}
//Start Writing
startFastWrite(buf,len); //Write the payload if a buffer is clear
startFastWrite(buf,len,0); //Write the payload if a buffer is clear
return 1; //Return 1 to indicate successful transmission
}
......@@ -638,7 +648,7 @@ void RF24::reUseTX(){
/****************************************************************************/
bool RF24::writeFast( const void* buf, uint8_t len )
bool RF24::writeFast( const void* buf, uint8_t len, const bool multicast )
{
//Block until the FIFO is NOT full.
//Keep track of the MAX retries and set auto-retry if seeing failures
......@@ -656,12 +666,14 @@ bool RF24::writeFast( const void* buf, uint8_t len )
}
//Start Writing
startFastWrite(buf,len);
startFastWrite(buf,len,multicast);
return 1;
}
bool RF24::writeFast( const void* buf, uint8_t len ){
writeFast(buf,len,0);
}
/****************************************************************************/
......@@ -670,9 +682,10 @@ bool RF24::writeFast( const void* buf, uint8_t len )
//Otherwise we enter Standby-II mode, which is still faster than standby mode
//Also, we remove the need to keep writing the config register over and over and delaying for 150 us each time if sending a stream of data
void RF24::startFastWrite( const void* buf, uint8_t len ){ //TMRh20
void RF24::startFastWrite( const void* buf, uint8_t len, const bool multicast){ //TMRh20
write_payload( buf,len);
//write_payload( buf,len);
write_payload( buf, len,multicast?static_cast<uint8_t>(W_TX_PAYLOAD_NO_ACK):static_cast<uint8_t>(W_TX_PAYLOAD) ) ;
ce(HIGH);
}
......@@ -680,11 +693,12 @@ void RF24::startFastWrite( const void* buf, uint8_t len ){ //TMRh20
//Added the original startWrite back in so users can still use interrupts, ack payloads, etc
//Allows the library to pass all tests
void RF24::startWrite( const void* buf, uint8_t len ){
void RF24::startWrite( const void* buf, uint8_t len, const bool multicast ){
// Send the payload
write_payload( buf, len );
//write_payload( buf, len );
write_payload( buf, len,multicast?static_cast<uint8_t>(W_TX_PAYLOAD_NO_ACK):static_cast<uint8_t>(W_TX_PAYLOAD) ) ;
ce(HIGH);
ce(LOW);
......@@ -933,6 +947,27 @@ void RF24::enableAckPayload(void)
/****************************************************************************/
void RF24::enableDynamicAck(void){
//
// enable dynamic ack features
//
write_register(FEATURE,read_register(FEATURE) | _BV(EN_DYN_ACK) );
// If it didn't work, the features are not enabled
if ( ! read_register(FEATURE) & _BV(EN_DYN_ACK) ){
// So enable them and try again
toggle_features();
write_register(FEATURE,read_register(FEATURE) | _BV(EN_DYN_ACK) );
}
IF_SERIAL_DEBUG(printf("FEATURE=%i\r\n",read_register(FEATURE)));
}
/****************************************************************************/
void RF24::writeAckPayload(uint8_t pipe, const void* buf, uint8_t len)
{
const uint8_t* current = reinterpret_cast<const uint8_t*>(buf);
......
......@@ -256,6 +256,22 @@ public:
*/
void powerUp(void) ;
/**
* Write for single NOACK writes. Disables acknowledgements/autoretries for a single write.
*
* @note enableDynamicAck() must be called to enable this feature
*
* Can be used with enableAckPayload() to request a response
* @see enableDynamicAck()
* @see setAutoAck()
* @see write()
*
* @param buf Pointer to the data to be sent
* @param len Number of bytes to be sent
* @param multicast Request ACK (0), NOACK (1)
*/
bool write( const void* buf, uint8_t len, const bool multicast );
/**
* @note Optimization: New Command *
* This will not block until the 3 FIFO buffers are filled with data.
......@@ -289,6 +305,19 @@ public:
*/
bool writeFast( const void* buf, uint8_t len );
/**
* WriteFast for single NOACK writes. Disables acknowledgements/autoretries for a single write.
*
* @note enableDynamicAck() must be called to enable this feature
* @see enableDynamicAck()
* @see setAutoAck()
*
* @param buf Pointer to the data to be sent
* @param len Number of bytes to be sent
* @param multicast Request ACK (0) or NOACK (1)
*/
bool writeFast( const void* buf, uint8_t len, const bool multicast );
/**
* @note Optimization: New Command
* This function extends the auto-retry mechanism to any specified duration.
......@@ -383,6 +412,20 @@ public:
*/
void writeAckPayload(uint8_t pipe, const void* buf, uint8_t len);
/**
* Enable dynamic ACKs (single write multicasting) for chosen messages
*
* @note To enable full multicasting or per-pipe multicast, use setAutoAck()
*
* @warning This MUST be called prior to attempting single write NOACK calls
* @code
* radio.enableDynamicAck();
* radio.write(&data,32,1); // Sends a payload with no acknowledgement requested
* radio.write(&data,32,0); // Sends a payload using auto-retry/autoACK
* @endcode
*/
void enableDynamicAck();
/**
* Determine if an ack payload was received in the most recent call to
* write().
......@@ -424,11 +467,16 @@ public:
* @see startWrite()
* @see writeBlocking()
*
* For single noAck writes see:
* @see enableDynamicAck()
* @see setAutoAck()
*
* @param buf Pointer to the data to be sent
* @param len Number of bytes to be sent
* @param multicast Request ACK (0) or NOACK (1)
* @return True if the payload was delivered successfully false if not
*/
void startFastWrite( const void* buf, uint8_t len );
void startFastWrite( const void* buf, uint8_t len, const bool multicast );
/**
* Non-blocking write to the open writing pipe
......@@ -445,11 +493,16 @@ public:
* @see startFastWrite()
* @see whatHappened()
*
* For single noAck writes see:
* @see enableDynamicAck()
* @see setAutoAck()
*
* @param buf Pointer to the data to be sent
* @param len Number of bytes to be sent
* @param multicast Request ACK (0) or NOACK (1)
*
*/
void startWrite( const void* buf, uint8_t len );
void startWrite( const void* buf, uint8_t len, const bool multicast );
/**
* Optimization: New Command
......@@ -776,7 +829,7 @@ private:
* @param len Number of bytes to be sent
* @return Current value of status register
*/
uint8_t write_payload(const void* buf, uint8_t len);
uint8_t write_payload(const void* buf, uint8_t len, const uint8_t writeType);
/**
* Read the receive payload
......@@ -1003,18 +1056,18 @@ private:
* @section Goals Design Goals
*
* This library fork is designed to be...
* @li More compliant with the manufacturer specified operation of the chip
* @li More compliant with the manufacturer specified operation of the chip, while allowing advanced users
* to work outside the reccommended operation.
* @li Utilize the capabilities of the radio to their full potential via Arduino
* @li More reliable, responsive and feature rich
* @li Easy for beginners to use
* @li Easy for beginners to use, with well documented examples and features
* @li Consumed with a public interface that's similiar to other Arduino standard libraries
*
* @section News News
*
* <b>March 2014: Optimization begun<br>
* April 2014: Optimization nearing completion </b><br>
* <b>April 2014: Official Release: Still some work to do, but most benefits have been realized </b><br>
* - The library has been tweaked to allow full use of the FIFO buffers for maximum transfer speeds
* - Changes to read() functionality have increased reliability and response
* - Changes to read() and available () functionality have increased reliability and response
* - Extended timeout periods have been added to aid in noisy or otherwise unreliable environments
* - Delays have been removed where possible to ensure maximum efficiency
* - Full Due support with extended SPI functions
......
/*
Copyright (c) 2007 Stefan Engelke <mbox@stefanengelke.de>
Portions Copyright (C) 2011 Greg Copeland
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use, copy,
modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use, copy,
modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
......@@ -117,6 +118,7 @@
/* P model memory Map */
#define RPD 0x09
#define W_TX_PAYLOAD_NO_ACK 0xB0
/* P model bit Mnemonics */
#define RF_DR_LOW 5
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment