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>
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 }
Generated on Fri Jul 15 2022 01:38:37 by 1.7.2