diff --git a/src/modules/Si443x/Si443x.cpp b/src/modules/Si443x/Si443x.cpp index 0de41b36..cf88f7a3 100644 --- a/src/modules/Si443x/Si443x.cpp +++ b/src/modules/Si443x/Si443x.cpp @@ -28,7 +28,7 @@ int16_t Si443x::begin(float br, float freqDev, float rxBw, uint8_t preambleLen) this->mod->SPIwriteRegister(RADIOLIB_SI443X_REG_OP_FUNC_CONTROL_1, RADIOLIB_SI443X_SOFTWARE_RESET); // clear POR interrupt - clearIRQFlags(); + clearIrqStatus(); // configure settings not accessible by API int16_t state = config(); @@ -107,7 +107,7 @@ int16_t Si443x::receive(uint8_t* data, size_t len) { while(this->mod->hal->digitalRead(this->mod->getIrq())) { if(this->mod->hal->millis() - start > timeout) { standby(); - clearIRQFlags(); + clearIrqStatus(); return(RADIOLIB_ERR_RX_TIMEOUT); } } @@ -243,7 +243,7 @@ int16_t Si443x::startTransmit(const uint8_t* data, size_t len, uint8_t addr) { this->mod->SPIsetRegValue(RADIOLIB_SI443X_REG_OP_FUNC_CONTROL_2, RADIOLIB_SI443X_TX_FIFO_CLEAR, 0, 0); // clear interrupt flags - clearIRQFlags(); + clearIrqStatus(); // set packet length if (this->packetLengthConfig == RADIOLIB_SI443X_FIXED_PACKET_LENGTH_OFF) { @@ -271,7 +271,7 @@ int16_t Si443x::startTransmit(const uint8_t* data, size_t len, uint8_t addr) { int16_t Si443x::finishTransmit() { // clear interrupt flags - clearIRQFlags(); + clearIrqStatus(); // set mode to standby to disable transmitter/RF switch return(standby()); @@ -287,7 +287,7 @@ int16_t Si443x::startReceive() { this->mod->SPIsetRegValue(RADIOLIB_SI443X_REG_OP_FUNC_CONTROL_2, RADIOLIB_SI443X_RX_FIFO_CLEAR, 1, 1); // clear interrupt flags - clearIRQFlags(); + clearIrqStatus(); // set RF switch (if present) this->mod->setRfSwitchState(Module::MODE_RX); @@ -311,8 +311,15 @@ int16_t Si443x::startReceive(uint32_t timeout, uint32_t irqFlags, uint32_t irqMa } int16_t Si443x::readData(uint8_t* data, size_t len) { - // clear interrupt flags - clearIRQFlags(); + // read interrupt flags + uint32_t irq = getIrqFlags(); + + // check integrity CRC + // Si443x does not have the option to keep the data after CRC failed + // reading the FIFO will just repeat the first byte (see https://github.com/jgromes/RadioLib/issues/1430) + if(irq & RADIOLIB_SI443X_CRC_ERROR_INTERRUPT) { + return(RADIOLIB_ERR_CRC_MISMATCH); + } // get packet length size_t length = getPacketLength(); @@ -339,7 +346,7 @@ int16_t Si443x::readData(uint8_t* data, size_t len) { RADIOLIB_ASSERT(state); // clear interrupt flags - clearIRQFlags(); + clearIrqStatus(); return(RADIOLIB_ERR_NONE); } @@ -635,6 +642,18 @@ int16_t Si443x::variablePacketLengthMode(uint8_t maxLen) { return(Si443x::setPacketMode(RADIOLIB_SI443X_FIXED_PACKET_LENGTH_OFF, maxLen)); } +uint32_t Si443x::getIrqFlags() { + uint8_t data[] = { 0x00, 0x00 }; + this->mod->SPIreadRegisterBurst(RADIOLIB_SI443X_REG_INTERRUPT_STATUS_1, 2, data); + return(((uint32_t)(data[0]) << 8) | data[1]); +} + +int16_t Si443x::clearIrqFlags(uint32_t irq) { + (void)irq; + (void)getIrqFlags(); + return(RADIOLIB_ERR_NONE); +} + Module* Si443x::getMod() { return(this->mod); } @@ -707,9 +726,8 @@ bool Si443x::findChip() { return(flagFound); } -void Si443x::clearIRQFlags() { - uint8_t buff[2]; - this->mod->SPIreadRegisterBurst(RADIOLIB_SI443X_REG_INTERRUPT_STATUS_1, 2, buff); +void Si443x::clearIrqStatus() { + (void)getIrqFlags(); } void Si443x::clearFIFO(size_t count) { diff --git a/src/modules/Si443x/Si443x.h b/src/modules/Si443x/Si443x.h index c100b04e..42ddc9e7 100644 --- a/src/modules/Si443x/Si443x.h +++ b/src/modules/Si443x/Si443x.h @@ -128,19 +128,19 @@ #define RADIOLIB_SI443X_IDLE 0b00000000 // 1 0 idle // RADIOLIB_SI443X_REG_INTERRUPT_STATUS_1 -#define RADIOLIB_SI443X_FIFO_LEVEL_ERROR_INTERRUPT 0b10000000 // 7 7 Tx/Rx FIFO overflow or underflow -#define RADIOLIB_SI443X_TX_FIFO_ALMOST_FULL_INTERRUPT 0b01000000 // 6 6 Tx FIFO almost full -#define RADIOLIB_SI443X_TX_FIFO_ALMOST_EMPTY_INTERRUPT 0b00100000 // 5 5 Tx FIFO almost empty -#define RADIOLIB_SI443X_RX_FIFO_ALMOST_FULL_INTERRUPT 0b00010000 // 4 4 Rx FIFO almost full -#define RADIOLIB_SI443X_EXTERNAL_INTERRUPT 0b00001000 // 3 3 external interrupt occurred on GPIOx -#define RADIOLIB_SI443X_PACKET_SENT_INTERRUPT 0b00000100 // 2 2 packet transmission done -#define RADIOLIB_SI443X_VALID_PACKET_RECEIVED_INTERRUPT 0b00000010 // 1 1 valid packet has been received -#define RADIOLIB_SI443X_CRC_ERROR_INTERRUPT 0b00000001 // 0 0 CRC failed +#define RADIOLIB_SI443X_FIFO_LEVEL_ERROR_INTERRUPT 0b10000000 << 8 // 7 7 Tx/Rx FIFO overflow or underflow +#define RADIOLIB_SI443X_TX_FIFO_ALMOST_FULL_INTERRUPT 0b01000000 << 8 // 6 6 Tx FIFO almost full +#define RADIOLIB_SI443X_TX_FIFO_ALMOST_EMPTY_INTERRUPT 0b00100000 << 8 // 5 5 Tx FIFO almost empty +#define RADIOLIB_SI443X_RX_FIFO_ALMOST_FULL_INTERRUPT 0b00010000 << 8 // 4 4 Rx FIFO almost full +#define RADIOLIB_SI443X_EXTERNAL_INTERRUPT 0b00001000 << 8 // 3 3 external interrupt occurred on GPIOx +#define RADIOLIB_SI443X_PACKET_SENT_INTERRUPT 0b00000100 << 8 // 2 2 packet transmission done +#define RADIOLIB_SI443X_VALID_PACKET_RECEIVED_INTERRUPT 0b00000010 << 8 // 1 1 valid packet has been received +#define RADIOLIB_SI443X_CRC_ERROR_INTERRUPT 0b00000001 << 8 // 0 0 CRC failed // RADIOLIB_SI443X_REG_INTERRUPT_STATUS_2 #define RADIOLIB_SI443X_SYNC_WORD_DETECTED_INTERRUPT 0b10000000 // 7 7 sync word has been detected -#define RADIOLIB_SI443X_VALID_RADIOLIB_PREAMBLE_DETECTED_INTERRUPT 0b01000000 // 6 6 valid preamble has been detected -#define RADIOLIB_SI443X_INVALID_RADIOLIB_PREAMBLE_DETECTED_INTERRUPT 0b00100000 // 5 5 invalid preamble has been detected +#define RADIOLIB_SI443X_VALID_PREAMBLE_DETECTED_INTERRUPT 0b01000000 // 6 6 valid preamble has been detected +#define RADIOLIB_SI443X_INVALID_PREAMBLE_DETECTED_INTERRUPT 0b00100000 // 5 5 invalid preamble has been detected #define RADIOLIB_SI443X_RSSI_INTERRUPT 0b00010000 // 4 4 RSSI exceeded programmed threshold #define RADIOLIB_SI443X_WAKEUP_TIMER_INTERRUPT 0b00001000 // 3 3 wake-up timer expired #define RADIOLIB_SI443X_LOW_BATTERY_INTERRUPT 0b00000100 // 2 2 low battery detected @@ -159,8 +159,8 @@ // RADIOLIB_SI443X_REG_INTERRUPT_ENABLE_2 #define RADIOLIB_SI443X_SYNC_WORD_DETECTED_ENABLED 0b10000000 // 7 7 sync word interrupt enabled -#define RADIOLIB_SI443X_VALID_RADIOLIB_PREAMBLE_DETECTED_ENABLED 0b01000000 // 6 6 valid preamble interrupt enabled -#define RADIOLIB_SI443X_INVALID_RADIOLIB_PREAMBLE_DETECTED_ENABLED 0b00100000 // 5 5 invalid preamble interrupt enabled +#define RADIOLIB_SI443X_VALID_PREAMBLE_DETECTED_ENABLED 0b01000000 // 6 6 valid preamble interrupt enabled +#define RADIOLIB_SI443X_INVALID_PREAMBLE_DETECTED_ENABLED 0b00100000 // 5 5 invalid preamble interrupt enabled #define RADIOLIB_SI443X_RSSI_ENABLED 0b00010000 // 4 4 RSSI exceeded programmed threshold interrupt enabled #define RADIOLIB_SI443X_WAKEUP_TIMER_ENABLED 0b00001000 // 3 3 wake-up timer interrupt enabled #define RADIOLIB_SI443X_LOW_BATTERY_ENABLED 0b00000100 // 2 2 low battery interrupt enabled @@ -810,18 +810,31 @@ class Si443x: public PhysicalLayer { #endif /*! - \brief Set modem in fixed packet length mode. - \param len Packet length. - \returns \ref status_codes - */ - int16_t fixedPacketLengthMode(uint8_t len = RADIOLIB_SI443X_MAX_PACKET_LENGTH); + \brief Set modem in fixed packet length mode. + \param len Packet length. + \returns \ref status_codes + */ + int16_t fixedPacketLengthMode(uint8_t len = RADIOLIB_SI443X_MAX_PACKET_LENGTH); /*! - \brief Set modem in variable packet length mode. - \param maxLen Maximum packet length. + \brief Set modem in variable packet length mode. + \param maxLen Maximum packet length. \returns \ref status_codes - */ - int16_t variablePacketLengthMode(uint8_t maxLen = RADIOLIB_SI443X_MAX_PACKET_LENGTH); + */ + int16_t variablePacketLengthMode(uint8_t maxLen = RADIOLIB_SI443X_MAX_PACKET_LENGTH); + + /*! + \brief Read currently active IRQ flags. + \returns IRQ flags. + */ + uint32_t getIrqFlags() override; + + /*! + \brief Clear interrupt on a specific IRQ bit (e.g. RxTimeout, CadDone). + \param irq Module-specific IRQ flags. + \returns \ref status_codes + */ + int16_t clearIrqFlags(uint32_t irq) override; #if !RADIOLIB_GODMODE && !RADIOLIB_LOW_LEVEL protected: @@ -847,7 +860,7 @@ class Si443x: public PhysicalLayer { uint8_t packetLengthConfig = RADIOLIB_SI443X_FIXED_PACKET_LENGTH_ON; bool findChip(); - void clearIRQFlags(); + void clearIrqStatus(); void clearFIFO(size_t count); int16_t config(); int16_t updateClockRecovery();