|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266 |
- // RH_NRF905.cpp
- //
- // Copyright (C) 2012 Mike McCauley
- // $Id: RH_NRF905.cpp,v 1.6 2015/12/11 01:10:24 mikem Exp $
-
- #include <RH_NRF905.h>
-
- RH_NRF905::RH_NRF905(uint8_t chipEnablePin, uint8_t txEnablePin, uint8_t slaveSelectPin, RHGenericSPI& spi)
- :
- RHNRFSPIDriver(slaveSelectPin, spi)
- {
- _chipEnablePin = chipEnablePin;
- _txEnablePin = txEnablePin;
- }
-
- bool RH_NRF905::init()
- {
- #if defined (__MK20DX128__) || defined (__MK20DX256__)
- // Teensy is unreliable at 8MHz:
- _spi.setFrequency(RHGenericSPI::Frequency1MHz);
- #else
- _spi.setFrequency(RHGenericSPI::Frequency8MHz);
- #endif
- if (!RHNRFSPIDriver::init())
- return false;
-
- // Initialise the slave select pin and the tx Enable pin
- pinMode(_chipEnablePin, OUTPUT);
- pinMode(_txEnablePin, OUTPUT);
- digitalWrite(_chipEnablePin, LOW);
- digitalWrite(_txEnablePin, LOW);
-
- // Configure the chip
- // CRC 16 bits enabled. 16MHz crystal freq
- spiWriteRegister(RH_NRF905_CONFIG_9, RH_NRF905_CONFIG_9_CRC_EN | RH_NRF905_CONFIG_9_CRC_MODE_16BIT | RH_NRF905_CONFIG_9_XOF_16MHZ);
-
- // Make sure we are powered down
- setModeIdle();
-
- // Some innocuous defaults
- setChannel(108, LOW); // 433.2 MHz
- setRF(RH_NRF905::TransmitPowerm10dBm);
-
- return true;
- }
-
- // Use the register commands to read and write the registers
- uint8_t RH_NRF905::spiReadRegister(uint8_t reg)
- {
- return spiRead((reg & RH_NRF905_REG_MASK) | RH_NRF905_REG_R_CONFIG);
- }
-
- uint8_t RH_NRF905::spiWriteRegister(uint8_t reg, uint8_t val)
- {
- return spiWrite((reg & RH_NRF905_REG_MASK) | RH_NRF905_REG_W_CONFIG, val);
- }
-
- uint8_t RH_NRF905::spiBurstReadRegister(uint8_t reg, uint8_t* dest, uint8_t len)
- {
- return spiBurstRead((reg & RH_NRF905_REG_MASK) | RH_NRF905_REG_R_CONFIG, dest, len);
- }
-
- uint8_t RH_NRF905::spiBurstWriteRegister(uint8_t reg, uint8_t* src, uint8_t len)
- {
- return spiBurstWrite((reg & RH_NRF905_REG_MASK) | RH_NRF905_REG_W_CONFIG, src, len);
- }
-
- uint8_t RH_NRF905::statusRead()
- {
- // The status is a byproduct of sending a command
- return spiCommand(0);
- }
-
- bool RH_NRF905::setChannel(uint16_t channel, bool hiFrequency)
- {
- spiWriteRegister(RH_NRF905_CONFIG_0, channel & RH_NRF905_CONFIG_0_CH_NO);
- // Set or clear the high bit of the channel
- uint8_t bit8 = (channel >> 8) & 0x01;
- uint8_t reg1 = spiReadRegister(RH_NRF905_CONFIG_1);
- reg1 = (reg1 & ~0x01) | bit8;
- // Set or clear the HFREQ_PLL bit
- reg1 &= ~RH_NRF905_CONFIG_1_HFREQ_PLL;
- if (hiFrequency)
- reg1 |= RH_NRF905_CONFIG_1_HFREQ_PLL;
- spiWriteRegister(RH_NRF905_CONFIG_1, reg1);
- return true;
- }
-
- bool RH_NRF905::setNetworkAddress(uint8_t* address, uint8_t len)
- {
- if (len < 1 || len > 4)
- return false;
- // Set RX_AFW and TX_AFW
- spiWriteRegister(RH_NRF905_CONFIG_2, len | (len << 4));
- spiBurstWrite(RH_NRF905_REG_W_TX_ADDRESS, address, len);
- spiBurstWriteRegister(RH_NRF905_CONFIG_5, address, len);
- return true;
- }
-
- bool RH_NRF905::setRF(TransmitPower power)
- {
- // Enum definitions of power are the same numerical values as the register
- uint8_t reg1 = spiReadRegister(RH_NRF905_CONFIG_1);
- reg1 &= ~RH_NRF905_CONFIG_1_PA_PWR;
- reg1 |= ((power & 0x3) << 2) & RH_NRF905_CONFIG_1_PA_PWR;
- spiWriteRegister(RH_NRF905_CONFIG_1, reg1);
- return true;
- }
-
- void RH_NRF905::setModeIdle()
- {
- if (_mode != RHModeIdle)
- {
- digitalWrite(_chipEnablePin, LOW);
- digitalWrite(_txEnablePin, LOW);
- _mode = RHModeIdle;
- }
- }
-
- void RH_NRF905::setModeRx()
- {
- if (_mode != RHModeRx)
- {
- digitalWrite(_txEnablePin, LOW);
- digitalWrite(_chipEnablePin, HIGH);
- _mode = RHModeRx;
- }
- }
-
- void RH_NRF905::setModeTx()
- {
- if (_mode != RHModeTx)
- {
- // Its the high transition that puts us into TX mode
- digitalWrite(_txEnablePin, HIGH);
- digitalWrite(_chipEnablePin, HIGH);
- _mode = RHModeTx;
- }
- }
-
- bool RH_NRF905::send(const uint8_t* data, uint8_t len)
- {
- if (len > RH_NRF905_MAX_MESSAGE_LEN)
- return false;
- // Set up the headers
- _buf[0] = _txHeaderTo;
- _buf[1] = _txHeaderFrom;
- _buf[2] = _txHeaderId;
- _buf[3] = _txHeaderFlags;
- _buf[4] = len;
- memcpy(_buf+RH_NRF905_HEADER_LEN, data, len);
- spiBurstWrite(RH_NRF905_REG_W_TX_PAYLOAD, _buf, len + RH_NRF905_HEADER_LEN);
- setModeTx();
- // Radio will return to Standby mode after transmission is complete
- _txGood++;
- return true;
- }
-
- bool RH_NRF905::waitPacketSent()
- {
- if (_mode != RHModeTx)
- return false;
-
- while (!(statusRead() & RH_NRF905_STATUS_DR))
- YIELD;
- setModeIdle();
- return true;
- }
-
- bool RH_NRF905::isSending()
- {
- if (_mode != RHModeTx)
- return false;
-
- return !(statusRead() & RH_NRF905_STATUS_DR);
- }
-
- bool RH_NRF905::printRegister(uint8_t reg)
- {
- #ifdef RH_HAVE_SERIAL
- Serial.print(reg, HEX);
- Serial.print(": ");
- Serial.println(spiReadRegister(reg), HEX);
- #endif
-
- return true;
- }
-
- bool RH_NRF905::printRegisters()
- {
- uint8_t registers[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09};
-
- uint8_t i;
- for (i = 0; i < sizeof(registers); i++)
- printRegister(registers[i]);
- return true;
- }
-
- // Check whether the latest received message is complete and uncorrupted
- void RH_NRF905::validateRxBuf()
- {
- // Check the length
- uint8_t len = _buf[4];
- if (len > RH_NRF905_MAX_MESSAGE_LEN)
- return; // Silly LEN header
-
- // Extract the 4 headers
- _rxHeaderTo = _buf[0];
- _rxHeaderFrom = _buf[1];
- _rxHeaderId = _buf[2];
- _rxHeaderFlags = _buf[3];
- if (_promiscuous ||
- _rxHeaderTo == _thisAddress ||
- _rxHeaderTo == RH_BROADCAST_ADDRESS)
- {
- _rxGood++;
- _bufLen = len + RH_NRF905_HEADER_LEN; // _buf still includes the headers
- _rxBufValid = true;
- }
- }
-
- bool RH_NRF905::available()
- {
- if (!_rxBufValid)
- {
- if (_mode == RHModeTx)
- return false;
- setModeRx();
- if (!(statusRead() & RH_NRF905_STATUS_DR))
- return false;
- // Get the message into the RX buffer, so we can inspect the headers
- // we still dont know how long is the user message
- spiBurstRead(RH_NRF905_REG_R_RX_PAYLOAD, _buf, RH_NRF905_MAX_PAYLOAD_LEN);
- validateRxBuf();
- if (_rxBufValid)
- setModeIdle(); // Got one
-
- }
- return _rxBufValid;
- }
-
- void RH_NRF905::clearRxBuf()
- {
- _rxBufValid = false;
- _bufLen = 0;
- }
-
- bool RH_NRF905::recv(uint8_t* buf, uint8_t* len)
- {
- if (!available())
- return false;
- if (buf && len)
- {
- // Skip the 4 headers that are at the beginning of the rxBuf
- if (*len > _bufLen-RH_NRF905_HEADER_LEN)
- *len = _bufLen-RH_NRF905_HEADER_LEN;
- memcpy(buf, _buf+RH_NRF905_HEADER_LEN, *len);
- }
- clearRxBuf(); // This message accepted and cleared
- return true;
- }
-
- uint8_t RH_NRF905::maxMessageLength()
- {
- return RH_NRF905_MAX_MESSAGE_LEN;
- }
|