From 36a4c557b7d663e770eedf5727822e45862eed6c Mon Sep 17 00:00:00 2001 From: Hasnain Virk Date: Thu, 26 Jul 2018 11:09:24 +0300 Subject: [PATCH 1/6] [IOTCELL-1182] User TX priority over automatic uplinks In the case when an automatic uplink was queued and the user do have something send, we should give priority to user data instead od automatic uplink message. --- features/lorawan/LoRaWANStack.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/features/lorawan/LoRaWANStack.cpp b/features/lorawan/LoRaWANStack.cpp index ece5aed9f8..fabb0895d8 100644 --- a/features/lorawan/LoRaWANStack.cpp +++ b/features/lorawan/LoRaWANStack.cpp @@ -805,8 +805,12 @@ void LoRaWANStack::send_event_to_application(const lorawan_event_t event) const void LoRaWANStack::send_automatic_uplink_message(const uint8_t port) { + // we will silently ignore the automatic uplink event if the user is already + // sending something const int16_t ret = handle_tx(port, NULL, 0, MSG_CONFIRMED_FLAG, true, true); - if (ret < 0) { + if (ret == LORAWAN_STATUS_WOULD_BLOCK) { + _automatic_uplink_ongoing = false; + } else if (ret < 0) { tr_debug("Failed to generate AUTOMATIC UPLINK, error code = %d", ret); send_event_to_application(AUTOMATIC_UPLINK_ERROR); } From b0b026126c01778d0f164fee410b7269091ab6af Mon Sep 17 00:00:00 2001 From: Hasnain Virk Date: Thu, 26 Jul 2018 11:41:35 +0300 Subject: [PATCH 2/6] [IOTCELL-1181] Using higher data rates to connect The stack was trying to connect with default data rates which happened to be the lowest data rates in a specific region. In the beginning device and NS do not have agreed upon tx rx parameters and there can be synchronization issues. When we use lower datarates, we may end up having a minute and a half long transmissions that hnot only blocks the channel for a long time but also reduce the chance of proper synch between device and NS. That's why we have decided to begin with higher data rates and gradually decrease datarate if we do not hear from the network server. --- features/lorawan/lorastack/mac/LoRaMac.cpp | 4 +--- features/lorawan/lorastack/phy/LoRaPHY.cpp | 12 ++++++++++-- features/lorawan/lorastack/phy/LoRaPHY.h | 8 ++++++++ 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/features/lorawan/lorastack/mac/LoRaMac.cpp b/features/lorawan/lorastack/mac/LoRaMac.cpp index 6d7ed946bd..de3d45bf3c 100644 --- a/features/lorawan/lorastack/mac/LoRaMac.cpp +++ b/features/lorawan/lorastack/mac/LoRaMac.cpp @@ -1755,9 +1755,7 @@ lorawan_status_t LoRaMac::initialize(EventQueue *queue) _params.timers.mac_init_time = _lora_time.get_current_time(); _params.sys_params.adr_on = MBED_CONF_LORA_ADR_ON; - - _params.is_nwk_public = MBED_CONF_LORA_PUBLIC_NETWORK; - _lora_phy->setup_public_network_mode(MBED_CONF_LORA_PUBLIC_NETWORK); + _params.sys_params.channel_data_rate = _lora_phy->get_default_max_tx_datarate(); return LORAWAN_STATUS_OK; } diff --git a/features/lorawan/lorastack/phy/LoRaPHY.cpp b/features/lorawan/lorastack/phy/LoRaPHY.cpp index f889a09161..5c288c9eb3 100644 --- a/features/lorawan/lorastack/phy/LoRaPHY.cpp +++ b/features/lorawan/lorastack/phy/LoRaPHY.cpp @@ -514,13 +514,16 @@ void LoRaPHY::reset_to_default_values(loramac_protocol_params *params, bool init params->sys_params.channel_tx_power = get_default_tx_power(); - params->sys_params.channel_data_rate = get_default_tx_datarate(); + // We shall always start with highest achievable data rate. + // Subsequent decrease in data rate will mean increase in range henceforth. + params->sys_params.channel_data_rate = get_default_max_tx_datarate(); params->sys_params.rx1_dr_offset = phy_params.default_rx1_dr_offset; params->sys_params.rx2_channel.frequency = get_default_rx2_frequency(); - params->sys_params.rx2_channel.datarate = get_default_rx2_datarate(); + // RX2 data rate should also start from the maximum + params->sys_params.rx2_channel.datarate = get_default_max_tx_datarate(); params->sys_params.uplink_dwell_time = phy_params.ul_dwell_time_setting; @@ -560,6 +563,11 @@ uint8_t LoRaPHY::get_default_tx_datarate() return phy_params.default_datarate; } +uint8_t LoRaPHY::get_default_max_tx_datarate() +{ + return phy_params.default_max_datarate; +} + uint8_t LoRaPHY::get_default_tx_power() { return phy_params.default_tx_power; diff --git a/features/lorawan/lorastack/phy/LoRaPHY.h b/features/lorawan/lorastack/phy/LoRaPHY.h index 2302064b8c..317c616297 100644 --- a/features/lorawan/lorastack/phy/LoRaPHY.h +++ b/features/lorawan/lorastack/phy/LoRaPHY.h @@ -423,6 +423,14 @@ public: */ uint8_t get_default_tx_datarate(); + /** + * @brief get_default_max_tx_datarate Gets the maximum achievable data rate for + * LoRa modulation. This will always be the highest data rate achievable with + * LoRa as defined in the regional specifications. + * @return Maximum achievable data rate with LoRa modulation. + */ + uint8_t get_default_max_tx_datarate(); + /** * @brief get_default_tx_power Gets the default TX power * @return Default TX power From 465fb447e559593aad63a172f55ee11f7bfb157c Mon Sep 17 00:00:00 2001 From: Hasnain Virk Date: Thu, 26 Jul 2018 11:47:56 +0300 Subject: [PATCH 3/6] AS923: Using LoRa modulation comatible DR as default DR7 is used for FSK in AS932 region. As a default max DR, we should use a LoRa modulation compatible data rate. Ofcourse if a device wishes to use FSK, it can set DR7 using set_data_rate() API and turning off ADR, or an NS can configure a new channel for the device utilizing DR7. --- features/lorawan/lorastack/phy/LoRaPHYAS923.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/lorawan/lorastack/phy/LoRaPHYAS923.cpp b/features/lorawan/lorastack/phy/LoRaPHYAS923.cpp index dc0d6b3368..a35f17db3c 100644 --- a/features/lorawan/lorastack/phy/LoRaPHYAS923.cpp +++ b/features/lorawan/lorastack/phy/LoRaPHYAS923.cpp @@ -67,7 +67,7 @@ */ #define AS923_DEFAULT_DATARATE DR_2 -#define AS923_DEFAULT_MAX_DATARATE DR_7 +#define AS923_DEFAULT_MAX_DATARATE DR_5 /*! * The minimum datarate which is used when the From 24c5c58d4f473d37eda2f4de54f9151448e3eb95 Mon Sep 17 00:00:00 2001 From: Hasnain Virk Date: Thu, 26 Jul 2018 14:10:18 +0300 Subject: [PATCH 4/6] Mark an error in post processing if ack not recvd If an ack is not received after maximum retries, we need to mark an error which was missing from the post processing sequence. --- features/lorawan/lorastack/mac/LoRaMac.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/features/lorawan/lorastack/mac/LoRaMac.cpp b/features/lorawan/lorastack/mac/LoRaMac.cpp index de3d45bf3c..dfb8cbb830 100644 --- a/features/lorawan/lorastack/mac/LoRaMac.cpp +++ b/features/lorawan/lorastack/mac/LoRaMac.cpp @@ -170,6 +170,8 @@ void LoRaMac::post_process_mcps_req() if (_params.is_ul_frame_counter_fixed == false) { _params.ul_frame_counter++; } + } else { + _mcps_confirmation.status = LORAMAC_EVENT_INFO_STATUS_ERROR; } } else { //UNCONFIRMED or PROPRIETARY From d76f6c07e9608ea08c4f4eb068097131a72ea98b Mon Sep 17 00:00:00 2001 From: Hasnain Virk Date: Thu, 26 Jul 2018 14:11:56 +0300 Subject: [PATCH 5/6] Making recv timing error and preamble length configurable We had a bug especially in the reception path. Our recv window opening delays were being calculated on the premise that the radio has to capture 5 preamble symbols out of 8 transmitted by the base station. However, in PHY layer while setting radio rc settings, we were setting preamble length to be 8. Preamble length register needs to be configured differently for Uplink and Downlink. For uplink, we wish to transmit 8 preamble symbols whereas in the reception path we need to receive 5 preamble symbols at least out of 8. Alongwith that the maximum range of timing error may vary from platform to platform as it is based upon the crystal in the chip. We have now made these parameters configurable and have loaded them with the most optimal defaults. --- features/lorawan/lorastack/mac/LoRaMac.cpp | 15 ++++++--------- features/lorawan/lorastack/phy/LoRaPHY.cpp | 6 ++++-- features/lorawan/mbed_lib.json | 12 ++++++++++++ features/lorawan/system/lorawan_data_structures.h | 11 ----------- 4 files changed, 22 insertions(+), 22 deletions(-) diff --git a/features/lorawan/lorastack/mac/LoRaMac.cpp b/features/lorawan/lorastack/mac/LoRaMac.cpp index dfb8cbb830..91fd4c1275 100644 --- a/features/lorawan/lorastack/mac/LoRaMac.cpp +++ b/features/lorawan/lorastack/mac/LoRaMac.cpp @@ -1080,13 +1080,13 @@ lorawan_status_t LoRaMac::schedule_tx() uint8_t dr_offset = _lora_phy->apply_DR_offset(_params.sys_params.channel_data_rate, _params.sys_params.rx1_dr_offset); - _lora_phy->compute_rx_win_params(dr_offset, _params.sys_params.min_rx_symb, - _params.sys_params.max_sys_rx_error, + _lora_phy->compute_rx_win_params(dr_offset, MBED_CONF_LORA_DOWNLINK_PREAMBLE_LENGTH, + MBED_CONF_LORA_MAX_SYS_RX_ERROR, &_params.rx_window1_config); _lora_phy->compute_rx_win_params(_params.sys_params.rx2_channel.datarate, - _params.sys_params.min_rx_symb, - _params.sys_params.max_sys_rx_error, + MBED_CONF_LORA_DOWNLINK_PREAMBLE_LENGTH, + MBED_CONF_LORA_MAX_SYS_RX_ERROR, &_params.rx_window2_config); if (!_is_nwk_joined) { @@ -1355,8 +1355,8 @@ void LoRaMac::set_device_class(const device_class_t &device_class, _params.is_node_ack_requested = false; _lora_phy->put_radio_to_sleep(); _lora_phy->compute_rx_win_params(_params.sys_params.rx2_channel.datarate, - _params.sys_params.min_rx_symb, - _params.sys_params.max_sys_rx_error, + MBED_CONF_LORA_DOWNLINK_PREAMBLE_LENGTH, + MBED_CONF_LORA_MAX_SYS_RX_ERROR, &_params.rx_window2_config); } @@ -1732,9 +1732,6 @@ lorawan_status_t LoRaMac::initialize(EventQueue *queue) _params.timers.aggregated_timeoff = 0; _lora_phy->reset_to_default_values(&_params, true); - - _params.sys_params.max_sys_rx_error = 10; - _params.sys_params.min_rx_symb = 6; _params.sys_params.retry_num = 1; reset_mac_parameters(); diff --git a/features/lorawan/lorastack/phy/LoRaPHY.cpp b/features/lorawan/lorastack/phy/LoRaPHY.cpp index 5c288c9eb3..84032956f7 100644 --- a/features/lorawan/lorastack/phy/LoRaPHY.cpp +++ b/features/lorawan/lorastack/phy/LoRaPHY.cpp @@ -853,7 +853,8 @@ bool LoRaPHY::rx_config(rx_config_params_t *rx_conf) false, rx_conf->is_rx_continuous); } else { modem = MODEM_LORA; - _radio->set_rx_config(modem, rx_conf->bandwidth, phy_dr, 1, 0, 8, + _radio->set_rx_config(modem, rx_conf->bandwidth, phy_dr, 1, 0, + MBED_CONF_LORA_DOWNLINK_PREAMBLE_LENGTH, rx_conf->window_timeout, false, 0, false, 0, 0, true, rx_conf->is_rx_continuous); } @@ -903,7 +904,8 @@ bool LoRaPHY::tx_config(tx_config_params_t *tx_conf, int8_t *tx_power, 3000); } else { modem = MODEM_LORA; - _radio->set_tx_config(modem, phy_tx_power, 0, bandwidth, phy_dr, 1, 8, + _radio->set_tx_config(modem, phy_tx_power, 0, bandwidth, phy_dr, 1, + MBED_CONF_LORA_UPLINK_PREAMBLE_LENGTH, false, true, 0, 0, false, 3000); } diff --git a/features/lorawan/mbed_lib.json b/features/lorawan/mbed_lib.json index a1003264da..d08c781705 100644 --- a/features/lorawan/mbed_lib.json +++ b/features/lorawan/mbed_lib.json @@ -64,6 +64,18 @@ "automatic-uplink-message": { "help": "Stack will automatically send an uplink message when lora server requires immediate response", "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 + }, + "downlink-preamble-length": { + "help": "Number of preamble symbols need to be captured (out of 8) for successful demodulation", + "value": 5 + }, + "uplink-preamble-length": { + "help": "Number of preamble symbols to transmit. Must be <= 8", + "value": 8 } } } diff --git a/features/lorawan/system/lorawan_data_structures.h b/features/lorawan/system/lorawan_data_structures.h index e43cb85f9d..038248fa8d 100644 --- a/features/lorawan/system/lorawan_data_structures.h +++ b/features/lorawan/system/lorawan_data_structures.h @@ -166,17 +166,6 @@ typedef struct { * The data rate in channels. */ int8_t channel_data_rate; - /*! - * The system overall timing error in milliseconds. - * [-SystemMaxRxError : +SystemMaxRxError] - * Default: +/-10 ms - */ - uint32_t max_sys_rx_error; - /*! - * The minimum number of symbols required to detect an RX frame. - * Default: 6 symbols - */ - uint8_t min_rx_symb; /*! * LoRaMac maximum time a reception window stays open. */ From c7f3585e2834806c977b17dd9f2ea878a3b6e9ce Mon Sep 17 00:00:00 2001 From: Hasnain Virk Date: Mon, 30 Jul 2018 15:21:34 +0300 Subject: [PATCH 6/6] Clear distinction b/w class A & C data paths --- features/lorawan/LoRaWANStack.cpp | 24 ++++++++++------------ features/lorawan/lorastack/mac/LoRaMac.cpp | 2 +- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/features/lorawan/LoRaWANStack.cpp b/features/lorawan/LoRaWANStack.cpp index fabb0895d8..9f07e51a55 100644 --- a/features/lorawan/LoRaWANStack.cpp +++ b/features/lorawan/LoRaWANStack.cpp @@ -603,17 +603,14 @@ void LoRaWANStack::process_transmission(void) _ctrl_flags &= ~TX_DONE_FLAG; tr_debug("Awaiting ACK"); _device_current_state = DEVICE_STATE_AWAITING_ACK; - return; - } - - // Class A unconfirmed message sent, TX_DONE event will be sent to - // application when RX2 windows is elapsed, i.e., in process_reception_timeout() - _ctrl_flags &= ~TX_ONGOING_FLAG; - _ctrl_flags |= TX_DONE_FLAG; - - // In Class C, reception timeout never happens, so we handle the state - // progression for TX_DONE in UNCONFIRMED case here - if (_loramac.get_device_class() == CLASS_C) { + } else if (_loramac.get_device_class() == CLASS_A) { + // Class A unconfirmed message sent, TX_DONE event will be sent to + // application when RX2 windows is elapsed, i.e., in process_reception_timeout() + _ctrl_flags &= ~TX_ONGOING_FLAG; + _ctrl_flags |= TX_DONE_FLAG; + } else if (_loramac.get_device_class() == CLASS_C) { + // In Class C, reception timeout never happens, so we handle the state + // progression for TX_DONE in UNCONFIRMED case here _loramac.post_process_mcps_req(); state_controller(DEVICE_STATE_STATUS_CHECK); state_machine_run_to_completion(); @@ -669,9 +666,10 @@ void LoRaWANStack::process_reception(const uint8_t *const payload, uint16_t size state_controller(DEVICE_STATE_STATUS_CHECK); } } - } else { + } else if (_loramac.get_device_class() == CLASS_A) { // handle UNCONFIRMED case here, RX slots were turned off due to - // valid packet reception + // valid packet reception. For Class C, an outgoing UNCONFIRMED message + // gets its handling in process_transmission. _loramac.post_process_mcps_req(); _ctrl_flags |= TX_DONE_FLAG; state_controller(DEVICE_STATE_STATUS_CHECK); diff --git a/features/lorawan/lorastack/mac/LoRaMac.cpp b/features/lorawan/lorastack/mac/LoRaMac.cpp index 91fd4c1275..289907eaaf 100644 --- a/features/lorawan/lorastack/mac/LoRaMac.cpp +++ b/features/lorawan/lorastack/mac/LoRaMac.cpp @@ -673,7 +673,7 @@ void LoRaMac::on_radio_rx_done(const uint8_t *const payload, uint16_t size, { if (_device_class == CLASS_C && !_continuous_rx2_window_open) { open_rx2_window(); - } else { + } else if (_device_class != CLASS_C){ _lora_time.stop(_params.timers.rx_window1_timer); _lora_phy->put_radio_to_sleep(); }