Port of the nRF24l01+ library of these dudes. Not GPLed, so yeah, you can use it. Copyright (c) 2007 Stefan Engelke <mbox@stefanengelke.de> Some parts copyright (c) 2012 Eric Brundick <spirilis [at] linux dot com>

Committer:
heroic
Date:
Tue May 28 03:48:04 2013 +0000
Revision:
0:670ecbc1478a
Initial commit to mbedland:  port of the Energia nRF24l01+ library as ported to mbed.; ; This is what happens if you use a GPLv3 license, guys:  people who want to use the chip have to write their own, or port someone else's MIT licensed one.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
heroic 0:670ecbc1478a 1 /* nRF24L01+ I/O for mbed
heroic 0:670ecbc1478a 2 * Ported by Jas Strong <jasmine@heroicrobotics.com>
heroic 0:670ecbc1478a 3 *
heroic 0:670ecbc1478a 4 * Copyright (c) 2013 Eric Brundick <spirilis [at] linux dot com>
heroic 0:670ecbc1478a 5 * Permission is hereby granted, free of charge, to any person
heroic 0:670ecbc1478a 6 * obtaining a copy of this software and associated documentation
heroic 0:670ecbc1478a 7 * files (the "Software"), to deal in the Software without
heroic 0:670ecbc1478a 8 * restriction, including without limitation the rights to use, copy,
heroic 0:670ecbc1478a 9 * modify, merge, publish, distribute, sublicense, and/or sell copies
heroic 0:670ecbc1478a 10 * of the Software, and to permit persons to whom the Software is
heroic 0:670ecbc1478a 11 * furnished to do so, subject to the following conditions:
heroic 0:670ecbc1478a 12 *
heroic 0:670ecbc1478a 13 * The above copyright notice and this permission notice shall be
heroic 0:670ecbc1478a 14 * included in all copies or substantial portions of the Software.
heroic 0:670ecbc1478a 15 *
heroic 0:670ecbc1478a 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
heroic 0:670ecbc1478a 17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
heroic 0:670ecbc1478a 18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
heroic 0:670ecbc1478a 19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
heroic 0:670ecbc1478a 20 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
heroic 0:670ecbc1478a 21 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
heroic 0:670ecbc1478a 22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
heroic 0:670ecbc1478a 23 * DEALINGS IN THE SOFTWARE.
heroic 0:670ecbc1478a 24 */
heroic 0:670ecbc1478a 25
heroic 0:670ecbc1478a 26 #include "mbed.h"
heroic 0:670ecbc1478a 27 #include <stdint.h>
heroic 0:670ecbc1478a 28 #include "Enrf24.h"
heroic 0:670ecbc1478a 29
heroic 0:670ecbc1478a 30 /* Constructor */
heroic 0:670ecbc1478a 31 Enrf24::Enrf24(PinName cePin, PinName csnPin, PinName irqPin, PinName miso, PinName mosi, PinName sck) :
heroic 0:670ecbc1478a 32 _cePin(cePin),
heroic 0:670ecbc1478a 33 _csnPin(csnPin),
heroic 0:670ecbc1478a 34 _irqPin(irqPin),
heroic 0:670ecbc1478a 35 _miso(miso),
heroic 0:670ecbc1478a 36 _mosi(mosi),
heroic 0:670ecbc1478a 37 _sck(sck),
heroic 0:670ecbc1478a 38 _spi(mosi, miso, sck)
heroic 0:670ecbc1478a 39 {
heroic 0:670ecbc1478a 40
heroic 0:670ecbc1478a 41 rf_status = 0;
heroic 0:670ecbc1478a 42 rf_addr_width = 5;
heroic 0:670ecbc1478a 43 txbuf_len = 0;
heroic 0:670ecbc1478a 44 readpending = 0;
heroic 0:670ecbc1478a 45 }
heroic 0:670ecbc1478a 46
heroic 0:670ecbc1478a 47 /* Initialization */
heroic 0:670ecbc1478a 48 void Enrf24::begin(uint32_t datarate, uint8_t channel)
heroic 0:670ecbc1478a 49 {
heroic 0:670ecbc1478a 50 _cePin = 0;
heroic 0:670ecbc1478a 51 _csnPin = 1;
heroic 0:670ecbc1478a 52
heroic 0:670ecbc1478a 53 _spi.format(8,0);
heroic 0:670ecbc1478a 54 _spi.frequency(2000000);
heroic 0:670ecbc1478a 55
heroic 0:670ecbc1478a 56 _spi.write(0); // Strawman transfer, fixes USCI issue on G2553
heroic 0:670ecbc1478a 57
heroic 0:670ecbc1478a 58 // Is the transceiver present/alive?
heroic 0:670ecbc1478a 59 if (!_isAlive())
heroic 0:670ecbc1478a 60 return; // Nothing more to do here...
heroic 0:670ecbc1478a 61
heroic 0:670ecbc1478a 62 // Init certain registers
heroic 0:670ecbc1478a 63 _writeReg(RF24_CONFIG, 0x00); // Deep power-down, everything disabled
heroic 0:670ecbc1478a 64 _writeReg(RF24_EN_AA, 0x03);
heroic 0:670ecbc1478a 65 _writeReg(RF24_EN_RXADDR, 0x03);
heroic 0:670ecbc1478a 66 _writeReg(RF24_RF_SETUP, 0x00);
heroic 0:670ecbc1478a 67 _writeReg(RF24_STATUS, ENRF24_IRQ_MASK); // Clear all IRQs
heroic 0:670ecbc1478a 68 _writeReg(RF24_DYNPD, 0x03);
heroic 0:670ecbc1478a 69 _writeReg(RF24_FEATURE, RF24_EN_DPL); // Dynamic payloads enabled by default
heroic 0:670ecbc1478a 70
heroic 0:670ecbc1478a 71 // Set all parameters
heroic 0:670ecbc1478a 72 if (channel > 125)
heroic 0:670ecbc1478a 73 channel = 125;
heroic 0:670ecbc1478a 74 deepsleep();
heroic 0:670ecbc1478a 75 _issueCmd(RF24_FLUSH_TX);
heroic 0:670ecbc1478a 76 _issueCmd(RF24_FLUSH_RX);
heroic 0:670ecbc1478a 77 readpending = 0;
heroic 0:670ecbc1478a 78 _irq_clear(ENRF24_IRQ_MASK);
heroic 0:670ecbc1478a 79 setChannel(channel);
heroic 0:670ecbc1478a 80 setSpeed(datarate);
heroic 0:670ecbc1478a 81 setTXpower();
heroic 0:670ecbc1478a 82 setAutoAckParams();
heroic 0:670ecbc1478a 83 setAddressLength(rf_addr_width);
heroic 0:670ecbc1478a 84 setCRC(true); // Default = CRC on, 8-bit
heroic 0:670ecbc1478a 85 }
heroic 0:670ecbc1478a 86
heroic 0:670ecbc1478a 87 /* Formal shut-down/clearing of library state */
heroic 0:670ecbc1478a 88 void Enrf24::end()
heroic 0:670ecbc1478a 89 {
heroic 0:670ecbc1478a 90 txbuf_len = 0;
heroic 0:670ecbc1478a 91 rf_status = 0;
heroic 0:670ecbc1478a 92 rf_addr_width = 5;
heroic 0:670ecbc1478a 93
heroic 0:670ecbc1478a 94 if (!_isAlive())
heroic 0:670ecbc1478a 95 return;
heroic 0:670ecbc1478a 96 deepsleep();
heroic 0:670ecbc1478a 97 _issueCmd(RF24_FLUSH_TX);
heroic 0:670ecbc1478a 98 _issueCmd(RF24_FLUSH_RX);
heroic 0:670ecbc1478a 99 readpending = 0;
heroic 0:670ecbc1478a 100 _irq_clear(ENRF24_IRQ_MASK);
heroic 0:670ecbc1478a 101 _cePin = 0;
heroic 0:670ecbc1478a 102 _csnPin = 1;
heroic 0:670ecbc1478a 103 }
heroic 0:670ecbc1478a 104
heroic 0:670ecbc1478a 105 /* Basic SPI I/O */
heroic 0:670ecbc1478a 106 uint8_t Enrf24::_readReg(uint8_t addr)
heroic 0:670ecbc1478a 107 {
heroic 0:670ecbc1478a 108 uint8_t result;
heroic 0:670ecbc1478a 109
heroic 0:670ecbc1478a 110 _csnPin = 0;
heroic 0:670ecbc1478a 111 rf_status = _spi.write(RF24_R_REGISTER | addr);
heroic 0:670ecbc1478a 112 result = _spi.write(RF24_NOP);
heroic 0:670ecbc1478a 113 _csnPin = 1;
heroic 0:670ecbc1478a 114 return result;
heroic 0:670ecbc1478a 115 }
heroic 0:670ecbc1478a 116
heroic 0:670ecbc1478a 117 void Enrf24::_readRegMultiLSB(uint8_t addr, uint8_t *buf, size_t len)
heroic 0:670ecbc1478a 118 {
heroic 0:670ecbc1478a 119 uint8_t i;
heroic 0:670ecbc1478a 120 _csnPin = 0;
heroic 0:670ecbc1478a 121 rf_status = _spi.write(RF24_R_REGISTER | addr);
heroic 0:670ecbc1478a 122 for (i=0; i<len; i++) {
heroic 0:670ecbc1478a 123 buf[len-i-1] = _spi.write(RF24_NOP);
heroic 0:670ecbc1478a 124 }
heroic 0:670ecbc1478a 125 _csnPin = 1;
heroic 0:670ecbc1478a 126 }
heroic 0:670ecbc1478a 127
heroic 0:670ecbc1478a 128 void Enrf24::_writeReg(uint8_t addr, uint8_t val)
heroic 0:670ecbc1478a 129 {
heroic 0:670ecbc1478a 130 _csnPin=0;
heroic 0:670ecbc1478a 131 rf_status = _spi.write(RF24_W_REGISTER | addr);
heroic 0:670ecbc1478a 132 _spi.write(val);
heroic 0:670ecbc1478a 133 _csnPin=1;
heroic 0:670ecbc1478a 134 }
heroic 0:670ecbc1478a 135
heroic 0:670ecbc1478a 136 void Enrf24::_writeRegMultiLSB(uint8_t addr, uint8_t *buf, size_t len)
heroic 0:670ecbc1478a 137 {
heroic 0:670ecbc1478a 138 size_t i;
heroic 0:670ecbc1478a 139
heroic 0:670ecbc1478a 140 _csnPin = 0;
heroic 0:670ecbc1478a 141 rf_status = _spi.write(RF24_W_REGISTER | addr);
heroic 0:670ecbc1478a 142 for (i=0; i<len; i++) {
heroic 0:670ecbc1478a 143 _spi.write(buf[len-i-1]);
heroic 0:670ecbc1478a 144 }
heroic 0:670ecbc1478a 145 _csnPin = 1;
heroic 0:670ecbc1478a 146 }
heroic 0:670ecbc1478a 147
heroic 0:670ecbc1478a 148 void Enrf24::_issueCmd(uint8_t cmd)
heroic 0:670ecbc1478a 149 {
heroic 0:670ecbc1478a 150 _csnPin=0;
heroic 0:670ecbc1478a 151 rf_status = _spi.write(cmd);
heroic 0:670ecbc1478a 152 _csnPin=1;
heroic 0:670ecbc1478a 153 }
heroic 0:670ecbc1478a 154
heroic 0:670ecbc1478a 155 void Enrf24::_issueCmdPayload(uint8_t cmd, uint8_t *buf, size_t len)
heroic 0:670ecbc1478a 156 {
heroic 0:670ecbc1478a 157 size_t i;
heroic 0:670ecbc1478a 158
heroic 0:670ecbc1478a 159 _csnPin = 0;
heroic 0:670ecbc1478a 160 rf_status = _spi.write(cmd);
heroic 0:670ecbc1478a 161 for (i=0; i<len; i++) {
heroic 0:670ecbc1478a 162 _spi.write(buf[i]);
heroic 0:670ecbc1478a 163 }
heroic 0:670ecbc1478a 164 _csnPin = 1;
heroic 0:670ecbc1478a 165 }
heroic 0:670ecbc1478a 166
heroic 0:670ecbc1478a 167 void Enrf24::_readCmdPayload(uint8_t cmd, uint8_t *buf, size_t len, size_t maxlen)
heroic 0:670ecbc1478a 168 {
heroic 0:670ecbc1478a 169 size_t i;
heroic 0:670ecbc1478a 170
heroic 0:670ecbc1478a 171 _csnPin = 0;
heroic 0:670ecbc1478a 172 rf_status = _spi.write(cmd);
heroic 0:670ecbc1478a 173 for (i=0; i<len; i++) {
heroic 0:670ecbc1478a 174 if (i < maxlen) {
heroic 0:670ecbc1478a 175 buf[i] = _spi.write(RF24_NOP);
heroic 0:670ecbc1478a 176 } else {
heroic 0:670ecbc1478a 177 _spi.write(RF24_NOP); // Beyond maxlen bytes, just discard the remaining data.
heroic 0:670ecbc1478a 178 }
heroic 0:670ecbc1478a 179 }
heroic 0:670ecbc1478a 180 _csnPin = 1;
heroic 0:670ecbc1478a 181 }
heroic 0:670ecbc1478a 182
heroic 0:670ecbc1478a 183 boolean Enrf24::_isAlive()
heroic 0:670ecbc1478a 184 {
heroic 0:670ecbc1478a 185 uint8_t aw;
heroic 0:670ecbc1478a 186
heroic 0:670ecbc1478a 187 aw = _readReg(RF24_SETUP_AW);
heroic 0:670ecbc1478a 188 return ((aw & 0xFC) == 0x00 && (aw & 0x03) != 0x00);
heroic 0:670ecbc1478a 189 }
heroic 0:670ecbc1478a 190
heroic 0:670ecbc1478a 191 uint8_t Enrf24::_irq_getreason()
heroic 0:670ecbc1478a 192 {
heroic 0:670ecbc1478a 193 lastirq = _readReg(RF24_STATUS) & ENRF24_IRQ_MASK;
heroic 0:670ecbc1478a 194 return lastirq;
heroic 0:670ecbc1478a 195 }
heroic 0:670ecbc1478a 196
heroic 0:670ecbc1478a 197 // Get IRQ from last known rf_status update without querying module over SPI.
heroic 0:670ecbc1478a 198 uint8_t Enrf24::_irq_derivereason()
heroic 0:670ecbc1478a 199 {
heroic 0:670ecbc1478a 200 lastirq = rf_status & ENRF24_IRQ_MASK;
heroic 0:670ecbc1478a 201 return lastirq;
heroic 0:670ecbc1478a 202 }
heroic 0:670ecbc1478a 203
heroic 0:670ecbc1478a 204 void Enrf24::_irq_clear(uint8_t irq)
heroic 0:670ecbc1478a 205 {
heroic 0:670ecbc1478a 206 _writeReg(RF24_STATUS, irq & ENRF24_IRQ_MASK);
heroic 0:670ecbc1478a 207 }
heroic 0:670ecbc1478a 208
heroic 0:670ecbc1478a 209 #define ENRF24_CFGMASK_CRC(a) (a & (RF24_EN_CRC | RF24_CRCO))
heroic 0:670ecbc1478a 210
heroic 0:670ecbc1478a 211 void Enrf24::_readTXaddr(uint8_t *buf)
heroic 0:670ecbc1478a 212 {
heroic 0:670ecbc1478a 213 _readRegMultiLSB(RF24_TX_ADDR, buf, rf_addr_width);
heroic 0:670ecbc1478a 214 }
heroic 0:670ecbc1478a 215
heroic 0:670ecbc1478a 216 void Enrf24::_writeRXaddrP0(uint8_t *buf)
heroic 0:670ecbc1478a 217 {
heroic 0:670ecbc1478a 218 _writeRegMultiLSB(RF24_RX_ADDR_P0, buf, rf_addr_width);
heroic 0:670ecbc1478a 219 }
heroic 0:670ecbc1478a 220
heroic 0:670ecbc1478a 221
heroic 0:670ecbc1478a 222 /* nRF24 I/O maintenance--called as a "hook" inside other I/O functions to give
heroic 0:670ecbc1478a 223 * the library a chance to take care of its buffers et al
heroic 0:670ecbc1478a 224 */
heroic 0:670ecbc1478a 225 void Enrf24::_maintenanceHook()
heroic 0:670ecbc1478a 226 {
heroic 0:670ecbc1478a 227 uint8_t i;
heroic 0:670ecbc1478a 228
heroic 0:670ecbc1478a 229 _irq_getreason();
heroic 0:670ecbc1478a 230
heroic 0:670ecbc1478a 231 if (lastirq & ENRF24_IRQ_TXFAILED) {
heroic 0:670ecbc1478a 232 lastTXfailed = true;
heroic 0:670ecbc1478a 233 _issueCmd(RF24_FLUSH_TX);
heroic 0:670ecbc1478a 234 _irq_clear(ENRF24_IRQ_TXFAILED);
heroic 0:670ecbc1478a 235 }
heroic 0:670ecbc1478a 236
heroic 0:670ecbc1478a 237 if (lastirq & ENRF24_IRQ_TX) {
heroic 0:670ecbc1478a 238 lastTXfailed = false;
heroic 0:670ecbc1478a 239 _irq_clear(ENRF24_IRQ_TX);
heroic 0:670ecbc1478a 240 }
heroic 0:670ecbc1478a 241
heroic 0:670ecbc1478a 242 if (lastirq & ENRF24_IRQ_RX) {
heroic 0:670ecbc1478a 243 if ( !(_readReg(RF24_FIFO_STATUS) & RF24_RX_FULL) ) { /* Don't feel it's necessary
heroic 0:670ecbc1478a 244 * to be notified of new
heroic 0:670ecbc1478a 245 * incoming packets if the RX
heroic 0:670ecbc1478a 246 * queue is full.
heroic 0:670ecbc1478a 247 */
heroic 0:670ecbc1478a 248 _irq_clear(ENRF24_IRQ_RX);
heroic 0:670ecbc1478a 249 }
heroic 0:670ecbc1478a 250
heroic 0:670ecbc1478a 251 /* Check if RX payload is 0-byte or >32byte (erroneous conditions)
heroic 0:670ecbc1478a 252 * Also check if data was received on pipe#0, which we are ignoring.
heroic 0:670ecbc1478a 253 * The reason for this is pipe#0 is needed for receiving AutoACK acknowledgements,
heroic 0:670ecbc1478a 254 * its address gets reset to the module's default and we do not care about data
heroic 0:670ecbc1478a 255 * coming in to that address...
heroic 0:670ecbc1478a 256 */
heroic 0:670ecbc1478a 257 _readCmdPayload(RF24_R_RX_PL_WID, &i, 1, 1);
heroic 0:670ecbc1478a 258 if (i == 0 || i > 32 || ((rf_status & 0x0E) >> 1) == 0) {
heroic 0:670ecbc1478a 259 /* Zero-width RX payload is an error that happens a lot
heroic 0:670ecbc1478a 260 * with non-AutoAck, and must be cleared with FLUSH_RX.
heroic 0:670ecbc1478a 261 * Erroneous >32byte packets are a similar phenomenon.
heroic 0:670ecbc1478a 262 */
heroic 0:670ecbc1478a 263 _issueCmd(RF24_FLUSH_RX);
heroic 0:670ecbc1478a 264 _irq_clear(ENRF24_IRQ_RX);
heroic 0:670ecbc1478a 265 readpending = 0;
heroic 0:670ecbc1478a 266 } else {
heroic 0:670ecbc1478a 267 readpending = 1;
heroic 0:670ecbc1478a 268 }
heroic 0:670ecbc1478a 269 // Actual scavenging of RX queues is performed by user-directed use of read().
heroic 0:670ecbc1478a 270 }
heroic 0:670ecbc1478a 271 }
heroic 0:670ecbc1478a 272
heroic 0:670ecbc1478a 273
heroic 0:670ecbc1478a 274
heroic 0:670ecbc1478a 275 /* Public functions */
heroic 0:670ecbc1478a 276 boolean Enrf24::available(boolean checkIrq)
heroic 0:670ecbc1478a 277 {
heroic 0:670ecbc1478a 278 if (checkIrq && _irqPin && readpending == 0)
heroic 0:670ecbc1478a 279 return false;
heroic 0:670ecbc1478a 280 _maintenanceHook();
heroic 0:670ecbc1478a 281 if ( !(_readReg(RF24_FIFO_STATUS) & RF24_RX_EMPTY) ) {
heroic 0:670ecbc1478a 282 return true;
heroic 0:670ecbc1478a 283 }
heroic 0:670ecbc1478a 284 if (readpending) {
heroic 0:670ecbc1478a 285 return true;
heroic 0:670ecbc1478a 286 }
heroic 0:670ecbc1478a 287 return false;
heroic 0:670ecbc1478a 288 }
heroic 0:670ecbc1478a 289
heroic 0:670ecbc1478a 290 size_t Enrf24::read(void *inbuf, uint8_t maxlen)
heroic 0:670ecbc1478a 291 {
heroic 0:670ecbc1478a 292 uint8_t *buf = (uint8_t *)inbuf;
heroic 0:670ecbc1478a 293 uint8_t plwidth;
heroic 0:670ecbc1478a 294
heroic 0:670ecbc1478a 295 _maintenanceHook();
heroic 0:670ecbc1478a 296 readpending = 0;
heroic 0:670ecbc1478a 297 if ((_readReg(RF24_FIFO_STATUS) & RF24_RX_EMPTY) || maxlen < 1) {
heroic 0:670ecbc1478a 298 return 0;
heroic 0:670ecbc1478a 299 }
heroic 0:670ecbc1478a 300 _readCmdPayload(RF24_R_RX_PL_WID, &plwidth, 1, 1);
heroic 0:670ecbc1478a 301 _readCmdPayload(RF24_R_RX_PAYLOAD, buf, plwidth, maxlen);
heroic 0:670ecbc1478a 302 buf[plwidth] = '\0'; // Zero-terminate in case this is a string.
heroic 0:670ecbc1478a 303 if (_irq_derivereason() & ENRF24_IRQ_RX) {
heroic 0:670ecbc1478a 304 _irq_clear(ENRF24_IRQ_RX);
heroic 0:670ecbc1478a 305 }
heroic 0:670ecbc1478a 306
heroic 0:670ecbc1478a 307 return (size_t) plwidth;
heroic 0:670ecbc1478a 308 }
heroic 0:670ecbc1478a 309
heroic 0:670ecbc1478a 310 // Perform TX of current ring-buffer contents
heroic 0:670ecbc1478a 311 void Enrf24::flush()
heroic 0:670ecbc1478a 312 {
heroic 0:670ecbc1478a 313 uint8_t reg, addrbuf[5];
heroic 0:670ecbc1478a 314 boolean enaa=false, origrx=false;
heroic 0:670ecbc1478a 315
heroic 0:670ecbc1478a 316 if (!txbuf_len)
heroic 0:670ecbc1478a 317 return; // Zero-length buffer? Nothing to send!
heroic 0:670ecbc1478a 318
heroic 0:670ecbc1478a 319 reg = _readReg(RF24_FIFO_STATUS);
heroic 0:670ecbc1478a 320 if (reg & BIT5) { // RF24_TX_FULL #define is BIT0, which is not the correct bit for FIFO_STATUS.
heroic 0:670ecbc1478a 321 return; // Should never happen, but nonetheless a precaution to take.
heroic 0:670ecbc1478a 322 }
heroic 0:670ecbc1478a 323
heroic 0:670ecbc1478a 324 _maintenanceHook();
heroic 0:670ecbc1478a 325
heroic 0:670ecbc1478a 326 if (reg & RF24_TX_REUSE) {
heroic 0:670ecbc1478a 327 // If somehow TX_REUSE is enabled, we need to flush the TX queue before loading our new payload.
heroic 0:670ecbc1478a 328 _issueCmd(RF24_FLUSH_TX);
heroic 0:670ecbc1478a 329 }
heroic 0:670ecbc1478a 330
heroic 0:670ecbc1478a 331 if (_readReg(RF24_EN_AA) & 0x01 && (_readReg(RF24_RF_SETUP) & 0x28) != 0x20) {
heroic 0:670ecbc1478a 332 /* AutoACK enabled, must write TX addr to RX pipe#0
heroic 0:670ecbc1478a 333 * Note that 250Kbps doesn't support auto-ack, so we check RF24_RF_SETUP to verify that.
heroic 0:670ecbc1478a 334 */
heroic 0:670ecbc1478a 335 enaa = true;
heroic 0:670ecbc1478a 336 _readTXaddr(addrbuf);
heroic 0:670ecbc1478a 337 _writeRXaddrP0(addrbuf);
heroic 0:670ecbc1478a 338 }
heroic 0:670ecbc1478a 339
heroic 0:670ecbc1478a 340 reg = _readReg(RF24_CONFIG);
heroic 0:670ecbc1478a 341 if ( !(reg & RF24_PWR_UP) ) {
heroic 0:670ecbc1478a 342 _writeReg(RF24_CONFIG, ENRF24_CFGMASK_IRQ | ENRF24_CFGMASK_CRC(reg) | RF24_PWR_UP);
heroic 0:670ecbc1478a 343 wait_us(5000); // 5ms delay required for nRF24 oscillator start-up
heroic 0:670ecbc1478a 344 }
heroic 0:670ecbc1478a 345 if (reg & RF24_PRIM_RX) {
heroic 0:670ecbc1478a 346 origrx=true;
heroic 0:670ecbc1478a 347 _cePin = 0;
heroic 0:670ecbc1478a 348 _writeReg(RF24_CONFIG, ENRF24_CFGMASK_IRQ | ENRF24_CFGMASK_CRC(reg) | RF24_PWR_UP);
heroic 0:670ecbc1478a 349 }
heroic 0:670ecbc1478a 350
heroic 0:670ecbc1478a 351 _issueCmdPayload(RF24_W_TX_PAYLOAD, txbuf, txbuf_len);
heroic 0:670ecbc1478a 352 _cePin = 1;
heroic 0:670ecbc1478a 353 wait_us(30);
heroic 0:670ecbc1478a 354 _cePin = 0;
heroic 0:670ecbc1478a 355
heroic 0:670ecbc1478a 356 txbuf_len = 0; // Reset TX ring buffer
heroic 0:670ecbc1478a 357
heroic 0:670ecbc1478a 358 while (_irqPin) // Wait until IRQ fires
heroic 0:670ecbc1478a 359 ;
heroic 0:670ecbc1478a 360 // IRQ fired
heroic 0:670ecbc1478a 361 _maintenanceHook(); // Handle/clear IRQ
heroic 0:670ecbc1478a 362
heroic 0:670ecbc1478a 363 // Purge Pipe#0 address (set to module's power-up default)
heroic 0:670ecbc1478a 364 if (enaa) {
heroic 0:670ecbc1478a 365 addrbuf[0] = 0xE7; addrbuf[1] = 0xE7; addrbuf[2] = 0xE7; addrbuf[3] = 0xE7; addrbuf[4] = 0xE7;
heroic 0:670ecbc1478a 366 _writeRXaddrP0(addrbuf);
heroic 0:670ecbc1478a 367 }
heroic 0:670ecbc1478a 368
heroic 0:670ecbc1478a 369 // If we were in RX mode before writing, return back to RX mode.
heroic 0:670ecbc1478a 370 if (origrx) {
heroic 0:670ecbc1478a 371 enableRX();
heroic 0:670ecbc1478a 372 }
heroic 0:670ecbc1478a 373 }
heroic 0:670ecbc1478a 374
heroic 0:670ecbc1478a 375 void Enrf24::purge()
heroic 0:670ecbc1478a 376 {
heroic 0:670ecbc1478a 377 txbuf_len = 0;
heroic 0:670ecbc1478a 378 }
heroic 0:670ecbc1478a 379
heroic 0:670ecbc1478a 380 size_t Enrf24::write(uint8_t c)
heroic 0:670ecbc1478a 381 {
heroic 0:670ecbc1478a 382 if (txbuf_len == 32) { // If we're trying to stuff an already-full buffer...
heroic 0:670ecbc1478a 383 flush(); // Blocking OTA TX
heroic 0:670ecbc1478a 384 }
heroic 0:670ecbc1478a 385
heroic 0:670ecbc1478a 386 txbuf[txbuf_len] = c;
heroic 0:670ecbc1478a 387 txbuf_len++;
heroic 0:670ecbc1478a 388
heroic 0:670ecbc1478a 389 return 1;
heroic 0:670ecbc1478a 390 }
heroic 0:670ecbc1478a 391
heroic 0:670ecbc1478a 392 uint8_t Enrf24::radioState()
heroic 0:670ecbc1478a 393 {
heroic 0:670ecbc1478a 394 uint8_t reg;
heroic 0:670ecbc1478a 395
heroic 0:670ecbc1478a 396 if (!_isAlive())
heroic 0:670ecbc1478a 397 return ENRF24_STATE_NOTPRESENT;
heroic 0:670ecbc1478a 398
heroic 0:670ecbc1478a 399 reg = _readReg(RF24_CONFIG);
heroic 0:670ecbc1478a 400 if ( !(reg & RF24_PWR_UP) )
heroic 0:670ecbc1478a 401 return ENRF24_STATE_DEEPSLEEP;
heroic 0:670ecbc1478a 402
heroic 0:670ecbc1478a 403 // At this point it's either Standby-I, II or PRX.
heroic 0:670ecbc1478a 404 if (reg & RF24_PRIM_RX) {
heroic 0:670ecbc1478a 405 if (_cePin)
heroic 0:670ecbc1478a 406 return ENRF24_STATE_PRX;
heroic 0:670ecbc1478a 407 // PRIM_RX=1 but CE=0 is a form of idle state.
heroic 0:670ecbc1478a 408 return ENRF24_STATE_IDLE;
heroic 0:670ecbc1478a 409 }
heroic 0:670ecbc1478a 410 // Check if TX queue is empty, if so it's idle, if not it's PTX.
heroic 0:670ecbc1478a 411 if (_readReg(RF24_FIFO_STATUS) & RF24_TX_EMPTY)
heroic 0:670ecbc1478a 412 return ENRF24_STATE_IDLE;
heroic 0:670ecbc1478a 413 return ENRF24_STATE_PTX;
heroic 0:670ecbc1478a 414 }
heroic 0:670ecbc1478a 415
heroic 0:670ecbc1478a 416 void Enrf24::deepsleep()
heroic 0:670ecbc1478a 417 {
heroic 0:670ecbc1478a 418 uint8_t reg;
heroic 0:670ecbc1478a 419
heroic 0:670ecbc1478a 420 reg = _readReg(RF24_CONFIG);
heroic 0:670ecbc1478a 421 if (reg & (RF24_PWR_UP | RF24_PRIM_RX)) {
heroic 0:670ecbc1478a 422 _writeReg(RF24_CONFIG, ENRF24_CFGMASK_IRQ | ENRF24_CFGMASK_CRC(reg));
heroic 0:670ecbc1478a 423 }
heroic 0:670ecbc1478a 424 _cePin = 0;
heroic 0:670ecbc1478a 425 }
heroic 0:670ecbc1478a 426
heroic 0:670ecbc1478a 427 void Enrf24::enableRX()
heroic 0:670ecbc1478a 428 {
heroic 0:670ecbc1478a 429 uint8_t reg;
heroic 0:670ecbc1478a 430
heroic 0:670ecbc1478a 431 reg = _readReg(RF24_CONFIG);
heroic 0:670ecbc1478a 432 _writeReg(RF24_CONFIG, ENRF24_CFGMASK_IRQ | ENRF24_CFGMASK_CRC(reg) | RF24_PWR_UP | RF24_PRIM_RX);
heroic 0:670ecbc1478a 433 _cePin = 1;
heroic 0:670ecbc1478a 434
heroic 0:670ecbc1478a 435 if ( !(reg & RF24_PWR_UP) ) { // Powering up from deep-sleep requires 5ms oscillator start delay
heroic 0:670ecbc1478a 436 wait(5 / 1000);
heroic 0:670ecbc1478a 437 }
heroic 0:670ecbc1478a 438 }
heroic 0:670ecbc1478a 439
heroic 0:670ecbc1478a 440 void Enrf24::disableRX()
heroic 0:670ecbc1478a 441 {
heroic 0:670ecbc1478a 442 uint8_t reg;
heroic 0:670ecbc1478a 443
heroic 0:670ecbc1478a 444 _cePin = 0;
heroic 0:670ecbc1478a 445
heroic 0:670ecbc1478a 446 reg = _readReg(RF24_CONFIG);
heroic 0:670ecbc1478a 447 if (reg & RF24_PWR_UP) { /* Keep us in standby-I if we're coming from RX mode, otherwise stay
heroic 0:670ecbc1478a 448 * in deep-sleep if we call this while already in PWR_UP=0 mode.
heroic 0:670ecbc1478a 449 */
heroic 0:670ecbc1478a 450 _writeReg(RF24_CONFIG, ENRF24_CFGMASK_IRQ | ENRF24_CFGMASK_CRC(reg) | RF24_PWR_UP);
heroic 0:670ecbc1478a 451 } else {
heroic 0:670ecbc1478a 452 _writeReg(RF24_CONFIG, ENRF24_CFGMASK_IRQ | ENRF24_CFGMASK_CRC(reg));
heroic 0:670ecbc1478a 453 }
heroic 0:670ecbc1478a 454 }
heroic 0:670ecbc1478a 455
heroic 0:670ecbc1478a 456 void Enrf24::autoAck(boolean onoff)
heroic 0:670ecbc1478a 457 {
heroic 0:670ecbc1478a 458 uint8_t reg;
heroic 0:670ecbc1478a 459
heroic 0:670ecbc1478a 460 reg = _readReg(RF24_EN_AA);
heroic 0:670ecbc1478a 461 if (onoff) {
heroic 0:670ecbc1478a 462 if ( !(reg & 0x01) || !(reg & 0x02) ) {
heroic 0:670ecbc1478a 463 _writeReg(RF24_EN_AA, 0x03);
heroic 0:670ecbc1478a 464 }
heroic 0:670ecbc1478a 465 } else {
heroic 0:670ecbc1478a 466 if (reg & 0x03) {
heroic 0:670ecbc1478a 467 _writeReg(RF24_EN_AA, 0x00);
heroic 0:670ecbc1478a 468 }
heroic 0:670ecbc1478a 469 }
heroic 0:670ecbc1478a 470 }
heroic 0:670ecbc1478a 471
heroic 0:670ecbc1478a 472 void Enrf24::setChannel(uint8_t channel)
heroic 0:670ecbc1478a 473 {
heroic 0:670ecbc1478a 474 if (channel > 125)
heroic 0:670ecbc1478a 475 channel = 125;
heroic 0:670ecbc1478a 476 _writeReg(RF24_RF_CH, channel);
heroic 0:670ecbc1478a 477 }
heroic 0:670ecbc1478a 478
heroic 0:670ecbc1478a 479 void Enrf24::setTXpower(int8_t dBm)
heroic 0:670ecbc1478a 480 {
heroic 0:670ecbc1478a 481 uint8_t reg, pwr;
heroic 0:670ecbc1478a 482
heroic 0:670ecbc1478a 483 reg = _readReg(RF24_RF_SETUP) & 0xF8; // preserve RF speed settings
heroic 0:670ecbc1478a 484 pwr = 0x03;
heroic 0:670ecbc1478a 485 if (dBm < 0)
heroic 0:670ecbc1478a 486 pwr = 0x02;
heroic 0:670ecbc1478a 487 if (dBm < -6)
heroic 0:670ecbc1478a 488 pwr = 0x01;
heroic 0:670ecbc1478a 489 if (dBm < -12)
heroic 0:670ecbc1478a 490 pwr = 0x00;
heroic 0:670ecbc1478a 491 _writeReg(RF24_RF_SETUP, reg | (pwr << 1));
heroic 0:670ecbc1478a 492 }
heroic 0:670ecbc1478a 493
heroic 0:670ecbc1478a 494 void Enrf24::setSpeed(uint32_t rfspeed)
heroic 0:670ecbc1478a 495 {
heroic 0:670ecbc1478a 496 uint8_t reg, spd;
heroic 0:670ecbc1478a 497
heroic 0:670ecbc1478a 498 reg = _readReg(RF24_RF_SETUP) & 0xD7; // preserve RF power settings
heroic 0:670ecbc1478a 499 spd = 0x01;
heroic 0:670ecbc1478a 500 if (rfspeed < 2000000)
heroic 0:670ecbc1478a 501 spd = 0x00;
heroic 0:670ecbc1478a 502 if (rfspeed < 1000000)
heroic 0:670ecbc1478a 503 spd = 0x04;
heroic 0:670ecbc1478a 504 _writeReg(RF24_RF_SETUP, reg | (spd << 3));
heroic 0:670ecbc1478a 505 }
heroic 0:670ecbc1478a 506
heroic 0:670ecbc1478a 507 void Enrf24::setCRC(boolean onoff, boolean crc16bit)
heroic 0:670ecbc1478a 508 {
heroic 0:670ecbc1478a 509 uint8_t reg, crcbits=0;
heroic 0:670ecbc1478a 510
heroic 0:670ecbc1478a 511 reg = _readReg(RF24_CONFIG) & 0xF3; // preserve IRQ mask, PWR_UP/PRIM_RX settings
heroic 0:670ecbc1478a 512 if (onoff)
heroic 0:670ecbc1478a 513 crcbits |= RF24_EN_CRC;
heroic 0:670ecbc1478a 514 if (crc16bit)
heroic 0:670ecbc1478a 515 crcbits |= RF24_CRCO;
heroic 0:670ecbc1478a 516 _writeReg(RF24_CONFIG, reg | crcbits);
heroic 0:670ecbc1478a 517 }
heroic 0:670ecbc1478a 518
heroic 0:670ecbc1478a 519 void Enrf24::setAutoAckParams(uint8_t autoretry_count, uint16_t autoretry_timeout)
heroic 0:670ecbc1478a 520 {
heroic 0:670ecbc1478a 521 uint8_t setup_retr=0;
heroic 0:670ecbc1478a 522
heroic 0:670ecbc1478a 523 setup_retr = autoretry_count & 0x0F;
heroic 0:670ecbc1478a 524 autoretry_timeout -= 250;
heroic 0:670ecbc1478a 525 setup_retr |= ((autoretry_timeout / 250) & 0x0F) << 4;
heroic 0:670ecbc1478a 526 _writeReg(RF24_SETUP_RETR, setup_retr);
heroic 0:670ecbc1478a 527 }
heroic 0:670ecbc1478a 528
heroic 0:670ecbc1478a 529 void Enrf24::setAddressLength(size_t len)
heroic 0:670ecbc1478a 530 {
heroic 0:670ecbc1478a 531 if (len < 3)
heroic 0:670ecbc1478a 532 len = 3;
heroic 0:670ecbc1478a 533 if (len > 5)
heroic 0:670ecbc1478a 534 len = 5;
heroic 0:670ecbc1478a 535
heroic 0:670ecbc1478a 536 _writeReg(RF24_SETUP_AW, len-2);
heroic 0:670ecbc1478a 537 rf_addr_width = len;
heroic 0:670ecbc1478a 538 }
heroic 0:670ecbc1478a 539
heroic 0:670ecbc1478a 540 void Enrf24::setRXaddress(void *rxaddr)
heroic 0:670ecbc1478a 541 {
heroic 0:670ecbc1478a 542 _writeRegMultiLSB(RF24_RX_ADDR_P1, (uint8_t*)rxaddr, rf_addr_width);
heroic 0:670ecbc1478a 543 }
heroic 0:670ecbc1478a 544
heroic 0:670ecbc1478a 545 void Enrf24::setTXaddress(void *rxaddr)
heroic 0:670ecbc1478a 546 {
heroic 0:670ecbc1478a 547 _writeRegMultiLSB(RF24_TX_ADDR, (uint8_t*)rxaddr, rf_addr_width);
heroic 0:670ecbc1478a 548 }
heroic 0:670ecbc1478a 549
heroic 0:670ecbc1478a 550 boolean Enrf24::rfSignalDetected()
heroic 0:670ecbc1478a 551 {
heroic 0:670ecbc1478a 552 uint8_t rpd;
heroic 0:670ecbc1478a 553
heroic 0:670ecbc1478a 554 rpd = _readReg(RF24_RPD);
heroic 0:670ecbc1478a 555 return (boolean)rpd;
heroic 0:670ecbc1478a 556 }