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_NRF905.cpp@0:ab4e012489ef, 2015-10-15 (annotated)
- 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?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| davidr99 | 0:ab4e012489ef | 1 | // RH_NRF905.cpp |
| davidr99 | 0:ab4e012489ef | 2 | // |
| davidr99 | 0:ab4e012489ef | 3 | // Copyright (C) 2012 Mike McCauley |
| davidr99 | 0:ab4e012489ef | 4 | // $Id: RH_NRF905.cpp,v 1.5 2015/08/12 23:18:51 mikem Exp $ |
| davidr99 | 0:ab4e012489ef | 5 | |
| davidr99 | 0:ab4e012489ef | 6 | #include <RH_NRF905.h> |
| davidr99 | 0:ab4e012489ef | 7 | |
| davidr99 | 0:ab4e012489ef | 8 | RH_NRF905::RH_NRF905(PINS chipEnablePin, PINS txEnablePin, PINS slaveSelectPin, RHGenericSPI& spi) |
| davidr99 | 0:ab4e012489ef | 9 | : |
| davidr99 | 0:ab4e012489ef | 10 | RHNRFSPIDriver(slaveSelectPin, spi) |
| davidr99 | 0:ab4e012489ef | 11 | { |
| davidr99 | 0:ab4e012489ef | 12 | _chipEnablePin = chipEnablePin; |
| davidr99 | 0:ab4e012489ef | 13 | _txEnablePin = txEnablePin; |
| davidr99 | 0:ab4e012489ef | 14 | } |
| davidr99 | 0:ab4e012489ef | 15 | |
| davidr99 | 0:ab4e012489ef | 16 | bool RH_NRF905::init() |
| davidr99 | 0:ab4e012489ef | 17 | { |
| davidr99 | 0:ab4e012489ef | 18 | #if defined (__MK20DX128__) || defined (__MK20DX256__) |
| davidr99 | 0:ab4e012489ef | 19 | // Teensy is unreliable at 8MHz: |
| davidr99 | 0:ab4e012489ef | 20 | _spi.setFrequency(RHGenericSPI::Frequency1MHz); |
| davidr99 | 0:ab4e012489ef | 21 | #else |
| davidr99 | 0:ab4e012489ef | 22 | _spi.setFrequency(RHGenericSPI::Frequency8MHz); |
| davidr99 | 0:ab4e012489ef | 23 | #endif |
| davidr99 | 0:ab4e012489ef | 24 | if (!RHNRFSPIDriver::init()) |
| davidr99 | 0:ab4e012489ef | 25 | return false; |
| davidr99 | 0:ab4e012489ef | 26 | |
| davidr99 | 0:ab4e012489ef | 27 | // Initialise the slave select pin and the tx Enable pin |
| davidr99 | 0:ab4e012489ef | 28 | #if (RH_PLATFORM != RH_PLATFORM_MBED) |
| davidr99 | 0:ab4e012489ef | 29 | pinMode(_chipEnablePin, OUTPUT); |
| davidr99 | 0:ab4e012489ef | 30 | pinMode(_txEnablePin, OUTPUT); |
| davidr99 | 0:ab4e012489ef | 31 | #endif |
| davidr99 | 0:ab4e012489ef | 32 | digitalWrite(_chipEnablePin, LOW); |
| davidr99 | 0:ab4e012489ef | 33 | digitalWrite(_txEnablePin, LOW); |
| davidr99 | 0:ab4e012489ef | 34 | |
| davidr99 | 0:ab4e012489ef | 35 | // Configure the chip |
| davidr99 | 0:ab4e012489ef | 36 | // CRC 16 bits enabled. 16MHz crystal freq |
| davidr99 | 0:ab4e012489ef | 37 | spiWriteRegister(RH_NRF905_CONFIG_9, RH_NRF905_CONFIG_9_CRC_EN | RH_NRF905_CONFIG_9_CRC_MODE_16BIT | RH_NRF905_CONFIG_9_XOF_16MHZ); |
| davidr99 | 0:ab4e012489ef | 38 | |
| davidr99 | 0:ab4e012489ef | 39 | // Make sure we are powered down |
| davidr99 | 0:ab4e012489ef | 40 | setModeIdle(); |
| davidr99 | 0:ab4e012489ef | 41 | |
| davidr99 | 0:ab4e012489ef | 42 | // Some innocuous defaults |
| davidr99 | 0:ab4e012489ef | 43 | setChannel(108, LOW); // 433.2 MHz |
| davidr99 | 0:ab4e012489ef | 44 | setRF(RH_NRF905::TransmitPowerm10dBm); |
| davidr99 | 0:ab4e012489ef | 45 | |
| davidr99 | 0:ab4e012489ef | 46 | return true; |
| davidr99 | 0:ab4e012489ef | 47 | } |
| davidr99 | 0:ab4e012489ef | 48 | |
| davidr99 | 0:ab4e012489ef | 49 | // Use the register commands to read and write the registers |
| davidr99 | 0:ab4e012489ef | 50 | uint8_t RH_NRF905::spiReadRegister(uint8_t reg) |
| davidr99 | 0:ab4e012489ef | 51 | { |
| davidr99 | 0:ab4e012489ef | 52 | return spiRead((reg & RH_NRF905_REG_MASK) | RH_NRF905_REG_R_CONFIG); |
| davidr99 | 0:ab4e012489ef | 53 | } |
| davidr99 | 0:ab4e012489ef | 54 | |
| davidr99 | 0:ab4e012489ef | 55 | uint8_t RH_NRF905::spiWriteRegister(uint8_t reg, uint8_t val) |
| davidr99 | 0:ab4e012489ef | 56 | { |
| davidr99 | 0:ab4e012489ef | 57 | return spiWrite((reg & RH_NRF905_REG_MASK) | RH_NRF905_REG_W_CONFIG, val); |
| davidr99 | 0:ab4e012489ef | 58 | } |
| davidr99 | 0:ab4e012489ef | 59 | |
| davidr99 | 0:ab4e012489ef | 60 | uint8_t RH_NRF905::spiBurstReadRegister(uint8_t reg, uint8_t* dest, uint8_t len) |
| davidr99 | 0:ab4e012489ef | 61 | { |
| davidr99 | 0:ab4e012489ef | 62 | return spiBurstRead((reg & RH_NRF905_REG_MASK) | RH_NRF905_REG_R_CONFIG, dest, len); |
| davidr99 | 0:ab4e012489ef | 63 | } |
| davidr99 | 0:ab4e012489ef | 64 | |
| davidr99 | 0:ab4e012489ef | 65 | uint8_t RH_NRF905::spiBurstWriteRegister(uint8_t reg, uint8_t* src, uint8_t len) |
| davidr99 | 0:ab4e012489ef | 66 | { |
| davidr99 | 0:ab4e012489ef | 67 | return spiBurstWrite((reg & RH_NRF905_REG_MASK) | RH_NRF905_REG_W_CONFIG, src, len); |
| davidr99 | 0:ab4e012489ef | 68 | } |
| davidr99 | 0:ab4e012489ef | 69 | |
| davidr99 | 0:ab4e012489ef | 70 | uint8_t RH_NRF905::statusRead() |
| davidr99 | 0:ab4e012489ef | 71 | { |
| davidr99 | 0:ab4e012489ef | 72 | // The status is a byproduct of sending a command |
| davidr99 | 0:ab4e012489ef | 73 | return spiCommand(0); |
| davidr99 | 0:ab4e012489ef | 74 | } |
| davidr99 | 0:ab4e012489ef | 75 | |
| davidr99 | 0:ab4e012489ef | 76 | bool RH_NRF905::setChannel(uint16_t channel, bool hiFrequency) |
| davidr99 | 0:ab4e012489ef | 77 | { |
| davidr99 | 0:ab4e012489ef | 78 | spiWriteRegister(RH_NRF905_CONFIG_0, channel & RH_NRF905_CONFIG_0_CH_NO); |
| davidr99 | 0:ab4e012489ef | 79 | // Set or clear the high bit of the channel |
| davidr99 | 0:ab4e012489ef | 80 | uint8_t bit8 = (channel >> 8) & 0x01; |
| davidr99 | 0:ab4e012489ef | 81 | uint8_t reg1 = spiReadRegister(RH_NRF905_CONFIG_1); |
| davidr99 | 0:ab4e012489ef | 82 | reg1 = (reg1 & ~0x01) | bit8; |
| davidr99 | 0:ab4e012489ef | 83 | // Set or clear the HFREQ_PLL bit |
| davidr99 | 0:ab4e012489ef | 84 | reg1 &= ~RH_NRF905_CONFIG_1_HFREQ_PLL; |
| davidr99 | 0:ab4e012489ef | 85 | if (hiFrequency) |
| davidr99 | 0:ab4e012489ef | 86 | reg1 |= RH_NRF905_CONFIG_1_HFREQ_PLL; |
| davidr99 | 0:ab4e012489ef | 87 | spiWriteRegister(RH_NRF905_CONFIG_1, reg1); |
| davidr99 | 0:ab4e012489ef | 88 | return true; |
| davidr99 | 0:ab4e012489ef | 89 | } |
| davidr99 | 0:ab4e012489ef | 90 | |
| davidr99 | 0:ab4e012489ef | 91 | bool RH_NRF905::setNetworkAddress(uint8_t* address, uint8_t len) |
| davidr99 | 0:ab4e012489ef | 92 | { |
| davidr99 | 0:ab4e012489ef | 93 | if (len < 1 || len > 4) |
| davidr99 | 0:ab4e012489ef | 94 | return false; |
| davidr99 | 0:ab4e012489ef | 95 | // Set RX_AFW and TX_AFW |
| davidr99 | 0:ab4e012489ef | 96 | spiWriteRegister(RH_NRF905_CONFIG_2, len | (len << 4)); |
| davidr99 | 0:ab4e012489ef | 97 | spiBurstWrite(RH_NRF905_REG_W_TX_ADDRESS, address, len); |
| davidr99 | 0:ab4e012489ef | 98 | spiBurstWriteRegister(RH_NRF905_CONFIG_5, address, len); |
| davidr99 | 0:ab4e012489ef | 99 | return true; |
| davidr99 | 0:ab4e012489ef | 100 | } |
| davidr99 | 0:ab4e012489ef | 101 | |
| davidr99 | 0:ab4e012489ef | 102 | bool RH_NRF905::setRF(TransmitPower power) |
| davidr99 | 0:ab4e012489ef | 103 | { |
| davidr99 | 0:ab4e012489ef | 104 | // Enum definitions of power are the same numerical values as the register |
| davidr99 | 0:ab4e012489ef | 105 | spiWriteRegister(RH_NRF905_CONFIG_1_PA_PWR, power); |
| davidr99 | 0:ab4e012489ef | 106 | return true; |
| davidr99 | 0:ab4e012489ef | 107 | } |
| davidr99 | 0:ab4e012489ef | 108 | |
| davidr99 | 0:ab4e012489ef | 109 | void RH_NRF905::setModeIdle() |
| davidr99 | 0:ab4e012489ef | 110 | { |
| davidr99 | 0:ab4e012489ef | 111 | if (_mode != RHModeIdle) |
| davidr99 | 0:ab4e012489ef | 112 | { |
| davidr99 | 0:ab4e012489ef | 113 | digitalWrite(_chipEnablePin, LOW); |
| davidr99 | 0:ab4e012489ef | 114 | digitalWrite(_txEnablePin, LOW); |
| davidr99 | 0:ab4e012489ef | 115 | _mode = RHModeIdle; |
| davidr99 | 0:ab4e012489ef | 116 | } |
| davidr99 | 0:ab4e012489ef | 117 | } |
| davidr99 | 0:ab4e012489ef | 118 | |
| davidr99 | 0:ab4e012489ef | 119 | void RH_NRF905::setModeRx() |
| davidr99 | 0:ab4e012489ef | 120 | { |
| davidr99 | 0:ab4e012489ef | 121 | if (_mode != RHModeRx) |
| davidr99 | 0:ab4e012489ef | 122 | { |
| davidr99 | 0:ab4e012489ef | 123 | digitalWrite(_txEnablePin, LOW); |
| davidr99 | 0:ab4e012489ef | 124 | digitalWrite(_chipEnablePin, HIGH); |
| davidr99 | 0:ab4e012489ef | 125 | _mode = RHModeRx; |
| davidr99 | 0:ab4e012489ef | 126 | } |
| davidr99 | 0:ab4e012489ef | 127 | } |
| davidr99 | 0:ab4e012489ef | 128 | |
| davidr99 | 0:ab4e012489ef | 129 | void RH_NRF905::setModeTx() |
| davidr99 | 0:ab4e012489ef | 130 | { |
| davidr99 | 0:ab4e012489ef | 131 | if (_mode != RHModeTx) |
| davidr99 | 0:ab4e012489ef | 132 | { |
| davidr99 | 0:ab4e012489ef | 133 | // Its the high transition that puts us into TX mode |
| davidr99 | 0:ab4e012489ef | 134 | digitalWrite(_txEnablePin, HIGH); |
| davidr99 | 0:ab4e012489ef | 135 | digitalWrite(_chipEnablePin, HIGH); |
| davidr99 | 0:ab4e012489ef | 136 | _mode = RHModeTx; |
| davidr99 | 0:ab4e012489ef | 137 | } |
| davidr99 | 0:ab4e012489ef | 138 | } |
| davidr99 | 0:ab4e012489ef | 139 | |
| davidr99 | 0:ab4e012489ef | 140 | bool RH_NRF905::send(const uint8_t* data, uint8_t len) |
| davidr99 | 0:ab4e012489ef | 141 | { |
| davidr99 | 0:ab4e012489ef | 142 | if (len > RH_NRF905_MAX_MESSAGE_LEN) |
| davidr99 | 0:ab4e012489ef | 143 | return false; |
| davidr99 | 0:ab4e012489ef | 144 | // Set up the headers |
| davidr99 | 0:ab4e012489ef | 145 | _buf[0] = _txHeaderTo; |
| davidr99 | 0:ab4e012489ef | 146 | _buf[1] = _txHeaderFrom; |
| davidr99 | 0:ab4e012489ef | 147 | _buf[2] = _txHeaderId; |
| davidr99 | 0:ab4e012489ef | 148 | _buf[3] = _txHeaderFlags; |
| davidr99 | 0:ab4e012489ef | 149 | _buf[4] = len; |
| davidr99 | 0:ab4e012489ef | 150 | memcpy(_buf+RH_NRF905_HEADER_LEN, data, len); |
| davidr99 | 0:ab4e012489ef | 151 | spiBurstWrite(RH_NRF905_REG_W_TX_PAYLOAD, _buf, len + RH_NRF905_HEADER_LEN); |
| davidr99 | 0:ab4e012489ef | 152 | setModeTx(); |
| davidr99 | 0:ab4e012489ef | 153 | // Radio will return to Standby mode after transmission is complete |
| davidr99 | 0:ab4e012489ef | 154 | _txGood++; |
| davidr99 | 0:ab4e012489ef | 155 | return true; |
| davidr99 | 0:ab4e012489ef | 156 | } |
| davidr99 | 0:ab4e012489ef | 157 | |
| davidr99 | 0:ab4e012489ef | 158 | bool RH_NRF905::waitPacketSent() |
| davidr99 | 0:ab4e012489ef | 159 | { |
| davidr99 | 0:ab4e012489ef | 160 | if (_mode != RHModeTx) |
| davidr99 | 0:ab4e012489ef | 161 | return false; |
| davidr99 | 0:ab4e012489ef | 162 | |
| davidr99 | 0:ab4e012489ef | 163 | while (!(statusRead() & RH_NRF905_STATUS_DR)) |
| davidr99 | 0:ab4e012489ef | 164 | YIELD; |
| davidr99 | 0:ab4e012489ef | 165 | setModeIdle(); |
| davidr99 | 0:ab4e012489ef | 166 | return true; |
| davidr99 | 0:ab4e012489ef | 167 | } |
| davidr99 | 0:ab4e012489ef | 168 | |
| davidr99 | 0:ab4e012489ef | 169 | bool RH_NRF905::isSending() |
| davidr99 | 0:ab4e012489ef | 170 | { |
| davidr99 | 0:ab4e012489ef | 171 | if (_mode != RHModeTx) |
| davidr99 | 0:ab4e012489ef | 172 | return false; |
| davidr99 | 0:ab4e012489ef | 173 | |
| davidr99 | 0:ab4e012489ef | 174 | return !(statusRead() & RH_NRF905_STATUS_DR); |
| davidr99 | 0:ab4e012489ef | 175 | } |
| davidr99 | 0:ab4e012489ef | 176 | |
| davidr99 | 0:ab4e012489ef | 177 | bool RH_NRF905::printRegister(uint8_t reg) |
| davidr99 | 0:ab4e012489ef | 178 | { |
| davidr99 | 0:ab4e012489ef | 179 | #ifdef RH_HAVE_SERIAL |
| davidr99 | 0:ab4e012489ef | 180 | Serial.print(reg, HEX); |
| davidr99 | 0:ab4e012489ef | 181 | Serial.print(": "); |
| davidr99 | 0:ab4e012489ef | 182 | Serial.println(spiReadRegister(reg), HEX); |
| davidr99 | 0:ab4e012489ef | 183 | #endif |
| davidr99 | 0:ab4e012489ef | 184 | |
| davidr99 | 0:ab4e012489ef | 185 | return true; |
| davidr99 | 0:ab4e012489ef | 186 | } |
| davidr99 | 0:ab4e012489ef | 187 | |
| davidr99 | 0:ab4e012489ef | 188 | bool RH_NRF905::printRegisters() |
| davidr99 | 0:ab4e012489ef | 189 | { |
| davidr99 | 0:ab4e012489ef | 190 | uint8_t registers[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09}; |
| davidr99 | 0:ab4e012489ef | 191 | |
| davidr99 | 0:ab4e012489ef | 192 | uint8_t i; |
| davidr99 | 0:ab4e012489ef | 193 | for (i = 0; i < sizeof(registers); i++) |
| davidr99 | 0:ab4e012489ef | 194 | printRegister(registers[i]); |
| davidr99 | 0:ab4e012489ef | 195 | return true; |
| davidr99 | 0:ab4e012489ef | 196 | } |
| davidr99 | 0:ab4e012489ef | 197 | |
| davidr99 | 0:ab4e012489ef | 198 | // Check whether the latest received message is complete and uncorrupted |
| davidr99 | 0:ab4e012489ef | 199 | void RH_NRF905::validateRxBuf() |
| davidr99 | 0:ab4e012489ef | 200 | { |
| davidr99 | 0:ab4e012489ef | 201 | // Check the length |
| davidr99 | 0:ab4e012489ef | 202 | uint8_t len = _buf[4]; |
| davidr99 | 0:ab4e012489ef | 203 | if (len > RH_NRF905_MAX_MESSAGE_LEN) |
| davidr99 | 0:ab4e012489ef | 204 | return; // Silly LEN header |
| davidr99 | 0:ab4e012489ef | 205 | |
| davidr99 | 0:ab4e012489ef | 206 | // Extract the 4 headers |
| davidr99 | 0:ab4e012489ef | 207 | _rxHeaderTo = _buf[0]; |
| davidr99 | 0:ab4e012489ef | 208 | _rxHeaderFrom = _buf[1]; |
| davidr99 | 0:ab4e012489ef | 209 | _rxHeaderId = _buf[2]; |
| davidr99 | 0:ab4e012489ef | 210 | _rxHeaderFlags = _buf[3]; |
| davidr99 | 0:ab4e012489ef | 211 | if (_promiscuous || |
| davidr99 | 0:ab4e012489ef | 212 | _rxHeaderTo == _thisAddress || |
| davidr99 | 0:ab4e012489ef | 213 | _rxHeaderTo == RH_BROADCAST_ADDRESS) |
| davidr99 | 0:ab4e012489ef | 214 | { |
| davidr99 | 0:ab4e012489ef | 215 | _rxGood++; |
| davidr99 | 0:ab4e012489ef | 216 | _bufLen = len + RH_NRF905_HEADER_LEN; // _buf still includes the headers |
| davidr99 | 0:ab4e012489ef | 217 | _rxBufValid = true; |
| davidr99 | 0:ab4e012489ef | 218 | } |
| davidr99 | 0:ab4e012489ef | 219 | } |
| davidr99 | 0:ab4e012489ef | 220 | |
| davidr99 | 0:ab4e012489ef | 221 | bool RH_NRF905::available() |
| davidr99 | 0:ab4e012489ef | 222 | { |
| davidr99 | 0:ab4e012489ef | 223 | if (!_rxBufValid) |
| davidr99 | 0:ab4e012489ef | 224 | { |
| davidr99 | 0:ab4e012489ef | 225 | if (_mode == RHModeTx) |
| davidr99 | 0:ab4e012489ef | 226 | return false; |
| davidr99 | 0:ab4e012489ef | 227 | setModeRx(); |
| davidr99 | 0:ab4e012489ef | 228 | if (!(statusRead() & RH_NRF905_STATUS_DR)) |
| davidr99 | 0:ab4e012489ef | 229 | return false; |
| davidr99 | 0:ab4e012489ef | 230 | // Get the message into the RX buffer, so we can inspect the headers |
| davidr99 | 0:ab4e012489ef | 231 | // we still dont know how long is the user message |
| davidr99 | 0:ab4e012489ef | 232 | spiBurstRead(RH_NRF905_REG_R_RX_PAYLOAD, _buf, RH_NRF905_MAX_PAYLOAD_LEN); |
| davidr99 | 0:ab4e012489ef | 233 | validateRxBuf(); |
| davidr99 | 0:ab4e012489ef | 234 | if (_rxBufValid) |
| davidr99 | 0:ab4e012489ef | 235 | setModeIdle(); // Got one |
| davidr99 | 0:ab4e012489ef | 236 | } |
| davidr99 | 0:ab4e012489ef | 237 | return _rxBufValid; |
| davidr99 | 0:ab4e012489ef | 238 | } |
| davidr99 | 0:ab4e012489ef | 239 | |
| davidr99 | 0:ab4e012489ef | 240 | void RH_NRF905::clearRxBuf() |
| davidr99 | 0:ab4e012489ef | 241 | { |
| davidr99 | 0:ab4e012489ef | 242 | _rxBufValid = false; |
| davidr99 | 0:ab4e012489ef | 243 | _bufLen = 0; |
| davidr99 | 0:ab4e012489ef | 244 | } |
| davidr99 | 0:ab4e012489ef | 245 | |
| davidr99 | 0:ab4e012489ef | 246 | bool RH_NRF905::recv(uint8_t* buf, uint8_t* len) |
| davidr99 | 0:ab4e012489ef | 247 | { |
| davidr99 | 0:ab4e012489ef | 248 | if (!available()) |
| davidr99 | 0:ab4e012489ef | 249 | return false; |
| davidr99 | 0:ab4e012489ef | 250 | if (buf && len) |
| davidr99 | 0:ab4e012489ef | 251 | { |
| davidr99 | 0:ab4e012489ef | 252 | // Skip the 4 headers that are at the beginning of the rxBuf |
| davidr99 | 0:ab4e012489ef | 253 | if (*len > _bufLen-RH_NRF905_HEADER_LEN) |
| davidr99 | 0:ab4e012489ef | 254 | *len = _bufLen-RH_NRF905_HEADER_LEN; |
| davidr99 | 0:ab4e012489ef | 255 | memcpy(buf, _buf+RH_NRF905_HEADER_LEN, *len); |
| davidr99 | 0:ab4e012489ef | 256 | } |
| davidr99 | 0:ab4e012489ef | 257 | clearRxBuf(); // This message accepted and cleared |
| davidr99 | 0:ab4e012489ef | 258 | return true; |
| davidr99 | 0:ab4e012489ef | 259 | } |
| davidr99 | 0:ab4e012489ef | 260 | |
| davidr99 | 0:ab4e012489ef | 261 | uint8_t RH_NRF905::maxMessageLength() |
| davidr99 | 0:ab4e012489ef | 262 | { |
| davidr99 | 0:ab4e012489ef | 263 | return RH_NRF905_MAX_MESSAGE_LEN; |
| davidr99 | 0:ab4e012489ef | 264 | } |
