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_NRF51.cpp
00001 // NRF51.cpp 00002 // 00003 // Per: nRF51_Series_Reference_manual v3.0.pdf 00004 // Copyright (C) 2012 Mike McCauley 00005 // $Id: RH_NRF51.cpp,v 1.1 2015/07/01 00:46:05 mikem Exp $ 00006 00007 // Set by Arduino IDE when compiling for nRF51 chips: 00008 #ifdef NRF51 00009 00010 #include <RH_NRF51.h> 00011 00012 RH_NRF51::RH_NRF51() 00013 : _rxBufValid(false) 00014 { 00015 } 00016 00017 bool RH_NRF51::init() 00018 { 00019 // Enable the High Frequency clock to the system as a whole 00020 NRF_CLOCK->EVENTS_HFCLKSTARTED = 0; 00021 NRF_CLOCK->TASKS_HFCLKSTART = 1; 00022 /* Wait for the external oscillator to start up */ 00023 while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0) { } 00024 00025 // Enables the DC/DC converter when the radio is enabled. Need this! 00026 NRF_POWER->DCDCEN = 0x00000001; 00027 00028 // Disable and reset the radio 00029 NRF_RADIO->POWER = RADIO_POWER_POWER_Disabled; 00030 NRF_RADIO->POWER = RADIO_POWER_POWER_Enabled; 00031 NRF_RADIO->EVENTS_DISABLED = 0; 00032 NRF_RADIO->TASKS_DISABLE = 1; 00033 // Wait until we are in DISABLE state 00034 while (NRF_RADIO->EVENTS_DISABLED == 0) {} 00035 00036 // Physical on-air address is set in PREFIX0 + BASE0 by setNetworkAddress 00037 NRF_RADIO->TXADDRESS = 0x00; // Use logical address 0 (PREFIX0 + BASE0) 00038 NRF_RADIO->RXADDRESSES = 0x01; // Enable reception on logical address 0 (PREFIX0 + BASE0) 00039 00040 // Configure the CRC 00041 NRF_RADIO->CRCCNF = (RADIO_CRCCNF_LEN_Two << RADIO_CRCCNF_LEN_Pos); // Number of checksum bits 00042 NRF_RADIO->CRCINIT = 0xFFFFUL; // Initial value 00043 NRF_RADIO->CRCPOLY = 0x11021UL; // CRC poly: x^16+x^12^x^5+1 00044 00045 // These shorts will make the radio transition from Ready to Start to Disable automatically 00046 // for both TX and RX, which makes for much shorter on-air times 00047 NRF_RADIO->SHORTS = (RADIO_SHORTS_READY_START_Enabled << RADIO_SHORTS_READY_START_Pos) 00048 | (RADIO_SHORTS_END_DISABLE_Enabled << RADIO_SHORTS_END_DISABLE_Pos); 00049 00050 NRF_RADIO->PCNF0 = ((8 << RADIO_PCNF0_LFLEN_Pos) & RADIO_PCNF0_LFLEN_Msk); // Payload length in bits 00051 00052 // Make sure we are powered down 00053 setModeIdle(); 00054 00055 // Set a default network address 00056 uint8_t default_network_address[] = {0xE7, 0xE7, 0xE7, 0xE7, 0xE7}; 00057 setNetworkAddress(default_network_address, sizeof(default_network_address)); 00058 00059 setChannel(2); // The default, in case it was set by another app without powering down 00060 setRF(RH_NRF51::DataRate2Mbps, RH_NRF51::TransmitPower0dBm); 00061 00062 return true; 00063 } 00064 00065 bool RH_NRF51::setChannel(uint8_t channel) 00066 { 00067 NRF_RADIO->FREQUENCY = ((channel << RADIO_FREQUENCY_FREQUENCY_Pos) & RADIO_FREQUENCY_FREQUENCY_Msk); 00068 return true; 00069 } 00070 00071 bool RH_NRF51::setNetworkAddress(uint8_t* address, uint8_t len) 00072 { 00073 if (len < 3 || len > 5) 00074 return false; 00075 00076 // First byte is the prefix, remainder are base 00077 NRF_RADIO->PREFIX0 = ((address[0] << RADIO_PREFIX0_AP0_Pos) & RADIO_PREFIX0_AP0_Msk); 00078 uint32_t base; 00079 memcpy(&base, address+1, len-1); 00080 NRF_RADIO->BASE0 = base; 00081 00082 NRF_RADIO->PCNF1 = ( 00083 (((sizeof(_buf)) << RADIO_PCNF1_MAXLEN_Pos) & RADIO_PCNF1_MAXLEN_Msk) // maximum length of payload 00084 | (((0UL) << RADIO_PCNF1_STATLEN_Pos) & RADIO_PCNF1_STATLEN_Msk) // expand the payload with 0 bytes 00085 | (((len-1) << RADIO_PCNF1_BALEN_Pos) & RADIO_PCNF1_BALEN_Msk)); // base address length in number of bytes. 00086 00087 return true; 00088 } 00089 00090 bool RH_NRF51::setRF(DataRate data_rate, TransmitPower power) 00091 { 00092 uint8_t mode; 00093 uint8_t p; 00094 00095 if (data_rate == DataRate2Mbps) 00096 mode = RADIO_MODE_MODE_Nrf_2Mbit; 00097 else if (data_rate == DataRate1Mbps) 00098 mode = RADIO_MODE_MODE_Nrf_1Mbit; 00099 else if (data_rate == DataRate250kbps) 00100 mode = RADIO_MODE_MODE_Nrf_250Kbit; 00101 else 00102 return false;// Invalid 00103 00104 if (power == TransmitPower4dBm) 00105 p = RADIO_TXPOWER_TXPOWER_Pos4dBm; 00106 else if (power == TransmitPower0dBm) 00107 p = RADIO_TXPOWER_TXPOWER_0dBm; 00108 else if (power == TransmitPowerm4dBm) 00109 p = RADIO_TXPOWER_TXPOWER_Neg4dBm; 00110 else if (power == TransmitPowerm8dBm) 00111 p = RADIO_TXPOWER_TXPOWER_Neg8dBm; 00112 else if (power == TransmitPowerm12dBm) 00113 p = RADIO_TXPOWER_TXPOWER_Neg12dBm; 00114 else if (power == TransmitPowerm16dBm) 00115 p = RADIO_TXPOWER_TXPOWER_Neg16dBm; 00116 else if (power == TransmitPowerm20dBm) 00117 p = RADIO_TXPOWER_TXPOWER_Neg20dBm; 00118 else if (power == TransmitPowerm30dBm) 00119 p = RADIO_TXPOWER_TXPOWER_Neg30dBm; 00120 else 00121 return false; // Invalid 00122 00123 00124 NRF_RADIO->TXPOWER = ((p << RADIO_TXPOWER_TXPOWER_Pos) & RADIO_TXPOWER_TXPOWER_Msk); 00125 NRF_RADIO->MODE = ((mode << RADIO_MODE_MODE_Pos) & RADIO_MODE_MODE_Msk); 00126 00127 return true; 00128 } 00129 00130 void RH_NRF51::setModeIdle() 00131 { 00132 if (_mode != RHModeIdle) 00133 { 00134 NRF_RADIO->TASKS_DISABLE = 1; 00135 _mode = RHModeIdle; 00136 } 00137 } 00138 00139 void RH_NRF51::setModeRx() 00140 { 00141 if (_mode != RHModeRx) 00142 { 00143 setModeIdle(); // Can only start RX from DISABLE state 00144 // Radio will transition automatically to Disable state when a messageis received 00145 NRF_RADIO->PACKETPTR = (uint32_t)_buf; 00146 NRF_RADIO->EVENTS_DISABLED = 0U; // So we can detect end of transmission 00147 NRF_RADIO->TASKS_RXEN = 1; 00148 _mode = RHModeRx; 00149 } 00150 } 00151 00152 void RH_NRF51::setModeTx() 00153 { 00154 if (_mode != RHModeTx) 00155 { 00156 setModeIdle(); // Can only start RX from DISABLE state 00157 // Radio will transition automatically to Disable state at the end of transmission 00158 NRF_RADIO->PACKETPTR = (uint32_t)_buf; 00159 NRF_RADIO->EVENTS_DISABLED = 0U; // So we can detect end of transmission 00160 NRF_RADIO->TASKS_TXEN = 1; 00161 _mode = RHModeTx; 00162 } 00163 } 00164 00165 bool RH_NRF51::send(const uint8_t* data, uint8_t len) 00166 { 00167 if (len > RH_NRF51_MAX_MESSAGE_LEN) 00168 return false; 00169 // Set up the headers 00170 _buf[0] = len + RH_NRF51_HEADER_LEN; 00171 _buf[1] = _txHeaderTo; 00172 _buf[2] = _txHeaderFrom; 00173 _buf[3] = _txHeaderId; 00174 _buf[4] = _txHeaderFlags; 00175 memcpy(_buf+RH_NRF51_HEADER_LEN+1, data, len); 00176 00177 _rxBufValid = false; 00178 setModeTx(); 00179 // Radio will return to Disabled state after transmission is complete 00180 _txGood++; 00181 return true; 00182 } 00183 00184 bool RH_NRF51::waitPacketSent() 00185 { 00186 // If we are not currently in transmit mode, there is no packet to wait for 00187 if (_mode != RHModeTx) 00188 return false; 00189 00190 // When the Disabled event occurs we know the transmission has completed 00191 while (NRF_RADIO->EVENTS_DISABLED == 0U) 00192 { 00193 YIELD; 00194 } 00195 setModeIdle(); 00196 00197 return true; 00198 } 00199 00200 bool RH_NRF51::isSending() 00201 { 00202 return (NRF_RADIO->STATE == RADIO_STATE_STATE_Tx) ? true : false; 00203 } 00204 00205 bool RH_NRF51::printRegisters() 00206 { 00207 #ifdef RH_HAVE_SERIAL 00208 uint16_t i; 00209 uint32_t* p = (uint32_t*)NRF_RADIO; 00210 for (i = 0; (p + i) < (uint32_t*) (((NRF_RADIO_Type*)NRF_RADIO) + 1); i++) 00211 { 00212 Serial.print("Offset: "); 00213 Serial.print(i, DEC); 00214 Serial.print(" "); 00215 Serial.println(*(p+i), HEX); 00216 } 00217 #endif 00218 00219 return true; 00220 } 00221 00222 // Check whether the latest received message is complete and uncorrupted 00223 void RH_NRF51::validateRxBuf() 00224 { 00225 if (_buf[0] < 4) 00226 return; // Too short to be a real message 00227 // Extract the 4 headers 00228 _rxHeaderTo = _buf[1]; 00229 _rxHeaderFrom = _buf[2]; 00230 _rxHeaderId = _buf[3]; 00231 _rxHeaderFlags = _buf[4]; 00232 if (_promiscuous || 00233 _rxHeaderTo == _thisAddress || 00234 _rxHeaderTo == RH_BROADCAST_ADDRESS) 00235 { 00236 _rxGood++; 00237 _rxBufValid = true; 00238 } 00239 } 00240 00241 bool RH_NRF51::available() 00242 { 00243 if (!_rxBufValid) 00244 { 00245 if (_mode == RHModeTx) 00246 return false; 00247 setModeRx(); 00248 if (NRF_RADIO->EVENTS_DISABLED == 0U) 00249 return false; // No message yet 00250 if (NRF_RADIO->CRCSTATUS == ((RADIO_CRCSTATUS_CRCSTATUS_CRCError << RADIO_CRCSTATUS_CRCSTATUS_Pos) & RADIO_CRCSTATUS_CRCSTATUS_Msk)) 00251 { 00252 // Bad CRC, restart the radio 00253 _rxBad++; 00254 setModeRx(); 00255 return false; 00256 } 00257 validateRxBuf(); 00258 if (_rxBufValid) 00259 setModeIdle(); // Got one 00260 } 00261 return _rxBufValid; 00262 } 00263 00264 void RH_NRF51::clearRxBuf() 00265 { 00266 _rxBufValid = false; 00267 _buf[0] = 0; 00268 } 00269 00270 bool RH_NRF51::recv(uint8_t* buf, uint8_t* len) 00271 { 00272 if (!available()) 00273 return false; 00274 if (buf && len) 00275 { 00276 // Skip the 4 headers that are at the beginning of the rxBuf 00277 // the payload length is the first octet in _buf 00278 if (*len > _buf[0]-RH_NRF51_HEADER_LEN) 00279 *len = _buf[0]-RH_NRF51_HEADER_LEN; 00280 memcpy(buf, _buf+RH_NRF51_HEADER_LEN+1, *len); 00281 } 00282 clearRxBuf(); // This message accepted and cleared 00283 return true; 00284 } 00285 00286 uint8_t RH_NRF51::maxMessageLength() 00287 { 00288 return RH_NRF51_MAX_MESSAGE_LEN; 00289 } 00290 00291 #endif // NRF51
Generated on Tue Jul 12 2022 18:05:55 by
1.7.2