V148

Fork of RadioHead-148 by David Rimer

Committer:
davidr99
Date:
Thu Oct 15 01:27:00 2015 +0000
Revision:
0:ab4e012489ef
Messy start, but a port for RadioHead.; Currently the SPI modulus are the only ones that work.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
davidr99 0:ab4e012489ef 1 // NRF51.cpp
davidr99 0:ab4e012489ef 2 //
davidr99 0:ab4e012489ef 3 // Per: nRF51_Series_Reference_manual v3.0.pdf
davidr99 0:ab4e012489ef 4 // Copyright (C) 2012 Mike McCauley
davidr99 0:ab4e012489ef 5 // $Id: RH_NRF51.cpp,v 1.1 2015/07/01 00:46:05 mikem Exp $
davidr99 0:ab4e012489ef 6
davidr99 0:ab4e012489ef 7 // Set by Arduino IDE when compiling for nRF51 chips:
davidr99 0:ab4e012489ef 8 #ifdef NRF51
davidr99 0:ab4e012489ef 9
davidr99 0:ab4e012489ef 10 #include <RH_NRF51.h>
davidr99 0:ab4e012489ef 11
davidr99 0:ab4e012489ef 12 RH_NRF51::RH_NRF51()
davidr99 0:ab4e012489ef 13 : _rxBufValid(false)
davidr99 0:ab4e012489ef 14 {
davidr99 0:ab4e012489ef 15 }
davidr99 0:ab4e012489ef 16
davidr99 0:ab4e012489ef 17 bool RH_NRF51::init()
davidr99 0:ab4e012489ef 18 {
davidr99 0:ab4e012489ef 19 // Enable the High Frequency clock to the system as a whole
davidr99 0:ab4e012489ef 20 NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
davidr99 0:ab4e012489ef 21 NRF_CLOCK->TASKS_HFCLKSTART = 1;
davidr99 0:ab4e012489ef 22 /* Wait for the external oscillator to start up */
davidr99 0:ab4e012489ef 23 while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0) { }
davidr99 0:ab4e012489ef 24
davidr99 0:ab4e012489ef 25 // Enables the DC/DC converter when the radio is enabled. Need this!
davidr99 0:ab4e012489ef 26 NRF_POWER->DCDCEN = 0x00000001;
davidr99 0:ab4e012489ef 27
davidr99 0:ab4e012489ef 28 // Disable and reset the radio
davidr99 0:ab4e012489ef 29 NRF_RADIO->POWER = RADIO_POWER_POWER_Disabled;
davidr99 0:ab4e012489ef 30 NRF_RADIO->POWER = RADIO_POWER_POWER_Enabled;
davidr99 0:ab4e012489ef 31 NRF_RADIO->EVENTS_DISABLED = 0;
davidr99 0:ab4e012489ef 32 NRF_RADIO->TASKS_DISABLE = 1;
davidr99 0:ab4e012489ef 33 // Wait until we are in DISABLE state
davidr99 0:ab4e012489ef 34 while (NRF_RADIO->EVENTS_DISABLED == 0) {}
davidr99 0:ab4e012489ef 35
davidr99 0:ab4e012489ef 36 // Physical on-air address is set in PREFIX0 + BASE0 by setNetworkAddress
davidr99 0:ab4e012489ef 37 NRF_RADIO->TXADDRESS = 0x00; // Use logical address 0 (PREFIX0 + BASE0)
davidr99 0:ab4e012489ef 38 NRF_RADIO->RXADDRESSES = 0x01; // Enable reception on logical address 0 (PREFIX0 + BASE0)
davidr99 0:ab4e012489ef 39
davidr99 0:ab4e012489ef 40 // Configure the CRC
davidr99 0:ab4e012489ef 41 NRF_RADIO->CRCCNF = (RADIO_CRCCNF_LEN_Two << RADIO_CRCCNF_LEN_Pos); // Number of checksum bits
davidr99 0:ab4e012489ef 42 NRF_RADIO->CRCINIT = 0xFFFFUL; // Initial value
davidr99 0:ab4e012489ef 43 NRF_RADIO->CRCPOLY = 0x11021UL; // CRC poly: x^16+x^12^x^5+1
davidr99 0:ab4e012489ef 44
davidr99 0:ab4e012489ef 45 // These shorts will make the radio transition from Ready to Start to Disable automatically
davidr99 0:ab4e012489ef 46 // for both TX and RX, which makes for much shorter on-air times
davidr99 0:ab4e012489ef 47 NRF_RADIO->SHORTS = (RADIO_SHORTS_READY_START_Enabled << RADIO_SHORTS_READY_START_Pos)
davidr99 0:ab4e012489ef 48 | (RADIO_SHORTS_END_DISABLE_Enabled << RADIO_SHORTS_END_DISABLE_Pos);
davidr99 0:ab4e012489ef 49
davidr99 0:ab4e012489ef 50 NRF_RADIO->PCNF0 = ((8 << RADIO_PCNF0_LFLEN_Pos) & RADIO_PCNF0_LFLEN_Msk); // Payload length in bits
davidr99 0:ab4e012489ef 51
davidr99 0:ab4e012489ef 52 // Make sure we are powered down
davidr99 0:ab4e012489ef 53 setModeIdle();
davidr99 0:ab4e012489ef 54
davidr99 0:ab4e012489ef 55 // Set a default network address
davidr99 0:ab4e012489ef 56 uint8_t default_network_address[] = {0xE7, 0xE7, 0xE7, 0xE7, 0xE7};
davidr99 0:ab4e012489ef 57 setNetworkAddress(default_network_address, sizeof(default_network_address));
davidr99 0:ab4e012489ef 58
davidr99 0:ab4e012489ef 59 setChannel(2); // The default, in case it was set by another app without powering down
davidr99 0:ab4e012489ef 60 setRF(RH_NRF51::DataRate2Mbps, RH_NRF51::TransmitPower0dBm);
davidr99 0:ab4e012489ef 61
davidr99 0:ab4e012489ef 62 return true;
davidr99 0:ab4e012489ef 63 }
davidr99 0:ab4e012489ef 64
davidr99 0:ab4e012489ef 65 bool RH_NRF51::setChannel(uint8_t channel)
davidr99 0:ab4e012489ef 66 {
davidr99 0:ab4e012489ef 67 NRF_RADIO->FREQUENCY = ((channel << RADIO_FREQUENCY_FREQUENCY_Pos) & RADIO_FREQUENCY_FREQUENCY_Msk);
davidr99 0:ab4e012489ef 68 return true;
davidr99 0:ab4e012489ef 69 }
davidr99 0:ab4e012489ef 70
davidr99 0:ab4e012489ef 71 bool RH_NRF51::setNetworkAddress(uint8_t* address, uint8_t len)
davidr99 0:ab4e012489ef 72 {
davidr99 0:ab4e012489ef 73 if (len < 3 || len > 5)
davidr99 0:ab4e012489ef 74 return false;
davidr99 0:ab4e012489ef 75
davidr99 0:ab4e012489ef 76 // First byte is the prefix, remainder are base
davidr99 0:ab4e012489ef 77 NRF_RADIO->PREFIX0 = ((address[0] << RADIO_PREFIX0_AP0_Pos) & RADIO_PREFIX0_AP0_Msk);
davidr99 0:ab4e012489ef 78 uint32_t base;
davidr99 0:ab4e012489ef 79 memcpy(&base, address+1, len-1);
davidr99 0:ab4e012489ef 80 NRF_RADIO->BASE0 = base;
davidr99 0:ab4e012489ef 81
davidr99 0:ab4e012489ef 82 NRF_RADIO->PCNF1 = (
davidr99 0:ab4e012489ef 83 (((sizeof(_buf)) << RADIO_PCNF1_MAXLEN_Pos) & RADIO_PCNF1_MAXLEN_Msk) // maximum length of payload
davidr99 0:ab4e012489ef 84 | (((0UL) << RADIO_PCNF1_STATLEN_Pos) & RADIO_PCNF1_STATLEN_Msk) // expand the payload with 0 bytes
davidr99 0:ab4e012489ef 85 | (((len-1) << RADIO_PCNF1_BALEN_Pos) & RADIO_PCNF1_BALEN_Msk)); // base address length in number of bytes.
davidr99 0:ab4e012489ef 86
davidr99 0:ab4e012489ef 87 return true;
davidr99 0:ab4e012489ef 88 }
davidr99 0:ab4e012489ef 89
davidr99 0:ab4e012489ef 90 bool RH_NRF51::setRF(DataRate data_rate, TransmitPower power)
davidr99 0:ab4e012489ef 91 {
davidr99 0:ab4e012489ef 92 uint8_t mode;
davidr99 0:ab4e012489ef 93 uint8_t p;
davidr99 0:ab4e012489ef 94
davidr99 0:ab4e012489ef 95 if (data_rate == DataRate2Mbps)
davidr99 0:ab4e012489ef 96 mode = RADIO_MODE_MODE_Nrf_2Mbit;
davidr99 0:ab4e012489ef 97 else if (data_rate == DataRate1Mbps)
davidr99 0:ab4e012489ef 98 mode = RADIO_MODE_MODE_Nrf_1Mbit;
davidr99 0:ab4e012489ef 99 else if (data_rate == DataRate250kbps)
davidr99 0:ab4e012489ef 100 mode = RADIO_MODE_MODE_Nrf_250Kbit;
davidr99 0:ab4e012489ef 101 else
davidr99 0:ab4e012489ef 102 return false;// Invalid
davidr99 0:ab4e012489ef 103
davidr99 0:ab4e012489ef 104 if (power == TransmitPower4dBm)
davidr99 0:ab4e012489ef 105 p = RADIO_TXPOWER_TXPOWER_Pos4dBm;
davidr99 0:ab4e012489ef 106 else if (power == TransmitPower0dBm)
davidr99 0:ab4e012489ef 107 p = RADIO_TXPOWER_TXPOWER_0dBm;
davidr99 0:ab4e012489ef 108 else if (power == TransmitPowerm4dBm)
davidr99 0:ab4e012489ef 109 p = RADIO_TXPOWER_TXPOWER_Neg4dBm;
davidr99 0:ab4e012489ef 110 else if (power == TransmitPowerm8dBm)
davidr99 0:ab4e012489ef 111 p = RADIO_TXPOWER_TXPOWER_Neg8dBm;
davidr99 0:ab4e012489ef 112 else if (power == TransmitPowerm12dBm)
davidr99 0:ab4e012489ef 113 p = RADIO_TXPOWER_TXPOWER_Neg12dBm;
davidr99 0:ab4e012489ef 114 else if (power == TransmitPowerm16dBm)
davidr99 0:ab4e012489ef 115 p = RADIO_TXPOWER_TXPOWER_Neg16dBm;
davidr99 0:ab4e012489ef 116 else if (power == TransmitPowerm20dBm)
davidr99 0:ab4e012489ef 117 p = RADIO_TXPOWER_TXPOWER_Neg20dBm;
davidr99 0:ab4e012489ef 118 else if (power == TransmitPowerm30dBm)
davidr99 0:ab4e012489ef 119 p = RADIO_TXPOWER_TXPOWER_Neg30dBm;
davidr99 0:ab4e012489ef 120 else
davidr99 0:ab4e012489ef 121 return false; // Invalid
davidr99 0:ab4e012489ef 122
davidr99 0:ab4e012489ef 123
davidr99 0:ab4e012489ef 124 NRF_RADIO->TXPOWER = ((p << RADIO_TXPOWER_TXPOWER_Pos) & RADIO_TXPOWER_TXPOWER_Msk);
davidr99 0:ab4e012489ef 125 NRF_RADIO->MODE = ((mode << RADIO_MODE_MODE_Pos) & RADIO_MODE_MODE_Msk);
davidr99 0:ab4e012489ef 126
davidr99 0:ab4e012489ef 127 return true;
davidr99 0:ab4e012489ef 128 }
davidr99 0:ab4e012489ef 129
davidr99 0:ab4e012489ef 130 void RH_NRF51::setModeIdle()
davidr99 0:ab4e012489ef 131 {
davidr99 0:ab4e012489ef 132 if (_mode != RHModeIdle)
davidr99 0:ab4e012489ef 133 {
davidr99 0:ab4e012489ef 134 NRF_RADIO->TASKS_DISABLE = 1;
davidr99 0:ab4e012489ef 135 _mode = RHModeIdle;
davidr99 0:ab4e012489ef 136 }
davidr99 0:ab4e012489ef 137 }
davidr99 0:ab4e012489ef 138
davidr99 0:ab4e012489ef 139 void RH_NRF51::setModeRx()
davidr99 0:ab4e012489ef 140 {
davidr99 0:ab4e012489ef 141 if (_mode != RHModeRx)
davidr99 0:ab4e012489ef 142 {
davidr99 0:ab4e012489ef 143 setModeIdle(); // Can only start RX from DISABLE state
davidr99 0:ab4e012489ef 144 // Radio will transition automatically to Disable state when a messageis received
davidr99 0:ab4e012489ef 145 NRF_RADIO->PACKETPTR = (uint32_t)_buf;
davidr99 0:ab4e012489ef 146 NRF_RADIO->EVENTS_DISABLED = 0U; // So we can detect end of transmission
davidr99 0:ab4e012489ef 147 NRF_RADIO->TASKS_RXEN = 1;
davidr99 0:ab4e012489ef 148 _mode = RHModeRx;
davidr99 0:ab4e012489ef 149 }
davidr99 0:ab4e012489ef 150 }
davidr99 0:ab4e012489ef 151
davidr99 0:ab4e012489ef 152 void RH_NRF51::setModeTx()
davidr99 0:ab4e012489ef 153 {
davidr99 0:ab4e012489ef 154 if (_mode != RHModeTx)
davidr99 0:ab4e012489ef 155 {
davidr99 0:ab4e012489ef 156 setModeIdle(); // Can only start RX from DISABLE state
davidr99 0:ab4e012489ef 157 // Radio will transition automatically to Disable state at the end of transmission
davidr99 0:ab4e012489ef 158 NRF_RADIO->PACKETPTR = (uint32_t)_buf;
davidr99 0:ab4e012489ef 159 NRF_RADIO->EVENTS_DISABLED = 0U; // So we can detect end of transmission
davidr99 0:ab4e012489ef 160 NRF_RADIO->TASKS_TXEN = 1;
davidr99 0:ab4e012489ef 161 _mode = RHModeTx;
davidr99 0:ab4e012489ef 162 }
davidr99 0:ab4e012489ef 163 }
davidr99 0:ab4e012489ef 164
davidr99 0:ab4e012489ef 165 bool RH_NRF51::send(const uint8_t* data, uint8_t len)
davidr99 0:ab4e012489ef 166 {
davidr99 0:ab4e012489ef 167 if (len > RH_NRF51_MAX_MESSAGE_LEN)
davidr99 0:ab4e012489ef 168 return false;
davidr99 0:ab4e012489ef 169 // Set up the headers
davidr99 0:ab4e012489ef 170 _buf[0] = len + RH_NRF51_HEADER_LEN;
davidr99 0:ab4e012489ef 171 _buf[1] = _txHeaderTo;
davidr99 0:ab4e012489ef 172 _buf[2] = _txHeaderFrom;
davidr99 0:ab4e012489ef 173 _buf[3] = _txHeaderId;
davidr99 0:ab4e012489ef 174 _buf[4] = _txHeaderFlags;
davidr99 0:ab4e012489ef 175 memcpy(_buf+RH_NRF51_HEADER_LEN+1, data, len);
davidr99 0:ab4e012489ef 176
davidr99 0:ab4e012489ef 177 _rxBufValid = false;
davidr99 0:ab4e012489ef 178 setModeTx();
davidr99 0:ab4e012489ef 179 // Radio will return to Disabled state after transmission is complete
davidr99 0:ab4e012489ef 180 _txGood++;
davidr99 0:ab4e012489ef 181 return true;
davidr99 0:ab4e012489ef 182 }
davidr99 0:ab4e012489ef 183
davidr99 0:ab4e012489ef 184 bool RH_NRF51::waitPacketSent()
davidr99 0:ab4e012489ef 185 {
davidr99 0:ab4e012489ef 186 // If we are not currently in transmit mode, there is no packet to wait for
davidr99 0:ab4e012489ef 187 if (_mode != RHModeTx)
davidr99 0:ab4e012489ef 188 return false;
davidr99 0:ab4e012489ef 189
davidr99 0:ab4e012489ef 190 // When the Disabled event occurs we know the transmission has completed
davidr99 0:ab4e012489ef 191 while (NRF_RADIO->EVENTS_DISABLED == 0U)
davidr99 0:ab4e012489ef 192 {
davidr99 0:ab4e012489ef 193 YIELD;
davidr99 0:ab4e012489ef 194 }
davidr99 0:ab4e012489ef 195 setModeIdle();
davidr99 0:ab4e012489ef 196
davidr99 0:ab4e012489ef 197 return true;
davidr99 0:ab4e012489ef 198 }
davidr99 0:ab4e012489ef 199
davidr99 0:ab4e012489ef 200 bool RH_NRF51::isSending()
davidr99 0:ab4e012489ef 201 {
davidr99 0:ab4e012489ef 202 return (NRF_RADIO->STATE == RADIO_STATE_STATE_Tx) ? true : false;
davidr99 0:ab4e012489ef 203 }
davidr99 0:ab4e012489ef 204
davidr99 0:ab4e012489ef 205 bool RH_NRF51::printRegisters()
davidr99 0:ab4e012489ef 206 {
davidr99 0:ab4e012489ef 207 #ifdef RH_HAVE_SERIAL
davidr99 0:ab4e012489ef 208 uint16_t i;
davidr99 0:ab4e012489ef 209 uint32_t* p = (uint32_t*)NRF_RADIO;
davidr99 0:ab4e012489ef 210 for (i = 0; (p + i) < (uint32_t*) (((NRF_RADIO_Type*)NRF_RADIO) + 1); i++)
davidr99 0:ab4e012489ef 211 {
davidr99 0:ab4e012489ef 212 Serial.print("Offset: ");
davidr99 0:ab4e012489ef 213 Serial.print(i, DEC);
davidr99 0:ab4e012489ef 214 Serial.print(" ");
davidr99 0:ab4e012489ef 215 Serial.println(*(p+i), HEX);
davidr99 0:ab4e012489ef 216 }
davidr99 0:ab4e012489ef 217 #endif
davidr99 0:ab4e012489ef 218
davidr99 0:ab4e012489ef 219 return true;
davidr99 0:ab4e012489ef 220 }
davidr99 0:ab4e012489ef 221
davidr99 0:ab4e012489ef 222 // Check whether the latest received message is complete and uncorrupted
davidr99 0:ab4e012489ef 223 void RH_NRF51::validateRxBuf()
davidr99 0:ab4e012489ef 224 {
davidr99 0:ab4e012489ef 225 if (_buf[0] < 4)
davidr99 0:ab4e012489ef 226 return; // Too short to be a real message
davidr99 0:ab4e012489ef 227 // Extract the 4 headers
davidr99 0:ab4e012489ef 228 _rxHeaderTo = _buf[1];
davidr99 0:ab4e012489ef 229 _rxHeaderFrom = _buf[2];
davidr99 0:ab4e012489ef 230 _rxHeaderId = _buf[3];
davidr99 0:ab4e012489ef 231 _rxHeaderFlags = _buf[4];
davidr99 0:ab4e012489ef 232 if (_promiscuous ||
davidr99 0:ab4e012489ef 233 _rxHeaderTo == _thisAddress ||
davidr99 0:ab4e012489ef 234 _rxHeaderTo == RH_BROADCAST_ADDRESS)
davidr99 0:ab4e012489ef 235 {
davidr99 0:ab4e012489ef 236 _rxGood++;
davidr99 0:ab4e012489ef 237 _rxBufValid = true;
davidr99 0:ab4e012489ef 238 }
davidr99 0:ab4e012489ef 239 }
davidr99 0:ab4e012489ef 240
davidr99 0:ab4e012489ef 241 bool RH_NRF51::available()
davidr99 0:ab4e012489ef 242 {
davidr99 0:ab4e012489ef 243 if (!_rxBufValid)
davidr99 0:ab4e012489ef 244 {
davidr99 0:ab4e012489ef 245 if (_mode == RHModeTx)
davidr99 0:ab4e012489ef 246 return false;
davidr99 0:ab4e012489ef 247 setModeRx();
davidr99 0:ab4e012489ef 248 if (NRF_RADIO->EVENTS_DISABLED == 0U)
davidr99 0:ab4e012489ef 249 return false; // No message yet
davidr99 0:ab4e012489ef 250 if (NRF_RADIO->CRCSTATUS == ((RADIO_CRCSTATUS_CRCSTATUS_CRCError << RADIO_CRCSTATUS_CRCSTATUS_Pos) & RADIO_CRCSTATUS_CRCSTATUS_Msk))
davidr99 0:ab4e012489ef 251 {
davidr99 0:ab4e012489ef 252 // Bad CRC, restart the radio
davidr99 0:ab4e012489ef 253 _rxBad++;
davidr99 0:ab4e012489ef 254 setModeRx();
davidr99 0:ab4e012489ef 255 return false;
davidr99 0:ab4e012489ef 256 }
davidr99 0:ab4e012489ef 257 validateRxBuf();
davidr99 0:ab4e012489ef 258 if (_rxBufValid)
davidr99 0:ab4e012489ef 259 setModeIdle(); // Got one
davidr99 0:ab4e012489ef 260 }
davidr99 0:ab4e012489ef 261 return _rxBufValid;
davidr99 0:ab4e012489ef 262 }
davidr99 0:ab4e012489ef 263
davidr99 0:ab4e012489ef 264 void RH_NRF51::clearRxBuf()
davidr99 0:ab4e012489ef 265 {
davidr99 0:ab4e012489ef 266 _rxBufValid = false;
davidr99 0:ab4e012489ef 267 _buf[0] = 0;
davidr99 0:ab4e012489ef 268 }
davidr99 0:ab4e012489ef 269
davidr99 0:ab4e012489ef 270 bool RH_NRF51::recv(uint8_t* buf, uint8_t* len)
davidr99 0:ab4e012489ef 271 {
davidr99 0:ab4e012489ef 272 if (!available())
davidr99 0:ab4e012489ef 273 return false;
davidr99 0:ab4e012489ef 274 if (buf && len)
davidr99 0:ab4e012489ef 275 {
davidr99 0:ab4e012489ef 276 // Skip the 4 headers that are at the beginning of the rxBuf
davidr99 0:ab4e012489ef 277 // the payload length is the first octet in _buf
davidr99 0:ab4e012489ef 278 if (*len > _buf[0]-RH_NRF51_HEADER_LEN)
davidr99 0:ab4e012489ef 279 *len = _buf[0]-RH_NRF51_HEADER_LEN;
davidr99 0:ab4e012489ef 280 memcpy(buf, _buf+RH_NRF51_HEADER_LEN+1, *len);
davidr99 0:ab4e012489ef 281 }
davidr99 0:ab4e012489ef 282 clearRxBuf(); // This message accepted and cleared
davidr99 0:ab4e012489ef 283 return true;
davidr99 0:ab4e012489ef 284 }
davidr99 0:ab4e012489ef 285
davidr99 0:ab4e012489ef 286 uint8_t RH_NRF51::maxMessageLength()
davidr99 0:ab4e012489ef 287 {
davidr99 0:ab4e012489ef 288 return RH_NRF51_MAX_MESSAGE_LEN;
davidr99 0:ab4e012489ef 289 }
davidr99 0:ab4e012489ef 290
davidr99 0:ab4e012489ef 291 #endif // NRF51