[Si443x] Fix CRC error IRQ (#1430)

This commit is contained in:
jgromes 2025-03-14 20:14:23 +01:00
parent d526ac3091
commit 416f52d92a
2 changed files with 64 additions and 33 deletions

View file

@ -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) {

View file

@ -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();