V148
Fork of RadioHead-148 by
RH_NRF905.cpp@1:b7641da2b203, 2017-10-25 (annotated)
- Committer:
- ilkaykozak
- Date:
- Wed Oct 25 05:14:09 2017 +0000
- Revision:
- 1:b7641da2b203
- Parent:
- 0:ab4e012489ef
V148
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 | } |