diff --git a/src/modules/LR11x0/LR11x0.cpp b/src/modules/LR11x0/LR11x0.cpp index 8aba735d..9a2085ba 100644 --- a/src/modules/LR11x0/LR11x0.cpp +++ b/src/modules/LR11x0/LR11x0.cpp @@ -414,73 +414,6 @@ void LR11x0::clearPacketSentAction() { 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(data), len); - RADIOLIB_ASSERT(state); - - } else { - // write packet to buffer - state = writeBuffer8(const_cast(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() { // clear interrupt flags 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)); } -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() { // there is no dedicated "get IRQ" command, the IRQ bits are sent after the status bytes uint8_t buff[6] = { 0 }; @@ -2052,6 +1945,124 @@ int16_t LR11x0::getModem(ModemType_t* 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) { this->mod->init(); 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); } -int16_t LR11x0::writeBuffer8(uint8_t* data, size_t len) { +int16_t LR11x0::writeBuffer8(const uint8_t* data, size_t len) { // check maximum size if(len > RADIOLIB_LR11X0_SPI_MAX_READ_WRITE_LEN) { 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(data), len)); } int16_t LR11x0::readBuffer8(uint8_t* data, size_t len, size_t offset) { diff --git a/src/modules/LR11x0/LR11x0.h b/src/modules/LR11x0/LR11x0.h index 03455d35..6e95bde3 100644 --- a/src/modules/LR11x0/LR11x0.h +++ b/src/modules/LR11x0/LR11x0.h @@ -877,6 +877,7 @@ class LR11x0: public PhysicalLayer { using PhysicalLayer::transmit; using PhysicalLayer::receive; using PhysicalLayer::startTransmit; + using PhysicalLayer::startReceive; using PhysicalLayer::readData; /*! @@ -1073,16 +1074,6 @@ class LR11x0: 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. 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. \returns \ref status_codes @@ -1097,20 +1088,6 @@ class LR11x0: public PhysicalLayer { */ 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. \returns IRQ status bits @@ -1622,6 +1599,12 @@ class LR11x0: public PhysicalLayer { */ 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 protected: #endif @@ -1630,7 +1613,7 @@ class LR11x0: public PhysicalLayer { // LR11x0 SPI command implementations 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 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 clearRxBuffer(void); int16_t writeRegMemMask32(uint32_t addr, uint32_t mask, uint32_t data); @@ -1829,6 +1812,7 @@ class LR11x0: public PhysicalLayer { uint8_t wifiScanMode = 0; bool gnss = false; + uint32_t rxTimeout = 0; int16_t modSetup(float tcxoVoltage, uint8_t modem); static int16_t SPIparseStatus(uint8_t in);