[LR11x0] Implement staged modes

This commit is contained in:
jgromes 2025-02-03 20:34:10 +01:00
parent bf734c4528
commit 47499f5a22
2 changed files with 129 additions and 134 deletions

View file

@ -414,73 +414,6 @@ void LR11x0::clearPacketSentAction() {
this->clearIrqAction(); this->clearIrqAction();
} }
int16_t LR11x0::startTransmit(const uint8_t* data, size_t len, uint8_t addr) {
// suppress unused variable warning
(void)addr;
// check packet length
if(len > RADIOLIB_LR11X0_MAX_PACKET_LENGTH) {
return(RADIOLIB_ERR_PACKET_TOO_LONG);
}
// maximum packet length is decreased by 1 when address filtering is active
if((this->addrComp != RADIOLIB_LR11X0_GFSK_ADDR_FILTER_DISABLED) && (len > RADIOLIB_LR11X0_MAX_PACKET_LENGTH - 1)) {
return(RADIOLIB_ERR_PACKET_TOO_LONG);
}
// set packet Length
int16_t state = RADIOLIB_ERR_NONE;
uint8_t modem = RADIOLIB_LR11X0_PACKET_TYPE_NONE;
state = getPacketType(&modem);
RADIOLIB_ASSERT(state);
if(modem == RADIOLIB_LR11X0_PACKET_TYPE_LORA) {
state = setPacketParamsLoRa(this->preambleLengthLoRa, this->headerType, len, this->crcTypeLoRa, this->invertIQEnabled);
} else if(modem == RADIOLIB_LR11X0_PACKET_TYPE_GFSK) {
state = setPacketParamsGFSK(this->preambleLengthGFSK, this->preambleDetLength, this->syncWordLength, this->addrComp, this->packetType, len, this->crcTypeGFSK, this->whitening);
} else if(modem != RADIOLIB_LR11X0_PACKET_TYPE_LR_FHSS) {
return(RADIOLIB_ERR_UNKNOWN);
}
RADIOLIB_ASSERT(state);
// set DIO mapping
state = setDioIrqParams(RADIOLIB_LR11X0_IRQ_TX_DONE | RADIOLIB_LR11X0_IRQ_TIMEOUT);
RADIOLIB_ASSERT(state);
if(modem == RADIOLIB_LR11X0_PACKET_TYPE_LR_FHSS) {
// in LR-FHSS mode, the packet is built by the device
// TODO add configurable device offset
state = lrFhssBuildFrame(this->lrFhssHdrCount, this->lrFhssCr, this->lrFhssGrid, true, this->lrFhssBw, this->lrFhssHopSeq, 0, const_cast<uint8_t*>(data), len);
RADIOLIB_ASSERT(state);
} else {
// write packet to buffer
state = writeBuffer8(const_cast<uint8_t*>(data), len);
RADIOLIB_ASSERT(state);
}
// clear interrupt flags
state = clearIrqState(RADIOLIB_LR11X0_IRQ_ALL);
RADIOLIB_ASSERT(state);
// set RF switch (if present)
this->mod->setRfSwitchState(Module::MODE_TX);
// start transmission
state = setTx(RADIOLIB_LR11X0_TX_TIMEOUT_NONE);
RADIOLIB_ASSERT(state);
// wait for BUSY to go low (= PA ramp up done)
while(this->mod->hal->digitalRead(this->mod->getGpio())) {
this->mod->hal->yield();
}
return(state);
}
int16_t LR11x0::finishTransmit() { int16_t LR11x0::finishTransmit() {
// clear interrupt flags // clear interrupt flags
clearIrqState(RADIOLIB_LR11X0_IRQ_ALL); clearIrqState(RADIOLIB_LR11X0_IRQ_ALL);
@ -493,46 +426,6 @@ int16_t LR11x0::startReceive() {
return(this->startReceive(RADIOLIB_LR11X0_RX_TIMEOUT_INF, RADIOLIB_IRQ_RX_DEFAULT_FLAGS, RADIOLIB_IRQ_RX_DEFAULT_MASK, 0)); return(this->startReceive(RADIOLIB_LR11X0_RX_TIMEOUT_INF, RADIOLIB_IRQ_RX_DEFAULT_FLAGS, RADIOLIB_IRQ_RX_DEFAULT_MASK, 0));
} }
int16_t LR11x0::startReceive(uint32_t timeout, uint32_t irqFlags, uint32_t irqMask, size_t len) {
(void)len;
// check active modem
int16_t state = RADIOLIB_ERR_NONE;
uint8_t modem = RADIOLIB_LR11X0_PACKET_TYPE_NONE;
state = getPacketType(&modem);
RADIOLIB_ASSERT(state);
if((modem != RADIOLIB_LR11X0_PACKET_TYPE_LORA) &&
(modem != RADIOLIB_LR11X0_PACKET_TYPE_GFSK)) {
return(RADIOLIB_ERR_WRONG_MODEM);
}
// set DIO mapping
uint32_t irq = irqMask;
if(timeout != RADIOLIB_LR11X0_RX_TIMEOUT_INF) {
irq |= (1UL << RADIOLIB_IRQ_TIMEOUT);
}
state = setDioIrqParams(getIrqMapped(irqFlags & irq));
RADIOLIB_ASSERT(state);
// clear interrupt flags
state = clearIrqState(RADIOLIB_LR11X0_IRQ_ALL);
RADIOLIB_ASSERT(state);
// set implicit mode and expected len if applicable
if((this->headerType == RADIOLIB_LR11X0_LORA_HEADER_IMPLICIT) && (modem == RADIOLIB_LR11X0_PACKET_TYPE_LORA)) {
state = setPacketParamsLoRa(this->preambleLengthLoRa, this->headerType, this->implicitLen, this->crcTypeLoRa, this->invertIQEnabled);
RADIOLIB_ASSERT(state);
}
// set RF switch (if present)
this->mod->setRfSwitchState(Module::MODE_RX);
// set mode to receive
state = setRx(timeout);
return(state);
}
uint32_t LR11x0::getIrqStatus() { uint32_t LR11x0::getIrqStatus() {
// there is no dedicated "get IRQ" command, the IRQ bits are sent after the status bytes // there is no dedicated "get IRQ" command, the IRQ bits are sent after the status bytes
uint8_t buff[6] = { 0 }; uint8_t buff[6] = { 0 };
@ -2052,6 +1945,124 @@ int16_t LR11x0::getModem(ModemType_t* modem) {
return(RADIOLIB_ERR_WRONG_MODEM); return(RADIOLIB_ERR_WRONG_MODEM);
} }
int16_t LR11x0::stageMode(RadioModeType_t mode, RadioModeConfig_t* cfg) {
int16_t state;
switch(mode) {
case(RADIOLIB_RADIO_MODE_RX): {
// check active modem
uint8_t modem = RADIOLIB_LR11X0_PACKET_TYPE_NONE;
state = getPacketType(&modem);
RADIOLIB_ASSERT(state);
if((modem != RADIOLIB_LR11X0_PACKET_TYPE_LORA) &&
(modem != RADIOLIB_LR11X0_PACKET_TYPE_GFSK)) {
return(RADIOLIB_ERR_WRONG_MODEM);
}
// set DIO mapping
if(cfg->receive.timeout != RADIOLIB_LR11X0_RX_TIMEOUT_INF) {
cfg->receive.irqMask |= (1UL << RADIOLIB_IRQ_TIMEOUT);
}
state = setDioIrqParams(getIrqMapped(cfg->receive.irqFlags & cfg->receive.irqMask));
RADIOLIB_ASSERT(state);
// clear interrupt flags
state = clearIrqState(RADIOLIB_LR11X0_IRQ_ALL);
RADIOLIB_ASSERT(state);
// set implicit mode and expected len if applicable
if((this->headerType == RADIOLIB_LR11X0_LORA_HEADER_IMPLICIT) && (modem == RADIOLIB_LR11X0_PACKET_TYPE_LORA)) {
state = setPacketParamsLoRa(this->preambleLengthLoRa, this->headerType, this->implicitLen, this->crcTypeLoRa, this->invertIQEnabled);
RADIOLIB_ASSERT(state);
}
this->rxTimeout = cfg->receive.timeout;
} break;
case(RADIOLIB_RADIO_MODE_TX): {
// check packet length
if(cfg->transmit.len > RADIOLIB_LR11X0_MAX_PACKET_LENGTH) {
return(RADIOLIB_ERR_PACKET_TOO_LONG);
}
// maximum packet length is decreased by 1 when address filtering is active
if((this->addrComp != RADIOLIB_LR11X0_GFSK_ADDR_FILTER_DISABLED) && (cfg->transmit.len > RADIOLIB_LR11X0_MAX_PACKET_LENGTH - 1)) {
return(RADIOLIB_ERR_PACKET_TOO_LONG);
}
// set packet Length
state = RADIOLIB_ERR_NONE;
uint8_t modem = RADIOLIB_LR11X0_PACKET_TYPE_NONE;
state = getPacketType(&modem);
RADIOLIB_ASSERT(state);
if(modem == RADIOLIB_LR11X0_PACKET_TYPE_LORA) {
state = setPacketParamsLoRa(this->preambleLengthLoRa, this->headerType, cfg->transmit.len, this->crcTypeLoRa, this->invertIQEnabled);
} else if(modem == RADIOLIB_LR11X0_PACKET_TYPE_GFSK) {
state = setPacketParamsGFSK(this->preambleLengthGFSK, this->preambleDetLength, this->syncWordLength, this->addrComp, this->packetType, cfg->transmit.len, this->crcTypeGFSK, this->whitening);
} else if(modem != RADIOLIB_LR11X0_PACKET_TYPE_LR_FHSS) {
return(RADIOLIB_ERR_UNKNOWN);
}
RADIOLIB_ASSERT(state);
// set DIO mapping
state = setDioIrqParams(RADIOLIB_LR11X0_IRQ_TX_DONE | RADIOLIB_LR11X0_IRQ_TIMEOUT);
RADIOLIB_ASSERT(state);
if(modem == RADIOLIB_LR11X0_PACKET_TYPE_LR_FHSS) {
// in LR-FHSS mode, the packet is built by the device
// TODO add configurable device offset
state = lrFhssBuildFrame(this->lrFhssHdrCount, this->lrFhssCr, this->lrFhssGrid, true, this->lrFhssBw, this->lrFhssHopSeq, 0, cfg->transmit.data, cfg->transmit.len);
RADIOLIB_ASSERT(state);
} else {
// write packet to buffer
state = writeBuffer8(cfg->transmit.data, cfg->transmit.len);
RADIOLIB_ASSERT(state);
}
// clear interrupt flags
state = clearIrqState(RADIOLIB_LR11X0_IRQ_ALL);
RADIOLIB_ASSERT(state);
} break;
default:
return(RADIOLIB_ERR_UNSUPPORTED);
}
this->stagedMode = mode;
return(state);
}
int16_t LR11x0::launchMode() {
int16_t state;
switch(this->stagedMode) {
case(RADIOLIB_RADIO_MODE_RX): {
this->mod->setRfSwitchState(Module::MODE_RX);
state = setRx(this->rxTimeout);
} break;
case(RADIOLIB_RADIO_MODE_TX): {
this->mod->setRfSwitchState(Module::MODE_TX);
state = setTx(RADIOLIB_LR11X0_TX_TIMEOUT_NONE);
RADIOLIB_ASSERT(state);
// wait for BUSY to go low (= PA ramp up done)
while(this->mod->hal->digitalRead(this->mod->getGpio())) {
this->mod->hal->yield();
}
} break;
default:
return(RADIOLIB_ERR_UNSUPPORTED);
}
this->stagedMode = RADIOLIB_RADIO_MODE_NONE;
return(state);
}
int16_t LR11x0::modSetup(float tcxoVoltage, uint8_t modem) { int16_t LR11x0::modSetup(float tcxoVoltage, uint8_t modem) {
this->mod->init(); this->mod->init();
this->mod->hal->pinMode(this->mod->getIrq(), this->mod->hal->GpioModeInput); this->mod->hal->pinMode(this->mod->getIrq(), this->mod->hal->GpioModeInput);
@ -2334,12 +2345,12 @@ int16_t LR11x0::readRegMem32(uint32_t addr, uint32_t* data, size_t len) {
return(state); return(state);
} }
int16_t LR11x0::writeBuffer8(uint8_t* data, size_t len) { int16_t LR11x0::writeBuffer8(const uint8_t* data, size_t len) {
// check maximum size // check maximum size
if(len > RADIOLIB_LR11X0_SPI_MAX_READ_WRITE_LEN) { if(len > RADIOLIB_LR11X0_SPI_MAX_READ_WRITE_LEN) {
return(RADIOLIB_ERR_SPI_CMD_INVALID); return(RADIOLIB_ERR_SPI_CMD_INVALID);
} }
return(this->SPIcommand(RADIOLIB_LR11X0_CMD_WRITE_BUFFER, true, data, len)); return(this->SPIcommand(RADIOLIB_LR11X0_CMD_WRITE_BUFFER, true, const_cast<uint8_t*>(data), len));
} }
int16_t LR11x0::readBuffer8(uint8_t* data, size_t len, size_t offset) { int16_t LR11x0::readBuffer8(uint8_t* data, size_t len, size_t offset) {

View file

@ -877,6 +877,7 @@ class LR11x0: public PhysicalLayer {
using PhysicalLayer::transmit; using PhysicalLayer::transmit;
using PhysicalLayer::receive; using PhysicalLayer::receive;
using PhysicalLayer::startTransmit; using PhysicalLayer::startTransmit;
using PhysicalLayer::startReceive;
using PhysicalLayer::readData; using PhysicalLayer::readData;
/*! /*!
@ -1073,16 +1074,6 @@ class LR11x0: public PhysicalLayer {
*/ */
void clearPacketSentAction() override; void clearPacketSentAction() override;
/*!
\brief Interrupt-driven binary transmit method.
Overloads for string-based transmissions are implemented in PhysicalLayer.
\param data Binary data to be sent.
\param len Number of bytes to send.
\param addr Address to send the data to. Will only be added if address filtering was enabled.
\returns \ref status_codes
*/
int16_t startTransmit(const uint8_t* data, size_t len, uint8_t addr = 0) override;
/*! /*!
\brief Clean up after transmission is done. \brief Clean up after transmission is done.
\returns \ref status_codes \returns \ref status_codes
@ -1097,20 +1088,6 @@ class LR11x0: public PhysicalLayer {
*/ */
int16_t startReceive() override; int16_t startReceive() override;
/*!
\brief Interrupt-driven receive method. IRQ1 will be activated when full packet is received.
\param timeout Raw timeout value, expressed as multiples of 1/32.768 kHz (approximately 30.52 us).
Defaults to RADIOLIB_LR11X0_RX_TIMEOUT_INF for infinite timeout (Rx continuous mode),
set to RADIOLIB_LR11X0_RX_TIMEOUT_NONE for no timeout (Rx single mode).
If timeout other than infinite is set, signal will be generated on IRQ1.
\param irqFlags Sets the IRQ flags that will trigger IRQ1, defaults to RADIOLIB_LR11X0_IRQ_RX_DONE.
\param irqMask Only for PhysicalLayer compatibility, not used.
\param len Only for PhysicalLayer compatibility, not used.
\returns \ref status_codes
*/
int16_t startReceive(uint32_t timeout, uint32_t irqFlags = RADIOLIB_LR11X0_IRQ_RX_DONE, uint32_t irqMask = 0, size_t len = 0);
/*! /*!
\brief Reads the current IRQ status. \brief Reads the current IRQ status.
\returns IRQ status bits \returns IRQ status bits
@ -1622,6 +1599,12 @@ class LR11x0: public PhysicalLayer {
*/ */
int16_t calibrateImageRejection(float freqMin, float freqMax); int16_t calibrateImageRejection(float freqMin, float freqMax);
/*! \copydoc PhysicalLayer::stageMode */
int16_t stageMode(RadioModeType_t mode, RadioModeConfig_t* cfg) override;
/*! \copydoc PhysicalLayer::launchMode */
int16_t launchMode() override;
#if !RADIOLIB_GODMODE && !RADIOLIB_LOW_LEVEL #if !RADIOLIB_GODMODE && !RADIOLIB_LOW_LEVEL
protected: protected:
#endif #endif
@ -1630,7 +1613,7 @@ class LR11x0: public PhysicalLayer {
// LR11x0 SPI command implementations // LR11x0 SPI command implementations
int16_t writeRegMem32(uint32_t addr, const uint32_t* data, size_t len); int16_t writeRegMem32(uint32_t addr, const uint32_t* data, size_t len);
int16_t readRegMem32(uint32_t addr, uint32_t* data, size_t len); int16_t readRegMem32(uint32_t addr, uint32_t* data, size_t len);
int16_t writeBuffer8(uint8_t* data, size_t len); int16_t writeBuffer8(const uint8_t* data, size_t len);
int16_t readBuffer8(uint8_t* data, size_t len, size_t offset); int16_t readBuffer8(uint8_t* data, size_t len, size_t offset);
int16_t clearRxBuffer(void); int16_t clearRxBuffer(void);
int16_t writeRegMemMask32(uint32_t addr, uint32_t mask, uint32_t data); int16_t writeRegMemMask32(uint32_t addr, uint32_t mask, uint32_t data);
@ -1829,6 +1812,7 @@ class LR11x0: public PhysicalLayer {
uint8_t wifiScanMode = 0; uint8_t wifiScanMode = 0;
bool gnss = false; bool gnss = false;
uint32_t rxTimeout = 0;
int16_t modSetup(float tcxoVoltage, uint8_t modem); int16_t modSetup(float tcxoVoltage, uint8_t modem);
static int16_t SPIparseStatus(uint8_t in); static int16_t SPIparseStatus(uint8_t in);