diff --git a/RFM69.cpp b/RFM69.cpp index 65af4e2..c7aefbf 100644 --- a/RFM69.cpp +++ b/RFM69.cpp @@ -90,9 +90,11 @@ bool RFM69::initialize(uint8_t freqBand, uint8_t nodeID, uint8_t networkID) digitalWrite(_slaveSelectPin, HIGH); pinMode(_slaveSelectPin, OUTPUT); SPI.begin(); - - do writeReg(REG_SYNCVALUE1, 0xAA); while (readReg(REG_SYNCVALUE1) != 0xAA); - do writeReg(REG_SYNCVALUE1, 0x55); while (readReg(REG_SYNCVALUE1) != 0x55); + unsigned long start = millis(); + uint8_t timeout = 50; + do writeReg(REG_SYNCVALUE1, 0xAA); while (readReg(REG_SYNCVALUE1) != 0xaa && millis()-start < timeout); + start = millis(); + do writeReg(REG_SYNCVALUE1, 0x55); while (readReg(REG_SYNCVALUE1) != 0x55 && millis()-start < timeout); for (uint8_t i = 0; CONFIG[i][0] != 255; i++) writeReg(CONFIG[i][0], CONFIG[i][1]); @@ -103,7 +105,10 @@ bool RFM69::initialize(uint8_t freqBand, uint8_t nodeID, uint8_t networkID) setHighPower(_isRFM69HW); // called regardless if it's a RFM69W or RFM69HW setMode(RF69_MODE_STANDBY); - while ((readReg(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00); // wait for ModeReady + start = millis(); + while (((readReg(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00) && millis()-start < timeout); // wait for ModeReady + if (millis()-start >= timeout) + return false; attachInterrupt(_interruptNum, RFM69::isr0, RISING); selfPointer = this; @@ -257,6 +262,7 @@ bool RFM69::ACKRequested() { // should be called immediately after reception in case sender wants ACK void RFM69::sendACK(const void* buffer, uint8_t bufferSize) { + ACK_REQUESTED = 0; // TWS added to make sure we don't end up in a timing race and infinite loop sending Acks uint8_t sender = SENDERID; int16_t _RSSI = RSSI; // save payload received RSSI value writeReg(REG_PACKETCONFIG2, (readReg(REG_PACKETCONFIG2) & 0xFB) | RF_PACKET2_RXRESTART); // avoid RX deadlocks @@ -277,9 +283,9 @@ void RFM69::sendFrame(uint8_t toAddress, const void* buffer, uint8_t bufferSize, // control byte uint8_t CTLbyte = 0x00; if (sendACK) - CTLbyte = 0x80; + CTLbyte = RFM69_CTL_SENDACK; else if (requestACK) - CTLbyte = 0x40; + CTLbyte = RFM69_CTL_REQACK; // write to FIFO select(); @@ -328,8 +334,10 @@ void RFM69::interruptHandler() { SENDERID = SPI.transfer(0); uint8_t CTLbyte = SPI.transfer(0); - ACK_RECEIVED = CTLbyte & 0x80; // extract ACK-received flag - ACK_REQUESTED = CTLbyte & 0x40; // extract ACK-requested flag + ACK_RECEIVED = CTLbyte & RFM69_CTL_SENDACK; // extract ACK-received flag + 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++) { @@ -774,4 +782,4 @@ void RFM69::rcCalibration() { writeReg(REG_OSC1, RF_OSC1_RCCAL_START); while ((readReg(REG_OSC1) & RF_OSC1_RCCAL_DONE) == 0x00); -} +} \ No newline at end of file diff --git a/RFM69.h b/RFM69.h index 8811bf9..009d815 100644 --- a/RFM69.h +++ b/RFM69.h @@ -71,6 +71,10 @@ #define RF69_TX_LIMIT_MS 1000 #define RF69_FSTEP 61.03515625 // == FXOSC / 2^19 = 32MHz / 2^19 (p13 in datasheet) +// TWS: define CTLbyte bits +#define RFM69_CTL_SENDACK 0x80 +#define RFM69_CTL_REQACK 0x40 + class RFM69 { public: static volatile uint8_t DATA[RF69_MAX_DATA_LEN]; // recv/xmit buf, including header & crc bytes @@ -97,20 +101,20 @@ class RFM69 { void setAddress(uint8_t addr); void setNetwork(uint8_t networkID); bool canSend(); - void send(uint8_t toAddress, const void* buffer, uint8_t bufferSize, bool requestACK=false); - bool sendWithRetry(uint8_t toAddress, const void* buffer, uint8_t bufferSize, uint8_t retries=2, uint8_t retryWaitTime=40); // 40ms roundtrip req for 61byte packets - bool receiveDone(); + virtual void send(uint8_t toAddress, const void* buffer, uint8_t bufferSize, bool requestACK=false); + virtual bool sendWithRetry(uint8_t toAddress, const void* buffer, uint8_t bufferSize, uint8_t retries=2, uint8_t retryWaitTime=40); // 40ms roundtrip req for 61byte packets + virtual bool receiveDone(); bool ACKReceived(uint8_t fromNodeID); bool ACKRequested(); - void sendACK(const void* buffer = "", uint8_t bufferSize=0); + virtual void sendACK(const void* buffer = "", uint8_t bufferSize=0); uint32_t getFrequency(); void setFrequency(uint32_t freqHz); void encrypt(const char* key); void setCS(uint8_t newSPISlaveSelect); int16_t readRSSI(bool forceTrigger=false); void promiscuous(bool onOff=true); - void setHighPower(bool onOFF=true); // has to be called after initialize() for RFM69HW - void setPowerLevel(uint8_t level); // reduce/increase transmit power level + virtual void setHighPower(bool onOFF=true); // has to be called after initialize() for RFM69HW + virtual void setPowerLevel(uint8_t level); // reduce/increase transmit power level void sleep(); uint8_t readTemperature(uint8_t calFactor=0); // get CMOS temperature (8bit) void rcCalibration(); // calibrate the internal RC oscillator for use in wide temperature variations - see datasheet section [4.3.5. RC Timer Accuracy] @@ -123,7 +127,8 @@ class RFM69 { protected: static void isr0(); void virtual interruptHandler(); - void sendFrame(uint8_t toAddress, const void* buffer, uint8_t size, bool requestACK=false, bool sendACK=false); + virtual void interruptHook(uint8_t CTLbyte) {}; + virtual void sendFrame(uint8_t toAddress, const void* buffer, uint8_t size, bool requestACK=false, bool sendACK=false); static RFM69* selfPointer; uint8_t _slaveSelectPin; @@ -136,11 +141,11 @@ class RFM69 { uint8_t _SPCR; uint8_t _SPSR; - void receiveBegin(); - void setMode(uint8_t mode); - void setHighPowerRegs(bool onOff); - void select(); - void unselect(); + virtual void receiveBegin(); + virtual void setMode(uint8_t mode); + virtual void setHighPowerRegs(bool onOff); + virtual void select(); + virtual void unselect(); }; -#endif +#endif \ No newline at end of file