Mongoose_Arduino_RadioHead/src/RH_NRF905.cpp

267 lines
6.6 KiB
C++

// 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;
}