[LoRaWAN] A-synchronize transmissions (#1410)

This commit is contained in:
StevenCellist 2025-02-03 00:15:50 +01:00
parent c43b89dc42
commit d6b6a0bf51
2 changed files with 66 additions and 8 deletions

View file

@ -906,14 +906,22 @@ int16_t LoRaWANNode::activateOTAA(uint8_t joinDr, LoRaWANJoinEvent_t *joinEvent)
RADIOLIB_ASSERT(state); RADIOLIB_ASSERT(state);
// calculate JoinRequest time-on-air in milliseconds // calculate JoinRequest time-on-air in milliseconds
RadioLibTime_t toa = this->phyLayer->getTimeOnAir(RADIOLIB_LORAWAN_JOIN_REQUEST_LEN) / 1000;
if(this->dwellTimeUp) { if(this->dwellTimeUp) {
RadioLibTime_t toa = this->phyLayer->getTimeOnAir(RADIOLIB_LORAWAN_JOIN_REQUEST_LEN) / 1000;
if(toa > this->dwellTimeUp) { if(toa > this->dwellTimeUp) {
RADIOLIB_DEBUG_PROTOCOL_PRINTLN("Dwell time exceeded: ToA = %lu, max = %d", (unsigned long)toa, this->dwellTimeUp); RADIOLIB_DEBUG_PROTOCOL_PRINTLN("Dwell time exceeded: ToA = %lu, max = %d", (unsigned long)toa, this->dwellTimeUp);
return(RADIOLIB_ERR_DWELL_TIME_EXCEEDED); return(RADIOLIB_ERR_DWELL_TIME_EXCEEDED);
} }
} }
RadioModeConfig_t modeCfg;
modeCfg.transmit.data = joinRequestMsg;
modeCfg.transmit.len = RADIOLIB_LORAWAN_JOIN_REQUEST_LEN;
modeCfg.transmit.addr = 0;
state = this->phyLayer->stageMode(RADIOLIB_RADIO_MODE_TX, modeCfg);
RADIOLIB_ASSERT(state);
// if requested, delay until transmitting JoinRequest // if requested, delay until transmitting JoinRequest
RadioLibTime_t tNow = mod->hal->millis(); RadioLibTime_t tNow = mod->hal->millis();
if(this->tUplink > tNow) { if(this->tUplink > tNow) {
@ -923,8 +931,26 @@ int16_t LoRaWANNode::activateOTAA(uint8_t joinDr, LoRaWANJoinEvent_t *joinEvent)
} }
} }
// send it // start transmission
state = this->phyLayer->transmit(joinRequestMsg, RADIOLIB_LORAWAN_JOIN_REQUEST_LEN); state = this->phyLayer->launchMode();
RADIOLIB_ASSERT(state);
// sleep for the duration of the transmission
mod->hal->delay(toa);
RadioLibTime_t txEnd = mod->hal->millis();
// wait for an additional transmission duration as Tx timeout period
while(!mod->hal->digitalRead(mod->getIrq())) {
// yield for multi-threaded platforms
mod->hal->yield();
if(mod->hal->millis() > txEnd + toa) {
return(RADIOLIB_ERR_TX_TIMEOUT);
}
}
state = this->phyLayer->finishTransmit();
// set the timestamp so that we can measure when to start receiving
this->rxDelayStart = mod->hal->millis(); this->rxDelayStart = mod->hal->millis();
RADIOLIB_ASSERT(state); RADIOLIB_ASSERT(state);
RADIOLIB_DEBUG_PROTOCOL_PRINTLN("JoinRequest sent (DevNonce = %d) <-- Rx Delay start", this->devNonce); RADIOLIB_DEBUG_PROTOCOL_PRINTLN("JoinRequest sent (DevNonce = %d) <-- Rx Delay start", this->devNonce);
@ -935,7 +961,7 @@ int16_t LoRaWANNode::activateOTAA(uint8_t joinDr, LoRaWANJoinEvent_t *joinEvent)
LoRaWANNode::hton<uint16_t>(&this->bufferNonces[RADIOLIB_LORAWAN_NONCES_DEV_NONCE], this->devNonce); LoRaWANNode::hton<uint16_t>(&this->bufferNonces[RADIOLIB_LORAWAN_NONCES_DEV_NONCE], this->devNonce);
// set the Time on Air of the JoinRequest // set the Time on Air of the JoinRequest
this->lastToA = this->phyLayer->getTimeOnAir(RADIOLIB_LORAWAN_JOIN_REQUEST_LEN) / 1000; this->lastToA = toa;
// configure Rx1 and Rx2 delay for JoinAccept message - these are re-configured once a valid JoinAccept is received // configure Rx1 and Rx2 delay for JoinAccept message - these are re-configured once a valid JoinAccept is received
this->rxDelays[1] = RADIOLIB_LORAWAN_JOIN_ACCEPT_DELAY_1_MS; this->rxDelays[1] = RADIOLIB_LORAWAN_JOIN_ACCEPT_DELAY_1_MS;
@ -1270,7 +1296,6 @@ int16_t LoRaWANNode::transmitUplink(const LoRaWANChannel_t* chnl, uint8_t* in, u
Module* mod = this->phyLayer->getMod(); Module* mod = this->phyLayer->getMod();
// check if the Rx windows were closed after sending the previous uplink // check if the Rx windows were closed after sending the previous uplink
// this FORCES a user to call downlink() after an uplink()
if(this->rxDelayEnd < this->rxDelayStart) { if(this->rxDelayEnd < this->rxDelayStart) {
// not enough time elapsed since the last uplink, we may still be in an Rx window // not enough time elapsed since the last uplink, we may still be in an Rx window
return(RADIOLIB_ERR_UPLINK_UNAVAILABLE); return(RADIOLIB_ERR_UPLINK_UNAVAILABLE);
@ -1295,6 +1320,22 @@ int16_t LoRaWANNode::transmitUplink(const LoRaWANChannel_t* chnl, uint8_t* in, u
RADIOLIB_LORAWAN_UPLINK, RADIOLIB_LORAWAN_UPLINK,
this->txPowerMax - 2*this->txPowerSteps); this->txPowerMax - 2*this->txPowerSteps);
RADIOLIB_ASSERT(state); RADIOLIB_ASSERT(state);
// check whether dwell time limitation is exceeded
RadioLibTime_t toa = this->phyLayer->getTimeOnAir(len) / 1000;
if(this->dwellTimeUp) {
if(toa > this->dwellTimeUp) {
RADIOLIB_DEBUG_PROTOCOL_PRINTLN("Dwell time exceeded: ToA = %lu, max = %d", (unsigned long)toa, this->dwellTimeUp);
return(RADIOLIB_ERR_DWELL_TIME_EXCEEDED);
}
}
RadioModeConfig_t modeCfg;
modeCfg.transmit.data = in;
modeCfg.transmit.len = len;
modeCfg.transmit.addr = 0;
state = this->phyLayer->stageMode(RADIOLIB_RADIO_MODE_TX, modeCfg);
RADIOLIB_ASSERT(state);
// if requested, wait until transmitting uplink // if requested, wait until transmitting uplink
tNow = mod->hal->millis(); tNow = mod->hal->millis();
@ -1305,14 +1346,31 @@ int16_t LoRaWANNode::transmitUplink(const LoRaWANChannel_t* chnl, uint8_t* in, u
} }
} }
state = this->phyLayer->transmit(in, len); // start transmission
state = this->phyLayer->launchMode();
RADIOLIB_ASSERT(state);
// sleep for the duration of the transmission
mod->hal->delay(toa);
RadioLibTime_t txEnd = mod->hal->millis();
// wait for an additional transmission duration as Tx timeout period
while(!mod->hal->digitalRead(mod->getIrq())) {
// yield for multi-threaded platforms
mod->hal->yield();
if(mod->hal->millis() > txEnd + toa) {
return(RADIOLIB_ERR_TX_TIMEOUT);
}
}
state = this->phyLayer->finishTransmit();
// set the timestamp so that we can measure when to start receiving // set the timestamp so that we can measure when to start receiving
this->rxDelayStart = mod->hal->millis(); this->rxDelayStart = mod->hal->millis();
RADIOLIB_DEBUG_PROTOCOL_PRINTLN("Uplink sent <-- Rx Delay start"); RADIOLIB_DEBUG_PROTOCOL_PRINTLN("Uplink sent <-- Rx Delay start");
// increase Time on Air of the uplink sequence // increase Time on Air of the uplink sequence
this->lastToA += this->phyLayer->getTimeOnAir(len) / 1000; this->lastToA += toa;
return(state); return(state);
} }

View file

@ -850,7 +850,7 @@ class LoRaWANNode {
500 is the **maximum** value, but it is not a good idea to go anywhere near that. 500 is the **maximum** value, but it is not a good idea to go anywhere near that.
If you have to go above 50 you probably have a bug somewhere. Check your device timing. If you have to go above 50 you probably have a bug somewhere. Check your device timing.
*/ */
RadioLibTime_t scanGuard = 4; RadioLibTime_t scanGuard = 5;
#if !RADIOLIB_GODMODE #if !RADIOLIB_GODMODE
protected: protected: