From c0bcc219a9ffda1e1ea00f761c9e8e0281f1ceeb Mon Sep 17 00:00:00 2001 From: jgromes Date: Mon, 3 Feb 2025 20:33:55 +0100 Subject: [PATCH] [SX128x] Implement staged modes --- src/modules/SX128x/SX128x.cpp | 229 ++++++++++++++++++---------------- src/modules/SX128x/SX128x.h | 32 ++--- 2 files changed, 130 insertions(+), 131 deletions(-) diff --git a/src/modules/SX128x/SX128x.cpp b/src/modules/SX128x/SX128x.cpp index 85fa91f6..fe58c7c0 100644 --- a/src/modules/SX128x/SX128x.cpp +++ b/src/modules/SX128x/SX128x.cpp @@ -513,70 +513,6 @@ void SX128x::clearPacketSentAction() { 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(data), len, 2); - RADIOLIB_ASSERT(state); - } else { - state = writeBuffer(const_cast(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() { // clear interrupt flags 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)); } -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) { // check active modem 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)); } +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 void SX128x::setDirectAction(void (*func)(void)) { // SX128x is unable to perform direct mode reception diff --git a/src/modules/SX128x/SX128x.h b/src/modules/SX128x/SX128x.h index cd143e96..0211ed26 100644 --- a/src/modules/SX128x/SX128x.h +++ b/src/modules/SX128x/SX128x.h @@ -354,6 +354,7 @@ class SX128x: public PhysicalLayer { using PhysicalLayer::transmit; using PhysicalLayer::receive; using PhysicalLayer::startTransmit; + using PhysicalLayer::startReceive; using PhysicalLayer::readData; /*! @@ -530,16 +531,6 @@ class SX128x: public PhysicalLayer { */ 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. \returns \ref status_codes @@ -554,20 +545,6 @@ class SX128x: public PhysicalLayer { */ 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. \returns IRQ status bits @@ -863,6 +840,12 @@ class SX128x: public PhysicalLayer { \returns \ref status_codes */ 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 /*! @@ -920,6 +903,7 @@ class SX128x: public PhysicalLayer { // common parameters uint8_t power = 0; + uint32_t rxTimeout = 0; // cached LoRa parameters uint8_t invertIQEnabled = RADIOLIB_SX128X_LORA_IQ_STANDARD;