Merge pull request #143 from Atalonica/master

Custom SPI support
This commit is contained in:
Felix Rusu 2020-06-03 15:19:04 -04:00 committed by GitHub
commit b8b22cec79
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 66 additions and 61 deletions

View File

@ -41,7 +41,7 @@ uint8_t RFM69::ACK_RECEIVED; // should be polled immediately after sending a pac
int16_t RFM69::RSSI; // most accurate RSSI during reception (closest to the reception)
volatile bool RFM69::_haveData;
RFM69::RFM69(uint8_t slaveSelectPin, uint8_t interruptPin, bool isRFM69HW)
RFM69::RFM69(uint8_t slaveSelectPin, uint8_t interruptPin, bool isRFM69HW, SPIClass *spi)
{
_slaveSelectPin = slaveSelectPin;
_interruptPin = interruptPin;
@ -49,6 +49,7 @@ RFM69::RFM69(uint8_t slaveSelectPin, uint8_t interruptPin, bool isRFM69HW)
_spyMode = false;
_powerLevel = 31;
_isRFM69HW = isRFM69HW;
_spi = spi;
#if defined(RF69_LISTENMODE_ENABLE)
_isHighSpeed = true;
_haveEncryptKey = false;
@ -111,13 +112,16 @@ bool RFM69::initialize(uint8_t freqBand, uint16_t nodeID, uint8_t networkID)
digitalWrite(_slaveSelectPin, HIGH);
pinMode(_slaveSelectPin, OUTPUT);
if(_spi == nullptr){
_spi = &SPI;
}
#if defined(ESP32)
SPI.begin(18,19,23,5); //SPI3 (SCK,MISO,MOSI,CS)
//SPI.begin(14,12,13,15); //SPI2 (SCK,MISO,MOSI,CS)
_spi->begin(18,19,23,5); //SPI3 (SCK,MISO,MOSI,CS)
//_spi->begin(14,12,13,15); //SPI2 (SCK,MISO,MOSI,CS)
#else
SPI.begin();
#endif
_spi->begin();
#endif
#ifdef SPI_HAS_TRANSACTION
_settings = SPISettings(8000000, MSBFIRST, SPI_MODE0);
#endif
@ -330,14 +334,14 @@ void RFM69::sendFrame(uint16_t toAddress, const void* buffer, uint8_t bufferSize
// write to FIFO
select();
SPI.transfer(REG_FIFO | 0x80);
SPI.transfer(bufferSize + 3);
SPI.transfer((uint8_t)toAddress);
SPI.transfer((uint8_t)_address);
SPI.transfer(CTLbyte);
_spi->transfer(REG_FIFO | 0x80);
_spi->transfer(bufferSize + 3);
_spi->transfer((uint8_t)toAddress);
_spi->transfer((uint8_t)_address);
_spi->transfer(CTLbyte);
for (uint8_t i = 0; i < bufferSize; i++)
SPI.transfer(((uint8_t*) buffer)[i]);
_spi->transfer(((uint8_t*) buffer)[i]);
unselect();
// no need to wait for transmit mode to be ready since its handled by the radio
@ -354,12 +358,12 @@ void RFM69::interruptHandler() {
{
setMode(RF69_MODE_STANDBY);
select();
SPI.transfer(REG_FIFO & 0x7F);
PAYLOADLEN = SPI.transfer(0);
_spi->transfer(REG_FIFO & 0x7F);
PAYLOADLEN = _spi->transfer(0);
PAYLOADLEN = PAYLOADLEN > 66 ? 66 : PAYLOADLEN; // precaution
TARGETID = SPI.transfer(0);
SENDERID = SPI.transfer(0);
uint8_t CTLbyte = SPI.transfer(0);
TARGETID = _spi->transfer(0);
SENDERID = _spi->transfer(0);
uint8_t CTLbyte = _spi->transfer(0);
TARGETID |= (uint16_t(CTLbyte) & 0x0C) << 6; //10 bit address (most significant 2 bits stored in bits(2,3) of CTL byte
SENDERID |= (uint16_t(CTLbyte) & 0x03) << 8; //10 bit address (most sifnigicant 2 bits stored in bits(0,1) of CTL byte
@ -377,7 +381,7 @@ void RFM69::interruptHandler() {
ACK_REQUESTED = CTLbyte & RFM69_CTL_REQACK; // extract ACK-requested flag
interruptHook(CTLbyte); // TWS: hook to derived class interrupt function
for (uint8_t i = 0; i < DATALEN; i++) DATA[i] = SPI.transfer(0);
for (uint8_t i = 0; i < DATALEN; i++) DATA[i] = _spi->transfer(0);
DATA[DATALEN] = 0; // add null at end of string // add null at end of string
unselect();
@ -440,9 +444,9 @@ void RFM69::encrypt(const char* key) {
memcpy(_encryptKey, key, 16);
#endif
select();
SPI.transfer(REG_AESKEY1 | 0x80);
_spi->transfer(REG_AESKEY1 | 0x80);
for (uint8_t i = 0; i < 16; i++)
SPI.transfer(key[i]);
_spi->transfer(key[i]);
unselect();
}
writeReg(REG_PACKETCONFIG2, (readReg(REG_PACKETCONFIG2) & 0xFE) | (key ? 1 : 0));
@ -465,8 +469,8 @@ int16_t RFM69::readRSSI(bool forceTrigger) {
uint8_t RFM69::readReg(uint8_t addr)
{
select();
SPI.transfer(addr & 0x7F);
uint8_t regval = SPI.transfer(0);
_spi->transfer(addr & 0x7F);
uint8_t regval = _spi->transfer(0);
unselect();
return regval;
}
@ -474,8 +478,8 @@ uint8_t RFM69::readReg(uint8_t addr)
void RFM69::writeReg(uint8_t addr, uint8_t value)
{
select();
SPI.transfer(addr | 0x80);
SPI.transfer(value);
_spi->transfer(addr | 0x80);
_spi->transfer(value);
unselect();
}
@ -488,15 +492,15 @@ void RFM69::select() {
#endif
#ifdef SPI_HAS_TRANSACTION
SPI.beginTransaction(_settings);
_spi->beginTransaction(_settings);
#else
// set RFM69 SPI settings explicitly
SPI.setDataMode(SPI_MODE0);
SPI.setBitOrder(MSBFIRST);
_spi->setDataMode(SPI_MODE0);
_spi->setBitOrder(MSBFIRST);
#ifdef defined(__SAMD51__)
SPI.setClockDivider(SPI_CLOCK_DIV16);
_spi->setClockDivider(SPI_CLOCK_DIV16);
#else
SPI.setClockDivider(SPI_CLOCK_DIV2);
_spi->setClockDivider(SPI_CLOCK_DIV2);
#endif
#endif
digitalWrite(_slaveSelectPin, LOW);
@ -506,7 +510,7 @@ void RFM69::select() {
void RFM69::unselect() {
digitalWrite(_slaveSelectPin, HIGH);
#ifdef SPI_HAS_TRANSACTION
SPI.endTransaction();
_spi->endTransaction();
#endif
// restore SPI settings to what they were before talking to RFM69
#if defined (SPCR) && defined (SPSR)
@ -578,8 +582,8 @@ void RFM69::readAllRegs()
for (uint8_t regAddr = 1; regAddr <= 0x4F; regAddr++)
{
select();
SPI.transfer(regAddr & 0x7F); // send address + r/w bit
regVal = SPI.transfer(0);
_spi->transfer(regAddr & 0x7F); // send address + r/w bit
regVal = _spi->transfer(0);
unselect();
Serial.print(regAddr, HEX);
@ -1058,10 +1062,10 @@ void RFM69::listenModeInterruptHandler(void)
burstRemaining.l = 0;
SPI.transfer(REG_FIFO & 0x7F);
PAYLOADLEN = SPI.transfer(0);
_spi->transfer(REG_FIFO & 0x7F);
PAYLOADLEN = _spi->transfer(0);
PAYLOADLEN = PAYLOADLEN > 64 ? 64 : PAYLOADLEN; // precaution
TARGETID = SPI.transfer(0);
TARGETID = _spi->transfer(0);
if(!(_spyMode || TARGETID == _address || TARGETID == RF69_BROADCAST_ADDR) // match this node's address, or broadcast address or anything in spy mode
|| PAYLOADLEN < 3) // address situation could receive packets that are malformed and don't fit this library's extra fields
{
@ -1071,13 +1075,13 @@ void RFM69::listenModeInterruptHandler(void)
// We've read the target, and will read the sender id and two time offset bytes for a total of 4 bytes
DATALEN = PAYLOADLEN - 4;
SENDERID = SPI.transfer(0);
burstRemaining.b[0] = SPI.transfer(0); // and get the time remaining
burstRemaining.b[1] = SPI.transfer(0);
SENDERID = spi->transfer(0);
burstRemaining.b[0] = _spi->transfer(0); // and get the time remaining
burstRemaining.b[1] = _spi->transfer(0);
RF69_LISTEN_BURST_REMAINING_MS = burstRemaining.l;
for (uint8_t i = 0; i < DATALEN; i++)
DATA[i] = SPI.transfer(0);
DATA[i] = _spi->transfer(0);
if (DATALEN < RF69_MAX_DATA_LEN)
DATA[DATALEN] = 0; // add null at end of string
@ -1184,17 +1188,17 @@ void RFM69::listenModeSendBurst( uint8_t targetNode, const void* buffer, uint8_t
noInterrupts();
// write to FIFO
select();
SPI.transfer(REG_FIFO | 0x80);
SPI.transfer(size + 4); // two bytes for target and sender node, two bytes for the burst time remaining
SPI.transfer(targetNode);
SPI.transfer(_address);
_spi->transfer(REG_FIFO | 0x80);
_spi->transfer(size + 4); // two bytes for target and sender node, two bytes for the burst time remaining
_spi->transfer(targetNode);
_spi->transfer(_address);
// We send the burst time remaining with the packet so the receiver knows how long to wait before trying to reply
SPI.transfer(timeRemaining.b[0]);
SPI.transfer(timeRemaining.b[1]);
_spi->transfer(timeRemaining.b[0]);
_spi->transfer(timeRemaining.b[1]);
for (uint8_t i = 0; i < size; i++) {
SPI.transfer(((uint8_t*) buffer)[i]);
_spi->transfer(((uint8_t*) buffer)[i]);
}
unselect();

View File

@ -197,7 +197,7 @@ class RFM69 {
RFM69(uint8_t slaveSelectPin, uint8_t interruptPin, bool isRFM69HW, uint8_t interruptNum) //interruptNum is now deprecated
: RFM69(slaveSelectPin, interruptPin, isRFM69HW){};
RFM69(uint8_t slaveSelectPin=RF69_SPI_CS, uint8_t interruptPin=RF69_IRQ_PIN, bool isRFM69HW=false);
RFM69(uint8_t slaveSelectPin=RF69_SPI_CS, uint8_t interruptPin=RF69_IRQ_PIN, bool isRFM69HW=false, SPIClass *spi=nullptr);
bool initialize(uint8_t freqBand, uint16_t ID, uint8_t networkID=1);
void setAddress(uint16_t addr);
@ -250,6 +250,7 @@ class RFM69 {
bool _spyMode;
uint8_t _powerLevel;
bool _isRFM69HW;
SPIClass *_spi;
#if defined (SPCR) && defined (SPSR)
uint8_t _SPCR;
uint8_t _SPSR;

View File

@ -99,29 +99,29 @@ void RFM69_ATC::sendFrame(uint16_t toAddress, const void* buffer, uint8_t buffer
// write to FIFO
select();
SPI.transfer(REG_FIFO | 0x80);
SPI.transfer(bufferSize + 3);
SPI.transfer((uint8_t)toAddress); //lower 8bits
SPI.transfer((uint8_t)_address); //lower 8bits
_spi->transfer(REG_FIFO | 0x80);
_spi->transfer(bufferSize + 3);
_spi->transfer((uint8_t)toAddress); //lower 8bits
_spi->transfer((uint8_t)_address); //lower 8bits
// CTL (control byte)
uint8_t CTLbyte=0x0;
if (toAddress > 0xFF) CTLbyte |= (toAddress & 0x300) >> 6; //assign last 2 bits of address if > 255
if (_address > 0xFF) CTLbyte |= (_address & 0x300) >> 8; //assign last 2 bits of address if > 255
if (sendACK) { // TomWS1: adding logic to return ACK_RSSI if requested
SPI.transfer(CTLbyte | RFM69_CTL_SENDACK | (sendRSSI?RFM69_CTL_RESERVE1:0)); // TomWS1 TODO: Replace with EXT1
_spi->transfer(CTLbyte | RFM69_CTL_SENDACK | (sendRSSI?RFM69_CTL_RESERVE1:0)); // TomWS1 TODO: Replace with EXT1
if (sendRSSI) {
SPI.transfer(abs(lastRSSI)); //RSSI dBm is negative expected between [-100 .. -20], convert to positive and pass along as single extra header byte
_spi->transfer(abs(lastRSSI)); //RSSI dBm is negative expected between [-100 .. -20], convert to positive and pass along as single extra header byte
bufferSize -=1; // account for the extra ACK-RSSI 'data' byte
}
}
else if (requestACK) { // TODO: add logic to request ackRSSI with ACK - this is when both ends of a transmission would dial power down. May not work well for gateways in multi node networks
SPI.transfer(CTLbyte | (_targetRSSI ? RFM69_CTL_REQACK | RFM69_CTL_RESERVE1 : RFM69_CTL_REQACK));
_spi->transfer(CTLbyte | (_targetRSSI ? RFM69_CTL_REQACK | RFM69_CTL_RESERVE1 : RFM69_CTL_REQACK));
}
else SPI.transfer(CTLbyte);
else _spi->transfer(CTLbyte);
for (uint8_t i = 0; i < bufferSize; i++)
SPI.transfer(((uint8_t*) buffer)[i]);
_spi->transfer(((uint8_t*) buffer)[i]);
unselect();
// no need to wait for transmit mode to be ready since its handled by the radio
@ -141,7 +141,7 @@ void RFM69_ATC::interruptHook(uint8_t CTLbyte) {
if (ACK_RECEIVED && ACK_RSSI_REQUESTED) {
// the next two bytes contain the ACK_RSSI (assuming the datalength is valid)
if (DATALEN >= 1) {
_ackRSSI = -1 * SPI.transfer(0); //rssi was sent as single byte positive value, get the real value by * -1
_ackRSSI = -1 * _spi->transfer(0); //rssi was sent as single byte positive value, get the real value by * -1
DATALEN -= 1; // and compensate data length accordingly
// TomWS1: Now dither transmitLevel value (register update occurs later when transmitting);
if (_targetRSSI != 0) {
@ -277,4 +277,4 @@ byte RFM69_ATC::setLNA(byte newReg) { // TomWS1: New method used to disable LNA
oldReg = readReg(REG_LNA);
writeReg(REG_LNA, ((newReg & 7) | (oldReg & ~7))); // just control the LNA Gain bits for now
return oldReg; // return the original value in case we need to restore it
}
}

View File

@ -36,8 +36,8 @@ class RFM69_ATC: public RFM69 {
public:
static volatile uint8_t ACK_RSSI_REQUESTED; // new flag in CTL byte to request RSSI with ACK (could potentially be merged with ACK_REQUESTED)
RFM69_ATC(uint8_t slaveSelectPin=RF69_SPI_CS, uint8_t interruptPin=RF69_IRQ_PIN, bool isRFM69HW=false, uint8_t interruptNum=0) :
RFM69(slaveSelectPin, interruptPin, isRFM69HW) {
RFM69_ATC(uint8_t slaveSelectPin=RF69_SPI_CS, uint8_t interruptPin=RF69_IRQ_PIN, bool isRFM69HW=false, SPIClass *spi=nullptr) :
RFM69(slaveSelectPin, interruptPin, isRFM69HW, spi) {
}
bool initialize(uint8_t freqBand, uint16_t ID, uint8_t networkID=1);
@ -66,4 +66,4 @@ class RFM69_ATC: public RFM69 {
uint8_t _PA_Reg; // saved and derived PA control bits so we don't have to spend time reading back from SPI port
};
#endif
#endif