From f4077af5b1d5e9ed637ecb30c696f695be9528ed Mon Sep 17 00:00:00 2001 From: Hasnain Virk Date: Tue, 20 Nov 2018 12:45:08 +0200 Subject: [PATCH 1/7] UL FCnt increment in case of retry exhaustion Previously we had been incrementing UL frame counter for a CONFIRMED message only when the transmission was deemed successful i.e., we would have received an ack before all the retries would have exhausted. Now we have opted to increment the frame counter if all the retries are exhausted considering the fact that we essentially treat the next message after retry exhaustion as a new packet so we should also increment the frame counter. --- features/lorawan/LoRaWANStack.cpp | 2 ++ features/lorawan/lorastack/mac/LoRaMac.cpp | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/features/lorawan/LoRaWANStack.cpp b/features/lorawan/LoRaWANStack.cpp index 0f125c5448b..79f899ef2ad 100644 --- a/features/lorawan/LoRaWANStack.cpp +++ b/features/lorawan/LoRaWANStack.cpp @@ -614,6 +614,8 @@ void LoRaWANStack::post_process_tx_with_reception() _loramac.get_device_class() == CLASS_A ? "A" : "C"); _ctrl_flags &= ~TX_DONE_FLAG; _ctrl_flags |= RETRY_EXHAUSTED_FLAG; + _loramac.post_process_mcps_req(); + make_tx_metadata_available(); state_controller(DEVICE_STATE_STATUS_CHECK); } } diff --git a/features/lorawan/lorastack/mac/LoRaMac.cpp b/features/lorawan/lorastack/mac/LoRaMac.cpp index 05c58a97cf5..a971fb9cd4f 100644 --- a/features/lorawan/lorastack/mac/LoRaMac.cpp +++ b/features/lorawan/lorastack/mac/LoRaMac.cpp @@ -166,11 +166,12 @@ void LoRaMac::post_process_mcps_req() _params.is_node_ack_requested = false; _mcps_confirmation.ack_received = false; _mcps_indication.is_ack_recvd = false; - _params.ul_frame_counter++; - _params.adr_ack_counter++; } else { _mcps_confirmation.status = LORAMAC_EVENT_INFO_STATUS_ERROR; } + + _params.ul_frame_counter++; + _params.adr_ack_counter++; } else { //UNCONFIRMED or PROPRIETARY _params.ul_frame_counter++; From 88490fb1454b4798dad356f1846b485d2e7c044e Mon Sep 17 00:00:00 2001 From: Hasnain Virk Date: Tue, 27 Nov 2018 12:53:15 +0200 Subject: [PATCH 2/7] Mitigating reception problems with lower data rates A new algorithm has been taken in use to calculate the receive window length and the timing offset involved in opening of the said receive window. This algorithm performs better than the stock algorthm and consumes less power. --- features/lorawan/lorastack/phy/LoRaPHY.cpp | 59 ++++++++++++++----- features/lorawan/lorastack/phy/LoRaPHY.h | 11 ++-- features/lorawan/mbed_lib.json | 12 ++-- .../lorawan/system/lorawan_data_structures.h | 2 +- 4 files changed, 56 insertions(+), 28 deletions(-) diff --git a/features/lorawan/lorastack/phy/LoRaPHY.cpp b/features/lorawan/lorastack/phy/LoRaPHY.cpp index c995cd211be..d3dd7bd2e37 100644 --- a/features/lorawan/lorastack/phy/LoRaPHY.cpp +++ b/features/lorawan/lorastack/phy/LoRaPHY.cpp @@ -32,8 +32,9 @@ SPDX-License-Identifier: BSD-3-Clause #define BACKOFF_DC_1_HOUR 100 #define BACKOFF_DC_10_HOURS 1000 #define BACKOFF_DC_24_HOURS 10000 - -#define CHANNELS_IN_MASK 16 +#define MAX_PREAMBLE_LENGTH 8.0 +#define TICK_GRANULARITY_JITTER 1.0 +#define CHANNELS_IN_MASK 16 LoRaPHY::LoRaPHY() : _radio(NULL), @@ -388,23 +389,49 @@ uint8_t LoRaPHY::verify_link_ADR_req(verify_adr_params_t *verify_params, return status; } -double LoRaPHY::compute_symb_timeout_lora(uint8_t phy_dr, uint32_t bandwidth) +float LoRaPHY::compute_symb_timeout_lora(uint8_t phy_dr, uint32_t bandwidth) { - return ((double)(1 << phy_dr) / (double) bandwidth) * 1000; + // in milliseconds + return ((float)(1 << phy_dr) / (float) bandwidth * 1000); } -double LoRaPHY::compute_symb_timeout_fsk(uint8_t phy_dr) +float LoRaPHY::compute_symb_timeout_fsk(uint8_t phy_dr) { - return (8.0 / (double) phy_dr); // 1 symbol equals 1 byte + return (8.0 / (float) phy_dr); // 1 symbol equals 1 byte } -void LoRaPHY::get_rx_window_params(double t_symb, uint8_t min_rx_symb, - uint32_t rx_error, uint32_t wakeup_time, - uint32_t *window_timeout, int32_t *window_offset) + +void LoRaPHY::get_rx_window_params(float t_symb, uint8_t min_rx_symb, + float error_fudge, float wakeup_time, + uint32_t *window_length, int32_t *window_offset, + uint8_t phy_dr) { - // Computed number of symbols - *window_timeout = MAX((uint32_t) ceil(((2 * min_rx_symb - 8) * t_symb + 2 * rx_error) / t_symb), min_rx_symb); - *window_offset = (int32_t) ceil((4.0 * t_symb) - ((*window_timeout * t_symb) / 2.0) - wakeup_time); + float min_rx_symbol_overlap_required = float (min_rx_symb); + float target_rx_window_offset; + float window_len_in_ms; + + if (phy_params.fsk_supported && phy_dr == phy_params.max_rx_datarate) { + min_rx_symbol_overlap_required = MAX_PREAMBLE_LENGTH; + } + + // We wish to be as close as possible to the actual start of data, i.e., + // we are interested in the preamble symbols which are at the tail of the + // preamble sequence. + target_rx_window_offset = (MAX_PREAMBLE_LENGTH - min_rx_symbol_overlap_required) * t_symb; //in ms + + // Actual window offset in ms in response to timing error fudge factor and + // radio wakeup/turned around time. + *window_offset = floor(target_rx_window_offset - error_fudge - wakeup_time); + + // Minimum reception time plus extra time (in ms) we may have turned on before the + // other side started transmission + window_len_in_ms = (min_rx_symbol_overlap_required * t_symb) - MIN(0, (*window_offset - error_fudge - TICK_GRANULARITY_JITTER)); + + // Setting the window_length in terms of 'symbols' for LoRa modulation or + // in terms of 'bytes' for FSK + *window_length = (uint32_t) ceil(window_len_in_ms / t_symb); + + } int8_t LoRaPHY::compute_tx_power(int8_t tx_power_idx, float max_eirp, @@ -791,7 +818,7 @@ void LoRaPHY::compute_rx_win_params(int8_t datarate, uint8_t min_rx_symbols, uint32_t rx_error, rx_config_params_t *rx_conf_params) { - double t_symbol = 0.0; + float t_symbol = 0.0; // Get the datarate, perform a boundary check rx_conf_params->datarate = MIN(datarate, phy_params.max_rx_datarate); @@ -811,9 +838,9 @@ void LoRaPHY::compute_rx_win_params(int8_t datarate, uint8_t min_rx_symbols, rx_conf_params->frequency = phy_params.channels.channel_list[rx_conf_params->channel].frequency; } - - get_rx_window_params(t_symbol, min_rx_symbols, rx_error, RADIO_WAKEUP_TIME, - &rx_conf_params->window_timeout, &rx_conf_params->window_offset); + get_rx_window_params(t_symbol, min_rx_symbols, (float) rx_error, RADIO_WAKEUP_TIME, + &rx_conf_params->window_timeout, &rx_conf_params->window_offset, + rx_conf_params->datarate); } bool LoRaPHY::rx_config(rx_config_params_t *rx_conf) diff --git a/features/lorawan/lorastack/phy/LoRaPHY.h b/features/lorawan/lorastack/phy/LoRaPHY.h index 76bad8993c5..a81b5bc7798 100644 --- a/features/lorawan/lorastack/phy/LoRaPHY.h +++ b/features/lorawan/lorastack/phy/LoRaPHY.h @@ -597,9 +597,10 @@ class LoRaPHY : private mbed::NonCopyable { /** * Computes the RX window timeout and the RX window offset. */ - void get_rx_window_params(double t_symbol, uint8_t min_rx_symbols, - uint32_t rx_error, uint32_t wakeup_time, - uint32_t *window_timeout, int32_t *window_offset); + void get_rx_window_params(float t_symbol, uint8_t min_rx_symbols, + float rx_error, float wakeup_time, + uint32_t *window_length, int32_t *window_offset, + uint8_t phy_dr); /** * Computes the txPower, based on the max EIRP and the antenna gain. @@ -632,12 +633,12 @@ class LoRaPHY : private mbed::NonCopyable { /** * Computes the symbol time for LoRa modulation. */ - double compute_symb_timeout_lora(uint8_t phy_dr, uint32_t bandwidth); + float compute_symb_timeout_lora(uint8_t phy_dr, uint32_t bandwidth); /** * Computes the symbol time for FSK modulation. */ - double compute_symb_timeout_fsk(uint8_t phy_dr); + float compute_symb_timeout_fsk(uint8_t phy_dr); protected: LoRaRadio *_radio; diff --git a/features/lorawan/mbed_lib.json b/features/lorawan/mbed_lib.json index e4eefd00e51..52611129862 100644 --- a/features/lorawan/mbed_lib.json +++ b/features/lorawan/mbed_lib.json @@ -70,16 +70,16 @@ "value": true }, "max-sys-rx-error": { - "help": "Maximum timing error of the receiver in ms. The receiver will turn on in [-RxError : + RxError]", - "value": 10 + "help": "Maximum timing error of the receiver in ms. The receiver will turn on in [-RxError : + RxError]", + "value": 1 }, "downlink-preamble-length": { - "help": "Number of preamble symbols need to be captured (out of 8) for successful demodulation", - "value": 5 + "help": "Number of whole preamble symbols needed to have a firm lock on the signal. Default: 5 + 1", + "value": 6 }, "uplink-preamble-length": { - "help": "Number of preamble symbols to transmit. Must be <= 8", - "value": 8 + "help": "Number of preamble symbols to transmit. Default: 8", + "value": 8 }, "fsb-mask": { "help": "FSB mask for upstream [Only for US915 & AU915] Check lorawan/FSB_Usage.txt for more details", diff --git a/features/lorawan/system/lorawan_data_structures.h b/features/lorawan/system/lorawan_data_structures.h index e35d5427617..a6e14ed197c 100644 --- a/features/lorawan/system/lorawan_data_structures.h +++ b/features/lorawan/system/lorawan_data_structures.h @@ -45,7 +45,7 @@ typedef uint32_t lorawan_time_t; #endif // Radio wake-up time from sleep - unit ms. -#define RADIO_WAKEUP_TIME 1 +#define RADIO_WAKEUP_TIME 1.0 /*! * Sets the length of the LoRaMAC footer field. From 3ec643f06a39840742a91b71fda1c94c35596e59 Mon Sep 17 00:00:00 2001 From: Hasnain Virk Date: Tue, 27 Nov 2018 12:55:37 +0200 Subject: [PATCH 3/7] Style alignment Minor style alignment. --- features/lorawan/mbed_lib.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/features/lorawan/mbed_lib.json b/features/lorawan/mbed_lib.json index 52611129862..b6d1404ba9a 100644 --- a/features/lorawan/mbed_lib.json +++ b/features/lorawan/mbed_lib.json @@ -82,12 +82,12 @@ "value": 8 }, "fsb-mask": { - "help": "FSB mask for upstream [Only for US915 & AU915] Check lorawan/FSB_Usage.txt for more details", - "value": "{0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x00FF}" + "help": "FSB mask for upstream [Only for US915 & AU915] Check lorawan/FSB_Usage.txt for more details", + "value": "{0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x00FF}" }, "fsb-mask-china": { - "help": "FSB mask for upstream [CN470 PHY] Check lorawan/FSB_Usage.txt for more details", - "value": "{0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF}" + "help": "FSB mask for upstream [CN470 PHY] Check lorawan/FSB_Usage.txt for more details", + "value": "{0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF}" } } } From ca083671ff782251bee7a5a9af622fd600d97620 Mon Sep 17 00:00:00 2001 From: Hasnain Virk Date: Tue, 27 Nov 2018 13:06:40 +0200 Subject: [PATCH 4/7] Updating get_rx_window_params() API in stubs Unittest stubs needed to be updated for the API change. Although this API is private and internal to LoRaPHY, somehow it appeared in the LoRaPHYStub. Updating it for consistency. --- UNITTESTS/stubs/LoRaPHY_stub.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/UNITTESTS/stubs/LoRaPHY_stub.cpp b/UNITTESTS/stubs/LoRaPHY_stub.cpp index 56862af5dfc..01b7312b7c3 100644 --- a/UNITTESTS/stubs/LoRaPHY_stub.cpp +++ b/UNITTESTS/stubs/LoRaPHY_stub.cpp @@ -168,9 +168,10 @@ uint8_t LoRaPHY::verify_link_ADR_req(verify_adr_params_t *verify_params, return LoRaPHY_stub::uint8_value; } -void LoRaPHY::get_rx_window_params(double t_symb, uint8_t min_rx_symb, - uint32_t rx_error, uint32_t wakeup_time, - uint32_t *window_timeout, int32_t *window_offset) +void LoRaPHY::get_rx_window_params(float t_symbol, uint8_t min_rx_symbols, + float rx_error, float wakeup_time, + uint32_t *window_length, int32_t *window_offset, + uint8_t phy_dr) { } From 5170daa00af7588bd9ddc41fd2aafccd5c6bcc6c Mon Sep 17 00:00:00 2001 From: Hasnain Virk Date: Wed, 28 Nov 2018 15:19:54 +0200 Subject: [PATCH 5/7] RX window calculation algorithm version 2 In this version we try to mitigate a situation when we start listening right in the middle of a preamble sequence (e.g., in high SF case). --- features/lorawan/lorastack/phy/LoRaPHY.cpp | 29 ++++++++++++++-------- features/lorawan/mbed_lib.json | 10 +++++--- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/features/lorawan/lorastack/phy/LoRaPHY.cpp b/features/lorawan/lorastack/phy/LoRaPHY.cpp index d3dd7bd2e37..8f8c3b21f23 100644 --- a/features/lorawan/lorastack/phy/LoRaPHY.cpp +++ b/features/lorawan/lorastack/phy/LoRaPHY.cpp @@ -406,32 +406,39 @@ void LoRaPHY::get_rx_window_params(float t_symb, uint8_t min_rx_symb, uint32_t *window_length, int32_t *window_offset, uint8_t phy_dr) { - float min_rx_symbol_overlap_required = float (min_rx_symb); float target_rx_window_offset; float window_len_in_ms; if (phy_params.fsk_supported && phy_dr == phy_params.max_rx_datarate) { - min_rx_symbol_overlap_required = MAX_PREAMBLE_LENGTH; + min_rx_symb = MAX_PREAMBLE_LENGTH; } // We wish to be as close as possible to the actual start of data, i.e., // we are interested in the preamble symbols which are at the tail of the // preamble sequence. - target_rx_window_offset = (MAX_PREAMBLE_LENGTH - min_rx_symbol_overlap_required) * t_symb; //in ms + target_rx_window_offset = (MAX_PREAMBLE_LENGTH - min_rx_symb) * t_symb; //in ms // Actual window offset in ms in response to timing error fudge factor and // radio wakeup/turned around time. - *window_offset = floor(target_rx_window_offset - error_fudge - wakeup_time); + *window_offset = floor(target_rx_window_offset - error_fudge - MBED_CONF_LORA_WAKEUP_TIME); + + // possible wait for next symbol start if we start inside the preamble + float possible_wait_for_symb_start = MIN(t_symb, + ((2 * error_fudge) + MBED_CONF_LORA_WAKEUP_TIME + TICK_GRANULARITY_JITTER)); + + // how early we might start reception relative to transmit start (so negative if before transmit starts) + float earliest_possible_start_time = *window_offset - error_fudge - TICK_GRANULARITY_JITTER; + + // time in (ms) we may have to wait for the other side to start transmission + float possible_wait_for_transmit = -earliest_possible_start_time; // Minimum reception time plus extra time (in ms) we may have turned on before the // other side started transmission - window_len_in_ms = (min_rx_symbol_overlap_required * t_symb) - MIN(0, (*window_offset - error_fudge - TICK_GRANULARITY_JITTER)); + window_len_in_ms = (min_rx_symb * t_symb) + MAX(possible_wait_for_transmit, possible_wait_for_symb_start); // Setting the window_length in terms of 'symbols' for LoRa modulation or // in terms of 'bytes' for FSK *window_length = (uint32_t) ceil(window_len_in_ms / t_symb); - - } int8_t LoRaPHY::compute_tx_power(int8_t tx_power_idx, float max_eirp, @@ -874,13 +881,13 @@ bool LoRaPHY::rx_config(rx_config_params_t *rx_conf) // Radio configuration if (dr == DR_7 && phy_params.fsk_supported) { modem = MODEM_FSK; - _radio->set_rx_config(modem, 50000, phy_dr * 1000, 0, 83333, 5, + _radio->set_rx_config(modem, 50000, phy_dr * 1000, 0, 83333, MAX_PREAMBLE_LENGTH, rx_conf->window_timeout, false, 0, true, 0, 0, false, rx_conf->is_rx_continuous); } else { modem = MODEM_LORA; _radio->set_rx_config(modem, rx_conf->bandwidth, phy_dr, 1, 0, - MBED_CONF_LORA_DOWNLINK_PREAMBLE_LENGTH, + MAX_PREAMBLE_LENGTH, rx_conf->window_timeout, false, 0, false, 0, 0, true, rx_conf->is_rx_continuous); } @@ -926,8 +933,8 @@ bool LoRaPHY::tx_config(tx_config_params_t *tx_conf, int8_t *tx_power, // High Speed FSK channel modem = MODEM_FSK; _radio->set_tx_config(modem, phy_tx_power, 25000, bandwidth, - phy_dr * 1000, 0, 5, false, true, 0, 0, false, - 3000); + phy_dr * 1000, 0, MBED_CONF_LORA_UPLINK_PREAMBLE_LENGTH, + false, true, 0, 0, false, 3000); } else { modem = MODEM_LORA; _radio->set_tx_config(modem, phy_tx_power, 0, bandwidth, phy_dr, 1, diff --git a/features/lorawan/mbed_lib.json b/features/lorawan/mbed_lib.json index b6d1404ba9a..967e7c8783a 100644 --- a/features/lorawan/mbed_lib.json +++ b/features/lorawan/mbed_lib.json @@ -70,12 +70,16 @@ "value": true }, "max-sys-rx-error": { - "help": "Maximum timing error of the receiver in ms. The receiver will turn on in [-RxError : + RxError]", - "value": 1 + "help": "Max. timing error fudge. The receiver will turn on in [-RxError : + RxError]", + "value": 5 + }, + "wakeup-time": { + "help": "Time in (ms) the platform takes to wakeup from sleep/deep sleep state. This number is platform dependent", + "value": 5 }, "downlink-preamble-length": { "help": "Number of whole preamble symbols needed to have a firm lock on the signal. Default: 5 + 1", - "value": 6 + "value": 5 }, "uplink-preamble-length": { "help": "Number of preamble symbols to transmit. Default: 8", From e1e48b492b6ee8027f5742f6bca28f9329b628a3 Mon Sep 17 00:00:00 2001 From: Hasnain Virk Date: Fri, 7 Dec 2018 12:47:06 +0200 Subject: [PATCH 6/7] Final cleanup and ASCII art for algorithm v2 Final code cleanup and adding ascii art for the version 2 of the algorithm. --- features/lorawan/lorastack/phy/LoRaPHY.cpp | 12 +-- features/lorawan/lorastack/phy/LoRaPHY.h | 87 ++++++++++++------- features/lorawan/mbed_lib.json | 2 +- .../lorawan/system/lorawan_data_structures.h | 7 +- 4 files changed, 64 insertions(+), 44 deletions(-) diff --git a/features/lorawan/lorastack/phy/LoRaPHY.cpp b/features/lorawan/lorastack/phy/LoRaPHY.cpp index 8f8c3b21f23..29414ee7aa0 100644 --- a/features/lorawan/lorastack/phy/LoRaPHY.cpp +++ b/features/lorawan/lorastack/phy/LoRaPHY.cpp @@ -32,8 +32,8 @@ SPDX-License-Identifier: BSD-3-Clause #define BACKOFF_DC_1_HOUR 100 #define BACKOFF_DC_10_HOURS 1000 #define BACKOFF_DC_24_HOURS 10000 -#define MAX_PREAMBLE_LENGTH 8.0 -#define TICK_GRANULARITY_JITTER 1.0 +#define MAX_PREAMBLE_LENGTH 8.0f +#define TICK_GRANULARITY_JITTER 1.0f #define CHANNELS_IN_MASK 16 LoRaPHY::LoRaPHY() @@ -397,7 +397,7 @@ float LoRaPHY::compute_symb_timeout_lora(uint8_t phy_dr, uint32_t bandwidth) float LoRaPHY::compute_symb_timeout_fsk(uint8_t phy_dr) { - return (8.0 / (float) phy_dr); // 1 symbol equals 1 byte + return (8.0f / (float) phy_dr); // 1 symbol equals 1 byte } @@ -420,11 +420,11 @@ void LoRaPHY::get_rx_window_params(float t_symb, uint8_t min_rx_symb, // Actual window offset in ms in response to timing error fudge factor and // radio wakeup/turned around time. - *window_offset = floor(target_rx_window_offset - error_fudge - MBED_CONF_LORA_WAKEUP_TIME); + *window_offset = floor(target_rx_window_offset - error_fudge - wakeup_time); // possible wait for next symbol start if we start inside the preamble float possible_wait_for_symb_start = MIN(t_symb, - ((2 * error_fudge) + MBED_CONF_LORA_WAKEUP_TIME + TICK_GRANULARITY_JITTER)); + ((2 * error_fudge) + wakeup_time + TICK_GRANULARITY_JITTER)); // how early we might start reception relative to transmit start (so negative if before transmit starts) float earliest_possible_start_time = *window_offset - error_fudge - TICK_GRANULARITY_JITTER; @@ -845,7 +845,7 @@ void LoRaPHY::compute_rx_win_params(int8_t datarate, uint8_t min_rx_symbols, rx_conf_params->frequency = phy_params.channels.channel_list[rx_conf_params->channel].frequency; } - get_rx_window_params(t_symbol, min_rx_symbols, (float) rx_error, RADIO_WAKEUP_TIME, + get_rx_window_params(t_symbol, min_rx_symbols, (float) rx_error, MBED_CONF_LORA_WAKEUP_TIME, &rx_conf_params->window_timeout, &rx_conf_params->window_offset, rx_conf_params->datarate); } diff --git a/features/lorawan/lorastack/phy/LoRaPHY.h b/features/lorawan/lorastack/phy/LoRaPHY.h index a81b5bc7798..d6be36b1dc9 100644 --- a/features/lorawan/lorastack/phy/LoRaPHY.h +++ b/features/lorawan/lorastack/phy/LoRaPHY.h @@ -202,40 +202,63 @@ class LoRaPHY : private mbed::NonCopyable { /** Computing Receive Windows * - * For more details please consult the following document, chapter 3.1.2. - * http://www.semtech.com/images/datasheet/SX1272_settings_for_LoRaWAN_v2.0.pdf - * or - * http://www.semtech.com/images/datasheet/SX1276_settings_for_LoRaWAN_v2.0.pdf - * - * Downlink start: T = Tx + 1s (+/- 20 us) - * | - * TRxEarly | TRxLate - * | | | - * | | +---+---+---+---+---+---+---+---+ - * | | | Latest Rx window | - * | | +---+---+---+---+---+---+---+---+ - * | | | + * The algorithm tries to calculate the length of receive windows (i.e., + * the minimum time it should remain to acquire a lock on the Preamble + * for synchronization) and the error offset which compensates for the system + * timing errors. Basic idea behind the algorithm is to optimize for the + * reception of last 'min_rx_symbols' symbols out of transmitted Premable + * symbols. The algorithm compensates for the clock drifts, tick granularity + * and system wake up time (from sleep state) by opening the window early for + * the lower SFs. For higher SFs, the symbol time is large enough that we can + * afford to open late (hence the positive offset). + * The table below shows the calculated values for SF7 to SF12 with 125 kHz + * bandwidth. + * + * +----+-----+----------+---------+-------------------------+----------------------+-------------------------+ + * | SF | BW (kHz) | rx_error (ms) | wake_up (ms) | min_rx_symbols | window_timeout(symb) | window_offset(ms) | + * +----+-----+----------+---------+-------------------------+----------------------+-------------------------+ + * | 7 | 125 | 5 | 5 | 5 | 18 | -7 | + * | 8 | 125 | 5 | 5 | 5 | 10 | -4 | + * | 9 | 125 | 5 | 5 | 5 | 6 | 2 | + * | 10 | 125 | 5 | 5 | 5 | 6 | 14 | + * | 11 | 125 | 5 | 5 | 5 | 6 | 39 | + * | 12 | 125 | 5 | 5 | 5 | 6 | 88 | + * +----+-----+----------+---------+-------------------------+----------------------+-------------------------+ + * + * For example for SF7, the receive window will open at downlink start time + * plus the offset calculated and will remain open for the length window_timeout. + * + * Symbol time = 1.024 ms + * Downlink start: T = Tx + 1s (+/- 20 us) + * | + * | + * | + * | + * | + * +---+---+---+---+---+---+---+---+ + * | 8 Preamble Symbols | + * +---+---+---+---+---+---+---+---+ + * | RX Window start time = T +/- Offset + * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + * | | | | | | | | | | | | | | | | | | | + * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + * + * Similarly for SF12: + * + * Symbol time = 32.768 ms + * Downlink start: T = Tx + 1s (+/- 20 us) + * | + * | + * | + * | + * | * +---+---+---+---+---+---+---+---+ - * | Earliest Rx window | + * | 8 Preamble Symbols | * +---+---+---+---+---+---+---+---+ - * | - * +---+---+---+---+---+---+---+---+ - *Downlink preamble 8 symbols | | | | | | | | | - * +---+---+---+---+---+---+---+---+ - * - * Worst case Rx window timings - * - * TRxLate = DEFAULT_MIN_RX_SYMBOLS * tSymbol - RADIO_WAKEUP_TIME - * TRxEarly = 8 - DEFAULT_MIN_RX_SYMBOLS * tSymbol - RxWindowTimeout - RADIO_WAKEUP_TIME - * - * TRxLate - TRxEarly = 2 * DEFAULT_SYSTEM_MAX_RX_ERROR - * - * RxOffset = ( TRxLate + TRxEarly ) / 2 - * - * RxWindowTimeout = ( 2 * DEFAULT_MIN_RX_SYMBOLS - 8 ) * tSymbol + 2 * DEFAULT_SYSTEM_MAX_RX_ERROR - * RxOffset = 4 * tSymbol - RxWindowTimeout / 2 - RADIO_WAKE_UP_TIME - * - * The minimum value of RxWindowTimeout must be 5 symbols which implies that the system always tolerates at least an error of 1.5 * tSymbol. + * | RX Window start time = T +/- Offset + * +---+---+---+---+---+---+ + * | | | | | | | + * +---+---+---+---+---+---+ */ /*! * Computes the RX window timeout and offset. diff --git a/features/lorawan/mbed_lib.json b/features/lorawan/mbed_lib.json index 967e7c8783a..30e130b3645 100644 --- a/features/lorawan/mbed_lib.json +++ b/features/lorawan/mbed_lib.json @@ -78,7 +78,7 @@ "value": 5 }, "downlink-preamble-length": { - "help": "Number of whole preamble symbols needed to have a firm lock on the signal. Default: 5 + 1", + "help": "Number of whole preamble symbols needed to have a firm lock on the signal.", "value": 5 }, "uplink-preamble-length": { diff --git a/features/lorawan/system/lorawan_data_structures.h b/features/lorawan/system/lorawan_data_structures.h index a6e14ed197c..dafcb29ff18 100644 --- a/features/lorawan/system/lorawan_data_structures.h +++ b/features/lorawan/system/lorawan_data_structures.h @@ -44,9 +44,6 @@ typedef uint32_t lorawan_time_t; #endif -// Radio wake-up time from sleep - unit ms. -#define RADIO_WAKEUP_TIME 1.0 - /*! * Sets the length of the LoRaMAC footer field. * Mainly indicates the MIC field length. @@ -1259,8 +1256,8 @@ typedef struct { /*! * LoRaMac reception windows delay - * \remark normal frame: RxWindowXDelay = ReceiveDelayX - RADIO_WAKEUP_TIME - * join frame : RxWindowXDelay = JoinAcceptDelayX - RADIO_WAKEUP_TIME + * \remark normal frame: RxWindowXDelay = ReceiveDelayX - Offset + * join frame : RxWindowXDelay = JoinAcceptDelayX - Offset */ uint32_t rx_window1_delay; uint32_t rx_window2_delay; From 138fd740b7e2882768770e0f37a6345f80938c99 Mon Sep 17 00:00:00 2001 From: Hasnain Virk Date: Mon, 10 Dec 2018 08:52:46 +0200 Subject: [PATCH 7/7] Unit test fix A missing macro definition is added to the unit-test cmake file for LoRaPHY class. --- UNITTESTS/features/lorawan/loraphy/unittest.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/UNITTESTS/features/lorawan/loraphy/unittest.cmake b/UNITTESTS/features/lorawan/loraphy/unittest.cmake index c1abde4e46a..b3c8a5854a4 100644 --- a/UNITTESTS/features/lorawan/loraphy/unittest.cmake +++ b/UNITTESTS/features/lorawan/loraphy/unittest.cmake @@ -37,5 +37,5 @@ set(unittest-test-sources ) -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DMBED_CONF_LORA_UPLINK_PREAMBLE_LENGTH=8 -DMBED_CONF_LORA_DUTY_CYCLE_ON_JOIN=true") -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMBED_CONF_LORA_UPLINK_PREAMBLE_LENGTH=8 -DMBED_CONF_LORA_DUTY_CYCLE_ON_JOIN=true") +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DMBED_CONF_LORA_UPLINK_PREAMBLE_LENGTH=8 -DMBED_CONF_LORA_DUTY_CYCLE_ON_JOIN=true -DMBED_CONF_LORA_WAKEUP_TIME=5") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMBED_CONF_LORA_UPLINK_PREAMBLE_LENGTH=8 -DMBED_CONF_LORA_DUTY_CYCLE_ON_JOIN=true -DMBED_CONF_LORA_WAKEUP_TIME=5")