Skip to content

Commit 828815c

Browse files
author
Hasnain Virk
committed
Adding precise timing for receive delays
RX1 and 2 delays needed to be more precise and aggregate tx time was drifiting because of timing difference between actual tx interrupt and our processing of that interrupt ever so slightly. We now take a timestamp of the tx interrupt and take a time diff while instantiating delay timers. The timestamp is then used to update the aggregate tx time. Two new methods are introduced in the LoRaMac class which provide current timing and current receive slot. These functions are used by LoRaWANStack for its processing.
1 parent ed9a1f1 commit 828815c

File tree

4 files changed

+74
-55
lines changed

4 files changed

+74
-55
lines changed

features/lorawan/LoRaWANStack.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,7 @@ lorawan_status_t LoRaWANStack::acquire_backoff_metadata(int& backoff)
503503
****************************************************************************/
504504
void LoRaWANStack::tx_interrupt_handler(void)
505505
{
506+
_tx_timestamp = _loramac.get_current_time();
506507
const int ret = _queue->call(this, &LoRaWANStack::process_transmission);
507508
MBED_ASSERT(ret != 0);
508509
(void)ret;
@@ -565,7 +566,7 @@ void LoRaWANStack::process_transmission_timeout()
565566
void LoRaWANStack::process_transmission(void)
566567
{
567568
tr_debug("Transmission completed");
568-
_loramac.on_radio_tx_done();
569+
_loramac.on_radio_tx_done(_tx_timestamp);
569570

570571
make_tx_metadata_available();
571572

@@ -680,10 +681,12 @@ void LoRaWANStack::process_reception(const uint8_t *const payload, uint16_t size
680681

681682
void LoRaWANStack::process_reception_timeout(bool is_timeout)
682683
{
684+
rx_slot_t slot = _loramac.get_current_slot();
685+
683686
// when is_timeout == false, a CRC error took place in the received frame
684687
// we treat that erroneous frame as no frame received at all, hence handle
685688
// it exactly as we would handle timeout
686-
rx_slot_t slot = _loramac.on_radio_rx_timeout(is_timeout);
689+
_loramac.on_radio_rx_timeout(is_timeout);
687690

688691
if (slot == RX_SLOT_WIN_2 && !_loramac.nwk_joined()) {
689692
state_controller(DEVICE_STATE_JOINING);

features/lorawan/LoRaWANStack.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -548,6 +548,7 @@ class LoRaWANStack: private mbed::NonCopyable<LoRaWANStack> {
548548
volatile bool _ready_for_rx;
549549
uint8_t _rx_payload[LORAMAC_PHY_MAXPAYLOAD];
550550
events::EventQueue *_queue;
551+
lorawan_time_t _tx_timestamp;
551552

552553
#if defined(LORAWAN_COMPLIANCE_TEST)
553554

features/lorawan/lorastack/mac/LoRaMac.cpp

Lines changed: 56 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -189,41 +189,14 @@ void LoRaMac::post_process_mlme_ind()
189189
_mlme_indication.pending = false;
190190
}
191191

192-
void LoRaMac::on_radio_tx_done(void)
192+
lorawan_time_t LoRaMac::get_current_time(void)
193193
{
194-
lorawan_time_t cur_time = _lora_time.get_current_time();
195-
196-
if (_device_class != CLASS_C) {
197-
_lora_phy.put_radio_to_sleep();
198-
} else {
199-
// this will open a continuous RX2 window until time==RECV_DELAY1
200-
if (!_continuous_rx2_window_open) {
201-
open_rx2_window();
202-
}
203-
}
204-
205-
if (_params.is_rx_window_enabled == true) {
206-
// start timer after which rx1_window will get opened
207-
_lora_time.start(_params.timers.rx_window1_timer, _params.rx_window1_delay);
208-
209-
if (_device_class != CLASS_C) {
210-
_lora_time.start(_params.timers.rx_window2_timer, _params.rx_window2_delay);
211-
}
212-
213-
if (_params.is_node_ack_requested) {
214-
_lora_time.start(_params.timers.ack_timeout_timer,
215-
_params.rx_window2_delay + _lora_phy.get_ack_timeout());
216-
}
217-
} else {
218-
_mcps_confirmation.status = LORAMAC_EVENT_INFO_STATUS_OK;
219-
_mlme_confirmation.status = LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT;
220-
}
221-
222-
_params.last_channel_idx = _params.channel;
223-
224-
_lora_phy.set_last_tx_done(_params.channel, _is_nwk_joined, cur_time);
194+
return _lora_time.get_current_time();
195+
}
225196

226-
_params.timers.aggregated_last_tx_time = cur_time;
197+
rx_slot_t LoRaMac::get_current_slot(void)
198+
{
199+
return _params.rx_slot;
227200
}
228201

229202
/**
@@ -656,7 +629,44 @@ void LoRaMac::set_batterylevel_callback(mbed::Callback<uint8_t(void)> battery_le
656629
_mac_commands.set_batterylevel_callback(battery_level);
657630
}
658631

659-
void LoRaMac::on_radio_rx_done(const uint8_t *const payload, uint16_t size,
632+
void LoRaMac::on_radio_tx_done(lorawan_time_t timestamp)
633+
{
634+
if (_device_class == CLASS_C) {
635+
// this will open a continuous RX2 window until time==RECV_DELAY1
636+
open_rx2_window();
637+
} else {
638+
_lora_phy.put_radio_to_sleep();
639+
}
640+
641+
if(_params.is_rx_window_enabled == true) {
642+
lorawan_time_t time_diff = _lora_time.get_current_time() - timestamp;
643+
// start timer after which rx1_window will get opened
644+
_lora_time.start(_params.timers.rx_window1_timer,
645+
_params.rx_window1_delay - time_diff);
646+
647+
if (_device_class != CLASS_C) {
648+
_lora_time.start(_params.timers.rx_window2_timer,
649+
_params.rx_window2_delay - time_diff);
650+
}
651+
652+
if (_params.is_node_ack_requested) {
653+
_lora_time.start(_params.timers.ack_timeout_timer,
654+
(_params.rx_window2_delay - time_diff) +
655+
_lora_phy.get_ack_timeout());
656+
}
657+
} else {
658+
_mcps_confirmation.status = LORAMAC_EVENT_INFO_STATUS_OK;
659+
_mlme_confirmation.status = LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT;
660+
}
661+
662+
_params.last_channel_idx = _params.channel;
663+
664+
_lora_phy.set_last_tx_done(_params.channel, _is_nwk_joined, timestamp);
665+
666+
_params.timers.aggregated_last_tx_time = timestamp;
667+
}
668+
669+
void LoRaMac::on_radio_rx_done(const uint8_t* const payload, uint16_t size,
660670
int16_t rssi, int8_t snr)
661671
{
662672
// stop the RX1 timer here if its the first RX slot.
@@ -731,9 +741,11 @@ void LoRaMac::on_radio_tx_timeout(void)
731741
post_process_mcps_req();
732742
}
733743

734-
rx_slot_t LoRaMac::on_radio_rx_timeout(bool is_timeout)
744+
void LoRaMac::on_radio_rx_timeout(bool is_timeout)
735745
{
736-
if (_device_class != CLASS_C) {
746+
if (_device_class == CLASS_C && !_continuous_rx2_window_open) {
747+
open_rx2_window();
748+
} else {
737749
_lora_phy.put_radio_to_sleep();
738750
}
739751

@@ -763,12 +775,6 @@ rx_slot_t LoRaMac::on_radio_rx_timeout(bool is_timeout)
763775
LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT :
764776
LORAMAC_EVENT_INFO_STATUS_RX2_ERROR;
765777
}
766-
767-
if (_device_class == CLASS_C) {
768-
open_rx2_window();
769-
}
770-
771-
return _params.rx_slot;
772778
}
773779

774780
bool LoRaMac::continue_joining_process()
@@ -857,7 +863,6 @@ void LoRaMac::on_backoff_timer_expiry(void)
857863
void LoRaMac::open_rx1_window(void)
858864
{
859865
Lock lock(*this);
860-
tr_debug("Opening RX1 Window");
861866
_continuous_rx2_window_open = false;
862867
_lora_time.stop(_params.timers.rx_window1_timer);
863868
_params.rx_slot = RX_SLOT_WIN_1;
@@ -878,25 +883,26 @@ void LoRaMac::open_rx1_window(void)
878883

879884
_lora_phy.setup_rx_window(_params.rx_window1_config.is_rx_continuous,
880885
_params.sys_params.max_rx_win_time);
886+
887+
tr_debug("Opening RX1 Window");
881888
}
882889

883890
void LoRaMac::open_rx2_window()
884891
{
885892
Lock lock(*this);
886-
tr_debug("Opening RX2 Window");
893+
_continuous_rx2_window_open = true;
887894
_lora_time.stop(_params.timers.rx_window2_timer);
888895

889896
_params.rx_window2_config.channel = _params.channel;
890897
_params.rx_window2_config.frequency = _params.sys_params.rx2_channel.frequency;
891898
_params.rx_window2_config.dl_dwell_time = _params.sys_params.downlink_dwell_time;
892899
_params.rx_window2_config.is_repeater_supported = _params.is_repeater_supported;
893-
_params.rx_window2_config.rx_slot = RX_SLOT_WIN_2;
900+
_params.rx_window2_config.rx_slot = _params.rx_window2_config.is_rx_continuous ?
901+
RX_SLOT_WIN_CLASS_C : RX_SLOT_WIN_2;
894902

895903
if (get_device_class() == CLASS_C) {
896-
_continuous_rx2_window_open = true;
897904
_params.rx_window2_config.is_rx_continuous = true;
898905
} else {
899-
_continuous_rx2_window_open = false;
900906
_params.rx_window2_config.is_rx_continuous = false;
901907
}
902908

@@ -907,9 +913,10 @@ void LoRaMac::open_rx2_window()
907913
_lora_phy.setup_rx_window(_params.rx_window2_config.is_rx_continuous,
908914
_params.sys_params.max_rx_win_time);
909915

910-
_params.rx_slot = _params.rx_window2_config.is_rx_continuous ?
911-
RX_SLOT_WIN_CLASS_C : RX_SLOT_WIN_2;
916+
_params.rx_slot = _params.rx_window2_config.rx_slot;
912917
}
918+
919+
tr_debug("Opening RX2 Window, Frequency = %u", _params.rx_window2_config.frequency);
913920
}
914921

915922
void LoRaMac::on_ack_timeout_timer_event(void)
@@ -1346,8 +1353,6 @@ void LoRaMac::set_device_class(const device_class_t &device_class,
13461353
tr_debug("Changing device class to -> CLASS_C");
13471354
open_rx2_window();
13481355
}
1349-
1350-
13511356
}
13521357

13531358
void LoRaMac::setup_link_check_request()

features/lorawan/lorastack/mac/LoRaMac.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,7 @@ class LoRaMac {
386386
/**
387387
* MAC operations upon successful transmission
388388
*/
389-
void on_radio_tx_done(void);
389+
void on_radio_tx_done(lorawan_time_t timestamp);
390390

391391
/**
392392
* MAC operations upon reception
@@ -407,7 +407,7 @@ class LoRaMac {
407407
*
408408
* @return current RX slot
409409
*/
410-
rx_slot_t on_radio_rx_timeout(bool is_timeout);
410+
void on_radio_rx_timeout(bool is_timeout);
411411

412412
/**
413413
* Handles retransmissions of Join requests if an Accept
@@ -455,6 +455,16 @@ class LoRaMac {
455455
*/
456456
lorawan_status_t clear_tx_pipe(void);
457457

458+
/**
459+
* Gets the current time
460+
*/
461+
lorawan_time_t get_current_time(void);
462+
463+
/**
464+
* Gets the current receive slot
465+
*/
466+
rx_slot_t get_current_slot(void);
467+
458468
/**
459469
* These locks trample through to the upper layers and make
460470
* the stack thread safe.

0 commit comments

Comments
 (0)