David Rimer / RadioHead-148
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers RH_NRF51.cpp Source File

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