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.
This commit is contained in:
parent
304e876c02
commit
537dae7913
2 changed files with 27 additions and 3 deletions
|
@ -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()));
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue