diff --git a/RF24.cpp b/RF24.cpp
index fef6a2745..e7acce84a 100644
--- a/RF24.cpp
+++ b/RF24.cpp
@@ -483,21 +483,17 @@ uint8_t RF24::flush_tx(void)
return status;
}
-/****************************************************************************/
-
-uint8_t RF24::get_status(void)
-{
- read_register(RF24_NOP, (uint8_t*)nullptr, 0);
- return status;
-}
-
/****************************************************************************/
#if !defined(MINIMAL)
-void RF24::print_status(uint8_t _status)
+void RF24::printStatus(uint8_t flags)
{
- printf_P(PSTR("STATUS\t\t= 0x%02x RX_DR=%x TX_DS=%x MAX_RT=%x RX_P_NO=%x TX_FULL=%x\r\n"), _status, (_status & _BV(RX_DR)) ? 1 : 0,
- (_status & _BV(TX_DS)) ? 1 : 0, (_status & _BV(MAX_RT)) ? 1 : 0, ((_status >> RX_P_NO) & 0x07), (_status & _BV(TX_FULL)) ? 1 : 0);
+ printf_P(PSTR("RX_DR=%x TX_DS=%x TX_DF=%x RX_PIPE=%x TX_FULL=%x\r\n"),
+ (flags & RF24_RX_DR) ? 1 : 0,
+ (flags & RF24_TX_DS) ? 1 : 0,
+ (flags & RF24_TX_DF) ? 1 : 0,
+ (flags >> RX_P_NO) & 0x07,
+ (flags & _BV(TX_FULL)) ? 1 : 0);
}
/****************************************************************************/
@@ -711,7 +707,9 @@ void RF24::printDetails(void)
printf("================ NRF Configuration ================\n");
#endif // defined(RF24_LINUX)
- print_status(get_status());
+ uint8_t status = update();
+ printf_P(PSTR("STATUS\t\t= 0x%02x "), status);
+ printStatus(status);
print_address_register(PSTR("RX_ADDR_P0-1"), RX_ADDR_P0, 2);
print_byte_register(PSTR("RX_ADDR_P2-5"), RX_ADDR_P2, 4);
@@ -1107,7 +1105,7 @@ bool RF24::_init_radio()
// Reset current status
// Notice reset and flush is the last thing we do
- write_register(NRF_STATUS, _BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT));
+ write_register(NRF_STATUS, RF24_IRQ_ALL);
// Flush buffers
flush_rx();
@@ -1152,7 +1150,7 @@ void RF24::startListening(void)
#endif
config_reg |= _BV(PRIM_RX);
write_register(NRF_CONFIG, config_reg);
- write_register(NRF_STATUS, _BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT));
+ write_register(NRF_STATUS, RF24_IRQ_ALL);
ce(HIGH);
// Restore the pipe0 address, if exists
@@ -1248,7 +1246,7 @@ bool RF24::write(const void* buf, uint8_t len, const bool multicast)
uint32_t timer = millis();
#endif // defined(FAILURE_HANDLING) || defined(RF24_LINUX)
- while (!(get_status() & (_BV(TX_DS) | _BV(MAX_RT)))) {
+ while (!(update() & (RF24_TX_DS | RF24_TX_DF))) {
#if defined(FAILURE_HANDLING) || defined(RF24_LINUX)
if (millis() - timer > 95) {
errNotify();
@@ -1263,10 +1261,10 @@ bool RF24::write(const void* buf, uint8_t len, const bool multicast)
ce(LOW);
- write_register(NRF_STATUS, _BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT));
+ write_register(NRF_STATUS, RF24_IRQ_ALL);
//Max retries exceeded
- if (status & _BV(MAX_RT)) {
+ if (status & RF24_TX_DF) {
flush_tx(); // Only going to be 1 packet in the FIFO at a time using this method, so just flush
return 0;
}
@@ -1291,10 +1289,10 @@ bool RF24::writeBlocking(const void* buf, uint8_t len, uint32_t timeout)
uint32_t timer = millis(); // Get the time that the payload transmission started
- while ((get_status() & (_BV(TX_FULL)))) { // Blocking only if FIFO is full. This will loop and block until TX is successful or timeout
+ while (update() & _BV(TX_FULL)) { // Blocking only if FIFO is full. This will loop and block until TX is successful or timeout
- if (status & _BV(MAX_RT)) { // If MAX Retries have been reached
- reUseTX(); // Set re-transmit and clear the MAX_RT interrupt flag
+ if (status & RF24_TX_DF) { // If MAX Retries have been reached
+ reUseTX(); // Set re-transmit and clear the MAX_RT interrupt flag
if (millis() - timer > timeout) {
return 0; // If this payload has exceeded the user-defined timeout, exit and return 0
}
@@ -1320,7 +1318,7 @@ bool RF24::writeBlocking(const void* buf, uint8_t len, uint32_t timeout)
void RF24::reUseTX()
{
ce(LOW);
- write_register(NRF_STATUS, _BV(MAX_RT)); //Clear max retry flag
+ write_register(NRF_STATUS, RF24_TX_DF); //Clear max retry flag
read_register(REUSE_TX_PL, (uint8_t*)nullptr, 0);
IF_RF24_DEBUG(printf_P("[Reusing payload in TX FIFO]"););
ce(HIGH); //Re-Transfer packet
@@ -1340,8 +1338,8 @@ bool RF24::writeFast(const void* buf, uint8_t len, const bool multicast)
#endif
//Blocking only if FIFO is full. This will loop and block until TX is successful or fail
- while ((get_status() & (_BV(TX_FULL)))) {
- if (status & _BV(MAX_RT)) {
+ while (update() & _BV(TX_FULL)) {
+ if (status & RF24_TX_DF) {
return 0; //Return 0. The previous payload has not been retransmitted
// From the user perspective, if you get a 0, call txStandBy()
}
@@ -1433,8 +1431,8 @@ bool RF24::txStandBy()
uint32_t timeout = millis();
#endif
while (!(read_register(FIFO_STATUS) & _BV(TX_EMPTY))) {
- if (status & _BV(MAX_RT)) {
- write_register(NRF_STATUS, _BV(MAX_RT));
+ if (status & RF24_TX_DF) {
+ write_register(NRF_STATUS, RF24_TX_DF);
ce(LOW);
flush_tx(); //Non blocking, flush the data
return 0;
@@ -1465,8 +1463,8 @@ bool RF24::txStandBy(uint32_t timeout, bool startTx)
uint32_t start = millis();
while (!(read_register(FIFO_STATUS) & _BV(TX_EMPTY))) {
- if (status & _BV(MAX_RT)) {
- write_register(NRF_STATUS, _BV(MAX_RT));
+ if (status & RF24_TX_DF) {
+ write_register(NRF_STATUS, RF24_TX_DF);
ce(LOW); // Set re-transmit
ce(HIGH);
if (millis() - start >= timeout) {
@@ -1526,7 +1524,7 @@ bool RF24::available(void)
bool RF24::available(uint8_t* pipe_num)
{
if (available()) { // if RX FIFO is not empty
- *pipe_num = (get_status() >> RX_P_NO) & 0x07;
+ *pipe_num = (update() >> RX_P_NO) & 0x07;
return 1;
}
return 0;
@@ -1541,7 +1539,7 @@ void RF24::read(void* buf, uint8_t len)
read_payload(buf, len);
//Clear the only applicable interrupt flags
- write_register(NRF_STATUS, _BV(RX_DR));
+ write_register(NRF_STATUS, RF24_RX_DR);
}
/****************************************************************************/
@@ -1550,12 +1548,44 @@ void RF24::whatHappened(bool& tx_ok, bool& tx_fail, bool& rx_ready)
{
// Read the status & reset the status in one easy call
// Or is that such a good idea?
- write_register(NRF_STATUS, _BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT));
+ write_register(NRF_STATUS, RF24_IRQ_ALL);
// Report to the user what happened
- tx_ok = status & _BV(TX_DS);
- tx_fail = status & _BV(MAX_RT);
- rx_ready = status & _BV(RX_DR);
+ tx_ok = status & RF24_TX_DS;
+ tx_fail = status & RF24_TX_DF;
+ rx_ready = status & RF24_RX_DR;
+}
+
+/****************************************************************************/
+
+uint8_t RF24::clearStatusFlags(uint8_t flags)
+{
+ write_register(NRF_STATUS, flags & RF24_IRQ_ALL);
+ return status;
+}
+
+/****************************************************************************/
+
+void RF24::setStatusFlags(uint8_t flags)
+{
+ // flip the `flags` to translate from "human understanding"
+ config_reg = (config_reg & ~RF24_IRQ_ALL) | (~flags & RF24_IRQ_ALL);
+ write_register(NRF_CONFIG, config_reg);
+}
+
+/****************************************************************************/
+
+uint8_t RF24::getStatusFlags()
+{
+ return status;
+}
+
+/****************************************************************************/
+
+uint8_t RF24::update()
+{
+ read_register(RF24_NOP, (uint8_t*)nullptr, 0);
+ return status;
}
/****************************************************************************/
diff --git a/RF24.h b/RF24.h
index fe72e441c..1b455470e 100644
--- a/RF24.h
+++ b/RF24.h
@@ -128,6 +128,30 @@ typedef enum
RF24_FIFO_INVALID,
} rf24_fifo_state_e;
+/**
+ * @}
+ * @defgroup StatusFlags Status flags
+ * @{
+ */
+
+/**
+ * @brief An enumeration of constants used to configure @ref StatusFlags
+ */
+typedef enum
+{
+#include "nRF24L01.h"
+ /// An alias of `0` to describe no IRQ events enabled.
+ RF24_IRQ_NONE = 0,
+ /// Represents an event where TX Data Failed to send.
+ RF24_TX_DF = 1 << MASK_MAX_RT,
+ /// Represents an event where TX Data Sent successfully.
+ RF24_TX_DS = 1 << TX_DS,
+ /// Represents an event where RX Data is Ready to `RF24::read()`.
+ RF24_RX_DR = 1 << RX_DR,
+ /// Equivalent to `RF24_RX_DR | RF24_TX_DS | RF24_TX_DF`.
+ RF24_IRQ_ALL = (1 << MASK_MAX_RT) | (1 << TX_DS) | (1 << RX_DR),
+} rf24_irq_flags_e;
+
/**
* @}
* @brief Driver class for nRF24L01(+) 2.4GHz Wireless Transceiver
@@ -378,13 +402,13 @@ class RF24
* that received the next available payload. According to the datasheet,
* the data about the pipe number that received the next available payload
* is "unreliable" during a FALLING transition on the IRQ pin. This means
- * you should call whatHappened() before calling this function
+ * you should call clearStatusFlags() before calling this function
* during an ISR (Interrupt Service Routine). For example:
* @code
* void isrCallbackFunction() {
* bool tx_ds, tx_df, rx_dr;
- * radio.whatHappened(tx_ds, tx_df, rx_dr); // resets the IRQ pin to HIGH
- * radio.available(); // returned data should now be reliable
+ * uint8_t flags = radio.clearStatusFlags(); // resets the IRQ pin to HIGH
+ * radio.available(); // returned data should now be reliable
* }
*
* void setup() {
@@ -628,6 +652,16 @@ class RF24
*/
void printDetails(void);
+ /**
+ * Decode and print the given STATUS byte to stdout.
+ *
+ * @param flags The STATUS byte to print.
+ * This value is fetched with update() or getStatusFlags().
+ *
+ * @warning Does nothing if stdout is not defined. See fdevopen in stdio.h
+ */
+ void printStatus(uint8_t flags);
+
/**
* Print a giant block of debugging information to stdout. This function
* differs from printDetails() because it makes the information more
@@ -789,14 +823,13 @@ class RF24
*
* @warning According to the datasheet, the data saved to `pipe_num` is
* "unreliable" during a FALLING transition on the IRQ pin. This means you
- * should call whatHappened() before calling this function during
+ * should call clearStatusFlags() before calling this function during
* an ISR (Interrupt Service Routine). For example:
* @code
* void isrCallbackFunction() {
- * bool tx_ds, tx_df, rx_dr;
- * radio.whatHappened(tx_ds, tx_df, rx_dr); // resets the IRQ pin to HIGH
- * uint8_t pipe; // initialize pipe data
- * radio.available(&pipe); // pipe data should now be reliable
+ * radio.clearStatusFlags(); // resets the IRQ pin to inactive HIGH
+ * uint8_t pipe = 7; // initialize pipe data
+ * radio.available(&pipe); // pipe data should now be reliable
* }
*
* void setup() {
@@ -840,6 +873,8 @@ class RF24
/**
* @deprecated Use RF24::isFifo(bool about_tx) instead.
+ * See our [migration guide](migration.md) to understand what you should update in your code.
+ *
* @param about_tx `true` focuses on the TX FIFO, `false` focuses on the RX FIFO
* @param check_empty
* - `true` checks if the specified FIFO is empty
@@ -1147,36 +1182,68 @@ class RF24
bool writeAckPayload(uint8_t pipe, const void* buf, uint8_t len);
/**
- * Call this when you get an Interrupt Request (IRQ) to find out why
+ * Clear the Status flags that caused an interrupt event.
*
- * This function describes what event triggered the IRQ pin to go active
- * LOW and clears the status of all events.
+ * @remark This function is similar to `whatHappened()` because it also returns the
+ * Status flags that caused the interrupt event. However, this function returns
+ * a STATUS byte instead of bit-banging into 3 1-byte booleans
+ * passed by reference.
*
- * @see maskIRQ()
+ * @note When used in an ISR (Interrupt Service routine), there is a chance that the
+ * returned bits 0b1110 (rx_pipe number) is inaccurate. See available(uint8_t*) (or the
+ * datasheet) for more detail.
*
- * @param[out] tx_ok The transmission attempt completed (TX_DS). This does
- * not imply that the transmitted data was received by another radio, rather
- * this only reports if the attempt to send was completed. This will
- * always be `true` when the auto-ack feature is disabled.
- * @param[out] tx_fail The transmission failed to be acknowledged, meaning
- * too many retries (MAX_RT) were made while expecting an ACK packet. This
- * event is only triggered when auto-ack feature is enabled.
- * @param[out] rx_ready There is a newly received payload (RX_DR) saved to
- * RX FIFO buffers. Remember that the RX FIFO can only hold up to 3
- * payloads. Once the RX FIFO is full, all further received transmissions
- * are rejected until there is space to save new data in the RX FIFO
- * buffers.
+ * @param flags The IRQ flags to clear. Default value is all of them (`RF24_IRQ_ALL`).
+ * Multiple flags can be cleared by OR-ing rf24_irq_flags_e values together.
*
- * @note This function expects no parameters in the python wrapper.
- * Instead, this function returns a 3 item tuple describing the IRQ
- * events' status. To use this function in the python wrapper:
- * @code{.py}
- * # let`radio` be the instantiated RF24 object
- * tx_ds, tx_df, rx_dr = radio.whatHappened() # get IRQ status flags
- * print("tx_ds: {}, tx_df: {}, rx_dr: {}".format(tx_ds, tx_df, rx_dr))
- * @endcode
+ * @returns The STATUS byte from the radio's register before it was modified. Use
+ * enumerations of rf24_irq_flags_e as masks to interpret the STATUS byte's meaning(s).
+ *
+ * @ingroup StatusFlags
*/
- void whatHappened(bool& tx_ok, bool& tx_fail, bool& rx_ready);
+ uint8_t clearStatusFlags(uint8_t flags = RF24_IRQ_ALL);
+
+ /**
+ * Set which flags shall be reflected on the radio's IRQ pin.
+ *
+ * @remarks This function is similar to maskIRQ() but with less confusing parameters.
+ *
+ * @param flags A value of rf24_irq_flags_e to influence the radio's IRQ pin.
+ * The default value (`RF24_IRQ_NONE`) will disable the radio's IRQ pin.
+ * Multiple events can be enabled by OR-ing rf24_irq_flags_e values together.
+ * ```cpp
+ * radio.setStatusFlags(RF24_IRQ_ALL);
+ * // is equivalent to
+ * radio.setStatusFlags(RF24_RX_DR | RF24_TX_DS | RF24_TX_DF);
+ * ```
+ *
+ * @ingroup StatusFlags
+ */
+ void setStatusFlags(uint8_t flags = RF24_IRQ_NONE);
+
+ /**
+ * Get the latest STATUS byte returned from the last SPI transaction.
+ *
+ * @note This does not actually perform any SPI transaction with the radio.
+ * Use `RF24::update()` instead to get a fresh copy of the Status flags at
+ * the slight cost of performance.
+ *
+ * @returns The STATUS byte from the radio's register as the latest SPI transaction. Use
+ * enumerations of rf24_irq_flags_e as masks to interpret the STATUS byte's meaning(s).
+ *
+ * @ingroup StatusFlags
+ */
+ uint8_t getStatusFlags();
+
+ /**
+ * Get an updated STATUS byte from the radio.
+ *
+ * @returns The STATUS byte fetched from the radio's register. Use enumerations of
+ * rf24_irq_flags_e as masks to interpret the STATUS byte's meaning(s).
+ *
+ * @ingroup StatusFlags
+ */
+ uint8_t update();
/**
* Non-blocking write to the open writing pipe used for buffered writes
@@ -1222,13 +1289,13 @@ class RF24
* Non-blocking write to the open writing pipe
*
* Just like write(), but it returns immediately. To find out what happened
- * to the send, catch the IRQ and then call whatHappened().
+ * to the send, catch the IRQ and then call clearStatusFlags() or update().
*
* @see
* - write()
* - writeFast()
* - startFastWrite()
- * - whatHappened()
+ * - clearStatusFlags()
* - setAutoAck() (for single noAck writes)
*
* @param buf Pointer to the data to be sent
@@ -1745,38 +1812,6 @@ class RF24
*/
void disableCRC(void);
- /**
- * This function is used to configure what events will trigger the Interrupt
- * Request (IRQ) pin active LOW.
- * The following events can be configured:
- * 1. "data sent": This does not mean that the data transmitted was
- * received, only that the attempt to send it was complete.
- * 2. "data failed": This means the data being sent was not received. This
- * event is only triggered when the auto-ack feature is enabled.
- * 3. "data received": This means that data from a receiving payload has
- * been loaded into the RX FIFO buffers. Remember that there are only 3
- * levels available in the RX FIFO buffers.
- *
- * By default, all events are configured to trigger the IRQ pin active LOW.
- * When the IRQ pin is active, use whatHappened() to determine what events
- * triggered it. Remember that calling whatHappened() also clears these
- * events' status, and the IRQ pin will then be reset to inactive HIGH.
- *
- * The following code configures the IRQ pin to only reflect the "data received"
- * event:
- * @code
- * radio.maskIRQ(1, 1, 0);
- * @endcode
- *
- * @param tx_ok `true` ignores the "data sent" event, `false` reflects the
- * "data sent" event on the IRQ pin.
- * @param tx_fail `true` ignores the "data failed" event, `false` reflects the
- * "data failed" event on the IRQ pin.
- * @param rx_ready `true` ignores the "data received" event, `false` reflects the
- * "data received" event on the IRQ pin.
- */
- void maskIRQ(bool tx_ok, bool tx_fail, bool rx_ready);
-
/**
*
* The driver will delay for this duration when stopListening() is called
@@ -1864,7 +1899,8 @@ class RF24
/**
* Open a pipe for reading
* @deprecated For compatibility with old code only, see newer function
- * openReadingPipe()
+ * openReadingPipe().
+ * See our [migration guide](migration.md) to understand what you should update in your code.
*
* @note Pipes 1-5 should share the first 32 bits.
* Only the least significant byte should be unique, e.g.
@@ -1889,7 +1925,8 @@ class RF24
/**
* Open a pipe for writing
* @deprecated For compatibility with old code only, see newer function
- * openWritingPipe()
+ * openWritingPipe().
+ * See our [migration guide](migration.md) to understand what you should update in your code.
*
* Addresses are 40-bit hex values, e.g.:
*
@@ -1907,11 +1944,84 @@ class RF24
*
* @deprecated For compatibility with old code only, see synonymous function available().
* Use read() to retrieve the ack payload and getDynamicPayloadSize() to get the ACK payload size.
+ * See our [migration guide](migration.md) to understand what you should update in your code.
*
* @return True if an ack payload is available.
*/
bool isAckPayloadAvailable(void);
+ /**
+ * This function is used to configure what events will trigger the Interrupt
+ * Request (IRQ) pin active LOW.
+ *
+ * @deprecated Use setStatusFlags() instead.
+ * See our [migration guide](migration.md) to understand what you should update in your code.
+ *
+ * The following events can be configured:
+ * 1. "data sent": This does not mean that the data transmitted was
+ * received, only that the attempt to send it was complete.
+ * 2. "data failed": This means the data being sent was not received. This
+ * event is only triggered when the auto-ack feature is enabled.
+ * 3. "data received": This means that data from a receiving payload has
+ * been loaded into the RX FIFO buffers. Remember that there are only 3
+ * levels available in the RX FIFO buffers.
+ *
+ * By default, all events are configured to trigger the IRQ pin active LOW.
+ * When the IRQ pin is active, use clearStatusFlags() or getStatusFlags() to
+ * determine what events triggered it.
+ * Remember that calling clearStatusFlags() also clears these
+ * events' status, and the IRQ pin will then be reset to inactive HIGH.
+ *
+ * The following code configures the IRQ pin to only reflect the "data received"
+ * event:
+ * @code
+ * radio.maskIRQ(1, 1, 0);
+ * @endcode
+ *
+ * @param tx_ok `true` ignores the "data sent" event, `false` reflects the
+ * "data sent" event on the IRQ pin.
+ * @param tx_fail `true` ignores the "data failed" event, `false` reflects the
+ * "data failed" event on the IRQ pin.
+ * @param rx_ready `true` ignores the "data received" event, `false` reflects the
+ * "data received" event on the IRQ pin.
+ */
+ void maskIRQ(bool tx_ok, bool tx_fail, bool rx_ready);
+
+ /**
+ * Call this when you get an Interrupt Request (IRQ) to find out why
+ *
+ * This function describes what event triggered the IRQ pin to go active
+ * LOW and clears the status of all events.
+ *
+ * @deprecated Use clearStatusFlags() instead.
+ * See our [migration guide](migration.md) to understand what you should update in your code.
+ *
+ * @see setStatusFlags()
+ *
+ * @param[out] tx_ok The transmission attempt completed (TX_DS). This does
+ * not imply that the transmitted data was received by another radio, rather
+ * this only reports if the attempt to send was completed. This will
+ * always be `true` when the auto-ack feature is disabled.
+ * @param[out] tx_fail The transmission failed to be acknowledged, meaning
+ * too many retries (MAX_RT) were made while expecting an ACK packet. This
+ * event is only triggered when auto-ack feature is enabled.
+ * @param[out] rx_ready There is a newly received payload (RX_DR) saved to
+ * RX FIFO buffers. Remember that the RX FIFO can only hold up to 3
+ * payloads. Once the RX FIFO is full, all further received transmissions
+ * are rejected until there is space to save new data in the RX FIFO
+ * buffers.
+ *
+ * @note This function expects no parameters in the python wrapper.
+ * Instead, this function returns a 3 item tuple describing the IRQ
+ * events' status. To use this function in the python wrapper:
+ * @code{.py}
+ * # let`radio` be the instantiated RF24 object
+ * tx_ds, tx_df, rx_dr = radio.whatHappened() # get IRQ status flags
+ * print("tx_ds: {}, tx_df: {}, rx_dr: {}".format(tx_ds, tx_df, rx_dr))
+ * @endcode
+ */
+ void whatHappened(bool& tx_ok, bool& tx_fail, bool& rx_ready);
+
private:
/**@}*/
/**
@@ -1999,24 +2109,8 @@ class RF24
*/
void read_payload(void* buf, uint8_t len);
- /**
- * Retrieve the current status of the chip
- *
- * @return Current value of status register
- */
- uint8_t get_status(void);
-
#if !defined(MINIMAL)
- /**
- * Decode and print the given status to stdout
- *
- * @param status Status value to print
- *
- * @warning Does nothing if stdout is not defined. See fdevopen in stdio.h
- */
- void print_status(uint8_t status);
-
/**
* Decode and print the given 'observe_tx' value to stdout
*
diff --git a/docs/main_page.md b/docs/main_page.md
index 197f9fdc2..f1f44b83b 100644
--- a/docs/main_page.md
+++ b/docs/main_page.md
@@ -19,6 +19,13 @@ See the releases' descriptions on
[the library's release page](http://github.com/nRF24/RF24/releases) for a list of
changes.
+> [!IMPORTANT]
+> There's going to be major changes in v2.0.
+> As of v1.5, there is [newer API](migration.md) that should be used instead of
+> the @ref deprecated "deprecated API".
+>
+> See our [migration guide](migration.md) to understand what you should update in your code.
+
## Useful References
- [RF24 Class Documentation](classRF24.html)
diff --git a/docs/migration.md b/docs/migration.md
new file mode 100644
index 000000000..f3139a05c
--- /dev/null
+++ b/docs/migration.md
@@ -0,0 +1,213 @@
+# Migration guide
+
+@tableofcontents
+
+
+
+This is a collection of snippets that highlight preferred API over the deprecated original API.
+
+## isAckPayloadAvailable()
+
+> **Deprecated since v1.4.2**
+
+This function is equivalent to `RF24::available()`.
+Any use of `RF24::isAckPayloadAvailable()` is interchangeable with `RF24::available()`.
+
+
+| Old |
+New (supported) |
+
|
+
+```cpp
+if radio.isAckPayloadAvailable() { /* .. */ }
+```
+
+ |
+
+```cpp
+if radio.available() { /* .. */ }
+```
+
+ |
+
+## openReadingPipe(uint8_t, uint64_t) and openWritingPipe(uint64_t)
+
+> **Deprecated since v1.3.11**
+
+These functions' address parameter used a 64-bit unsigned integer (`uint64_t`).
+The nRF24L01 can only use up to 40 bit addresses.
+Thus, there was an unused 24 bits being allocated for addresses using this function.
+
+There are overloaded functions that use a buffer instead:
+
+- `RF24::openReadingPipe(uint8_t, const uint8_t*)`
+- `RF24::openWritingPipe(const uint8_t*)`
+
+These eliminate the unnecessary 24 bits by only using the length of the buffer (`uint8_t*`)
+specified by `RF24::setAddressWidth()`.
+
+> [!CAUTION]
+> The endianness (byte order) of a buffer is reversed compared to a 64-bit integer.
+> ```c
+> uint64_t address = 0xB3B4B5B6C2;
+> // is the same address as
+> uint8_t address[5] = {0xC2, 0xB6, 0xB5, 0xB4, 0xB3};
+> ```
+> Notice the MSB (Most Significant Byte) `0xC2` is last in the integer but first in the buffer.
+
+
+| Old |
+New (supported) |
+
|
+
+```cpp
+uint64_t address = 0xB3B4B5B6C2;
+radio.openReadingPipe(1, address);
+```
+
+ |
+
+```cpp
+uint8_t address[5] = {0xC2, 0xB6, 0xB5, 0xB4, 0xB3};
+radio.openReadingPipe(1, address);
+```
+
+ |
+
+> [!NOTE]
+> Our examples actually use a C-string casted as an array of 6 bytes.
+> That's because a C-string (`char*`) must be NULL terminated (`\0` at the end) in memory.
+> ```c
+> uint8_t address[][6] = { "1Node", "2Node" };
+> // is equivalent to
+> uint8_t address[][6] = { { '1', 'N', 'o', 'd', 'e', '\0' },
+> { '2', 'N', 'o', 'd', 'e', '\0' } };
+> ```
+
+## isFifo(bool, bool)
+
+> **Deprecated since v1.4.11**
+
+Introduced as a compliment to `RF24::isFifo(bool)` in v1.4.3, this function was
+supposed to provide a specific detail about a specified radio's FIFO. However, it was
+discovered that the function may not highlight binary corruption (`RF24_FIFO_INVALID`)
+observed in the SPI bus' MISO line.
+
+A fix was introduced using enumerated values of `rf24_fifo_state_e`.
+Since then, `RF24::isFifo(bool)` is now preferred as it accurately describes the result.
+
+
+| Old |
+New (supported) |
+
|
+
+```cpp
+bool rxFifoEmpty = radio.isFifo(false, true);
+```
+
+ |
+
+```cpp
+bool rxFifoEmpty = radio.isFifo(false) == RF24_FIFO_EMPTY;
+```
+
+ |
+
+## maskIRQ()
+
+> **Deprecated since v1.5**
+
+Originally `RF24::maskIRQ()` was the only function provided to influence the radio's IRQ pin.
+However, the 3 required boolean parameters made this prone to bugs in user code.
+The parameters' meaning was confusingly reversed, and they were easily misplaced in the wrong order.
+
+A better approach was introduced with `RF24::setStatusFlags()`.
+It's 1 parameter accepts values defined by the `rf24_irq_flags_e` enumerated constants.
+These constant values specify individual events;
+they can also be OR'd together to specify multiple events.
+
+
+| Old |
+New (supported) |
+
|
+
+```cpp
+// IRQ pin only activated by "RX Data Ready" event
+radio.maskIRQ(1, 1, 0);
+
+// IRQ pin activated by "TX Data Sent" and TX Data Failed" events
+radio.maskIRQ(0, 0, 1);
+
+// IRQ pin activated by all events
+radio.maskIRQ(0, 0, 0);
+
+// IRQ pin disabled
+radio.maskIRQ(1, 1, 1);
+```
+
+ |
+
+```cpp
+// IRQ pin only activated by "RX Data Ready" event
+radio.setStatusFlags(RF24_RX_DR);
+
+// IRQ pin activated by "TX Data Sent" and TX Data Failed" events
+radio.setStatusFlags(RF24_TX_DS | RF24_TX_DF);
+
+// IRQ pin activated by all events
+radio.setStatusFlags(RF24_IRQ_ALL);
+
+// IRQ pin disabled
+radio.setStatusFlags(RF24_IRQ_NONE);
+// or equivalently
+radio.setStatusFlags();
+```
+
+ |
+
+## whatHappened()
+
+> **Deprecated since v1.5**
+
+Originally, `RF24::whatHappened()` was the only way to clear the events that triggered the IRQ pin.
+Like `maskIRQ()`, this was also prone to bugs because of the 3 required boolean parameters
+(passed by reference).
+
+The aptly named `RF24::clearStatusFlags()` is designed to be a replacement for `RF24::whatHappened()`.
+Like `RF24::clearStatusFlags()`, `RF24::setStatusFlags()` takes 1 parameter whose value is defined by
+the `rf24_irq_flags_e` enumerated constants. These constant values specify individual flags;
+they can also be OR'd together to specify multiple flags.
+Additionally, `RF24::clearStatusFlags()` returns the STATUS byte containing the flags that
+caused the IRQ pin to go active LOW.
+This allows the user code to allocate less memory when diagnosing the IRQ pin's meaning.
+
+
+| Old |
+New (supported) |
+
|
+
+```cpp
+bool tx_ds, tx_df, rx_dr;
+radio.whatHappened(tx_ds, tx_df, rx_dr);
+```
+
+ |
+
+```cpp
+uint8_t flags = radio.clearStatusFlags();
+// or equivalently
+uint8_t flags = radio.clearStatusFlags(RF24_IRQ_ALL);
+
+// focus on the events you care about
+if (flags & RF24_TX_DS) { /* TX data sent */ }
+if (flags & RF24_TX_DF) { /* TX data failed to send */ }
+if (flags & RF24_RX_DR) { /* RX data is in the RX FIFO */ }
+
+// only clear the "TX Data Sent" and TX Data Failed" events
+radio.clearStatusFlags(RF24_TX_DS | RF24_TX_DF);
+
+// only clear the "RX Data Ready" event
+radio.clearStatusFlags(RF24_RX_DR);
+```
+
+ |
diff --git a/examples/InterruptConfigure/InterruptConfigure.ino b/examples/InterruptConfigure/InterruptConfigure.ino
index 19ef9c504..48f6a4c9c 100644
--- a/examples/InterruptConfigure/InterruptConfigure.ino
+++ b/examples/InterruptConfigure/InterruptConfigure.ino
@@ -118,8 +118,8 @@ void setup() {
} else {
// setup for RX mode
- // let IRQ pin only trigger on "data ready" event in RX mode
- radio.maskIRQ(1, 1, 0); // args = "data_sent", "data_fail", "data_ready"
+ // let IRQ pin only trigger on "data_ready" event in RX mode
+ radio.setStatusFlags(RF24_RX_DR);
// Fill the TX FIFO with 3 ACK payloads for the first 3 received
// transmissions on pipe 1
@@ -150,21 +150,22 @@ void loop() {
// Test the "data ready" event with the IRQ pin
Serial.println(F("\nConfiguring IRQ pin to ignore the 'data sent' event"));
- radio.maskIRQ(true, false, false); // args = "data_sent", "data_fail", "data_ready"
+ radio.setStatusFlags(RF24_RX_DR | RF24_TX_DF);
Serial.println(F(" Pinging RX node for 'data ready' event..."));
} else if (pl_iterator == 1) {
// Test the "data sent" event with the IRQ pin
Serial.println(F("\nConfiguring IRQ pin to ignore the 'data ready' event"));
- radio.maskIRQ(false, false, true); // args = "data_sent", "data_fail", "data_ready"
+ radio.setStatusFlags(RF24_TX_DS | RF24_TX_DF);
Serial.println(F(" Pinging RX node for 'data sent' event..."));
} else if (pl_iterator == 2) {
// Use this iteration to fill the RX node's FIFO which sets us up for the next test.
// write() uses virtual interrupt flags that work despite the masking of the IRQ pin
- radio.maskIRQ(1, 1, 1); // disable IRQ masking for this step
+ // disable IRQ pin for this step
+ radio.setStatusFlags();
Serial.println(F("\nSending 1 payload to fill RX node's FIFO. IRQ pin is neglected."));
// write() will call flush_tx() on 'data fail' events
@@ -183,7 +184,7 @@ void loop() {
// test the "data fail" event with the IRQ pin
Serial.println(F("\nConfiguring IRQ pin to reflect all events"));
- radio.maskIRQ(0, 0, 0); // args = "data_sent", "data_fail", "data_ready"
+ radio.setStatusFlags(RF24_IRQ_ALL);
Serial.println(F(" Pinging inactive RX node for 'data fail' event..."));
}
@@ -266,7 +267,8 @@ void loop() {
role = false;
- radio.maskIRQ(0, 0, 0); // the IRQ pin should only trigger on "data ready" event
+ // let IRQ pin only trigger on "data_ready" event in RX mode
+ radio.setStatusFlags(RF24_RX_DR);
// Fill the TX FIFO with 3 ACK payloads for the first 3 received
// transmissions on pipe 1
@@ -298,33 +300,32 @@ void assessInterruptEvent() {
Serial.println(F("\tIRQ pin is actively LOW")); // show that this function was called
delayMicroseconds(250);
- bool tx_ds, tx_df, rx_dr; // declare variables for IRQ masks
- radio.whatHappened(tx_ds, tx_df, rx_dr); // get values for IRQ masks
- // whatHappened() clears the IRQ masks also. This is required for
+ uint8_t flags = radio.clearStatusFlags();
+ // Resetting the tx_df flag is required for
// continued TX operations when a transmission fails.
- // clearing the IRQ masks resets the IRQ pin to its inactive state (HIGH)
+ // clearing the status flags resets the IRQ pin to its inactive state (HIGH)
Serial.print(F("\tdata_sent: "));
- Serial.print(tx_ds); // print "data sent" mask state
+ Serial.print((flags & RF24_TX_DS) > 0); // print "data sent" flag state
Serial.print(F(", data_fail: "));
- Serial.print(tx_df); // print "data fail" mask state
+ Serial.print((flags & RF24_TX_DF) > 0); // print "data fail" flag state
Serial.print(F(", data_ready: "));
- Serial.println(rx_dr); // print "data ready" mask state
+ Serial.println((flags & RF24_RX_DR) > 0); // print "data ready" flag state
- if (tx_df) // if TX payload failed
- radio.flush_tx(); // clear all payloads from the TX FIFO
+ if (flags & RF24_TX_DF) // if TX payload failed
+ radio.flush_tx(); // clear all payloads from the TX FIFO
// print if test passed or failed. Unintentional fails mean the RX node was not listening.
// pl_iterator has already been incremented by now
if (pl_iterator <= 1) {
Serial.print(F(" 'Data Ready' event test "));
- Serial.println(rx_dr ? F("passed") : F("failed"));
+ Serial.println(flags & RF24_RX_DR ? F("passed") : F("failed"));
} else if (pl_iterator == 2) {
Serial.print(F(" 'Data Sent' event test "));
- Serial.println(tx_ds ? F("passed") : F("failed"));
+ Serial.println(flags & RF24_TX_DS ? F("passed") : F("failed"));
} else if (pl_iterator == 4) {
Serial.print(F(" 'Data Fail' event test "));
- Serial.println(tx_df ? F("passed") : F("failed"));
+ Serial.println(flags & RF24_TX_DF ? F("passed") : F("failed"));
}
got_interrupt = false; // reset this flag to prevent calling this function from loop()
wait_for_event = false; // ready to continue with loop() operations
diff --git a/examples/StreamingData/StreamingData.ino b/examples/StreamingData/StreamingData.ino
index 3a2153b42..0c3d6458f 100644
--- a/examples/StreamingData/StreamingData.ino
+++ b/examples/StreamingData/StreamingData.ino
@@ -113,8 +113,15 @@ void loop() {
while (i < SIZE) {
makePayload(i); // make the payload
if (!radio.writeFast(&buffer, SIZE)) {
- failures++;
- radio.reUseTX();
+ uint8_t flags = radio.getStatusFlags();
+ if (flags & RF24_TX_DF) {
+ failures++;
+ // now we need to reset the tx_df flag and the radio's CE pin
+ radio.ce(LOW);
+ radio.clearStatusFlags(RF24_TX_DF);
+ radio.ce(HIGH);
+ }
+ // else the TX FIFO is full; just continue loop.
} else {
i++;
}
diff --git a/examples_linux/interruptConfigure.cpp b/examples_linux/interruptConfigure.cpp
index ec71b7a51..fc68131a1 100644
--- a/examples_linux/interruptConfigure.cpp
+++ b/examples_linux/interruptConfigure.cpp
@@ -174,22 +174,23 @@ void master()
// Test the "data ready" event with the IRQ pin
cout << "\nConfiguring IRQ pin to ignore the 'data sent' event\n";
- radio.maskIRQ(true, false, false); // args = "data_sent", "data_fail", "data_ready"
+ radio.setStatusFlags(RF24_RX_DR | RF24_TX_DF);
cout << " Pinging RX node for 'data ready' event..." << endl;
ping_n_wait(); // transmit a payload and detect the IRQ pin
pl_iterator++; // increment iterator for next test
// Test the "data sent" event with the IRQ pin
cout << "\nConfiguring IRQ pin to ignore the 'data ready' event\n";
- radio.maskIRQ(false, false, true); // args = "data_sent", "data_fail", "data_ready"
+ radio.setStatusFlags(RF24_TX_DS | RF24_TX_DF);
cout << " Pinging RX node for 'data sent' event..." << endl;
radio.flush_tx(); // flush payloads from any failed prior test
ping_n_wait(); // transmit a payload and detect the IRQ pin
pl_iterator++; // increment iterator for next test
// Use this iteration to fill the RX node's FIFO which sets us up for the next test.
- // write() uses virtual interrupt flags that work despite the masking of the IRQ pin
- radio.maskIRQ(1, 1, 1); // disable IRQ masking for this step
+ // write() uses virtual interrupt flags that work despite the masking of the IRQ pin.
+ // disable IRQ pin for this step
+ radio.setStatusFlags();
cout << "\nSending 1 payload to fill RX node's FIFO. IRQ pin is neglected.\n";
// write() will call flush_tx() on 'data fail' events
@@ -203,7 +204,7 @@ void master()
// test the "data fail" event with the IRQ pin
cout << "\nConfiguring IRQ pin to reflect all events\n";
- radio.maskIRQ(0, 0, 0); // args = "data_sent", "data_fail", "data_ready"
+ radio.setStatusFlags(RF24_IRQ_ALL);
cout << " Pinging inactive RX node for 'data fail' event..." << endl;
ping_n_wait(); // transmit a payload and detect the IRQ pin
@@ -223,7 +224,7 @@ void slave()
{
// let IRQ pin only trigger on "data_ready" event in RX mode
- radio.maskIRQ(1, 1, 0); // args = "data_sent", "data_fail", "data_ready"
+ radio.setStatusFlags(RF24_RX_DR);
// Fill the TX FIFO with 3 ACK payloads for the first 3 received
// transmissions on pipe 0.
@@ -277,26 +278,24 @@ void ping_n_wait()
cout << "\tIRQ pin is actively LOW" << endl; // show that this function was called
- bool tx_ds, tx_df, rx_dr; // declare variables for IRQ masks
- radio.whatHappened(tx_ds, tx_df, rx_dr); // get values for IRQ masks
- // whatHappened() clears the IRQ masks also. This is required for
+ uint8_t flags = radio.clearStatusFlags();
+ // Resetting the tx_df flag is required for
// continued TX operations when a transmission fails.
- // clearing the IRQ masks resets the IRQ pin to its inactive state (HIGH)
+ // clearing the status flags resets the IRQ pin to its inactive state (HIGH)
- cout << "\tdata_sent: " << tx_ds; // print "data sent" mask state
- cout << ", data_fail: " << tx_df; // print "data fail" mask state
- cout << ", data_ready: " << rx_dr << endl; // print "data ready" mask state
+ cout << "\t";
+ radio.printStatus(flags); // print StatusFlags description
- if (tx_df) // if TX payload failed
- radio.flush_tx(); // clear all payloads from the TX FIFO
+ if (flags & RF24_TX_DF) // if TX payload failed
+ radio.flush_tx(); // clear all payloads from the TX FIFO
// print if test passed or failed. Unintentional fails mean the RX node was not listening.
if (pl_iterator == 0)
- cout << " 'Data Ready' event test " << (rx_dr ? "passed" : "failed") << endl;
+ cout << " 'Data Ready' event test " << (flags & RF24_RX_DR ? "passed" : "failed") << endl;
else if (pl_iterator == 1)
- cout << " 'Data Sent' event test " << (tx_ds ? "passed" : "failed") << endl;
+ cout << " 'Data Sent' event test " << (flags & RF24_TX_DS ? "passed" : "failed") << endl;
else if (pl_iterator == 3)
- cout << " 'Data Fail' event test " << (tx_df ? "passed" : "failed") << endl;
+ cout << " 'Data Fail' event test " << (flags & RF24_TX_DF ? "passed" : "failed") << endl;
got_interrupt = false;
}
diff --git a/examples_linux/interrupt_configure.py b/examples_linux/interrupt_configure.py
index 54aea0bb1..72f945c5a 100644
--- a/examples_linux/interrupt_configure.py
+++ b/examples_linux/interrupt_configure.py
@@ -6,7 +6,15 @@
"""
import time
-from RF24 import RF24, RF24_PA_LOW, RF24_DRIVER
+from RF24 import (
+ RF24,
+ RF24_PA_LOW,
+ RF24_DRIVER,
+ RF24_TX_DF,
+ RF24_TX_DS,
+ RF24_RX_DR,
+ RF24_IRQ_ALL,
+)
try:
import gpiod
@@ -97,14 +105,25 @@
def interrupt_handler():
"""This function is called when IRQ pin is detected active LOW"""
print("\tIRQ pin went active LOW.")
- tx_ds, tx_df, rx_dr = radio.whatHappened() # update IRQ status flags
- print(f"\ttx_ds: {tx_ds}, tx_df: {tx_df}, rx_dr: {rx_dr}")
+ flags = radio.clearStatusFlags()
+ # Resetting the tx_df flag is required for
+ # continued TX operations when a transmission fails.
+ # clearing the status flags resets the IRQ pin to its inactive state (HIGH)
+ print("\t", end="", flush=True)
+ radio.printStatus(flags)
if pl_iterator[0] == 0:
- print(" 'data ready' event test", ("passed" if rx_dr else "failed"))
+ print(
+ " 'data ready' event test",
+ ("passed" if flags & RF24_RX_DR else "failed"),
+ )
elif pl_iterator[0] == 1:
- print(" 'data sent' event test", ("passed" if tx_ds else "failed"))
+ print(
+ " 'data sent' event test", ("passed" if flags & RF24_TX_DS else "failed")
+ )
elif pl_iterator[0] == 2:
- print(" 'data fail' event test", ("passed" if tx_df else "failed"))
+ print(
+ " 'data fail' event test", ("passed" if flags & RF24_TX_DF else "failed")
+ )
# setup IRQ GPIO pin
@@ -143,7 +162,7 @@ def master():
# on data ready test
print("\nConfiguring IRQ pin to only ignore 'on data sent' event")
- radio.maskIRQ(True, False, False) # args = tx_ds, tx_df, rx_dr
+ radio.setStatusFlags(RF24_RX_DR | RF24_TX_DF)
print(" Pinging slave node for an ACK payload...")
pl_iterator[0] = 0
radio.startFastWrite(tx_payloads[0], False) # False means expecting an ACK
@@ -152,7 +171,7 @@ def master():
# on "data sent" test
print("\nConfiguring IRQ pin to only ignore 'on data ready' event")
- radio.maskIRQ(False, False, True) # args = tx_ds, tx_df, rx_dr
+ radio.setStatusFlags(RF24_TX_DS | RF24_TX_DF)
print(" Pinging slave node again...")
pl_iterator[0] = 1
radio.startFastWrite(tx_payloads[1], False) # False means expecting an ACK
@@ -162,7 +181,7 @@ def master():
# trigger slave node to exit by filling the slave node's RX FIFO
print("\nSending one extra payload to fill RX FIFO on slave node.")
print("Disabling IRQ pin for all events.")
- radio.maskIRQ(True, True, True) # args = tx_ds, tx_df, rx_dr
+ radio.setStatusFlags()
if radio.write(tx_payloads[2]):
print("Slave node should not be listening anymore.")
else:
@@ -170,7 +189,7 @@ def master():
# on "data fail" test
print("\nConfiguring IRQ pin to go active for all events.")
- radio.maskIRQ(False, False, False) # args = tx_ds, tx_df, rx_dr
+ radio.setStatusFlags(RF24_IRQ_ALL)
print(" Sending a ping to inactive slave node...")
radio.flush_tx() # just in case any previous tests failed
pl_iterator[0] = 2
@@ -189,7 +208,7 @@ def slave(timeout=6): # will listen for 6 seconds before timing out
# the "data sent" or "data fail" events will trigger when we
# receive with ACK payloads enabled (& loaded in TX FIFO)
print("\nDisabling IRQ pin for all events.")
- radio.maskIRQ(True, True, True) # args = tx_ds, tx_df, rx_dr
+ radio.setStatusFlags()
# setup radio to receive pings, fill TX FIFO with ACK payloads
radio.writeAckPayload(1, ack_payloads[0])
radio.writeAckPayload(1, ack_payloads[1])
diff --git a/examples_linux/streamingData.cpp b/examples_linux/streamingData.cpp
index e1a9b26ca..30ca66b92 100644
--- a/examples_linux/streamingData.cpp
+++ b/examples_linux/streamingData.cpp
@@ -208,8 +208,16 @@ void master()
while (i < SIZE) {
makePayload(i);
if (!radio.writeFast(&buffer, SIZE)) {
- failures++;
- radio.reUseTX();
+ uint8_t flags = radio.getStatusFlags();
+ if (flags & RF24_TX_DF) {
+ failures++;
+ // failed to transmit a previous payload.
+ // Now we need to reset the tx_df flag and the CE pin
+ radio.ce(LOW);
+ radio.clearStatusFlags(RF24_TX_DF);
+ radio.ce(HIGH);
+ }
+ // else the TX FIFO is full; just continue loop
}
else {
i++;
@@ -241,10 +249,10 @@ void slave()
time_t startTimer = time(nullptr); // start a timer
while (time(nullptr) - startTimer < 6) { // use 6 second timeout
if (radio.available()) { // is there a payload
+ counter++; // increment counter
radio.read(&buffer, SIZE); // fetch payload from FIFO
cout << "Received: " << buffer; // print the payload's value
cout << " - " << counter << endl; // print the counter
- counter++; // increment counter
startTimer = time(nullptr); // reset timer
}
}
diff --git a/examples_linux/streaming_data.py b/examples_linux/streaming_data.py
index 717a7efeb..eb38ab26c 100644
--- a/examples_linux/streaming_data.py
+++ b/examples_linux/streaming_data.py
@@ -7,7 +7,7 @@
"""
import time
-from RF24 import RF24, RF24_PA_LOW, RF24_DRIVER
+from RF24 import RF24, RF24_PA_LOW, RF24_DRIVER, RF24_TX_DF
print(__file__) # print example name
@@ -94,27 +94,32 @@ def master(count: int = 1):
radio.stopListening() # put radio in TX mode
radio.flush_tx() # clear the TX FIFO so we can use all 3 levels
failures = 0 # keep track of manual retries
- start_timer = time.monotonic_ns() # start timer
for multiplier in range(count): # repeat transmit the same data stream
buf_iter = 0 # iterator of payloads for the while loop
+ start_timer = time.monotonic_ns() # start timer
while buf_iter < SIZE: # cycle through all the payloads
buffer = make_buffer(buf_iter) # make a payload
if not radio.writeFast(buffer): # transmission failed
- failures += 1 # increment manual retry count
+ flags = radio.getStatusFlags()
+ if flags & RF24_TX_DF:
+ failures += 1 # increment manual retry count
+ # now we need to reset the tx_df flag and the radio's CE pin
+ radio.ce(False)
+ flags = radio.clearStatusFlags(RF24_TX_DF)
+ radio.ce(True)
if failures > 99 and buf_iter < 7 and multiplier < 2:
# we need to prevent an infinite loop
print("Too many failures detected. Aborting at payload ", buffer[0])
multiplier = count # be sure to exit the for loop
break # exit the while loop
- radio.reUseTX() # resend payload in top level of TX FIFO
else: # transmission succeeded
buf_iter += 1
- end_timer = time.monotonic_ns() # end timer
- print(
- f"Time to transmit data = {(end_timer - start_timer) / 1000} us.",
- f"Detected {failures} failures.",
- )
+ end_timer = time.monotonic_ns() # end timer
+ print(
+ f"Time to transmit data = {(end_timer - start_timer) / 1000} us.",
+ f"Detected {failures} failures.",
+ )
def slave(timeout: int = 6):
diff --git a/examples_pico/interruptConfigure.cpp b/examples_pico/interruptConfigure.cpp
index 27a272696..b1414d567 100644
--- a/examples_pico/interruptConfigure.cpp
+++ b/examples_pico/interruptConfigure.cpp
@@ -75,6 +75,7 @@ bool setup()
printf("radioNumber = %d\n", (int)radioNumber);
// setup the IRQ_PIN
+ gpio_init(IRQ_PIN);
gpio_set_irq_enabled_with_callback(IRQ_PIN, GPIO_IRQ_EDGE_FALL, true, &interruptHandler);
// IMPORTANT: do not call radio.available() before calling
// radio.whatHappened() when the interruptHandler() is triggered by the
@@ -110,8 +111,8 @@ bool setup()
else {
// setup for RX mode
- // let IRQ pin not trigger in RX mode
- radio.maskIRQ(1, 1, 1); // args = "data_sent", "data_fail", "data_ready"
+ // disable IRQ pin in RX mode
+ radio.setStatusFlags();
// Fill the TX FIFO with 3 ACK payloads for the first 3 received
// transmissions on pipe 1
@@ -142,21 +143,22 @@ void loop()
// Test the "data ready" event with the IRQ pin
printf("\nConfiguring IRQ pin to ignore the 'data sent' event\n");
- radio.maskIRQ(true, false, false); // args = "data_sent", "data_fail", "data_ready"
+ radio.setStatusFlags(RF24_RX_DR | RF24_TX_DF);
printf(" Pinging RX node for 'data ready' event...\n");
}
else if (pl_iterator == 1) {
// Test the "data sent" event with the IRQ pin
printf("\nConfiguring IRQ pin to ignore the 'data ready' event\n");
- radio.maskIRQ(false, false, true); // args = "data_sent", "data_fail", "data_ready"
+ radio.setStatusFlags(RF24_TX_DS | RF24_TX_DF);
printf(" Pinging RX node for 'data sent' event...\n");
}
else if (pl_iterator == 2) {
// Use this iteration to fill the RX node's FIFO which sets us up for the next test.
// write() uses virtual interrupt flags that work despite the masking of the IRQ pin
- radio.maskIRQ(1, 1, 1); // disable IRQ masking for this step
+ // disable IRQ pin for this step
+ radio.setStatusFlags();
printf("\nSending 1 payload to fill RX node's FIFO. IRQ pin is neglected.\n");
// write() will call flush_tx() on 'data fail' events
@@ -177,7 +179,7 @@ void loop()
// test the "data fail" event with the IRQ pin
printf("\nConfiguring IRQ pin to reflect all events\n");
- radio.maskIRQ(0, 0, 0); // args = "data_sent", "data_fail", "data_ready"
+ radio.setStatusFlags(RF24_IRQ_ALL);
printf(" Pinging inactive RX node for 'data fail' event...\n");
}
@@ -263,7 +265,8 @@ void loop()
printf("*** CHANGING TO RECEIVE ROLE -- PRESS 'T' TO SWITCH BACK\n");
role = false;
- radio.maskIRQ(1, 1, 1); // the IRQ pin should not trigger in this example's RX rode
+ // do not trigger IRQ pin in RX mode
+ radio.setStatusFlags();
// Fill the TX FIFO with 3 ACK payloads for the first 3 received
// transmissions on pipe 1
@@ -287,7 +290,7 @@ void loop()
*/
void interruptHandler(uint gpio, uint32_t events)
{
- if (gpio != IRQ_PIN && !(events | GPIO_IRQ_EDGE_FALL)) {
+ if (gpio != IRQ_PIN && (events & GPIO_IRQ_EDGE_FALL) == 0) {
// the gpio pin and event does not match the configuration we specified
return;
}
@@ -301,32 +304,28 @@ void interruptHandler(uint gpio, uint32_t events)
void assessInterruptEvent()
{
// print IRQ status and all masking flags' states
- printf("\tIRQ pin is actively LOW\n"); // show that this function was called
- bool tx_ds, tx_df, rx_dr; // declare variables for IRQ masks
- radio.whatHappened(tx_ds, tx_df, rx_dr); // get values for IRQ masks
- // whatHappened() clears the IRQ masks also. This is required for
+ printf("\tIRQ pin is actively LOW\n"); // show that this function was called
+ uint8_t flags = radio.clearStatusFlags();
+ // Resetting the tx_df flag is required for
// continued TX operations when a transmission fails.
- // clearing the IRQ masks resets the IRQ pin to its inactive state (HIGH)
+ // clearing the status flags resets the IRQ pin to its inactive state (HIGH)
- // print "data sent", "data fail", "data ready" mask states
- printf("\tdata_sent: %s, data_fail: %s, data_ready: %s\n",
- tx_ds ? "true" : "false",
- tx_df ? "true" : "false",
- rx_dr ? "true" : "false");
+ printf("\t");
+ radio.printStatus(flags); // print status flags info
- if (tx_df) // if TX payload failed
- radio.flush_tx(); // clear all payloads from the TX FIFO
+ if (flags & RF24_TX_DF) // if TX payload failed
+ radio.flush_tx(); // clear all payloads from the TX FIFO
// print if test passed or failed. Unintentional fails mean the RX node was not listening.
// pl_iterator has already been incremented by now
if (pl_iterator <= 1) {
- printf(" 'Data Ready' event test %s\n", rx_dr ? "passed" : "failed");
+ printf(" 'Data Ready' event test %s\n", flags & RF24_RX_DR ? "passed" : "failed");
}
else if (pl_iterator == 2) {
- printf(" 'Data Sent' event test %s\n", tx_ds ? "passed" : "failed");
+ printf(" 'Data Sent' event test %s\n", flags & RF24_TX_DS ? "passed" : "failed");
}
else if (pl_iterator == 4) {
- printf(" 'Data Fail' event test %s\n", tx_df ? "passed" : "failed");
+ printf(" 'Data Fail' event test %s\n", flags & RF24_TX_DF ? "passed" : "failed");
}
got_interrupt = false; // reset this flag to prevent calling this function from loop()
wait_for_event = false; // ready to continue with loop() operations
diff --git a/examples_pico/streamingData.cpp b/examples_pico/streamingData.cpp
index 4d02e1024..8e8d61138 100644
--- a/examples_pico/streamingData.cpp
+++ b/examples_pico/streamingData.cpp
@@ -110,8 +110,15 @@ void loop()
while (i < SIZE) {
makePayload(i); // make the payload
if (!radio.writeFast(&buffer, SIZE)) {
- failures++;
- radio.reUseTX();
+ uint8_t flags = radio.getStatusFlags();
+ if (flags & RF24_TX_DF) {
+ failures++;
+ // now we need to reset the tx_df flag and the radio's CE pin.
+ radio.ce(LOW);
+ radio.clearStatusFlags(RF24_TX_DF);
+ radio.ce(HIGH);
+ }
+ // else the TX FIFO is full; just continue loop.
}
else {
i++;
diff --git a/pyRF24/pyRF24.cpp b/pyRF24/pyRF24.cpp
index 197a42a83..92ceeb158 100644
--- a/pyRF24/pyRF24.cpp
+++ b/pyRF24/pyRF24.cpp
@@ -287,6 +287,14 @@ BOOST_PYTHON_MODULE(RF24)
.value("RF24_FIFO_INVALID", RF24_FIFO_INVALID)
.export_values();
+ bp::enum_("rf24_irq_flags_e")
+ .value("RF24_TX_DF", RF24_TX_DF)
+ .value("RF24_TX_DS", RF24_TX_DS)
+ .value("RF24_RX_DR", RF24_RX_DR)
+ .value("RF24_IRQ_ALL", RF24_IRQ_ALL)
+ .value("RF24_IRQ_NONE", RF24_IRQ_NONE)
+ .export_values();
+
// ******************** RF24 class **************************
bp::class_("RF24", bp::init((bp::arg("_cepin"), bp::arg("_cspin"))))
#if defined(RF24_LINUX) && !defined(MRAA)
@@ -323,6 +331,7 @@ BOOST_PYTHON_MODULE(RF24)
.def("powerDown", &RF24::powerDown)
.def("powerUp", &RF24::powerUp)
.def("printDetails", &RF24::printDetails)
+ .def("printStatus", &RF24::printStatus)
.def("printPrettyDetails", &RF24::printPrettyDetails)
.def("sprintfPrettyDetails", &sprintfPrettyDetails_wrap)
.def("reUseTX", &RF24::reUseTX)
@@ -349,6 +358,12 @@ BOOST_PYTHON_MODULE(RF24)
.def("setRadiation", &RF24::setRadiation)
.def("txStandBy", (bool(::RF24::*)(::uint32_t, bool))(&RF24::txStandBy), txStandBy_wrap1(bp::args("timeout", "startTx")))
.def("whatHappened", &whatHappened_wrap)
+ .def("setStatusFlags", (uint8_t(::RF24::*)(void))(&RF24::setStatusFlags))
+ .def("setStatusFlags", (uint8_t(::RF24::*)(uint8_t))(&RF24::setStatusFlags), (bp::arg("flags")))
+ .def("clearStatusFlags", (uint8_t(::RF24::*)(void))(&RF24::clearStatusFlags))
+ .def("clearStatusFlags", (uint8_t(::RF24::*)(uint8_t))(&RF24::clearStatusFlags), (bp::arg("flags")))
+ .def("getStatusFlags", &RF24::getStatusFlags)
+ .def("update", &RF24::update)
.def("startConstCarrier", &RF24::startConstCarrier, (bp::arg("level"), bp::arg("channel")))
.def("stopConstCarrier", &RF24::stopConstCarrier)
.def("write", &write_wrap1, (bp::arg("buf")))