From 537dae791371067ce9897761fb8f922999d0efe3 Mon Sep 17 00:00:00 2001 From: Federico Fuga Date: Thu, 2 Sep 2021 15:50:43 +0200 Subject: [PATCH] Fix issue #357. Interrupt is triggered when Transmit is completed, calling the receiver function When transmitting a packet, the GDO0 pin is set to trigger when the transmission is ongoing. Unfortunately this will call the user interrupt even if the user intended to use only on receiving packets. The issue occurs because GDO0 is monitored for transmit completion in the transmit() function, but a change will trigger the user interrupt as well. The solution is to redirect the interrupt to a separate interrupt handler until the transmit function is completed, then restoring the original handler before returning. --- src/modules/CC1101/CC1101.cpp | 26 +++++++++++++++++++++++--- src/modules/CC1101/CC1101.h | 4 ++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/modules/CC1101/CC1101.cpp b/src/modules/CC1101/CC1101.cpp index 9c143ad9..9074639b 100644 --- a/src/modules/CC1101/CC1101.cpp +++ b/src/modules/CC1101/CC1101.cpp @@ -95,11 +95,25 @@ int16_t CC1101::begin(float freq, float br, float freqDev, float rxBw, int8_t po return(state); } +void CC1101::reattachGdo0Interrupt() +{ + if (gdo0action != nullptr) + Module::attachInterrupt(RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(_mod->getIrq()), gdo0action, gdo0dir); +} + +static void handleTxInterrupt(void) +{ + return; +} + + int16_t CC1101::transmit(uint8_t* data, size_t len, uint8_t addr) { // calculate timeout (5ms + 500 % of expected time-on-air) uint32_t timeout = 5000000 + (uint32_t)((((float)(len * 8)) / (_br * 1000.0)) * 5000000.0); - // start transmission + Module::attachInterrupt(RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(_mod->getIrq()), handleTxInterrupt, gdo0dir); + + // start transmission int16_t state = startTransmit(data, len, addr); RADIOLIB_ASSERT(state); @@ -109,7 +123,8 @@ int16_t CC1101::transmit(uint8_t* data, size_t len, uint8_t addr) { Module::yield(); if(Module::micros() - start > timeout) { - standby(); + reattachGdo0Interrupt(); + standby(); SPIsendCommand(CC1101_CMD_FLUSH_TX); return(ERR_TX_TIMEOUT); } @@ -121,12 +136,14 @@ int16_t CC1101::transmit(uint8_t* data, size_t len, uint8_t addr) { Module::yield(); if(Module::micros() - start > timeout) { + reattachGdo0Interrupt(); standby(); SPIsendCommand(CC1101_CMD_FLUSH_TX); return(ERR_TX_TIMEOUT); } } + reattachGdo0Interrupt(); // set mode to standby standby(); @@ -212,10 +229,13 @@ int16_t CC1101::packetMode() { } void CC1101::setGdo0Action(void (*func)(void), RADIOLIB_INTERRUPT_STATUS dir) { - Module::attachInterrupt(RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(_mod->getIrq()), func, dir); + gdo0action = func; + gdo0dir = dir; + Module::attachInterrupt(RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(_mod->getIrq()), gdo0action, gdo0dir); } void CC1101::clearGdo0Action() { + gdo0action = nullptr; Module::detachInterrupt(RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(_mod->getIrq())); } diff --git a/src/modules/CC1101/CC1101.h b/src/modules/CC1101/CC1101.h index 95e8f455..8cfaa7c8 100644 --- a/src/modules/CC1101/CC1101.h +++ b/src/modules/CC1101/CC1101.h @@ -947,10 +947,14 @@ class CC1101: public PhysicalLayer { uint8_t _syncWordLength = 2; int8_t _power = 0; + void (*gdo0action)(void) = nullptr; + RADIOLIB_INTERRUPT_STATUS gdo0dir; + int16_t config(); int16_t directMode(); static void getExpMant(float target, uint16_t mantOffset, uint8_t divExp, uint8_t expMax, uint8_t& exp, uint8_t& mant); int16_t setPacketMode(uint8_t mode, uint8_t len); + void reattachGdo0Interrupt(); }; #endif