Commit 9da3eac0 authored by TMRh20's avatar TMRh20

Fix: Multicast pipe0 address handling issue

Previous behaviour:
1. Radio #1: Pipe 0 opened for writing (Address1), pipe 1 opened for
reading (Address2)
2. The radio would end up listening on the following pipes/addresses,
because pipe0 was not assigned a separate reading address.
Pipe0: Address1
Pipe1: Address2
3. This is generally not a problem with 2 radios, but when multicasting
with three. If two of the radios transmit to the same address, then
start listening, all three radios will be listening to the same address
on pipe0, unless pipe0 has been assigned a separate reading address

New behaviour:
1. Radio #1: Pipe 0 opened for writing (Address1), pipe 1 opened for
reading (Address2)
2. When calling radio.startListening() pipe0 is closed, because it is
not assigned a reading address
3. Pipe0 is re-opened for writing only, unless a reading address is
assigned to pipe0

This wouldn't really affect things while using auto-ack, because two
radios should not be writing to the same pipe/address.

- Add closeReadingPipe for RPi
- Also adjusted timing for startListening();
- Fix failure detect variable on RPi
parent 9e12c236
......@@ -510,7 +510,9 @@ void RF24::startListening(void)
// Restore the pipe0 adddress, if exists
if (pipe0_reading_address[0] > 0){
write_register(RX_ADDR_P0, pipe0_reading_address, addr_width);
write_register(RX_ADDR_P0, pipe0_reading_address, addr_width);
}else{
closeReadingPipe(0);
}
// Flush buffers
......@@ -519,23 +521,30 @@ void RF24::startListening(void)
// Go!
ce(HIGH);
}
/****************************************************************************/
static const uint8_t child_pipe_enable[] PROGMEM =
{
ERX_P0, ERX_P1, ERX_P2, ERX_P3, ERX_P4, ERX_P5
};
void RF24::stopListening(void)
{
ce(LOW);
//#if defined(__arm__)
delayMicroseconds(140);
//#endif
#if defined(__arm__)
delayMicroseconds(300);
#endif
delayMicroseconds(130);
flush_tx();
//flush_rx();
write_register(CONFIG, ( read_register(CONFIG) ) & ~_BV(PRIM_RX) );
delayMicroseconds(140); //Found that adding this delay back actually increases response time
write_register(EN_RXADDR,read_register(EN_RXADDR) | _BV(pgm_read_byte(&child_pipe_enable[0]))); // Enable RX on pipe0
delayMicroseconds(100);
}
/****************************************************************************/
......@@ -865,7 +874,8 @@ void RF24::openWritingPipe(uint64_t value)
write_register(RX_ADDR_P0, reinterpret_cast<uint8_t*>(&value), addr_width);
write_register(TX_ADDR, reinterpret_cast<uint8_t*>(&value), addr_width);
//const uint8_t max_payload_size = 32;
//write_register(RX_PW_P0,min(payload_size,max_payload_size));
write_register(RX_PW_P0,payload_size);
......@@ -894,10 +904,7 @@ static const uint8_t child_payload_size[] PROGMEM =
{
RX_PW_P0, RX_PW_P1, RX_PW_P2, RX_PW_P3, RX_PW_P4, RX_PW_P5
};
static const uint8_t child_pipe_enable[] PROGMEM =
{
ERX_P0, ERX_P1, ERX_P2, ERX_P3, ERX_P4, ERX_P5
};
void RF24::openReadingPipe(uint8_t child, uint64_t address)
{
......
......@@ -46,13 +46,12 @@ class RF24
{
private:
uint8_t ce_pin; /**< "Chip Enable" pin, activates the RX or TX role */
uint8_t csn_pin; /**< SPI Chip select */
uint8_t csn_pin; /**< SPI Chip select */
bool p_variant; /* False for RF24L01 and true for RF24L01P */
uint8_t payload_size; /**< Fixed size of payloads */
bool dynamic_payloads_enabled; /**< Whether dynamic payloads are enabled. */
uint8_t pipe0_reading_address[5]; /**< Last address set on pipe 0 for reading. */
uint8_t addr_width;
uint8_t addr_width; /**< The address width to use - 3,4 or 5 bytes. */
public:
......@@ -79,9 +78,6 @@ public:
* Begin operation of the chip
*
* Call this in setup(), before calling any other methods.
*
* @note Optimization: The radio is partially configured in PTX mode
* when begin is called to make the transition to PTX mode simpler.
*/
void begin(void);
......@@ -90,7 +86,7 @@ public:
*
* Be sure to call openReadingPipe() first. Do not call write() while
* in this mode, without first calling stopListening(). Call
* isAvailable() to check for incoming traffic, and read() to get it.
* Available() to check for incoming traffic, and read() to get it.
*/
void startListening(void);
......@@ -98,27 +94,12 @@ public:
* Stop listening for incoming messages
*
* Do this before calling write().
*
* @note Optimization: The radio will be taken out of PRX mode as soon
* as listening is stopped. Enables quicker and simpler engaging of
* primary transmitter (PTX) mode.
*/
void stopListening(void);
/**
* Test whether there are bytes available to be read
*
* @note Optimization: The available functino now checks the FIFO
* buffers directly for data instead of relying of interrupt flags.
*
* @note Interrupt flags will not be cleared until a payload is
* actually read from the FIFO
*
* @see txStandBy()
* @see startWrite()
* @see write()
* @see writeFast()
*
* @return True if there is a payload available, false if none is
*/
bool available(void);
......@@ -131,9 +112,9 @@ public:
* @note I specifically chose 'void*' as a data type to make it easier
* for beginners to use. No casting needed.
*
* @note Optimization: No longer boolean. Use available to
* determine if packets are available. Interrupt flags are now cleared
* during reads instead of when calling available().
* @note No longer boolean. Use available to determine if packets are
* available. Interrupt flags are now cleared during reads instead of
* when calling available().
*
* @param buf Pointer to a buffer where the data should be written
* @param len Maximum number of bytes to read into the buffer
......@@ -142,15 +123,12 @@ public:
void read( void* buf, uint8_t len );
/**
* @note Optimization: Improved performance slightly
* Write to the open writing pipe
*
* Be sure to call openWritingPipe() first to set the destination
* of where to write to.
*
* This blocks until the message is successfully acknowledged by
* the receiver or the timeout/retransmit maxima are reached. In
* the current configuration, the max delay here is 60ms.
* the current configuration, the max delay here is 60-70ms.
*
* The maximum size of data written is the fixed payload size, see
* getPayloadSize(). However, you can write less, and the remainder
......@@ -165,9 +143,10 @@ public:
bool write( const void* buf, uint8_t len );
/**
* New: Open a pipe for writing
* New: Open a pipe for writing via byte array. Old addressing format retained
* for compatibility.
*
* Only one pipe can be open at once, but you can change the pipe
* Only one writing pipe can be open at once, but you can change the address
* you'll write to. Call stopListening() first.
*
* Addresses are assigned via a byte array, default is 5 byte address length
......@@ -213,14 +192,7 @@ public:
void openReadingPipe(uint8_t number, const uint8_t *address);
/**
* Close a pipe after it has been previously opened.
* Can be safely called without having previously opened a pipe.
* @param pipe Which pipe # to close, 0-5.
*/
void closeReadingPipe( uint8_t pipe ) ;
/**@}*/
/**@}*/
/**
* @name Advanced Operation
*
......@@ -240,9 +212,6 @@ public:
* FIFO buffers. This optimized version does not rely on interrupt
* flags, but checks the actual FIFO buffers.
*
* @note Optimization: Interrupt flags are no longer cleared when available is called,
* but will be reset only when the data is read from the FIFO buffers.
*
* @param[out] pipe_num Which pipe has the payload available
* @return True if there is a payload available, false if none is
*/
......@@ -254,20 +223,24 @@ public:
* To return to normal power mode, either write() some data or
* startListening, or powerUp().
*
* @note Optimization: The radio will never enter power down unless instructed
* by the MCU via this command.
* @note After calling startListening(), a basic radio will consume about 13.5mA
* at max PA level.
* During active transmission, the radio will consume about 11.5mA, but this will
* be reduced to 26uA (.026mA) between sending.
* In full powerDown mode, the radio will consume approximately 900nA (.0009mA)
*/
void powerDown(void);
/**
* Leave low-power mode - making radio more responsive
*
* Leave low-power mode - required for normal radio operation after calling powerDown()
*
* To return to low power mode, call powerDown().
* @note This will take up to 5ms for maximum compatibility
*/
void powerUp(void) ;
/**
* Write for single NOACK writes. Disables acknowledgements/autoretries for a single write.
* Write for single NOACK writes. Optionally disables acknowledgements/autoretries for a single write.
*
* @note enableDynamicAck() must be called to enable this feature
*
......@@ -283,13 +256,12 @@ public:
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.
* Once the FIFOs are full, writeFast will simply wait for success or
* timeout, and return 1 or 0 respectively. From a user perspective, just
* keep trying to send the same data. The library will keep auto retrying
* the current payload using the built in functionality.
* @warning It is important to never keep the nRF24L01 in TX mode for more than 4ms at a time. If the auto
* @warning It is important to never keep the nRF24L01 in TX mode and FIFO full for more than 4ms at a time. If the auto
* retransmit is enabled, the nRF24L01 is never in TX mode long enough to disobey this rule. Allow the FIFO
* to clear by issuing txStandBy() or ensure appropriate time between transmissions.
*
......@@ -329,12 +301,11 @@ public:
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.
* It will not block until the 3 FIFO buffers are filled with data.
* If so the library will auto retry until a new payload is written
* or the user specified timeout period is reached.
* @warning It is important to never keep the nRF24L01 in TX mode for more than 4ms at a time. If the auto
* @warning It is important to never keep the nRF24L01 in TX mode and FIFO full for more than 4ms at a time. If the auto
* retransmit is enabled, the nRF24L01 is never in TX mode long enough to disobey this rule. Allow the FIFO
* to clear by issuing txStandBy() or ensure appropriate time between transmissions.
*
......@@ -359,7 +330,6 @@ public:
bool writeBlocking( const void* buf, uint8_t len, uint32_t timeout );
/**
* @note Optimization: New Command
* This function should be called as soon as transmission is finished to
* drop the radio back to STANDBY-I mode. If not issued, the radio will
* remain in STANDBY-II mode which, per the data sheet, is not a recommended
......@@ -387,8 +357,6 @@ public:
bool txStandBy();
/**
* @note Optimization: New Command
*
* This function allows extended blocking and auto-retries per a user defined timeout
* @code
* Fully Blocking Example:
......@@ -412,8 +380,7 @@ public:
* The next time a message is received on @p pipe, the data in @p buf will
* be sent back in the acknowledgement.
*
* @warning According to the data sheet, only three of these can be pending
* at any time as there are only 3 FIFO buffers.
* @warning Only three of these can be pending at any time as there are only 3 FIFO buffers.
*
* @param pipe Which pipe# (typically 1-5) will get this response.
* @param buf Pointer to data that is sent
......@@ -438,14 +405,10 @@ public:
/**
* Determine if an ack payload was received in the most recent call to
* write().
* write(). The regular available() can also be used.
*
* Call read() to retrieve the ack payload.
*
* @note Optimization: Calling this function NO LONGER clears the interrupt
* flag. The new functionality checks the RX FIFO buffer for an ACK payload
* instead of relying on interrupt flags.Reading the payload will clear the flags.
*
* @return True if an ack payload is available.
*/
bool isAckPayloadAvailable(void);
......@@ -468,7 +431,7 @@ public:
* @note Optimization: This function now leaves the CE pin high, so the radio
* will remain in TX or STANDBY-II Mode until a txStandBy() command is issued.
* This allows the chip to be used to its full potential in TX mode.
* @warning It is important to never keep the nRF24L01 in TX mode for more than 4ms at a time. If the auto
* @warning It is important to never keep the nRF24L01 in TX mode with FIFO full for more than 4ms at a time. If the auto
* retransmit is enabled, the nRF24L01 is never in TX mode long enough to disobey this rule. Allow the FIFO
* to clear by issuing txStandBy() or ensure appropriate time between transmissions.
*
......@@ -494,10 +457,6 @@ public:
* Just like write(), but it returns immediately. To find out what happened
* to the send, catch the IRQ and then call whatHappened().
*
* @note Optimization: This function again behaves as it did previously for backwards-compatibility.
* with user code. The library uses startFastWrite() internally.
* This is mainly used for single-payload transactions.
*
* @see write()
* @see writeFast()
* @see startFastWrite()
......@@ -515,8 +474,6 @@ public:
void startWrite( const void* buf, uint8_t len, const bool multicast );
/**
* Optimization: New Command
*
* This function is mainly used internally to take advantage of the auto payload
* re-use functionality of the chip, but can be beneficial to users as well.
*
......@@ -588,7 +545,7 @@ public:
* @param rx_ready Mask payload received interrupts
*/
void maskIRQ(bool tx_ok,bool tx_fail,bool rx_ready);
/**
* Set the address width from 3 to 5 bytes (24, 32 or 40 bit)
*
......@@ -597,6 +554,14 @@ public:
void setAddressWidth(uint8_t a_width);
/**
* Close a pipe after it has been previously opened.
* Can be safely called without having previously opened a pipe.
* @param pipe Which pipe # to close, 0-5.
*/
void closeReadingPipe( uint8_t pipe ) ;
/**@}*/
/**@}*/
......@@ -654,7 +619,7 @@ public:
* For dynamic payloads, this pulls the size of the payload off
* the chip
*
* @note Optimization: Corrupt packets are now detected and flushed per the
* @note Corrupt packets are now detected and flushed per the
* manufacturer.
*
* @return Payload length of last-received dynamic payload
......@@ -667,7 +632,7 @@ public:
* Ack payloads are a handy way to return data back to senders without
* manually changing the radio modes on both units.
*
* @see examples/pingpair_pl/pingpair_pl.pde
* @see examples/GettingStarted_CallResponse/GettingStarted_CallResponse.ino
*/
void enableAckPayload(void);
......@@ -792,9 +757,11 @@ public:
* }
* @endcode
*/
#if defined (FAILURE_HANDLING)
//#if defined (FAILURE_HANDLING)
bool failureDetected;
#endif
//#endif
/**@}*/
/**
* @name Deprecated
......@@ -1163,6 +1130,7 @@ private:
*
* <b>Main changes: </b><br>
* - The library has been tweaked to allow full use of the FIFO buffers for maximum transfer speeds
* - Many issues and bugs have been resolved
* - 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
......@@ -1178,9 +1146,12 @@ private:
*
* @li <a href="http://tmrh20.github.io/">Documentation Main Page</a>
* @li <a href="http://tmrh20.github.io/RF24/classRF24.html">RF24 Class Documentation</a>
* @li <a href="http://tmrh20.blogspot.com/2014/03/high-speed-data-transfers-and-wireless.html">My Blog: RF24 Optimization Overview</a>
* @li <a href="https://github.com/tmrh20/RF24/">Source Code</a>
* @li <a href="https://github.com/TMRh20/RF24/archive/master.zip">Download</a>
* @li <a href="http://www.nordicsemi.com/files/Product/data_sheet/nRF24L01_Product_Specification_v2_0.pdf">Chip Datasheet</a>
* @li <a href="http://tmrh20.github.io/RF24Network/">RF24Network: Easily create a home or long-range RF24 sensor network</a>
* @li <a href="http://tmrh20.blogspot.com/2014/03/arduino-radiointercomwireless-audio.html">My Blog: RF24 Wireless Audio</a>
* @li <a href="https://github.com/maniacbug/RF24">Original Library</a>
*
* This chip uses the SPI bus, plus two chip control pins. Remember that pin 10 must still remain an output, or
......
......@@ -510,6 +510,8 @@ void RF24::startListening(void)
// Restore the pipe0 adddress, if exists
if (pipe0_reading_address[0] > 0){
write_register(RX_ADDR_P0, pipe0_reading_address,addr_width);
}else{
closeReadingPipe(0);
}
// Flush buffers
//flush_rx();
......@@ -523,6 +525,11 @@ void RF24::startListening(void)
}
/****************************************************************************/
static const uint8_t child_pipe_enable[] =
{
ERX_P0, ERX_P1, ERX_P2, ERX_P3, ERX_P4, ERX_P5
};
void RF24::stopListening(void)
{
......@@ -532,6 +539,7 @@ void RF24::stopListening(void)
//flush_rx();
write_register(CONFIG, ( read_register(CONFIG) ) & ~_BV(PRIM_RX) );
write_register(EN_RXADDR,read_register(EN_RXADDR) | _BV(pgm_read_byte(&child_pipe_enable[0])));
delayMicroseconds(130);
}
......@@ -874,10 +882,6 @@ static const uint8_t child_payload_size[] =
{
RX_PW_P0, RX_PW_P1, RX_PW_P2, RX_PW_P3, RX_PW_P4, RX_PW_P5
};
static const uint8_t child_pipe_enable[] =
{
ERX_P0, ERX_P1, ERX_P2, ERX_P3, ERX_P4, ERX_P5
};
void RF24::openReadingPipe(uint8_t child, uint64_t address)
{
......@@ -946,6 +950,13 @@ void RF24::openReadingPipe(uint8_t child, const uint8_t *address)
/****************************************************************************/
void RF24::closeReadingPipe( uint8_t pipe )
{
write_register(EN_RXADDR,read_register(EN_RXADDR) & ~_BV(pgm_read_byte(&child_pipe_enable[pipe])));
}
/****************************************************************************/
void RF24::toggle_features(void)
{
bcm2835_spi_transfer( ACTIVATE );
......
......@@ -73,7 +73,7 @@ public:
* @endcode
**/
#if defined (FAILURE_HANDLING)
bool failureDetect;
bool failureDetected;
#endif
private:
uint8_t ce_pin; /**< "Chip Enable" pin, activates the RX or TX role */
......@@ -966,6 +966,13 @@ public:
void setAddressWidth(uint8_t a_width);
/**
* Close a pipe after it has been previously opened.
* Can be safely called without having previously opened a pipe.
* @param pipe Which pipe # to close, 0-5.
*/
void closeReadingPipe( uint8_t pipe ) ;
/**@}*/
};
......
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