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.
Fork of RadioHead-148 by
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 20:15:57 by
1.7.2
