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>

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Enrf24.cpp Source File

Enrf24.cpp

00001 /* nRF24L01+ I/O for mbed
00002  * Ported by Jas Strong <jasmine@heroicrobotics.com>
00003  *
00004  * Copyright (c) 2013 Eric Brundick <spirilis [at] linux dot com>
00005  *  Permission is hereby granted, free of charge, to any person 
00006  *  obtaining a copy of this software and associated documentation 
00007  *  files (the "Software"), to deal in the Software without 
00008  *  restriction, including without limitation the rights to use, copy, 
00009  *  modify, merge, publish, distribute, sublicense, and/or sell copies 
00010  *  of the Software, and to permit persons to whom the Software is 
00011  *  furnished to do so, subject to the following conditions:
00012  *
00013  *  The above copyright notice and this permission notice shall be 
00014  *  included in all copies or substantial portions of the Software.
00015  *
00016  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
00017  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
00018  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
00019  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 
00020  *  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
00021  *  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
00022  *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
00023  *  DEALINGS IN THE SOFTWARE.
00024  */
00025 
00026 #include "mbed.h"
00027 #include <stdint.h>
00028 #include "Enrf24.h"
00029 
00030 /* Constructor */
00031 Enrf24::Enrf24(PinName cePin, PinName csnPin, PinName irqPin, PinName miso, PinName mosi, PinName sck) :
00032     _cePin(cePin),
00033     _csnPin(csnPin),
00034     _irqPin(irqPin),
00035     _miso(miso),
00036     _mosi(mosi),
00037     _sck(sck),
00038     _spi(mosi, miso, sck)
00039 {
00040 
00041   rf_status = 0;
00042   rf_addr_width = 5;
00043   txbuf_len = 0;
00044   readpending = 0;
00045 }
00046 
00047 /* Initialization */
00048 void Enrf24::begin(uint32_t datarate, uint8_t channel)
00049 {
00050   _cePin = 0;
00051   _csnPin = 1;
00052 
00053   _spi.format(8,0);
00054   _spi.frequency(2000000);
00055     
00056   _spi.write(0);  // Strawman transfer, fixes USCI issue on G2553
00057 
00058   // Is the transceiver present/alive?
00059   if (!_isAlive())
00060     return;  // Nothing more to do here...
00061 
00062   // Init certain registers
00063   _writeReg(RF24_CONFIG, 0x00);  // Deep power-down, everything disabled
00064   _writeReg(RF24_EN_AA, 0x03);
00065   _writeReg(RF24_EN_RXADDR, 0x03);
00066   _writeReg(RF24_RF_SETUP, 0x00);
00067   _writeReg(RF24_STATUS, ENRF24_IRQ_MASK);  // Clear all IRQs
00068   _writeReg(RF24_DYNPD, 0x03);
00069   _writeReg(RF24_FEATURE, RF24_EN_DPL);  // Dynamic payloads enabled by default
00070 
00071   // Set all parameters
00072   if (channel > 125)
00073     channel = 125;
00074   deepsleep();
00075   _issueCmd(RF24_FLUSH_TX);
00076   _issueCmd(RF24_FLUSH_RX);
00077   readpending = 0;
00078   _irq_clear(ENRF24_IRQ_MASK);
00079   setChannel(channel);
00080   setSpeed(datarate);
00081   setTXpower();
00082   setAutoAckParams();
00083   setAddressLength(rf_addr_width);
00084   setCRC(true);  // Default = CRC on, 8-bit
00085 }
00086 
00087 /* Formal shut-down/clearing of library state */
00088 void Enrf24::end()
00089 {
00090   txbuf_len = 0;
00091   rf_status = 0;
00092   rf_addr_width = 5;
00093 
00094   if (!_isAlive())
00095     return;
00096   deepsleep();
00097   _issueCmd(RF24_FLUSH_TX);
00098   _issueCmd(RF24_FLUSH_RX);
00099   readpending = 0;
00100   _irq_clear(ENRF24_IRQ_MASK);
00101   _cePin = 0;
00102   _csnPin = 1;
00103 }
00104 
00105 /* Basic SPI I/O */
00106 uint8_t Enrf24::_readReg(uint8_t addr)
00107 {
00108   uint8_t result;
00109 
00110   _csnPin = 0;
00111   rf_status = _spi.write(RF24_R_REGISTER | addr);
00112   result = _spi.write(RF24_NOP);
00113   _csnPin = 1;
00114   return result;
00115 }
00116 
00117 void Enrf24::_readRegMultiLSB(uint8_t addr, uint8_t *buf, size_t len)
00118 {
00119   uint8_t i;
00120   _csnPin = 0;
00121   rf_status = _spi.write(RF24_R_REGISTER | addr);
00122   for (i=0; i<len; i++) {
00123     buf[len-i-1] = _spi.write(RF24_NOP);
00124   }
00125   _csnPin = 1;
00126 }
00127 
00128 void Enrf24::_writeReg(uint8_t addr, uint8_t val)
00129 {
00130   _csnPin=0;
00131   rf_status = _spi.write(RF24_W_REGISTER | addr);
00132   _spi.write(val);
00133   _csnPin=1;
00134 }
00135 
00136 void Enrf24::_writeRegMultiLSB(uint8_t addr, uint8_t *buf, size_t len)
00137 {
00138   size_t i;
00139 
00140   _csnPin = 0;
00141   rf_status = _spi.write(RF24_W_REGISTER | addr);
00142   for (i=0; i<len; i++) {
00143     _spi.write(buf[len-i-1]);
00144   }
00145   _csnPin = 1;
00146 }
00147 
00148 void Enrf24::_issueCmd(uint8_t cmd)
00149 {
00150   _csnPin=0;
00151   rf_status = _spi.write(cmd);
00152   _csnPin=1;
00153 }
00154 
00155 void Enrf24::_issueCmdPayload(uint8_t cmd, uint8_t *buf, size_t len)
00156 {
00157   size_t i;
00158 
00159   _csnPin = 0;
00160   rf_status = _spi.write(cmd);
00161   for (i=0; i<len; i++) {
00162     _spi.write(buf[i]);
00163   }
00164   _csnPin = 1;
00165 }
00166 
00167 void Enrf24::_readCmdPayload(uint8_t cmd, uint8_t *buf, size_t len, size_t maxlen)
00168 {
00169   size_t i;
00170 
00171   _csnPin = 0;
00172   rf_status = _spi.write(cmd);
00173   for (i=0; i<len; i++) {
00174     if (i < maxlen) {
00175       buf[i] = _spi.write(RF24_NOP);
00176     } else {
00177       _spi.write(RF24_NOP);  // Beyond maxlen bytes, just discard the remaining data.
00178     }
00179   }
00180   _csnPin = 1;
00181 }
00182 
00183 boolean Enrf24::_isAlive()
00184 {
00185   uint8_t aw;
00186 
00187   aw = _readReg(RF24_SETUP_AW);
00188   return ((aw & 0xFC) == 0x00 && (aw & 0x03) != 0x00);
00189 }
00190 
00191 uint8_t Enrf24::_irq_getreason()
00192 {
00193   lastirq = _readReg(RF24_STATUS) & ENRF24_IRQ_MASK;
00194   return lastirq;
00195 }
00196 
00197 // Get IRQ from last known rf_status update without querying module over SPI.
00198 uint8_t Enrf24::_irq_derivereason()
00199 {
00200   lastirq = rf_status & ENRF24_IRQ_MASK;
00201   return lastirq;
00202 }
00203 
00204 void Enrf24::_irq_clear(uint8_t irq)
00205 {
00206   _writeReg(RF24_STATUS, irq & ENRF24_IRQ_MASK);
00207 }
00208 
00209 #define ENRF24_CFGMASK_CRC(a) (a & (RF24_EN_CRC | RF24_CRCO))
00210 
00211 void Enrf24::_readTXaddr(uint8_t *buf)
00212 {
00213   _readRegMultiLSB(RF24_TX_ADDR, buf, rf_addr_width);
00214 }
00215 
00216 void Enrf24::_writeRXaddrP0(uint8_t *buf)
00217 {
00218   _writeRegMultiLSB(RF24_RX_ADDR_P0, buf, rf_addr_width);
00219 }
00220 
00221 
00222 /* nRF24 I/O maintenance--called as a "hook" inside other I/O functions to give
00223  * the library a chance to take care of its buffers et al
00224  */
00225 void Enrf24::_maintenanceHook()
00226 {
00227   uint8_t i;
00228 
00229   _irq_getreason();
00230 
00231   if (lastirq & ENRF24_IRQ_TXFAILED) {
00232     lastTXfailed = true;
00233     _issueCmd(RF24_FLUSH_TX);
00234     _irq_clear(ENRF24_IRQ_TXFAILED);
00235   }
00236 
00237   if (lastirq & ENRF24_IRQ_TX) {
00238     lastTXfailed = false;
00239     _irq_clear(ENRF24_IRQ_TX);
00240   }
00241 
00242   if (lastirq & ENRF24_IRQ_RX) {
00243     if ( !(_readReg(RF24_FIFO_STATUS) & RF24_RX_FULL) ) {  /* Don't feel it's necessary
00244                                                             * to be notified of new
00245                                                             * incoming packets if the RX
00246                                                             * queue is full.
00247                                                             */
00248       _irq_clear(ENRF24_IRQ_RX);
00249     }
00250 
00251     /* Check if RX payload is 0-byte or >32byte (erroneous conditions)
00252      * Also check if data was received on pipe#0, which we are ignoring.
00253      * The reason for this is pipe#0 is needed for receiving AutoACK acknowledgements,
00254      * its address gets reset to the module's default and we do not care about data
00255      * coming in to that address...
00256      */
00257     _readCmdPayload(RF24_R_RX_PL_WID, &i, 1, 1);
00258     if (i == 0 || i > 32 || ((rf_status & 0x0E) >> 1) == 0) {
00259                              /* Zero-width RX payload is an error that happens a lot
00260                               * with non-AutoAck, and must be cleared with FLUSH_RX.
00261                               * Erroneous >32byte packets are a similar phenomenon.
00262                               */
00263       _issueCmd(RF24_FLUSH_RX);
00264       _irq_clear(ENRF24_IRQ_RX);
00265       readpending = 0;
00266     } else {
00267       readpending = 1;
00268     }
00269     // Actual scavenging of RX queues is performed by user-directed use of read().
00270   }
00271 }
00272 
00273 
00274 
00275 /* Public functions */
00276 boolean Enrf24::available(boolean checkIrq)
00277 {
00278   if (checkIrq && _irqPin && readpending == 0)
00279     return false;
00280   _maintenanceHook();
00281   if ( !(_readReg(RF24_FIFO_STATUS) & RF24_RX_EMPTY) ) {
00282     return true;
00283   }
00284   if (readpending) {
00285     return true;
00286   }
00287   return false;
00288 }
00289 
00290 size_t Enrf24::read(void *inbuf, uint8_t maxlen)
00291 {
00292   uint8_t *buf = (uint8_t *)inbuf;
00293   uint8_t plwidth;
00294 
00295   _maintenanceHook();
00296   readpending = 0;
00297   if ((_readReg(RF24_FIFO_STATUS) & RF24_RX_EMPTY) || maxlen < 1) {
00298     return 0;
00299   }
00300   _readCmdPayload(RF24_R_RX_PL_WID, &plwidth, 1, 1);
00301   _readCmdPayload(RF24_R_RX_PAYLOAD, buf, plwidth, maxlen);
00302   buf[plwidth] = '\0';  // Zero-terminate in case this is a string.
00303   if (_irq_derivereason() & ENRF24_IRQ_RX) {
00304     _irq_clear(ENRF24_IRQ_RX);
00305   }
00306 
00307   return (size_t) plwidth;
00308 }
00309 
00310 // Perform TX of current ring-buffer contents
00311 void Enrf24::flush()
00312 {
00313   uint8_t reg, addrbuf[5];
00314   boolean enaa=false, origrx=false;
00315 
00316   if (!txbuf_len)
00317     return;  // Zero-length buffer?  Nothing to send!
00318 
00319   reg = _readReg(RF24_FIFO_STATUS);
00320   if (reg & BIT5) {  // RF24_TX_FULL #define is BIT0, which is not the correct bit for FIFO_STATUS.
00321     return;  // Should never happen, but nonetheless a precaution to take.
00322   }
00323 
00324   _maintenanceHook();
00325 
00326   if (reg & RF24_TX_REUSE) {
00327     // If somehow TX_REUSE is enabled, we need to flush the TX queue before loading our new payload.
00328     _issueCmd(RF24_FLUSH_TX);
00329   }
00330 
00331   if (_readReg(RF24_EN_AA) & 0x01 && (_readReg(RF24_RF_SETUP) & 0x28) != 0x20) {
00332     /* AutoACK enabled, must write TX addr to RX pipe#0
00333      * Note that 250Kbps doesn't support auto-ack, so we check RF24_RF_SETUP to verify that.
00334      */
00335     enaa = true;
00336     _readTXaddr(addrbuf);
00337     _writeRXaddrP0(addrbuf);
00338   }
00339 
00340   reg = _readReg(RF24_CONFIG);
00341   if ( !(reg & RF24_PWR_UP) ) {
00342     _writeReg(RF24_CONFIG, ENRF24_CFGMASK_IRQ | ENRF24_CFGMASK_CRC(reg) | RF24_PWR_UP);
00343     wait_us(5000);  // 5ms delay required for nRF24 oscillator start-up
00344   }
00345   if (reg & RF24_PRIM_RX) {
00346     origrx=true;
00347     _cePin = 0;
00348     _writeReg(RF24_CONFIG, ENRF24_CFGMASK_IRQ | ENRF24_CFGMASK_CRC(reg) | RF24_PWR_UP);
00349   }
00350 
00351   _issueCmdPayload(RF24_W_TX_PAYLOAD, txbuf, txbuf_len);
00352   _cePin = 1;
00353   wait_us(30);
00354   _cePin = 0;
00355 
00356   txbuf_len = 0;  // Reset TX ring buffer
00357 
00358   while (_irqPin)  // Wait until IRQ fires
00359     ;
00360   // IRQ fired
00361   _maintenanceHook();  // Handle/clear IRQ
00362 
00363   // Purge Pipe#0 address (set to module's power-up default)
00364   if (enaa) {
00365     addrbuf[0] = 0xE7; addrbuf[1] = 0xE7; addrbuf[2] = 0xE7; addrbuf[3] = 0xE7; addrbuf[4] = 0xE7;
00366     _writeRXaddrP0(addrbuf);
00367   }
00368 
00369   // If we were in RX mode before writing, return back to RX mode.
00370   if (origrx) {
00371     enableRX();
00372   }
00373 }
00374 
00375 void Enrf24::purge()
00376 {
00377   txbuf_len = 0;
00378 }
00379 
00380 size_t Enrf24::write(uint8_t c)
00381 {
00382   if (txbuf_len == 32) {  // If we're trying to stuff an already-full buffer...
00383     flush();  // Blocking OTA TX
00384   }
00385 
00386   txbuf[txbuf_len] = c;
00387   txbuf_len++;
00388 
00389   return 1;
00390 }
00391 
00392 uint8_t Enrf24::radioState()
00393 {
00394   uint8_t reg;
00395 
00396   if (!_isAlive())
00397     return ENRF24_STATE_NOTPRESENT;
00398   
00399   reg = _readReg(RF24_CONFIG);
00400   if ( !(reg & RF24_PWR_UP) )
00401     return ENRF24_STATE_DEEPSLEEP;
00402 
00403   // At this point it's either Standby-I, II or PRX.
00404   if (reg & RF24_PRIM_RX) {
00405     if (_cePin)
00406       return ENRF24_STATE_PRX;
00407     // PRIM_RX=1 but CE=0 is a form of idle state.
00408     return ENRF24_STATE_IDLE;
00409   }
00410   // Check if TX queue is empty, if so it's idle, if not it's PTX.
00411   if (_readReg(RF24_FIFO_STATUS) & RF24_TX_EMPTY)
00412     return ENRF24_STATE_IDLE;
00413   return ENRF24_STATE_PTX;
00414 }
00415 
00416 void Enrf24::deepsleep()
00417 {
00418   uint8_t reg;
00419 
00420   reg = _readReg(RF24_CONFIG);
00421   if (reg & (RF24_PWR_UP | RF24_PRIM_RX)) {
00422     _writeReg(RF24_CONFIG, ENRF24_CFGMASK_IRQ | ENRF24_CFGMASK_CRC(reg));
00423   }
00424   _cePin = 0;
00425 }
00426 
00427 void Enrf24::enableRX()
00428 {
00429   uint8_t reg;
00430 
00431   reg = _readReg(RF24_CONFIG);
00432   _writeReg(RF24_CONFIG, ENRF24_CFGMASK_IRQ | ENRF24_CFGMASK_CRC(reg) | RF24_PWR_UP | RF24_PRIM_RX);
00433   _cePin = 1;
00434 
00435   if ( !(reg & RF24_PWR_UP) ) {  // Powering up from deep-sleep requires 5ms oscillator start delay
00436     wait(5 / 1000);
00437   }
00438 }
00439 
00440 void Enrf24::disableRX()
00441 {
00442   uint8_t reg;
00443 
00444   _cePin = 0;
00445 
00446   reg = _readReg(RF24_CONFIG);
00447   if (reg & RF24_PWR_UP) {  /* Keep us in standby-I if we're coming from RX mode, otherwise stay
00448                              * in deep-sleep if we call this while already in PWR_UP=0 mode.
00449                              */
00450     _writeReg(RF24_CONFIG, ENRF24_CFGMASK_IRQ | ENRF24_CFGMASK_CRC(reg) | RF24_PWR_UP);
00451   } else {
00452     _writeReg(RF24_CONFIG, ENRF24_CFGMASK_IRQ | ENRF24_CFGMASK_CRC(reg));
00453   }
00454 }
00455 
00456 void Enrf24::autoAck(boolean onoff)
00457 {
00458   uint8_t reg;
00459 
00460   reg = _readReg(RF24_EN_AA);
00461   if (onoff) {
00462     if ( !(reg & 0x01) || !(reg & 0x02) ) {
00463       _writeReg(RF24_EN_AA, 0x03);
00464     }
00465   } else {
00466     if (reg & 0x03) {
00467       _writeReg(RF24_EN_AA, 0x00);
00468     }
00469   }
00470 }
00471 
00472 void Enrf24::setChannel(uint8_t channel)
00473 {
00474   if (channel > 125)
00475     channel = 125;
00476   _writeReg(RF24_RF_CH, channel);
00477 }
00478 
00479 void Enrf24::setTXpower(int8_t dBm)
00480 {
00481   uint8_t reg, pwr;
00482 
00483   reg = _readReg(RF24_RF_SETUP) & 0xF8;  // preserve RF speed settings
00484   pwr = 0x03;
00485   if (dBm < 0)
00486     pwr = 0x02;
00487   if (dBm < -6)
00488     pwr = 0x01;
00489   if (dBm < -12)
00490     pwr = 0x00;
00491   _writeReg(RF24_RF_SETUP, reg | (pwr << 1));
00492 }
00493 
00494 void Enrf24::setSpeed(uint32_t rfspeed)
00495 {
00496   uint8_t reg, spd;
00497 
00498   reg = _readReg(RF24_RF_SETUP) & 0xD7;  // preserve RF power settings
00499   spd = 0x01;
00500   if (rfspeed < 2000000)
00501     spd = 0x00;
00502   if (rfspeed < 1000000)
00503     spd = 0x04;
00504   _writeReg(RF24_RF_SETUP, reg | (spd << 3));
00505 }
00506 
00507 void Enrf24::setCRC(boolean onoff, boolean crc16bit)
00508 {
00509   uint8_t reg, crcbits=0;
00510 
00511   reg = _readReg(RF24_CONFIG) & 0xF3;  // preserve IRQ mask, PWR_UP/PRIM_RX settings
00512   if (onoff)
00513     crcbits |= RF24_EN_CRC;
00514   if (crc16bit)
00515     crcbits |= RF24_CRCO;
00516   _writeReg(RF24_CONFIG, reg | crcbits);
00517 }
00518 
00519 void Enrf24::setAutoAckParams(uint8_t autoretry_count, uint16_t autoretry_timeout)
00520 {
00521   uint8_t setup_retr=0;
00522 
00523   setup_retr = autoretry_count & 0x0F;
00524   autoretry_timeout -= 250;
00525   setup_retr |= ((autoretry_timeout / 250) & 0x0F) << 4;
00526   _writeReg(RF24_SETUP_RETR, setup_retr);
00527 }
00528 
00529 void Enrf24::setAddressLength(size_t len)
00530 {
00531   if (len < 3)
00532     len = 3;
00533   if (len > 5)
00534     len = 5;
00535 
00536   _writeReg(RF24_SETUP_AW, len-2);
00537   rf_addr_width = len;
00538 }
00539 
00540 void Enrf24::setRXaddress(void *rxaddr)
00541 {
00542   _writeRegMultiLSB(RF24_RX_ADDR_P1, (uint8_t*)rxaddr, rf_addr_width);
00543 }
00544 
00545 void Enrf24::setTXaddress(void *rxaddr)
00546 {
00547   _writeRegMultiLSB(RF24_TX_ADDR, (uint8_t*)rxaddr, rf_addr_width);
00548 }
00549 
00550 boolean Enrf24::rfSignalDetected()
00551 {
00552   uint8_t rpd;
00553 
00554   rpd = _readReg(RF24_RPD);
00555   return (boolean)rpd;
00556 }