[SX127x] Added generalized IRQ handling via PHY
This commit is contained in:
parent
fcdc1d782e
commit
7067c67304
2 changed files with 108 additions and 43 deletions
|
@ -12,6 +12,18 @@ int16_t SX127x::begin(uint8_t* chipVersions, uint8_t numVersions, uint8_t syncWo
|
|||
this->mod->hal->pinMode(this->mod->getIrq(), this->mod->hal->GpioModeInput);
|
||||
this->mod->hal->pinMode(this->mod->getGpio(), this->mod->hal->GpioModeInput);
|
||||
|
||||
// set IRQ mapping - it is different for LoRa and FSK mode
|
||||
this->irqMap[RADIOLIB_IRQ_TX_DONE] = RADIOLIB_SX127X_CLEAR_IRQ_FLAG_TX_DONE;
|
||||
this->irqMap[RADIOLIB_IRQ_RX_DONE] = RADIOLIB_SX127X_CLEAR_IRQ_FLAG_RX_DONE;
|
||||
this->irqMap[RADIOLIB_IRQ_PREAMBLE_DETECTED] = RADIOLIB_IRQ_NOT_SUPPORTED;
|
||||
this->irqMap[RADIOLIB_IRQ_SYNC_WORD_VALID] = RADIOLIB_IRQ_NOT_SUPPORTED;
|
||||
this->irqMap[RADIOLIB_IRQ_HEADER_VALID] = RADIOLIB_SX127X_CLEAR_IRQ_FLAG_VALID_HEADER;
|
||||
this->irqMap[RADIOLIB_IRQ_HEADER_ERR] = RADIOLIB_IRQ_NOT_SUPPORTED;
|
||||
this->irqMap[RADIOLIB_IRQ_CRC_ERR] = RADIOLIB_SX127X_CLEAR_IRQ_FLAG_PAYLOAD_CRC_ERROR;
|
||||
this->irqMap[RADIOLIB_IRQ_CAD_DONE] = RADIOLIB_SX127X_CLEAR_IRQ_FLAG_CAD_DONE;
|
||||
this->irqMap[RADIOLIB_IRQ_CAD_DETECTED] = RADIOLIB_SX127X_CLEAR_IRQ_FLAG_CAD_DETECTED;
|
||||
this->irqMap[RADIOLIB_IRQ_TIMEOUT] = RADIOLIB_SX127X_CLEAR_IRQ_FLAG_RX_TIMEOUT;
|
||||
|
||||
// try to find the SX127x chip
|
||||
if(!SX127x::findChip(chipVersions, numVersions)) {
|
||||
RADIOLIB_DEBUG_BASIC_PRINTLN("No SX127x found!");
|
||||
|
@ -63,6 +75,18 @@ int16_t SX127x::beginFSK(uint8_t* chipVersions, uint8_t numVersions, float freqD
|
|||
this->mod->hal->pinMode(this->mod->getIrq(), this->mod->hal->GpioModeInput);
|
||||
this->mod->hal->pinMode(this->mod->getGpio(), this->mod->hal->GpioModeInput);
|
||||
|
||||
// set IRQ mapping - it is different for LoRa and FSK mode
|
||||
this->irqMap[RADIOLIB_IRQ_TX_DONE] = RADIOLIB_SX127X_FLAG_PACKET_SENT << 8;
|
||||
this->irqMap[RADIOLIB_IRQ_RX_DONE] = RADIOLIB_SX127X_FLAG_PAYLOAD_READY << 8;
|
||||
this->irqMap[RADIOLIB_IRQ_PREAMBLE_DETECTED] = RADIOLIB_SX127X_FLAG_PREAMBLE_DETECT << 0;
|
||||
this->irqMap[RADIOLIB_IRQ_SYNC_WORD_VALID] = RADIOLIB_SX127X_FLAG_SYNC_ADDRESS_MATCH << 0;
|
||||
this->irqMap[RADIOLIB_IRQ_HEADER_VALID] = RADIOLIB_IRQ_NOT_SUPPORTED;
|
||||
this->irqMap[RADIOLIB_IRQ_HEADER_ERR] = RADIOLIB_IRQ_NOT_SUPPORTED;
|
||||
this->irqMap[RADIOLIB_IRQ_CRC_ERR] = RADIOLIB_IRQ_NOT_SUPPORTED;
|
||||
this->irqMap[RADIOLIB_IRQ_CAD_DONE] = RADIOLIB_IRQ_NOT_SUPPORTED;
|
||||
this->irqMap[RADIOLIB_IRQ_CAD_DETECTED] = RADIOLIB_IRQ_NOT_SUPPORTED;
|
||||
this->irqMap[RADIOLIB_IRQ_TIMEOUT] = RADIOLIB_SX127X_FLAG_TIMEOUT << 0;
|
||||
|
||||
// try to find the SX127x chip
|
||||
if(!SX127x::findChip(chipVersions, numVersions)) {
|
||||
RADIOLIB_DEBUG_BASIC_PRINTLN("No SX127x found!");
|
||||
|
@ -211,13 +235,13 @@ int16_t SX127x::receive(uint8_t* data, size_t len) {
|
|||
if(this->mod->getGpio() == RADIOLIB_NC) {
|
||||
// no GPIO pin provided, use software timeout
|
||||
if(this->mod->hal->millis() - start > timeout) {
|
||||
clearIRQFlags();
|
||||
clearIrqFlags(RADIOLIB_SX127X_FLAGS_ALL);
|
||||
return(RADIOLIB_ERR_RX_TIMEOUT);
|
||||
}
|
||||
} else {
|
||||
// GPIO provided, use that
|
||||
if(this->mod->hal->digitalRead(this->mod->getGpio())) {
|
||||
clearIRQFlags();
|
||||
clearIrqFlags(RADIOLIB_SX127X_FLAGS_ALL);
|
||||
return(RADIOLIB_ERR_RX_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
@ -237,7 +261,7 @@ int16_t SX127x::receive(uint8_t* data, size_t len) {
|
|||
while(!this->mod->hal->digitalRead(this->mod->getIrq())) {
|
||||
this->mod->hal->yield();
|
||||
if(this->mod->hal->millis() - start > timeout) {
|
||||
clearIRQFlags();
|
||||
clearIrqFlags(RADIOLIB_SX127X_FLAGS_ALL);
|
||||
return(RADIOLIB_ERR_RX_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
@ -389,7 +413,7 @@ int16_t SX127x::startReceive(uint8_t len, uint8_t mode) {
|
|||
RADIOLIB_ERRATA_SX127X(true);
|
||||
|
||||
// clear interrupt flags
|
||||
clearIRQFlags();
|
||||
clearIrqFlags(RADIOLIB_SX127X_FLAGS_ALL);
|
||||
|
||||
// set FIFO pointers
|
||||
state |= this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_FIFO_RX_BASE_ADDR, RADIOLIB_SX127X_FIFO_RX_BASE_ADDR_MAX);
|
||||
|
@ -402,7 +426,7 @@ int16_t SX127x::startReceive(uint8_t len, uint8_t mode) {
|
|||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// clear interrupt flags
|
||||
clearIRQFlags();
|
||||
clearIrqFlags(RADIOLIB_SX127X_FLAGS_ALL);
|
||||
|
||||
// FSK modem does not distinguish between Rx single and continuous
|
||||
if(mode == RADIOLIB_SX127X_RXCONTINUOUS) {
|
||||
|
@ -571,7 +595,7 @@ int16_t SX127x::startTransmit(const uint8_t* data, size_t len, uint8_t addr) {
|
|||
RADIOLIB_ERRATA_SX127X(false);
|
||||
|
||||
// clear interrupt flags
|
||||
clearIRQFlags();
|
||||
clearIrqFlags(RADIOLIB_SX127X_FLAGS_ALL);
|
||||
|
||||
// set packet length
|
||||
state |= this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PAYLOAD_LENGTH, len);
|
||||
|
@ -582,7 +606,7 @@ int16_t SX127x::startTransmit(const uint8_t* data, size_t len, uint8_t addr) {
|
|||
|
||||
} else if(modem == RADIOLIB_SX127X_FSK_OOK) {
|
||||
// clear interrupt flags
|
||||
clearIRQFlags();
|
||||
clearIrqFlags(RADIOLIB_SX127X_FLAGS_ALL);
|
||||
|
||||
// set DIO mapping
|
||||
if(len > RADIOLIB_SX127X_MAX_PACKET_LENGTH_FSK) {
|
||||
|
@ -628,7 +652,7 @@ int16_t SX127x::finishTransmit() {
|
|||
mod->hal->delayMicroseconds(1000000/1200);
|
||||
|
||||
// clear interrupt flags
|
||||
clearIRQFlags();
|
||||
clearIrqFlags(RADIOLIB_SX127X_FLAGS_ALL);
|
||||
|
||||
// set mode to standby to disable transmitter/RF switch
|
||||
return(standby());
|
||||
|
@ -686,7 +710,7 @@ int16_t SX127x::readData(uint8_t* data, size_t len) {
|
|||
this->packetLengthQueried = false;
|
||||
|
||||
// clear interrupt flags
|
||||
clearIRQFlags();
|
||||
clearIrqFlags(RADIOLIB_SX127X_FLAGS_ALL);
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
@ -702,7 +726,7 @@ int16_t SX127x::startChannelScan() {
|
|||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// clear interrupt flags
|
||||
clearIRQFlags();
|
||||
clearIrqFlags(RADIOLIB_SX127X_FLAGS_ALL);
|
||||
|
||||
// set DIO pin mapping
|
||||
state = this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DIO_MAPPING_1, RADIOLIB_SX127X_DIO0_LORA_CAD_DONE | RADIOLIB_SX127X_DIO1_LORA_CAD_DETECTED, 7, 4);
|
||||
|
@ -1302,29 +1326,66 @@ int16_t SX127x::irqRxDoneRxTimeout(uint32_t &irqFlags, uint32_t &irqMask) {
|
|||
return(RADIOLIB_ERR_NONE);
|
||||
}
|
||||
|
||||
int16_t SX127x::checkIrq(uint8_t irq) {
|
||||
uint16_t flags = getIRQFlags();
|
||||
switch(irq) {
|
||||
case RADIOLIB_IRQ_TX_DONE:
|
||||
return(flags & RADIOLIB_SX127X_CLEAR_IRQ_FLAG_TX_DONE);
|
||||
case RADIOLIB_IRQ_RX_DONE:
|
||||
return(flags & RADIOLIB_SX127X_CLEAR_IRQ_FLAG_RX_DONE);
|
||||
case RADIOLIB_IRQ_HEADER_VALID:
|
||||
return(flags & RADIOLIB_SX127X_CLEAR_IRQ_FLAG_VALID_HEADER);
|
||||
case RADIOLIB_IRQ_CRC_ERR:
|
||||
return(flags & RADIOLIB_SX127X_CLEAR_IRQ_FLAG_PAYLOAD_CRC_ERROR);
|
||||
case RADIOLIB_IRQ_CAD_DONE:
|
||||
return(flags & RADIOLIB_SX127X_CLEAR_IRQ_FLAG_CAD_DONE);
|
||||
case RADIOLIB_IRQ_CAD_DETECTED:
|
||||
return(flags & RADIOLIB_SX127X_CLEAR_IRQ_FLAG_CAD_DETECTED);
|
||||
case RADIOLIB_IRQ_TIMEOUT:
|
||||
return(flags & RADIOLIB_SX127X_CLEAR_IRQ_FLAG_RX_TIMEOUT);
|
||||
default:
|
||||
return(RADIOLIB_ERR_UNSUPPORTED);
|
||||
uint32_t SX127x::getIrqFlags() {
|
||||
return((uint32_t)this->getIRQFlags());
|
||||
}
|
||||
|
||||
int16_t SX127x::setIrqFlags(uint32_t irq) {
|
||||
// this is a bit convoluted, but unfortunately SX127x IRQ flags are not used to enable/disable that IRQ ...
|
||||
int16_t modem = getActiveModem();
|
||||
if(modem == RADIOLIB_SX127X_LORA) {
|
||||
switch(irq) {
|
||||
case(RADIOLIB_SX127X_CLEAR_IRQ_FLAG_TX_DONE):
|
||||
return(this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DIO_MAPPING_1, RADIOLIB_SX127X_DIO0_PACK_PACKET_SENT, 7, 6));
|
||||
case(RADIOLIB_SX127X_CLEAR_IRQ_FLAG_RX_DONE):
|
||||
return(this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DIO_MAPPING_1, RADIOLIB_SX127X_DIO0_LORA_RX_DONE, 7, 6));
|
||||
case(RADIOLIB_SX127X_CLEAR_IRQ_FLAG_VALID_HEADER):
|
||||
return(this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DIO_MAPPING_1, RADIOLIB_SX127X_DIO3_LORA_VALID_HEADER, 1, 0));
|
||||
case(RADIOLIB_SX127X_CLEAR_IRQ_FLAG_PAYLOAD_CRC_ERROR):
|
||||
return(this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DIO_MAPPING_1, RADIOLIB_SX127X_DIO3_LORA_PAYLOAD_CRC_ERROR, 1, 0));
|
||||
case(RADIOLIB_SX127X_CLEAR_IRQ_FLAG_CAD_DONE):
|
||||
return(this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DIO_MAPPING_1, RADIOLIB_SX127X_DIO0_LORA_CAD_DONE, 7, 6));
|
||||
case(RADIOLIB_SX127X_CLEAR_IRQ_FLAG_CAD_DETECTED):
|
||||
return(this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DIO_MAPPING_1, RADIOLIB_SX127X_DIO1_LORA_CAD_DETECTED, 5, 4));
|
||||
case(RADIOLIB_SX127X_CLEAR_IRQ_FLAG_RX_TIMEOUT):
|
||||
return(this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DIO_MAPPING_1, RADIOLIB_SX127X_DIO1_LORA_RX_TIMEOUT, 5, 4));
|
||||
}
|
||||
return(RADIOLIB_ERR_UNSUPPORTED);
|
||||
|
||||
} else if(modem == RADIOLIB_SX127X_FSK_OOK) {
|
||||
switch(irq) {
|
||||
case(RADIOLIB_SX127X_FLAG_PACKET_SENT << 8):
|
||||
return(this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DIO_MAPPING_1, RADIOLIB_SX127X_DIO0_PACK_PACKET_SENT, 7, 6));
|
||||
case(RADIOLIB_SX127X_FLAG_PAYLOAD_READY << 8):
|
||||
return(this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DIO_MAPPING_1, RADIOLIB_SX127X_DIO0_PACK_PAYLOAD_READY, 7, 6));
|
||||
case(RADIOLIB_SX127X_FLAG_PREAMBLE_DETECT << 0):
|
||||
return(this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DIO_MAPPING_2, RADIOLIB_SX127X_DIO4_PACK_RSSI_PREAMBLE_DETECT, 7, 6));
|
||||
case(RADIOLIB_SX127X_FLAG_SYNC_ADDRESS_MATCH << 0):
|
||||
return(this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DIO_MAPPING_1, RADIOLIB_SX127X_DIO2_PACK_SYNC_ADDRESS, 3, 2));
|
||||
case(RADIOLIB_SX127X_FLAG_TIMEOUT << 0):
|
||||
return(this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DIO_MAPPING_1, RADIOLIB_SX127X_DIO2_PACK_TIMEOUT, 3, 2));
|
||||
}
|
||||
return(RADIOLIB_ERR_UNSUPPORTED);
|
||||
}
|
||||
|
||||
return(RADIOLIB_ERR_UNSUPPORTED);
|
||||
}
|
||||
|
||||
int16_t SX127x::clearIrqFlags(uint32_t irq) {
|
||||
int16_t modem = getActiveModem();
|
||||
if(modem == RADIOLIB_SX127X_LORA) {
|
||||
this->mod->SPIwriteRegister(RADIOLIB_SX127X_REG_IRQ_FLAGS, (uint8_t)irq);
|
||||
return(RADIOLIB_ERR_NONE);
|
||||
|
||||
} else if(modem == RADIOLIB_SX127X_FSK_OOK) {
|
||||
this->mod->SPIwriteRegister(RADIOLIB_SX127X_REG_IRQ_FLAGS_1, (uint8_t)irq);
|
||||
this->mod->SPIwriteRegister(RADIOLIB_SX127X_REG_IRQ_FLAGS_2, (uint8_t)(irq >> 8));
|
||||
return(RADIOLIB_ERR_NONE);
|
||||
}
|
||||
|
||||
return(RADIOLIB_ERR_UNKNOWN);
|
||||
}
|
||||
|
||||
int16_t SX127x::setCrcFiltering(bool enable) {
|
||||
this->crcOn = enable;
|
||||
|
||||
|
@ -1619,16 +1680,6 @@ int16_t SX127x::setActiveModem(uint8_t modem) {
|
|||
return(state);
|
||||
}
|
||||
|
||||
void SX127x::clearIRQFlags() {
|
||||
int16_t modem = getActiveModem();
|
||||
if(modem == RADIOLIB_SX127X_LORA) {
|
||||
this->mod->SPIwriteRegister(RADIOLIB_SX127X_REG_IRQ_FLAGS, 0b11111111);
|
||||
} else if(modem == RADIOLIB_SX127X_FSK_OOK) {
|
||||
this->mod->SPIwriteRegister(RADIOLIB_SX127X_REG_IRQ_FLAGS_1, 0b11111111);
|
||||
this->mod->SPIwriteRegister(RADIOLIB_SX127X_REG_IRQ_FLAGS_2, 0b11111111);
|
||||
}
|
||||
}
|
||||
|
||||
void SX127x::clearFIFO(size_t count) {
|
||||
while(count) {
|
||||
this->mod->SPIreadRegister(RADIOLIB_SX127X_REG_FIFO);
|
||||
|
|
|
@ -500,6 +500,7 @@
|
|||
#define RADIOLIB_SX127X_FLAG_PAYLOAD_READY 0b00000100 // 2 2 packet was successfully received
|
||||
#define RADIOLIB_SX127X_FLAG_CRC_OK 0b00000010 // 1 1 CRC check passed
|
||||
#define RADIOLIB_SX127X_FLAG_LOW_BAT 0b00000001 // 0 0 battery voltage dropped below threshold
|
||||
#define RADIOLIB_SX127X_FLAGS_ALL 0xFFFF
|
||||
|
||||
// RADIOLIB_SX127X_REG_DIO_MAPPING_1
|
||||
#define RADIOLIB_SX127X_DIO0_LORA_RX_DONE 0b00000000 // 7 6
|
||||
|
@ -1073,10 +1074,24 @@ class SX127x: public PhysicalLayer {
|
|||
int16_t irqRxDoneRxTimeout(uint32_t &irqFlags, uint32_t &irqMask) override;
|
||||
|
||||
/*!
|
||||
\brief Check whether a specific IRQ bit is set (e.g. RxTimeout, CadDone).
|
||||
\returns Whether requested IRQ is set.
|
||||
\brief Read currently active IRQ flags.
|
||||
\returns IRQ flags.
|
||||
*/
|
||||
int16_t checkIrq(uint8_t irq) override;
|
||||
uint32_t getIrqFlags();
|
||||
|
||||
/*!
|
||||
\brief Set interrupt on DIO1 to be sent on a specific IRQ bit (e.g. RxTimeout, CadDone).
|
||||
\param irq Module-specific IRQ flags.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setIrqFlags(uint32_t irq);
|
||||
|
||||
/*!
|
||||
\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);
|
||||
|
||||
/*!
|
||||
\brief Enable CRC filtering and generation.
|
||||
|
@ -1257,7 +1272,6 @@ class SX127x: public PhysicalLayer {
|
|||
bool findChip(const uint8_t* vers, uint8_t num);
|
||||
int16_t setMode(uint8_t mode);
|
||||
int16_t setActiveModem(uint8_t modem);
|
||||
void clearIRQFlags();
|
||||
void clearFIFO(size_t count); // used mostly to clear remaining bytes in FIFO after a packet read
|
||||
|
||||
/*!
|
||||
|
|
Loading…
Add table
Reference in a new issue