From 557d2bfcfaa185cb2f88063f2367f3dbf51495ae Mon Sep 17 00:00:00 2001 From: jgromes Date: Sat, 1 Feb 2025 16:55:17 +0000 Subject: [PATCH] [SX126x] Add support for staged Rx/Tx --- src/modules/SX126x/SX126x.cpp | 284 ++++++++++++++++++++-------------- src/modules/SX126x/SX126x.h | 6 + 2 files changed, 174 insertions(+), 116 deletions(-) diff --git a/src/modules/SX126x/SX126x.cpp b/src/modules/SX126x/SX126x.cpp index 777dce09..fa90ea80 100644 --- a/src/modules/SX126x/SX126x.cpp +++ b/src/modules/SX126x/SX126x.cpp @@ -519,112 +519,18 @@ void SX126x::clearChannelScanAction() { } int16_t SX126x::startTransmit(const uint8_t* data, size_t len, uint8_t addr) { - (void)addr; - - // check packet length - if(len > RADIOLIB_SX126X_MAX_PACKET_LENGTH) { - return(RADIOLIB_ERR_PACKET_TOO_LONG); - } - - // maximum packet length is decreased by 1 when address filtering is active - if((RADIOLIB_SX126X_GFSK_ADDRESS_FILT_OFF != RADIOLIB_SX126X_GFSK_ADDRESS_FILT_OFF) && (len > RADIOLIB_SX126X_MAX_PACKET_LENGTH - 1)) { - return(RADIOLIB_ERR_PACKET_TOO_LONG); - } - - // set packet Length - int16_t state = RADIOLIB_ERR_NONE; - uint8_t modem = getPacketType(); - if(modem == RADIOLIB_SX126X_PACKET_TYPE_LORA) { - state = setPacketParams(this->preambleLengthLoRa, this->crcTypeLoRa, len, this->headerType, this->invertIQEnabled); - - } else if(modem == RADIOLIB_SX126X_PACKET_TYPE_GFSK) { - state = setPacketParamsFSK(this->preambleLengthFSK, this->preambleDetLength, this->crcTypeFSK, this->syncWordLength, RADIOLIB_SX126X_GFSK_ADDRESS_FILT_OFF, this->whitening, this->packetType, len); - - } else if(modem != RADIOLIB_SX126X_PACKET_TYPE_LR_FHSS) { - return(RADIOLIB_ERR_UNKNOWN); - - } - RADIOLIB_ASSERT(state); - - // set DIO mapping - if(modem != RADIOLIB_SX126X_PACKET_TYPE_LR_FHSS) { - state = setDioIrqParams(RADIOLIB_SX126X_IRQ_TX_DONE | RADIOLIB_SX126X_IRQ_TIMEOUT, RADIOLIB_SX126X_IRQ_TX_DONE); - } else { - state = setDioIrqParams(RADIOLIB_SX126X_IRQ_TX_DONE | RADIOLIB_SX126X_IRQ_LR_FHSS_HOP, RADIOLIB_SX126X_IRQ_TX_DONE | RADIOLIB_SX126X_IRQ_LR_FHSS_HOP); - } - RADIOLIB_ASSERT(state); - - // set buffer pointers - state = setBufferBaseAddress(); - RADIOLIB_ASSERT(state); - - // write packet to buffer - if(modem != RADIOLIB_SX126X_PACKET_TYPE_LR_FHSS) { - state = writeBuffer(const_cast(data), len); - - } else { - // first, reset the LR-FHSS state machine - state = resetLRFHSS(); - RADIOLIB_ASSERT(state); - - // skip hopping for the first 4 - lrFhssHdrCount blocks - for(int i = 0; i < 4 - this->lrFhssHdrCount; ++i ) { - stepLRFHSS(); + RadioModeConfig_t cfg = { + .transmit = { + .data = const_cast(data), + .len = len, + .addr = addr, } + }; - // in LR-FHSS mode, we need to build the entire packet manually - uint8_t frame[RADIOLIB_SX126X_MAX_PACKET_LENGTH] = { 0 }; - size_t frameLen = 0; - this->lrFhssFrameBitsRem = 0; - this->lrFhssFrameHopsRem = 0; - this->lrFhssHopNum = 0; - state = buildLRFHSSPacket(const_cast(data), len, frame, &frameLen, &this->lrFhssFrameBitsRem, &this->lrFhssFrameHopsRem); - RADIOLIB_ASSERT(state); - - // FIXME check max len for FHSS - state = writeBuffer(frame, frameLen); - RADIOLIB_ASSERT(state); - - // activate hopping - uint8_t hopCfg[] = { RADIOLIB_SX126X_HOPPING_ENABLED, (uint8_t)frameLen, (uint8_t)this->lrFhssFrameHopsRem }; - state = writeRegister(RADIOLIB_SX126X_REG_HOPPING_ENABLE, hopCfg, 3); - RADIOLIB_ASSERT(state); - - // write the initial hopping table - uint8_t initHops = this->lrFhssFrameHopsRem; - if(initHops > 16) { - initHops = 16; - }; - for(size_t i = 0; i < initHops; i++) { - // set the hop frequency and symbols - state = this->setLRFHSSHop(i); - RADIOLIB_ASSERT(state); - } - - } + int16_t state = this->stageMode(RADIOLIB_RADIO_MODE_TX, cfg); RADIOLIB_ASSERT(state); - // clear interrupt flags - state = clearIrqStatus(); - RADIOLIB_ASSERT(state); - - // fix sensitivity - state = fixSensitivity(); - RADIOLIB_ASSERT(state); - - // set RF switch (if present) - this->mod->setRfSwitchState(this->txMode); - - // start transmission - state = setTx(RADIOLIB_SX126X_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); + return(this->launchMode()); } int16_t SX126x::finishTransmit() { @@ -641,22 +547,18 @@ int16_t SX126x::startReceive() { } int16_t SX126x::startReceive(uint32_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_SX126X_LORA_HEADER_IMPLICIT) && (len != 0)) { - this->implicitLen = len; - } + RadioModeConfig_t cfg = { + .receive = { + .timeout = timeout, + .irqFlags = irqFlags, + .irqMask = irqMask, + .len = len, + } + }; - int16_t state = startReceiveCommon(timeout, irqFlags, irqMask); + int16_t state = this->stageMode(RADIOLIB_RADIO_MODE_RX, cfg); RADIOLIB_ASSERT(state); - - // set RF switch (if present) - this->mod->setRfSwitchState(Module::MODE_RX); - - // set mode to receive - state = setRx(timeout); - - return(state); + return(this->launchMode()); } int16_t SX126x::startReceiveDutyCycle(uint32_t rxPeriod, uint32_t sleepPeriod, RadioLibIrqFlags_t irqFlags, RadioLibIrqFlags_t irqMask) { @@ -1666,6 +1568,156 @@ int16_t SX126x::getModem(ModemType_t* modem) { return(RADIOLIB_ERR_WRONG_MODEM); } +int16_t SX126x::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_SX126X_LORA_HEADER_IMPLICIT) && (cfg.receive.len != 0)) { + this->implicitLen = cfg.receive.len; + } + + state = startReceiveCommon(cfg.receive.timeout, cfg.receive.irqFlags, cfg.receive.irqMask); + RADIOLIB_ASSERT(state); + + // set RF switch (if present) + this->mod->setRfSwitchState(Module::MODE_RX); + } break; + + case(RADIOLIB_RADIO_MODE_TX): { + // check packet length + if(cfg.transmit.len > RADIOLIB_SX126X_MAX_PACKET_LENGTH) { + return(RADIOLIB_ERR_PACKET_TOO_LONG); + } + + // maximum packet length is decreased by 1 when address filtering is active + if((RADIOLIB_SX126X_GFSK_ADDRESS_FILT_OFF != RADIOLIB_SX126X_GFSK_ADDRESS_FILT_OFF) && + (cfg.transmit.len > RADIOLIB_SX126X_MAX_PACKET_LENGTH - 1)) { + return(RADIOLIB_ERR_PACKET_TOO_LONG); + } + + // set packet Length + int16_t state = RADIOLIB_ERR_NONE; + uint8_t modem = getPacketType(); + if(modem == RADIOLIB_SX126X_PACKET_TYPE_LORA) { + state = setPacketParams(this->preambleLengthLoRa, this->crcTypeLoRa, cfg.transmit.len, this->headerType, this->invertIQEnabled); + + } else if(modem == RADIOLIB_SX126X_PACKET_TYPE_GFSK) { + state = setPacketParamsFSK(this->preambleLengthFSK, this->preambleDetLength, this->crcTypeFSK, this->syncWordLength, RADIOLIB_SX126X_GFSK_ADDRESS_FILT_OFF, this->whitening, this->packetType, cfg.transmit.len); + + } else if(modem != RADIOLIB_SX126X_PACKET_TYPE_LR_FHSS) { + return(RADIOLIB_ERR_UNKNOWN); + + } + RADIOLIB_ASSERT(state); + + // set DIO mapping + if(modem != RADIOLIB_SX126X_PACKET_TYPE_LR_FHSS) { + state = setDioIrqParams(RADIOLIB_SX126X_IRQ_TX_DONE | RADIOLIB_SX126X_IRQ_TIMEOUT, RADIOLIB_SX126X_IRQ_TX_DONE); + } else { + state = setDioIrqParams(RADIOLIB_SX126X_IRQ_TX_DONE | RADIOLIB_SX126X_IRQ_LR_FHSS_HOP, RADIOLIB_SX126X_IRQ_TX_DONE | RADIOLIB_SX126X_IRQ_LR_FHSS_HOP); + } + RADIOLIB_ASSERT(state); + + // set buffer pointers + state = setBufferBaseAddress(); + RADIOLIB_ASSERT(state); + + // write packet to buffer + if(modem != RADIOLIB_SX126X_PACKET_TYPE_LR_FHSS) { + state = writeBuffer(const_cast(cfg.transmit.data), cfg.transmit.len); + + } else { + // first, reset the LR-FHSS state machine + state = resetLRFHSS(); + RADIOLIB_ASSERT(state); + + // skip hopping for the first 4 - lrFhssHdrCount blocks + for(int i = 0; i < 4 - this->lrFhssHdrCount; ++i ) { + stepLRFHSS(); + } + + // in LR-FHSS mode, we need to build the entire packet manually + uint8_t frame[RADIOLIB_SX126X_MAX_PACKET_LENGTH] = { 0 }; + size_t frameLen = 0; + this->lrFhssFrameBitsRem = 0; + this->lrFhssFrameHopsRem = 0; + this->lrFhssHopNum = 0; + state = buildLRFHSSPacket(const_cast(cfg.transmit.data), cfg.transmit.len, frame, &frameLen, &this->lrFhssFrameBitsRem, &this->lrFhssFrameHopsRem); + RADIOLIB_ASSERT(state); + + // FIXME check max len for FHSS + state = writeBuffer(frame, frameLen); + RADIOLIB_ASSERT(state); + + // activate hopping + uint8_t hopCfg[] = { RADIOLIB_SX126X_HOPPING_ENABLED, (uint8_t)frameLen, (uint8_t)this->lrFhssFrameHopsRem }; + state = writeRegister(RADIOLIB_SX126X_REG_HOPPING_ENABLE, hopCfg, 3); + RADIOLIB_ASSERT(state); + + // write the initial hopping table + uint8_t initHops = this->lrFhssFrameHopsRem; + if(initHops > 16) { + initHops = 16; + }; + for(size_t i = 0; i < initHops; i++) { + // set the hop frequency and symbols + state = this->setLRFHSSHop(i); + RADIOLIB_ASSERT(state); + } + + } + RADIOLIB_ASSERT(state); + + // clear interrupt flags + state = clearIrqStatus(); + RADIOLIB_ASSERT(state); + + // fix sensitivity + state = fixSensitivity(); + RADIOLIB_ASSERT(state); + + // set RF switch (if present) + this->mod->setRfSwitchState(this->txMode); + } break; + + default: + return(RADIOLIB_ERR_UNSUPPORTED); + } + + this->stagedMode = mode; + this->stagedConfig = cfg; + + return(state); +} + +int16_t SX126x::launchMode() { + int16_t state; + switch(this->stagedMode) { + case(RADIOLIB_RADIO_MODE_RX): { + state = setRx(this->stagedConfig.receive.timeout); + } break; + + case(RADIOLIB_RADIO_MODE_TX): { + state = setTx(RADIOLIB_SX126X_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 void SX126x::setDirectAction(void (*func)(void)) { setDio1Action(func); diff --git a/src/modules/SX126x/SX126x.h b/src/modules/SX126x/SX126x.h index 371926ca..05f7316e 100644 --- a/src/modules/SX126x/SX126x.h +++ b/src/modules/SX126x/SX126x.h @@ -1145,6 +1145,12 @@ class SX126x: public PhysicalLayer { \returns \ref status_codes */ int16_t getModem(ModemType_t* modem) override; + + /*! \copydoc PhysicalLayer::stageMode */ + int16_t stageMode(RadioModeType_t mode, RadioModeConfig_t cfg); + + /*! \copydoc PhysicalLayer::launchMode */ + int16_t launchMode(); #if !RADIOLIB_EXCLUDE_DIRECT_RECEIVE /*!