[SX128x] Implement staged modes

This commit is contained in:
jgromes 2025-02-03 20:33:55 +01:00
parent a8bbdc6eaa
commit c0bcc219a9
2 changed files with 130 additions and 131 deletions

View file

@ -513,70 +513,6 @@ void SX128x::clearPacketSentAction() {
this->clearDio1Action(); this->clearDio1Action();
} }
int16_t SX128x::startTransmit(const uint8_t* data, size_t len, uint8_t addr) {
// suppress unused variable warning
(void)addr;
// check packet length
if(len > RADIOLIB_SX128X_MAX_PACKET_LENGTH) {
return(RADIOLIB_ERR_PACKET_TOO_LONG);
}
// set packet Length
int16_t state = RADIOLIB_ERR_NONE;
uint8_t modem = getPacketType();
if(modem == RADIOLIB_SX128X_PACKET_TYPE_LORA) {
state = setPacketParamsLoRa(this->preambleLengthLoRa, this->headerType, len, this->crcLoRa, this->invertIQEnabled);
} else if((modem == RADIOLIB_SX128X_PACKET_TYPE_GFSK) || (modem == RADIOLIB_SX128X_PACKET_TYPE_FLRC)) {
state = setPacketParamsGFSK(this->preambleLengthGFSK, this->syncWordLen, this->syncWordMatch, this->crcGFSK, this->whitening, len);
} else if(modem == RADIOLIB_SX128X_PACKET_TYPE_BLE) {
state = setPacketParamsBLE(this->connectionState, this->crcBLE, this->bleTestPayload, this->whitening);
} else {
return(RADIOLIB_ERR_WRONG_MODEM);
}
RADIOLIB_ASSERT(state);
// update output power
state = setTxParams(this->power);
RADIOLIB_ASSERT(state);
// set buffer pointers
state = setBufferBaseAddress();
RADIOLIB_ASSERT(state);
// write packet to buffer
if(modem == RADIOLIB_SX128X_PACKET_TYPE_BLE) {
// first 2 bytes of BLE payload are PDU header
state = writeBuffer(const_cast<uint8_t*>(data), len, 2);
RADIOLIB_ASSERT(state);
} else {
state = writeBuffer(const_cast<uint8_t*>(data), len);
RADIOLIB_ASSERT(state);
}
// set DIO mapping
state = setDioIrqParams(RADIOLIB_SX128X_IRQ_TX_DONE | RADIOLIB_SX128X_IRQ_RX_TX_TIMEOUT, RADIOLIB_SX128X_IRQ_TX_DONE);
RADIOLIB_ASSERT(state);
// clear interrupt flags
state = clearIrqStatus();
RADIOLIB_ASSERT(state);
// set RF switch (if present)
this->mod->setRfSwitchState(Module::MODE_TX);
// start transmission
state = setTx(RADIOLIB_SX128X_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 SX128x::finishTransmit() { int16_t SX128x::finishTransmit() {
// clear interrupt flags // clear interrupt flags
clearIrqStatus(); clearIrqStatus();
@ -589,49 +525,6 @@ int16_t SX128x::startReceive() {
return(this->startReceive(RADIOLIB_SX128X_RX_TIMEOUT_INF, RADIOLIB_IRQ_RX_DEFAULT_FLAGS, RADIOLIB_IRQ_RX_DEFAULT_MASK, 0)); return(this->startReceive(RADIOLIB_SX128X_RX_TIMEOUT_INF, RADIOLIB_IRQ_RX_DEFAULT_FLAGS, RADIOLIB_IRQ_RX_DEFAULT_MASK, 0));
} }
int16_t SX128x::startReceive(uint16_t timeout, RadioLibIrqFlags_t irqFlags, RadioLibIrqFlags_t irqMask, size_t len) {
// in implicit header mode, use the provided length if it is nonzero
// otherwise we trust the user has previously set the payload length manually
if((this->headerType == RADIOLIB_SX128X_LORA_HEADER_IMPLICIT) && (len != 0)) {
this->payloadLen = len;
}
// check active modem
if(getPacketType() == RADIOLIB_SX128X_PACKET_TYPE_RANGING) {
return(RADIOLIB_ERR_WRONG_MODEM);
}
// set DIO mapping
if(timeout != RADIOLIB_SX128X_RX_TIMEOUT_INF) {
irqMask |= (1UL << RADIOLIB_IRQ_TIMEOUT);
}
int16_t state = setDioIrqParams(getIrqMapped(irqFlags), getIrqMapped(irqMask));
RADIOLIB_ASSERT(state);
// set buffer pointers
state = setBufferBaseAddress();
RADIOLIB_ASSERT(state);
// clear interrupt flags
state = clearIrqStatus();
RADIOLIB_ASSERT(state);
// set implicit mode and expected len if applicable
if((this->headerType == RADIOLIB_SX128X_LORA_HEADER_IMPLICIT) && (getPacketType() == RADIOLIB_SX128X_PACKET_TYPE_LORA)) {
state = setPacketParamsLoRa(this->preambleLengthLoRa, this->headerType, this->payloadLen, this->crcLoRa, 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);
}
int16_t SX128x::readData(uint8_t* data, size_t len) { int16_t SX128x::readData(uint8_t* data, size_t len) {
// check active modem // check active modem
if(getPacketType() == RADIOLIB_SX128X_PACKET_TYPE_RANGING) { if(getPacketType() == RADIOLIB_SX128X_PACKET_TYPE_RANGING) {
@ -1493,6 +1386,128 @@ int16_t SX128x::invertIQ(bool enable) {
return(setPacketParamsLoRa(this->preambleLengthLoRa, this->headerType, this->payloadLen, this->crcLoRa, this->invertIQEnabled)); return(setPacketParamsLoRa(this->preambleLengthLoRa, this->headerType, this->payloadLen, this->crcLoRa, this->invertIQEnabled));
} }
int16_t SX128x::stageMode(RadioModeType_t mode, RadioModeConfig_t* cfg) {
int16_t state;
switch(mode) {
case(RADIOLIB_RADIO_MODE_RX): {
// in implicit header mode, use the provided length if it is nonzero
// otherwise we trust the user has previously set the payload length manually
if((this->headerType == RADIOLIB_SX128X_LORA_HEADER_IMPLICIT) && (cfg->receive.len != 0)) {
this->payloadLen = cfg->receive.len;
}
// check active modem
if(getPacketType() == RADIOLIB_SX128X_PACKET_TYPE_RANGING) {
return(RADIOLIB_ERR_WRONG_MODEM);
}
// set DIO mapping
if(cfg->receive.timeout != RADIOLIB_SX128X_RX_TIMEOUT_INF) {
cfg->receive.irqMask |= (1UL << RADIOLIB_IRQ_TIMEOUT);
}
state = setDioIrqParams(getIrqMapped(cfg->receive.irqFlags), getIrqMapped(cfg->receive.irqMask));
RADIOLIB_ASSERT(state);
// set buffer pointers
state = setBufferBaseAddress();
RADIOLIB_ASSERT(state);
// clear interrupt flags
state = clearIrqStatus();
RADIOLIB_ASSERT(state);
// set implicit mode and expected len if applicable
if((this->headerType == RADIOLIB_SX128X_LORA_HEADER_IMPLICIT) && (getPacketType() == RADIOLIB_SX128X_PACKET_TYPE_LORA)) {
state = setPacketParamsLoRa(this->preambleLengthLoRa, this->headerType, this->payloadLen, this->crcLoRa, this->invertIQEnabled);
RADIOLIB_ASSERT(state);
}
this->rxTimeout = cfg->receive.timeout;
} break;
case(RADIOLIB_RADIO_MODE_TX): {
// check packet length
if(cfg->transmit.len > RADIOLIB_SX128X_MAX_PACKET_LENGTH) {
return(RADIOLIB_ERR_PACKET_TOO_LONG);
}
// set packet Length
uint8_t modem = getPacketType();
if(modem == RADIOLIB_SX128X_PACKET_TYPE_LORA) {
state = setPacketParamsLoRa(this->preambleLengthLoRa, this->headerType, cfg->transmit.len, this->crcLoRa, this->invertIQEnabled);
} else if((modem == RADIOLIB_SX128X_PACKET_TYPE_GFSK) || (modem == RADIOLIB_SX128X_PACKET_TYPE_FLRC)) {
state = setPacketParamsGFSK(this->preambleLengthGFSK, this->syncWordLen, this->syncWordMatch, this->crcGFSK, this->whitening, cfg->transmit.len);
} else if(modem == RADIOLIB_SX128X_PACKET_TYPE_BLE) {
state = setPacketParamsBLE(this->connectionState, this->crcBLE, this->bleTestPayload, this->whitening);
} else {
return(RADIOLIB_ERR_WRONG_MODEM);
}
RADIOLIB_ASSERT(state);
// update output power
state = setTxParams(this->power);
RADIOLIB_ASSERT(state);
// set buffer pointers
state = setBufferBaseAddress();
RADIOLIB_ASSERT(state);
// write packet to buffer
if(modem == RADIOLIB_SX128X_PACKET_TYPE_BLE) {
// first 2 bytes of BLE payload are PDU header
state = writeBuffer(cfg->transmit.data, cfg->transmit.len, 2);
RADIOLIB_ASSERT(state);
} else {
state = writeBuffer(cfg->transmit.data, cfg->transmit.len);
RADIOLIB_ASSERT(state);
}
// set DIO mapping
state = setDioIrqParams(RADIOLIB_SX128X_IRQ_TX_DONE | RADIOLIB_SX128X_IRQ_RX_TX_TIMEOUT, RADIOLIB_SX128X_IRQ_TX_DONE);
RADIOLIB_ASSERT(state);
// clear interrupt flags
state = clearIrqStatus();
RADIOLIB_ASSERT(state);
} break;
default:
return(RADIOLIB_ERR_UNSUPPORTED);
}
this->stagedMode = mode;
return(state);
}
int16_t SX128x::launchMode() {
int16_t state;
switch(this->stagedMode) {
case(RADIOLIB_RADIO_MODE_RX): {
this->mod->setRfSwitchState(Module::MODE_RX);
state = setRx(this->rxTimeout);
RADIOLIB_ASSERT(state);
} break;
case(RADIOLIB_RADIO_MODE_TX): {
this->mod->setRfSwitchState(Module::MODE_TX);
state = setTx(RADIOLIB_SX128X_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);
}
#if !RADIOLIB_EXCLUDE_DIRECT_RECEIVE #if !RADIOLIB_EXCLUDE_DIRECT_RECEIVE
void SX128x::setDirectAction(void (*func)(void)) { void SX128x::setDirectAction(void (*func)(void)) {
// SX128x is unable to perform direct mode reception // SX128x is unable to perform direct mode reception

View file

@ -354,6 +354,7 @@ class SX128x: 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;
/*! /*!
@ -530,16 +531,6 @@ class SX128x: 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. Unsupported, compatibility only.
\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
@ -554,20 +545,6 @@ class SX128x: public PhysicalLayer {
*/ */
int16_t startReceive() override; int16_t startReceive() override;
/*!
\brief Interrupt-driven receive method. DIO1 will be activated when full packet is received.
\param timeout Raw timeout value, expressed as multiples of 15.625 us. Defaults to
RADIOLIB_SX128X_RX_TIMEOUT_INF for infinite timeout (Rx continuous mode),
set to RADIOLIB_SX128X_RX_TIMEOUT_NONE for no timeout (Rx single mode).
If timeout other than infinite is set, signal will be generated on DIO1.
\param irqFlags Sets the IRQ flags, defaults to RX done, RX timeout, CRC error and header error.
\param irqMask Sets the mask of IRQ flags that will trigger DIO1, defaults to RX done.
\param len Only for PhysicalLayer compatibility, not used.
\returns \ref status_codes
*/
int16_t startReceive(uint16_t timeout, RadioLibIrqFlags_t irqFlags = RADIOLIB_IRQ_RX_DEFAULT_FLAGS, RadioLibIrqFlags_t irqMask = RADIOLIB_IRQ_RX_DEFAULT_MASK, size_t len = 0);
/*! /*!
\brief Reads the current IRQ status. \brief Reads the current IRQ status.
\returns IRQ status bits \returns IRQ status bits
@ -863,6 +840,12 @@ class SX128x: public PhysicalLayer {
\returns \ref status_codes \returns \ref status_codes
*/ */
int16_t invertIQ(bool enable) override; int16_t invertIQ(bool enable) override;
/*! \copydoc PhysicalLayer::stageMode */
int16_t stageMode(RadioModeType_t mode, RadioModeConfig_t* cfg) override;
/*! \copydoc PhysicalLayer::launchMode */
int16_t launchMode() override;
#if !RADIOLIB_EXCLUDE_DIRECT_RECEIVE #if !RADIOLIB_EXCLUDE_DIRECT_RECEIVE
/*! /*!
@ -920,6 +903,7 @@ class SX128x: public PhysicalLayer {
// common parameters // common parameters
uint8_t power = 0; uint8_t power = 0;
uint32_t rxTimeout = 0;
// cached LoRa parameters // cached LoRa parameters
uint8_t invertIQEnabled = RADIOLIB_SX128X_LORA_IQ_STANDARD; uint8_t invertIQEnabled = RADIOLIB_SX128X_LORA_IQ_STANDARD;