[SX126x] Add support for staged Rx/Tx
This commit is contained in:
parent
61c5bdb831
commit
557d2bfcfa
2 changed files with 174 additions and 116 deletions
|
@ -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<uint8_t*>(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<uint8_t*>(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<uint8_t*>(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<uint8_t*>(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<uint8_t*>(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);
|
||||
|
|
|
@ -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
|
||||
/*!
|
||||
|
|
Loading…
Add table
Reference in a new issue