| 1 | # Migration guide |
| 2 | |
| 3 | @tableofcontents |
| 4 | |
| 5 | <!-- markdownlint-disable MD033 MD031 --> |
| 6 | |
| 7 | This is a collection of snippets that highlight preferred API over the deprecated original API. |
| 8 | |
| 9 | ## isAckPayloadAvailable() |
| 10 | |
| 11 | > **Deprecated since v1.4.2** |
| 12 | |
| 13 | This function is equivalent to `RF24::available()`. |
| 14 | Any use of `RF24::isAckPayloadAvailable()` is interchangeable with `RF24::available()`. |
| 15 | |
| 16 | <table><tr> |
| 17 | <th>Old</th> |
| 18 | <th>New (supported)</th> |
| 19 | </tr><tr><td> |
| 20 | |
| 21 | ```cpp |
| 22 | if radio.isAckPayloadAvailable() { /* .. */ } |
| 23 | ``` |
| 24 | |
| 25 | </td><td> |
| 26 | |
| 27 | ```cpp |
| 28 | if radio.available() { /* .. */ } |
| 29 | ``` |
| 30 | |
| 31 | </td></tr></table> |
| 32 | |
| 33 | ## 64-bit integer addresses |
| 34 | |
| 35 | Any function that accept an address in the form of `uint64_t` is discouraged. This includes |
| 36 | |
| 37 | - `RF24::openReadingPipe(uint8_t, uint64_t)` |
| 38 | > **Deprecated since v1.3.11** |
| 39 | - `RF24::openWritingPipe(uint64_t)` |
| 40 | > **Deprecated since v1.3.11** |
| 41 | - `RF24::stopListening(const uint64_t)` |
| 42 | > **Deprecated since v1.5** |
| 43 | |
| 44 | These functions' address parameter use a 64-bit unsigned integer (`uint64_t`). |
| 45 | The nRF24L01 can only use up to 40 bit addresses. |
| 46 | Thus, there is an unused 24 bits being allocated for addresses using these functions. |
| 47 | |
| 48 | There are overloaded functions that use a buffer instead: |
| 49 | |
| 50 | - `RF24::openReadingPipe(uint8_t, const uint8_t*)` |
| 51 | - `RF24::openWritingPipe(const uint8_t*)` |
| 52 | - `RF24::stopListening(const uint8_t*)` |
| 53 | |
| 54 | These eliminate the unnecessary 24 bits by only using the length of the buffer (`uint8_t*`) |
| 55 | specified by `RF24::setAddressWidth()`. |
| 56 | |
| 57 | @see The `RF24::openWritingPipe(const uint8_t*)` is now deprecated in favor of the |
| 58 | overloaded `RF24::stopListening(const uint8_t*)` function. |
| 59 | See the section below for more detail. |
| 60 | |
| 61 | > [!CAUTION] |
| 62 | > The endianness (byte order) of a buffer is reversed compared to a 64-bit integer. |
| 63 | > ```c |
| 64 | > uint64_t address = 0xB3B4B5B6C2; |
| 65 | > // is the same address as |
| 66 | > uint8_t address[5] = {0xC2, 0xB6, 0xB5, 0xB4, 0xB3}; |
| 67 | > ``` |
| 68 | > Notice the MSB (Most Significant Byte) `0xC2` is last in the integer but first in the buffer. |
| 69 | |
| 70 | <table><tr> |
| 71 | <th>Old</th> |
| 72 | <th>New (supported)</th> |
| 73 | </tr><tr><td> |
| 74 | |
| 75 | ```cpp |
| 76 | uint64_t address = 0xB3B4B5B6C2; |
| 77 | radio.openReadingPipe(1, address); |
| 78 | ``` |
| 79 | |
| 80 | </td><td> |
| 81 | |
| 82 | ```cpp |
| 83 | uint8_t address[5] = {0xC2, 0xB6, 0xB5, 0xB4, 0xB3}; |
| 84 | radio.openReadingPipe(1, address); |
| 85 | ``` |
| 86 | |
| 87 | </td></tr></table> |
| 88 | |
| 89 | > [!NOTE] |
| 90 | > Our examples actually use a C-string casted as an array of 6 bytes. |
| 91 | > That's because a C-string (`char*`) must be NULL terminated (`\0` at the end) in memory. |
| 92 | > ```c |
| 93 | > uint8_t address[][6] = { "1Node", "2Node" }; |
| 94 | > // is equivalent to |
| 95 | > uint8_t address[][6] = { { '1', 'N', 'o', 'd', 'e', '\0' }, |
| 96 | > { '2', 'N', 'o', 'd', 'e', '\0' } }; |
| 97 | > ``` |
| 98 | |
| 99 | ## isFifo(bool, bool) |
| 100 | |
| 101 | > **Deprecated since v1.4.11** |
| 102 | |
| 103 | Introduced as a compliment to `RF24::isFifo(bool)` in v1.4.3, this function was |
| 104 | supposed to provide a specific detail about a specified radio's FIFO. However, it was |
| 105 | discovered that the function may not highlight binary corruption (`RF24_FIFO_INVALID`) |
| 106 | observed in the SPI bus' MISO line. |
| 107 | |
| 108 | A fix was introduced using enumerated values of `rf24_fifo_state_e`. |
| 109 | Since then, `RF24::isFifo(bool)` is now preferred as it accurately describes the result. |
| 110 | |
| 111 | <table><tr> |
| 112 | <th>Old</th> |
| 113 | <th>New (supported)</th> |
| 114 | </tr><tr><td> |
| 115 | |
| 116 | ```cpp |
| 117 | bool rxFifoEmpty = radio.isFifo(false, true); |
| 118 | ``` |
| 119 | |
| 120 | </td><td> |
| 121 | |
| 122 | ```cpp |
| 123 | bool rxFifoEmpty = radio.isFifo(false) == RF24_FIFO_EMPTY; |
| 124 | ``` |
| 125 | |
| 126 | </td></tr></table> |
| 127 | |
| 128 | ## maskIRQ() |
| 129 | |
| 130 | > **Deprecated since v1.5** |
| 131 | |
| 132 | Originally `RF24::maskIRQ()` was the only function provided to influence the radio's IRQ pin. |
| 133 | However, the 3 required boolean parameters made this prone to bugs in user code. |
| 134 | The parameters' meaning was confusingly reversed, and they were easily misplaced in the wrong order. |
| 135 | |
| 136 | A better approach was introduced with `RF24::setStatusFlags()`. |
| 137 | It's 1 parameter accepts values defined by the `rf24_irq_flags_e` enumerated constants. |
| 138 | These constant values specify individual events; |
| 139 | they can also be OR'd together to specify multiple events. |
| 140 | |
| 141 | <table><tr> |
| 142 | <th>Old</th> |
| 143 | <th>New (supported)</th> |
| 144 | </tr><tr><td> |
| 145 | |
| 146 | ```cpp |
| 147 | // IRQ pin only activated by "RX Data Ready" event |
| 148 | radio.maskIRQ(1, 1, 0); |
| 149 | |
| 150 | // IRQ pin activated by "TX Data Sent" and TX Data Failed" events |
| 151 | radio.maskIRQ(0, 0, 1); |
| 152 | |
| 153 | // IRQ pin activated by all events |
| 154 | radio.maskIRQ(0, 0, 0); |
| 155 | |
| 156 | // IRQ pin disabled |
| 157 | radio.maskIRQ(1, 1, 1); |
| 158 | ``` |
| 159 | |
| 160 | </td><td> |
| 161 | |
| 162 | ```cpp |
| 163 | // IRQ pin only activated by "RX Data Ready" event |
| 164 | radio.setStatusFlags(RF24_RX_DR); |
| 165 | |
| 166 | // IRQ pin activated by "TX Data Sent" and TX Data Failed" events |
| 167 | radio.setStatusFlags(RF24_TX_DS | RF24_TX_DF); |
| 168 | |
| 169 | // IRQ pin activated by all events |
| 170 | radio.setStatusFlags(RF24_IRQ_ALL); |
| 171 | |
| 172 | // IRQ pin disabled |
| 173 | radio.setStatusFlags(RF24_IRQ_NONE); |
| 174 | // or equivalently |
| 175 | radio.setStatusFlags(); |
| 176 | ``` |
| 177 | |
| 178 | </td></tr></table> |
| 179 | |
| 180 | ## whatHappened() |
| 181 | |
| 182 | > **Deprecated since v1.5** |
| 183 | |
| 184 | Originally, `RF24::whatHappened()` was the only way to clear the events that triggered the IRQ pin. |
| 185 | Like `maskIRQ()`, this was also prone to bugs because of the 3 required boolean parameters |
| 186 | (passed by reference). |
| 187 | |
| 188 | The aptly named `RF24::clearStatusFlags()` is designed to be a replacement for `RF24::whatHappened()`. |
| 189 | Like `RF24::clearStatusFlags()`, `RF24::setStatusFlags()` takes 1 parameter whose value is defined by |
| 190 | the `rf24_irq_flags_e` enumerated constants. These constant values specify individual flags; |
| 191 | they can also be OR'd together to specify multiple flags. |
| 192 | |
| 193 | Additionally, `RF24::clearStatusFlags()` returns the STATUS byte containing the flags that |
| 194 | caused the IRQ pin to go active LOW. |
| 195 | This allows the user code to allocate less memory when diagnosing the IRQ pin's meaning. |
| 196 | |
| 197 | <table><tr> |
| 198 | <th>Old</th> |
| 199 | <th>New (supported)</th> |
| 200 | </tr><tr><td> |
| 201 | |
| 202 | ```cpp |
| 203 | bool tx_ds, tx_df, rx_dr; |
| 204 | radio.whatHappened(tx_ds, tx_df, rx_dr); |
| 205 | ``` |
| 206 | |
| 207 | </td><td> |
| 208 | |
| 209 | ```cpp |
| 210 | uint8_t flags = radio.clearStatusFlags(); |
| 211 | // or equivalently |
| 212 | uint8_t flags = radio.clearStatusFlags(RF24_IRQ_ALL); |
| 213 | |
| 214 | // focus on the events you care about |
| 215 | if (flags & RF24_TX_DS) { /* TX data sent */ } |
| 216 | if (flags & RF24_TX_DF) { /* TX data failed to send */ } |
| 217 | if (flags & RF24_RX_DR) { /* RX data is in the RX FIFO */ } |
| 218 | |
| 219 | // only clear the "TX Data Sent" and TX Data Failed" events |
| 220 | radio.clearStatusFlags(RF24_TX_DS | RF24_TX_DF); |
| 221 | |
| 222 | // only clear the "RX Data Ready" event |
| 223 | radio.clearStatusFlags(RF24_RX_DR); |
| 224 | ``` |
| 225 | |
| 226 | </td></tr></table> |
| 227 | |
| 228 | ## openWritingPipe(const uint8_t*) |
| 229 | |
| 230 | > Deprecated since v1.5 |
| 231 | |
| 232 | Originally, `RF24::openWritingPipe(const uint8_t*)` was just a compliment to |
| 233 | `RF24::openReadingPipe()`. |
| 234 | It changes the address on pipe 0 because that is the only pipe that can be |
| 235 | used for transmitting. |
| 236 | |
| 237 | Unfortunately, there was a bug that prevented the given TX address from being |
| 238 | persistent on pipe 0 if the user code also set an RX address to pipe 0. |
| 239 | This bug would surface when switching between RX mode and TX mode (via |
| 240 | `RF24::startListening()` and `RF24::stopListening()` respectively) or after |
| 241 | `RF24::stopConstCarrier()` (if `RF24::isPVariant()` returns `true`). |
| 242 | |
| 243 | The solution is to cache the TX address on the `RF24` instance. |
| 244 | Consequently, this solution did not fit well with the traditional order of |
| 245 | functions used to set up the radio's TX or RX mode. |
| 246 | |
| 247 | By overloading `RF24::stopListening(const uint8_t*)`, we are able to ensure proper radio |
| 248 | setup without requiring certain functions are called in a certain order. |
| 249 | |
| 250 | - Use `RF24::stopListening(const uint8_t*)` to set the TX address and enter inactive TX mode. |
| 251 | `RF24::openReadingPipe()` can now (as of v1.5) be used in TX mode without consequence. |
| 252 | - Use `RF24::stopListening()` to enter inactive TX mode without changing the TX address. |
| 253 | |
| 254 | > [!warning] |
| 255 | > Avoid using pipe 0 for RX operations to improve performance and reliability. |
| 256 | > |
| 257 | > For implementation detail, see the source for `RF24::openReadingPipe()` and |
| 258 | > `RF24::stopListening()`. Ultimately, the datasheet's Appendix A has a detailed |
| 259 | > example outlining the order of a proper radio setup. |
| 260 | |
| 261 | <table><tr> |
| 262 | <th>Old</th> |
| 263 | <th>New (supported)</th> |
| 264 | </tr><tr><td> |
| 265 | |
| 266 | ```cpp |
| 267 | // set TX address (pipe 0) |
| 268 | radio.openWritingPipe(tx_address); |
| 269 | |
| 270 | // set RX address (pipe 1) |
| 271 | radio.openReadingPipe(1, rx_address); |
| 272 | |
| 273 | // idle radio using inactive TX mode |
| 274 | radio.stopListening(); |
| 275 | ``` |
| 276 | |
| 277 | </td><td> |
| 278 | |
| 279 | ```cpp |
| 280 | // set TX address (pipe 0) |
| 281 | radio.stopListening(tx_address); // enters inactive TX mode |
| 282 | |
| 283 | // set RX address (pipe 1) |
| 284 | radio.openReadingPipe(1, rx_address); |
| 285 | ``` |
| 286 | |
| 287 | </td></tr></table> |