Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
RH_NRF24.cpp
00001 // NRF24.cpp 00002 // 00003 // Copyright (C) 2012 Mike McCauley 00004 // $Id: RH_NRF24.cpp,v 1.21 2015/03/29 03:53:47 mikem Exp $ 00005 00006 #include <RH_NRF24.h> 00007 00008 RH_NRF24::RH_NRF24(PINS chipEnablePin, PINS slaveSelectPin, RHGenericSPI& spi) 00009 : 00010 RHNRFSPIDriver(slaveSelectPin, spi), 00011 _rxBufValid(0) 00012 { 00013 _configuration = RH_NRF24_EN_CRC | RH_NRF24_CRCO; // Default: 2 byte CRC enabled 00014 _chipEnablePin = chipEnablePin; 00015 } 00016 00017 bool RH_NRF24::init() 00018 { 00019 // Teensy with nRF24 is unreliable at 8MHz: 00020 // so is Arduino with RF73 00021 _spi.setFrequency(RHGenericSPI::Frequency1MHz); 00022 if (!RHNRFSPIDriver::init()) 00023 return false; 00024 00025 // Initialise the slave select pin 00026 #if (RH_PLATFORM != RH_PLATFORM_MBED) 00027 pinMode(_chipEnablePin, OUTPUT); 00028 #endif 00029 digitalWrite(_chipEnablePin, LOW); 00030 00031 // Clear interrupts 00032 spiWriteRegister(RH_NRF24_REG_07_STATUS, RH_NRF24_RX_DR | RH_NRF24_TX_DS | RH_NRF24_MAX_RT); 00033 // Enable dynamic payload length on all pipes 00034 spiWriteRegister(RH_NRF24_REG_1C_DYNPD, RH_NRF24_DPL_ALL); 00035 // Enable dynamic payload length, disable payload-with-ack, enable noack 00036 spiWriteRegister(RH_NRF24_REG_1D_FEATURE, RH_NRF24_EN_DPL | RH_NRF24_EN_DYN_ACK); 00037 // Test if there is actually a device connected and responding 00038 // CAUTION: RFM73 and version 2.0 silicon may require ACTIVATE 00039 if (spiReadRegister(RH_NRF24_REG_1D_FEATURE) != (RH_NRF24_EN_DPL | RH_NRF24_EN_DYN_ACK)) 00040 { 00041 spiWrite(RH_NRF24_COMMAND_ACTIVATE, 0x73); 00042 // Enable dynamic payload length, disable payload-with-ack, enable noack 00043 spiWriteRegister(RH_NRF24_REG_1D_FEATURE, RH_NRF24_EN_DPL | RH_NRF24_EN_DYN_ACK); 00044 if (spiReadRegister(RH_NRF24_REG_1D_FEATURE) != (RH_NRF24_EN_DPL | RH_NRF24_EN_DYN_ACK)) 00045 return false; 00046 } 00047 00048 // Make sure we are powered down 00049 setModeIdle(); 00050 00051 // Flush FIFOs 00052 flushTx(); 00053 flushRx(); 00054 00055 setChannel(2); // The default, in case it was set by another app without powering down 00056 setRF(RH_NRF24::DataRate2Mbps, RH_NRF24::TransmitPower0dBm); 00057 00058 return true; 00059 } 00060 00061 // Use the register commands to read and write the registers 00062 uint8_t RH_NRF24::spiReadRegister(uint8_t reg) 00063 { 00064 return spiRead((reg & RH_NRF24_REGISTER_MASK) | RH_NRF24_COMMAND_R_REGISTER); 00065 } 00066 00067 uint8_t RH_NRF24::spiWriteRegister(uint8_t reg, uint8_t val) 00068 { 00069 return spiWrite((reg & RH_NRF24_REGISTER_MASK) | RH_NRF24_COMMAND_W_REGISTER, val); 00070 } 00071 00072 uint8_t RH_NRF24::spiBurstReadRegister(uint8_t reg, uint8_t* dest, uint8_t len) 00073 { 00074 return spiBurstRead((reg & RH_NRF24_REGISTER_MASK) | RH_NRF24_COMMAND_R_REGISTER, dest, len); 00075 } 00076 00077 uint8_t RH_NRF24::spiBurstWriteRegister(uint8_t reg, uint8_t* src, uint8_t len) 00078 { 00079 return spiBurstWrite((reg & RH_NRF24_REGISTER_MASK) | RH_NRF24_COMMAND_W_REGISTER, src, len); 00080 } 00081 00082 uint8_t RH_NRF24::statusRead() 00083 { 00084 // status is a side-effect of NOP, faster than reading reg 07 00085 return spiCommand(RH_NRF24_COMMAND_NOP); 00086 } 00087 00088 uint8_t RH_NRF24::flushTx() 00089 { 00090 return spiCommand(RH_NRF24_COMMAND_FLUSH_TX); 00091 } 00092 00093 uint8_t RH_NRF24::flushRx() 00094 { 00095 return spiCommand(RH_NRF24_COMMAND_FLUSH_RX); 00096 } 00097 00098 bool RH_NRF24::setChannel(uint8_t channel) 00099 { 00100 spiWriteRegister(RH_NRF24_REG_05_RF_CH, channel & RH_NRF24_RF_CH); 00101 return true; 00102 } 00103 00104 bool RH_NRF24::setOpMode(uint8_t mode) 00105 { 00106 _configuration = mode; 00107 return true; 00108 } 00109 00110 bool RH_NRF24::setNetworkAddress(uint8_t* address, uint8_t len) 00111 { 00112 if (len < 3 || len > 5) 00113 return false; 00114 00115 // Set both TX_ADDR and RX_ADDR_P0 for auto-ack with Enhanced shockwave 00116 spiWriteRegister(RH_NRF24_REG_03_SETUP_AW, len-2); // Mapping [3..5] = [1..3] 00117 spiBurstWriteRegister(RH_NRF24_REG_0A_RX_ADDR_P0, address, len); 00118 spiBurstWriteRegister(RH_NRF24_REG_10_TX_ADDR, address, len); 00119 return true; 00120 } 00121 00122 bool RH_NRF24::setRF(DataRate data_rate, TransmitPower power) 00123 { 00124 uint8_t value = (power << 1) & RH_NRF24_PWR; 00125 // Ugly mapping of data rates to noncontiguous 2 bits: 00126 if (data_rate == DataRate250kbps) 00127 value |= RH_NRF24_RF_DR_LOW; 00128 else if (data_rate == DataRate2Mbps) 00129 value |= RH_NRF24_RF_DR_HIGH; 00130 // else DataRate1Mbps, 00 00131 00132 // RFM73 needs this: 00133 value |= RH_NRF24_LNA_HCURR; 00134 00135 spiWriteRegister(RH_NRF24_REG_06_RF_SETUP, value); 00136 // If we were using auto-ack, we would have to set the appropriate timeout in reg 4 here 00137 // see NRF24::setRF() 00138 return true; 00139 } 00140 00141 void RH_NRF24::setModeIdle() 00142 { 00143 if (_mode != RHModeIdle) 00144 { 00145 spiWriteRegister(RH_NRF24_REG_00_CONFIG, _configuration); 00146 digitalWrite(_chipEnablePin, LOW); 00147 _mode = RHModeIdle; 00148 } 00149 } 00150 00151 bool RH_NRF24::sleep() 00152 { 00153 if (_mode != RHModeSleep) 00154 { 00155 spiWriteRegister(RH_NRF24_REG_00_CONFIG, 0); // Power Down mode 00156 digitalWrite(_chipEnablePin, LOW); 00157 _mode = RHModeSleep; 00158 } 00159 } 00160 00161 void RH_NRF24::setModeRx() 00162 { 00163 if (_mode != RHModeRx) 00164 { 00165 spiWriteRegister(RH_NRF24_REG_00_CONFIG, _configuration | RH_NRF24_PWR_UP | RH_NRF24_PRIM_RX); 00166 digitalWrite(_chipEnablePin, HIGH); 00167 _mode = RHModeRx; 00168 } 00169 } 00170 00171 void RH_NRF24::setModeTx() 00172 { 00173 if (_mode != RHModeTx) 00174 { 00175 // Its the CE rising edge that puts us into TX mode 00176 // CE staying high makes us go to standby-II when the packet is sent 00177 digitalWrite(_chipEnablePin, LOW); 00178 // Ensure DS is not set 00179 spiWriteRegister(RH_NRF24_REG_07_STATUS, RH_NRF24_TX_DS | RH_NRF24_MAX_RT); 00180 spiWriteRegister(RH_NRF24_REG_00_CONFIG, _configuration | RH_NRF24_PWR_UP); 00181 digitalWrite(_chipEnablePin, HIGH); 00182 _mode = RHModeTx; 00183 } 00184 } 00185 00186 bool RH_NRF24::send(const uint8_t* data, uint8_t len) 00187 { 00188 if (len > RH_NRF24_MAX_MESSAGE_LEN) 00189 return false; 00190 // Set up the headers 00191 _buf[0] = _txHeaderTo; 00192 _buf[1] = _txHeaderFrom; 00193 _buf[2] = _txHeaderId; 00194 _buf[3] = _txHeaderFlags; 00195 memcpy(_buf+RH_NRF24_HEADER_LEN, data, len); 00196 spiBurstWrite(RH_NRF24_COMMAND_W_TX_PAYLOAD_NOACK, _buf, len + RH_NRF24_HEADER_LEN); 00197 setModeTx(); 00198 // Radio will return to Standby II mode after transmission is complete 00199 _txGood++; 00200 return true; 00201 } 00202 00203 bool RH_NRF24::waitPacketSent() 00204 { 00205 // If we are not currently in transmit mode, there is no packet to wait for 00206 if (_mode != RHModeTx) 00207 return false; 00208 00209 // Wait for either the Data Sent or Max ReTries flag, signalling the 00210 // end of transmission 00211 // We dont actually use auto-ack, so prob dont expect to see RH_NRF24_MAX_RT 00212 uint8_t status; 00213 while (!((status = statusRead()) & (RH_NRF24_TX_DS | RH_NRF24_MAX_RT))) 00214 YIELD; 00215 00216 // Must clear RH_NRF24_MAX_RT if it is set, else no further comm 00217 if (status & RH_NRF24_MAX_RT) 00218 flushTx(); 00219 setModeIdle(); 00220 spiWriteRegister(RH_NRF24_REG_07_STATUS, RH_NRF24_TX_DS | RH_NRF24_MAX_RT); 00221 // Return true if data sent, false if MAX_RT 00222 return status & RH_NRF24_TX_DS; 00223 } 00224 00225 bool RH_NRF24::isSending() 00226 { 00227 return !(spiReadRegister(RH_NRF24_REG_00_CONFIG) & RH_NRF24_PRIM_RX) && 00228 !(statusRead() & (RH_NRF24_TX_DS | RH_NRF24_MAX_RT)); 00229 } 00230 00231 bool RH_NRF24::printRegisters() 00232 { 00233 #ifdef RH_HAVE_SERIAL 00234 // Iterate over register range, but don't process registers not in use. 00235 for (uint8_t r = RH_NRF24_REG_00_CONFIG; r <= RH_NRF24_REG_1D_FEATURE; r++) 00236 { 00237 if ((r <= RH_NRF24_REG_17_FIFO_STATUS) || (r >= RH_NRF24_REG_1C_DYNPD)) 00238 { 00239 Serial.print(r, HEX); 00240 Serial.print(": "); 00241 uint8_t len = 1; 00242 // Address registers are 5 bytes in size 00243 if ( (RH_NRF24_REG_0A_RX_ADDR_P0 == r) 00244 || (RH_NRF24_REG_0B_RX_ADDR_P1 == r) 00245 || (RH_NRF24_REG_10_TX_ADDR == r) ) 00246 { 00247 len = 5; 00248 } 00249 uint8_t buf[5]; 00250 spiBurstReadRegister(r, buf, len); 00251 for (uint8_t j = 0; j < len; ++j) 00252 { 00253 Serial.print(buf[j], HEX); 00254 Serial.print(" "); 00255 } 00256 Serial.println(""); 00257 } 00258 } 00259 #endif 00260 00261 return true; 00262 } 00263 00264 // Check whether the latest received message is complete and uncorrupted 00265 void RH_NRF24::validateRxBuf() 00266 { 00267 if (_bufLen < 4) 00268 return; // Too short to be a real message 00269 // Extract the 4 headers 00270 _rxHeaderTo = _buf[0]; 00271 _rxHeaderFrom = _buf[1]; 00272 _rxHeaderId = _buf[2]; 00273 _rxHeaderFlags = _buf[3]; 00274 if (_promiscuous || 00275 _rxHeaderTo == _thisAddress || 00276 _rxHeaderTo == RH_BROADCAST_ADDRESS) 00277 { 00278 _rxGood++; 00279 _rxBufValid = true; 00280 } 00281 } 00282 00283 bool RH_NRF24::available() 00284 { 00285 if (!_rxBufValid) 00286 { 00287 if (_mode == RHModeTx) 00288 return false; 00289 setModeRx(); 00290 if (spiReadRegister(RH_NRF24_REG_17_FIFO_STATUS) & RH_NRF24_RX_EMPTY) 00291 return false; 00292 // Manual says that messages > 32 octets should be discarded 00293 uint8_t len = spiRead(RH_NRF24_COMMAND_R_RX_PL_WID); 00294 if (len > 32) 00295 { 00296 flushRx(); 00297 clearRxBuf(); 00298 setModeIdle(); 00299 return false; 00300 } 00301 // Clear read interrupt 00302 spiWriteRegister(RH_NRF24_REG_07_STATUS, RH_NRF24_RX_DR); 00303 // Get the message into the RX buffer, so we can inspect the headers 00304 spiBurstRead(RH_NRF24_COMMAND_R_RX_PAYLOAD, _buf, len); 00305 _bufLen = len; 00306 // 140 microsecs (32 octet payload) 00307 validateRxBuf(); 00308 if (_rxBufValid) 00309 setModeIdle(); // Got one 00310 } 00311 return _rxBufValid; 00312 } 00313 00314 void RH_NRF24::clearRxBuf() 00315 { 00316 _rxBufValid = false; 00317 _bufLen = 0; 00318 } 00319 00320 bool RH_NRF24::recv(uint8_t* buf, uint8_t* len) 00321 { 00322 if (!available()) 00323 return false; 00324 if (buf && len) 00325 { 00326 // Skip the 4 headers that are at the beginning of the rxBuf 00327 if (*len > _bufLen-RH_NRF24_HEADER_LEN) 00328 *len = _bufLen-RH_NRF24_HEADER_LEN; 00329 memcpy(buf, _buf+RH_NRF24_HEADER_LEN, *len); 00330 } 00331 clearRxBuf(); // This message accepted and cleared 00332 return true; 00333 } 00334 00335 uint8_t RH_NRF24::maxMessageLength() 00336 { 00337 return RH_NRF24_MAX_MESSAGE_LEN; 00338 }
Generated on Tue Jul 12 2022 18:05:55 by
