diff --git a/features/lorawan/LoRaWANStack.cpp b/features/lorawan/LoRaWANStack.cpp index d91de2e7f6..bf2656e109 100644 --- a/features/lorawan/LoRaWANStack.cpp +++ b/features/lorawan/LoRaWANStack.cpp @@ -68,20 +68,20 @@ using namespace events; * Constructor * ****************************************************************************/ LoRaWANStack::LoRaWANStack() -: _loramac(), - _device_current_state(DEVICE_STATE_NOT_INITIALIZED), - _lw_session(), - _tx_msg(), - _rx_msg(), - _tx_metadata(), - _rx_metadata(), - _num_retry(1), - _ctrl_flags(IDLE_FLAG), - _app_port(INVALID_PORT), - _link_check_requested(false), - _automatic_uplink_ongoing(false), - _ready_for_rx(true), - _queue(NULL) + : _loramac(), + _device_current_state(DEVICE_STATE_NOT_INITIALIZED), + _lw_session(), + _tx_msg(), + _rx_msg(), + _tx_metadata(), + _rx_metadata(), + _num_retry(1), + _ctrl_flags(IDLE_FLAG), + _app_port(INVALID_PORT), + _link_check_requested(false), + _automatic_uplink_ongoing(false), + _ready_for_rx(true), + _queue(NULL) { _tx_metadata.stale = true; _rx_metadata.stale = true; @@ -481,7 +481,7 @@ lorawan_status_t LoRaWANStack::acquire_rx_metadata(lorawan_rx_metadata &metadata return LORAWAN_STATUS_METADATA_NOT_AVAILABLE; } -lorawan_status_t LoRaWANStack::acquire_backoff_metadata(int& backoff) +lorawan_status_t LoRaWANStack::acquire_backoff_metadata(int &backoff) { if (DEVICE_STATE_NOT_INITIALIZED == _device_current_state) { return LORAWAN_STATUS_NOT_INITIALIZED; @@ -503,6 +503,7 @@ lorawan_status_t LoRaWANStack::acquire_backoff_metadata(int& backoff) ****************************************************************************/ void LoRaWANStack::tx_interrupt_handler(void) { + _tx_timestamp = _loramac.get_current_time(); const int ret = _queue->call(this, &LoRaWANStack::process_transmission); MBED_ASSERT(ret != 0); (void)ret; @@ -565,7 +566,7 @@ void LoRaWANStack::process_transmission_timeout() void LoRaWANStack::process_transmission(void) { tr_debug("Transmission completed"); - _loramac.on_radio_tx_done(); + _loramac.on_radio_tx_done(_tx_timestamp); make_tx_metadata_available(); @@ -680,10 +681,12 @@ void LoRaWANStack::process_reception(const uint8_t *const payload, uint16_t size void LoRaWANStack::process_reception_timeout(bool is_timeout) { + rx_slot_t slot = _loramac.get_current_slot(); + // when is_timeout == false, a CRC error took place in the received frame // we treat that erroneous frame as no frame received at all, hence handle // it exactly as we would handle timeout - rx_slot_t slot = _loramac.on_radio_rx_timeout(is_timeout); + _loramac.on_radio_rx_timeout(is_timeout); if (slot == RX_SLOT_WIN_2 && !_loramac.nwk_joined()) { state_controller(DEVICE_STATE_JOINING); @@ -851,9 +854,11 @@ void LoRaWANStack::mlme_indication_handler() #if MBED_CONF_LORA_AUTOMATIC_UPLINK_MESSAGE _automatic_uplink_ongoing = true; tr_debug("mlme indication: sending empty uplink to port 0 to acknowledge MAC commands..."); - send_automatic_uplink_message(0); + const uint8_t port = 0; + const int ret = _queue->call(this, &LoRaWANStack::send_automatic_uplink_message, port); + MBED_ASSERT(ret != 0); + (void)ret; #else - send_event_to_application(UPLINK_REQUIRED); #endif return; @@ -957,8 +962,9 @@ void LoRaWANStack::mcps_indication_handler() _rx_msg.msg.mcps_indication.type = mcps_indication->type; // Notify application about received frame.. - tr_debug("Packet Received %d bytes", - _rx_msg.msg.mcps_indication.buffer_size); + tr_debug("Packet Received %d bytes, Port=%d", + _rx_msg.msg.mcps_indication.buffer_size, + mcps_indication->port); _rx_msg.receive_ready = true; send_event_to_application(RX_DONE); } @@ -981,7 +987,9 @@ void LoRaWANStack::mcps_indication_handler() #if (MBED_CONF_LORA_AUTOMATIC_UPLINK_MESSAGE) tr_debug("Sending empty uplink message..."); _automatic_uplink_ongoing = true; - send_automatic_uplink_message(mcps_indication->port); + const int ret = _queue->call(this, &LoRaWANStack::send_automatic_uplink_message, mcps_indication->port); + MBED_ASSERT(ret != 0); + (void)ret; #else send_event_to_application(UPLINK_REQUIRED); #endif @@ -1354,9 +1362,11 @@ void LoRaWANStack::compliance_test_handler(loramac_mcps_indication_t *mcps_indic } else if (mcps_indication->buffer_size == 7) { loramac_mlme_req_t mlme_req; mlme_req.type = MLME_TXCW_1; - mlme_req.cw_tx_mode.timeout = (uint16_t)((mcps_indication->buffer[1] << 8) | mcps_indication->buffer[2]); - mlme_req.cw_tx_mode.frequency = (uint32_t)((mcps_indication->buffer[3] << 16) | (mcps_indication->buffer[4] << 8) - | mcps_indication->buffer[5]) * 100; + mlme_req.cw_tx_mode.timeout = (uint16_t)((mcps_indication->buffer[1] << 8) + | mcps_indication->buffer[2]); + mlme_req.cw_tx_mode.frequency = (uint32_t)((mcps_indication->buffer[3] << 16) + | (mcps_indication->buffer[4] << 8) + | mcps_indication->buffer[5]) * 100; mlme_req.cw_tx_mode.power = mcps_indication->buffer[6]; _loramac.mlme_request(&mlme_req); } diff --git a/features/lorawan/LoRaWANStack.h b/features/lorawan/LoRaWANStack.h index b373a5d3d0..21e85d752b 100644 --- a/features/lorawan/LoRaWANStack.h +++ b/features/lorawan/LoRaWANStack.h @@ -548,6 +548,7 @@ private: volatile bool _ready_for_rx; uint8_t _rx_payload[LORAMAC_PHY_MAXPAYLOAD]; events::EventQueue *_queue; + lorawan_time_t _tx_timestamp; #if defined(LORAWAN_COMPLIANCE_TEST) diff --git a/features/lorawan/lorastack/mac/LoRaMac.cpp b/features/lorawan/lorastack/mac/LoRaMac.cpp index d8be5bde1f..4f5f20a7a4 100644 --- a/features/lorawan/lorastack/mac/LoRaMac.cpp +++ b/features/lorawan/lorastack/mac/LoRaMac.cpp @@ -72,19 +72,19 @@ using namespace mbed; LoRaMac::LoRaMac() - : _lora_time(), - _lora_phy(_lora_time), - _mac_commands(), - _channel_plan(), - _lora_crypto(), - _ev_queue(NULL), - _mcps_indication(), - _mcps_confirmation(), - _mlme_indication(), - _mlme_confirmation(), - _is_nwk_joined(false), - _continuous_rx2_window_open(false), - _device_class(CLASS_A) + : _lora_time(), + _lora_phy(_lora_time), + _mac_commands(), + _channel_plan(), + _lora_crypto(), + _ev_queue(NULL), + _mcps_indication(), + _mcps_confirmation(), + _mlme_indication(), + _mlme_confirmation(), + _is_nwk_joined(false), + _continuous_rx2_window_open(false), + _device_class(CLASS_A) { _params.keys.dev_eui = NULL; _params.keys.app_eui = NULL; @@ -189,41 +189,14 @@ void LoRaMac::post_process_mlme_ind() _mlme_indication.pending = false; } -void LoRaMac::on_radio_tx_done(void) +lorawan_time_t LoRaMac::get_current_time(void) { - lorawan_time_t cur_time = _lora_time.get_current_time(); + return _lora_time.get_current_time(); +} - if (_device_class != CLASS_C) { - _lora_phy.put_radio_to_sleep(); - } else { - // this will open a continuous RX2 window until time==RECV_DELAY1 - if (!_continuous_rx2_window_open) { - open_rx2_window(); - } - } - - if (_params.is_rx_window_enabled == true) { - // start timer after which rx1_window will get opened - _lora_time.start(_params.timers.rx_window1_timer, _params.rx_window1_delay); - - if (_device_class != CLASS_C) { - _lora_time.start(_params.timers.rx_window2_timer, _params.rx_window2_delay); - } - - if (_params.is_node_ack_requested) { - _lora_time.start(_params.timers.ack_timeout_timer, - _params.rx_window2_delay + _lora_phy.get_ack_timeout()); - } - } else { - _mcps_confirmation.status = LORAMAC_EVENT_INFO_STATUS_OK; - _mlme_confirmation.status = LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT; - } - - _params.last_channel_idx = _params.channel; - - _lora_phy.set_last_tx_done(_params.channel, _is_nwk_joined, cur_time); - - _params.timers.aggregated_last_tx_time = cur_time; +rx_slot_t LoRaMac::get_current_slot(void) +{ + return _params.rx_slot; } /** @@ -311,7 +284,7 @@ void LoRaMac::check_frame_size(uint16_t size) uint8_t value = _lora_phy.get_max_payload(_mcps_indication.rx_datarate, _params.is_repeater_supported); - if (MAX(0, (int16_t) ((int16_t)size - (int16_t)LORA_MAC_FRMPAYLOAD_OVERHEAD)) + if (MAX(0, (int16_t)((int16_t)size - (int16_t)LORA_MAC_FRMPAYLOAD_OVERHEAD)) > (int32_t) value) { tr_error("Invalid frame size"); } @@ -339,7 +312,7 @@ bool LoRaMac::message_integrity_check(const uint8_t *const payload, mic_rx |= ((uint32_t) payload[size - LORAMAC_MFR_LEN + 2] << 16); mic_rx |= ((uint32_t) payload[size - LORAMAC_MFR_LEN + 3] << 24); - sequence_counter_prev = (uint16_t) *downlink_counter; + sequence_counter_prev = (uint16_t)*downlink_counter; sequence_counter_diff = sequence_counter - sequence_counter_prev; *downlink_counter += sequence_counter_diff; if (sequence_counter < sequence_counter_prev) { @@ -444,7 +417,7 @@ void LoRaMac::extract_data_and_mac_commands(const uint8_t *payload, if (_lora_crypto.decrypt_payload(payload + payload_start_index, frame_len, app_skey, - sizeof(_params.keys.app_skey)*8, + sizeof(_params.keys.app_skey) * 8, address, DOWN_LINK, downlink_counter, @@ -656,26 +629,53 @@ void LoRaMac::set_batterylevel_callback(mbed::Callback battery_le _mac_commands.set_batterylevel_callback(battery_level); } +void LoRaMac::on_radio_tx_done(lorawan_time_t timestamp) +{ + if (_device_class == CLASS_C) { + // this will open a continuous RX2 window until time==RECV_DELAY1 + open_rx2_window(); + } else { + _lora_phy.put_radio_to_sleep(); + } + + if (_params.is_rx_window_enabled == true) { + lorawan_time_t time_diff = _lora_time.get_current_time() - timestamp; + // start timer after which rx1_window will get opened + _lora_time.start(_params.timers.rx_window1_timer, + _params.rx_window1_delay - time_diff); + + if (_device_class != CLASS_C) { + _lora_time.start(_params.timers.rx_window2_timer, + _params.rx_window2_delay - time_diff); + } + + if (_params.is_node_ack_requested) { + _lora_time.start(_params.timers.ack_timeout_timer, + (_params.rx_window2_delay - time_diff) + + _lora_phy.get_ack_timeout()); + } + } else { + _mcps_confirmation.status = LORAMAC_EVENT_INFO_STATUS_OK; + _mlme_confirmation.status = LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT; + } + + _params.last_channel_idx = _params.channel; + + _lora_phy.set_last_tx_done(_params.channel, _is_nwk_joined, timestamp); + + _params.timers.aggregated_last_tx_time = timestamp; +} + void LoRaMac::on_radio_rx_done(const uint8_t *const payload, uint16_t size, int16_t rssi, int8_t snr) { - // stop the RX1 timer here if its the first RX slot. - // If the MIC will pass we will stop RX2 timer as well later. - // If its RX2, stop RX2 timer. - if (_params.rx_slot == RX_SLOT_WIN_1) { + if (_device_class == CLASS_C && !_continuous_rx2_window_open) { + open_rx2_window(); + } else { _lora_time.stop(_params.timers.rx_window1_timer); - } else if (_params.rx_slot == RX_SLOT_WIN_2) { - _lora_time.stop(_params.timers.rx_window2_timer); + _lora_phy.put_radio_to_sleep(); } - if (_device_class == CLASS_C) { - if (!_continuous_rx2_window_open) { - open_rx2_window(); - } - } else { - _lora_phy.put_radio_to_sleep(); - } - loramac_mhdr_t mac_hdr; uint8_t pos = 0; mac_hdr.value = payload[pos++]; @@ -731,21 +731,23 @@ void LoRaMac::on_radio_tx_timeout(void) post_process_mcps_req(); } -rx_slot_t LoRaMac::on_radio_rx_timeout(bool is_timeout) +void LoRaMac::on_radio_rx_timeout(bool is_timeout) { - if (_device_class != CLASS_C) { + if (_device_class == CLASS_C && !_continuous_rx2_window_open) { + open_rx2_window(); + } else { _lora_phy.put_radio_to_sleep(); } if (_params.rx_slot == RX_SLOT_WIN_1) { if (_params.is_node_ack_requested == true) { _mcps_confirmation.status = is_timeout ? - LORAMAC_EVENT_INFO_STATUS_RX1_TIMEOUT : - LORAMAC_EVENT_INFO_STATUS_RX1_ERROR; + LORAMAC_EVENT_INFO_STATUS_RX1_TIMEOUT : + LORAMAC_EVENT_INFO_STATUS_RX1_ERROR; } _mlme_confirmation.status = is_timeout ? - LORAMAC_EVENT_INFO_STATUS_RX1_TIMEOUT : - LORAMAC_EVENT_INFO_STATUS_RX1_ERROR; + LORAMAC_EVENT_INFO_STATUS_RX1_TIMEOUT : + LORAMAC_EVENT_INFO_STATUS_RX1_ERROR; if (_device_class != CLASS_C) { if (_lora_time.get_elapsed_time(_params.timers.aggregated_last_tx_time) >= _params.rx_window2_delay) { @@ -755,20 +757,14 @@ rx_slot_t LoRaMac::on_radio_rx_timeout(bool is_timeout) } else { if (_params.is_node_ack_requested == true) { _mcps_confirmation.status = is_timeout ? - LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT : - LORAMAC_EVENT_INFO_STATUS_RX2_ERROR; + LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT : + LORAMAC_EVENT_INFO_STATUS_RX2_ERROR; } _mlme_confirmation.status = is_timeout ? - LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT : - LORAMAC_EVENT_INFO_STATUS_RX2_ERROR; + LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT : + LORAMAC_EVENT_INFO_STATUS_RX2_ERROR; } - - if (_device_class == CLASS_C) { - open_rx2_window(); - } - - return _params.rx_slot; } bool LoRaMac::continue_joining_process() @@ -804,8 +800,8 @@ lorawan_status_t LoRaMac::send_join_request() loramac_mhdr_t mac_hdr; loramac_frame_ctrl_t fctrl; - _params.sys_params.channel_data_rate = _lora_phy.get_alternate_DR( - _params.join_request_trial_counter + 1); + _params.sys_params.channel_data_rate = + _lora_phy.get_alternate_DR(_params.join_request_trial_counter + 1); mac_hdr.value = 0; mac_hdr.bits.mtype = FRAME_TYPE_JOIN_REQ; @@ -850,14 +846,13 @@ void LoRaMac::on_backoff_timer_expiry(void) { Lock lock(*this); lorawan_status_t status = schedule_tx(); - MBED_ASSERT(status==LORAWAN_STATUS_OK); + MBED_ASSERT(status == LORAWAN_STATUS_OK); (void) status; } void LoRaMac::open_rx1_window(void) { Lock lock(*this); - tr_debug("Opening RX1 Window"); _continuous_rx2_window_open = false; _lora_time.stop(_params.timers.rx_window1_timer); _params.rx_slot = RX_SLOT_WIN_1; @@ -878,25 +873,26 @@ void LoRaMac::open_rx1_window(void) _lora_phy.setup_rx_window(_params.rx_window1_config.is_rx_continuous, _params.sys_params.max_rx_win_time); + + tr_debug("Opening RX1 Window"); } void LoRaMac::open_rx2_window() { Lock lock(*this); - tr_debug("Opening RX2 Window"); + _continuous_rx2_window_open = true; _lora_time.stop(_params.timers.rx_window2_timer); _params.rx_window2_config.channel = _params.channel; _params.rx_window2_config.frequency = _params.sys_params.rx2_channel.frequency; _params.rx_window2_config.dl_dwell_time = _params.sys_params.downlink_dwell_time; _params.rx_window2_config.is_repeater_supported = _params.is_repeater_supported; - _params.rx_window2_config.rx_slot = RX_SLOT_WIN_2; + _params.rx_window2_config.rx_slot = _params.rx_window2_config.is_rx_continuous ? + RX_SLOT_WIN_CLASS_C : RX_SLOT_WIN_2; if (get_device_class() == CLASS_C) { - _continuous_rx2_window_open = true; _params.rx_window2_config.is_rx_continuous = true; } else { - _continuous_rx2_window_open = false; _params.rx_window2_config.is_rx_continuous = false; } @@ -907,9 +903,10 @@ void LoRaMac::open_rx2_window() _lora_phy.setup_rx_window(_params.rx_window2_config.is_rx_continuous, _params.sys_params.max_rx_win_time); - _params.rx_slot = _params.rx_window2_config.is_rx_continuous ? - RX_SLOT_WIN_CLASS_C : RX_SLOT_WIN_2; + _params.rx_slot = _params.rx_window2_config.rx_slot; } + + tr_debug("Opening RX2 Window, Frequency = %u", _params.rx_window2_config.frequency); } void LoRaMac::on_ack_timeout_timer_event(void) @@ -953,7 +950,7 @@ void LoRaMac::on_ack_timeout_timer_event(void) // now that is a critical failure lorawan_status_t status = handle_retransmission(); - MBED_ASSERT(status==LORAWAN_STATUS_OK); + MBED_ASSERT(status == LORAWAN_STATUS_OK); (void) status; } @@ -1095,9 +1092,9 @@ lorawan_status_t LoRaMac::schedule_tx() if (!_is_nwk_joined) { _params.rx_window1_delay = _params.sys_params.join_accept_delay1 - + _params.rx_window1_config.window_offset; + + _params.rx_window1_config.window_offset; _params.rx_window2_delay = _params.sys_params.join_accept_delay2 - + _params.rx_window2_config.window_offset; + + _params.rx_window2_config.window_offset; } else { if (validate_payload_length(_params.tx_buffer_len, _params.sys_params.channel_data_rate, @@ -1105,9 +1102,9 @@ lorawan_status_t LoRaMac::schedule_tx() return LORAWAN_STATUS_LENGTH_ERROR; } _params.rx_window1_delay = _params.sys_params.recv_delay1 - + _params.rx_window1_config.window_offset; + + _params.rx_window1_config.window_offset; _params.rx_window2_delay = _params.sys_params.recv_delay2 - + _params.rx_window2_config.window_offset; + + _params.rx_window2_config.window_offset; } // handle the ack to the server here so that if the sending was cancelled @@ -1248,9 +1245,9 @@ int16_t LoRaMac::prepare_ongoing_tx(const uint8_t port, // Handles unconfirmed messages if (flags & MSG_UNCONFIRMED_FLAG) { - _ongoing_tx_msg.type = MCPS_UNCONFIRMED; - _ongoing_tx_msg.fport = port; - _ongoing_tx_msg.nb_trials = 1; + _ongoing_tx_msg.type = MCPS_UNCONFIRMED; + _ongoing_tx_msg.fport = port; + _ongoing_tx_msg.nb_trials = 1; } // Handles confirmed messages @@ -1346,8 +1343,6 @@ void LoRaMac::set_device_class(const device_class_t &device_class, tr_debug("Changing device class to -> CLASS_C"); open_rx2_window(); } - - } void LoRaMac::setup_link_check_request() @@ -1542,7 +1537,7 @@ lorawan_status_t LoRaMac::prepare_frame(loramac_mhdr_t *machdr, _params.tx_buffer[pkt_header_len++] = _params.ul_frame_counter & 0xFF; _params.tx_buffer[pkt_header_len++] = (_params.ul_frame_counter >> 8) - & 0xFF; + & 0xFF; _mac_commands.copy_repeat_commands_to_buffer(); @@ -1556,8 +1551,7 @@ lorawan_status_t LoRaMac::prepare_frame(loramac_mhdr_t *machdr, // Update FCtrl field with new value of OptionsLength _params.tx_buffer[0x05] = fctrl->value; - const uint8_t *buffer = - _mac_commands.get_mac_commands_buffer(); + const uint8_t *buffer = _mac_commands.get_mac_commands_buffer(); for (i = 0; i < mac_commands_len; i++) { _params.tx_buffer[pkt_header_len++] = buffer[i]; } @@ -1582,13 +1576,13 @@ lorawan_status_t LoRaMac::prepare_frame(loramac_mhdr_t *machdr, _params.tx_buffer[pkt_header_len++] = frame_port; uint8_t *key = _params.keys.app_skey; - uint32_t key_length = sizeof(_params.keys.app_skey)*8; + uint32_t key_length = sizeof(_params.keys.app_skey) * 8; if (frame_port == 0) { _mac_commands.clear_command_buffer(); key = _params.keys.nwk_skey; - key_length = sizeof(_params.keys.nwk_skey)*8; + key_length = sizeof(_params.keys.nwk_skey) * 8; } - if (0 != _lora_crypto.encrypt_payload((uint8_t*) payload, _params.tx_buffer_len, + if (0 != _lora_crypto.encrypt_payload((uint8_t *) payload, _params.tx_buffer_len, key, key_length, _params.dev_addr, UP_LINK, _params.ul_frame_counter, @@ -1600,7 +1594,7 @@ lorawan_status_t LoRaMac::prepare_frame(loramac_mhdr_t *machdr, _params.tx_buffer_len = pkt_header_len + _params.tx_buffer_len; if (0 != _lora_crypto.compute_mic(_params.tx_buffer, _params.tx_buffer_len, - _params.keys.nwk_skey, sizeof(_params.keys.nwk_skey)*8, + _params.keys.nwk_skey, sizeof(_params.keys.nwk_skey) * 8, _params.dev_addr, UP_LINK, _params.ul_frame_counter, &mic)) { status = LORAWAN_STATUS_CRYPTO_FAIL; @@ -1775,7 +1769,7 @@ uint8_t LoRaMac::get_max_possible_tx_size(uint8_t size) uint8_t max_possible_payload_size = 0; uint8_t current_payload_size = 0; uint8_t fopt_len = _mac_commands.get_mac_cmd_length() - + _mac_commands.get_repeat_commands_length(); + + _mac_commands.get_repeat_commands_length(); if (_params.sys_params.adr_on) { _lora_phy.get_next_ADR(false, _params.sys_params.channel_data_rate, @@ -1923,16 +1917,16 @@ lorawan_status_t LoRaMac::mlme_request(loramac_mlme_req_t *mlmeRequest) if (MLME_TXCW == mlmeRequest->type) { set_tx_continuous_wave(_params.channel, _params.sys_params.channel_data_rate, _params.sys_params.channel_tx_power, - _params.sys_params.max_eirp, _params.sys_params.antenna_gain, mlmeRequest->cw_tx_mode.timeout); + _params.sys_params.max_eirp, _params.sys_params.antenna_gain, mlmeRequest->cw_tx_mode.timeout); _lora_time.start(_params.timers.mac_state_check_timer, - MAC_STATE_CHECK_TIMEOUT); + MAC_STATE_CHECK_TIMEOUT); _params.mac_state |= LORAMAC_TX_RUNNING; status = LORAWAN_STATUS_OK; } else if (MLME_TXCW_1 == mlmeRequest->type) { set_tx_continuous_wave(0, 0, mlmeRequest->cw_tx_mode.power, 0, 0, mlmeRequest->cw_tx_mode.timeout); _lora_time.start(_params.timers.mac_state_check_timer, - MAC_STATE_CHECK_TIMEOUT); + MAC_STATE_CHECK_TIMEOUT); _params.mac_state |= LORAMAC_TX_RUNNING; status = LORAWAN_STATUS_OK; @@ -1946,7 +1940,7 @@ lorawan_status_t LoRaMac::mlme_request(loramac_mlme_req_t *mlmeRequest) return status; } -lorawan_status_t LoRaMac::test_request( loramac_compliance_test_req_t *mcpsRequest ) +lorawan_status_t LoRaMac::test_request(loramac_compliance_test_req_t *mcpsRequest) { if (_params.mac_state != LORAMAC_IDLE) { return LORAWAN_STATUS_BUSY; @@ -1981,7 +1975,7 @@ lorawan_status_t LoRaMac::test_request( loramac_compliance_test_req_t *mcpsReque break; } default: - return LORAWAN_STATUS_PARAMETER_INVALID; + return LORAWAN_STATUS_PARAMETER_INVALID; } // Filter fPorts @@ -1999,7 +1993,7 @@ lorawan_status_t LoRaMac::test_request( loramac_compliance_test_req_t *mcpsReque } lorawan_status_t status = send(&machdr, mcpsRequest->fport, mcpsRequest->f_buffer, - mcpsRequest->f_buffer_size); + mcpsRequest->f_buffer_size); if (status == LORAWAN_STATUS_OK) { _mcps_confirmation.req_type = mcpsRequest->type; _params.flags.bits.mcps_req = 1; @@ -2010,38 +2004,37 @@ lorawan_status_t LoRaMac::test_request( loramac_compliance_test_req_t *mcpsReque return status; } -lorawan_status_t LoRaMac::LoRaMacSetTxTimer( uint32_t TxDutyCycleTime ) +lorawan_status_t LoRaMac::LoRaMacSetTxTimer(uint32_t TxDutyCycleTime) { _lora_time.start(tx_next_packet_timer, TxDutyCycleTime); return LORAWAN_STATUS_OK; } -lorawan_status_t LoRaMac::LoRaMacStopTxTimer( ) +lorawan_status_t LoRaMac::LoRaMacStopTxTimer() { _lora_time.stop(tx_next_packet_timer); return LORAWAN_STATUS_OK; } -void LoRaMac::LoRaMacTestRxWindowsOn( bool enable ) +void LoRaMac::LoRaMacTestRxWindowsOn(bool enable) { _params.is_rx_window_enabled = enable; } -void LoRaMac::LoRaMacTestSetMic( uint16_t txPacketCounter ) +void LoRaMac::LoRaMacTestSetMic(uint16_t txPacketCounter) { _params.ul_frame_counter = txPacketCounter; _params.is_ul_frame_counter_fixed = true; } -void LoRaMac::LoRaMacTestSetDutyCycleOn( bool enable ) +void LoRaMac::LoRaMacTestSetDutyCycleOn(bool enable) { - if(_lora_phy.verify_duty_cycle(enable) == true) - { + if (_lora_phy.verify_duty_cycle(enable) == true) { _params.is_dutycycle_on = enable; } } -void LoRaMac::LoRaMacTestSetChannel( uint8_t channel ) +void LoRaMac::LoRaMacTestSetChannel(uint8_t channel) { _params.channel = channel; } diff --git a/features/lorawan/lorastack/mac/LoRaMac.h b/features/lorawan/lorastack/mac/LoRaMac.h index 479869aa97..915cb5ce16 100644 --- a/features/lorawan/lorastack/mac/LoRaMac.h +++ b/features/lorawan/lorastack/mac/LoRaMac.h @@ -386,7 +386,7 @@ public: /** * MAC operations upon successful transmission */ - void on_radio_tx_done(void); + void on_radio_tx_done(lorawan_time_t timestamp); /** * MAC operations upon reception @@ -407,7 +407,7 @@ public: * * @return current RX slot */ - rx_slot_t on_radio_rx_timeout(bool is_timeout); + void on_radio_rx_timeout(bool is_timeout); /** * Handles retransmissions of Join requests if an Accept @@ -455,6 +455,16 @@ public: */ lorawan_status_t clear_tx_pipe(void); + /** + * Gets the current time + */ + lorawan_time_t get_current_time(void); + + /** + * Gets the current receive slot + */ + rx_slot_t get_current_slot(void); + /** * These locks trample through to the upper layers and make * the stack thread safe. @@ -757,7 +767,7 @@ public: // Test interface * \ref LORAWAN_STATUS_OK * \ref LORAWAN_STATUS_PARAMETER_INVALID */ - lorawan_status_t LoRaMacSetTxTimer( uint32_t NextTxTime ); + lorawan_status_t LoRaMacSetTxTimer(uint32_t NextTxTime); /** * \brief LoRaMAC stop tx timer. @@ -768,7 +778,7 @@ public: // Test interface * \ref LORAWAN_STATUS_OK * \ref LORAWAN_STATUS_PARAMETER_INVALID */ - lorawan_status_t LoRaMacStopTxTimer( ); + lorawan_status_t LoRaMacStopTxTimer(); /** * \brief Enabled or disables the reception windows @@ -778,7 +788,7 @@ public: // Test interface * * \param [in] enable - Enabled or disables the reception windows */ - void LoRaMacTestRxWindowsOn( bool enable ); + void LoRaMacTestRxWindowsOn(bool enable); /** * \brief Enables the MIC field test @@ -788,7 +798,7 @@ public: // Test interface * * \param [in] txPacketCounter - Fixed Tx packet counter value */ - void LoRaMacTestSetMic( uint16_t txPacketCounter ); + void LoRaMacTestSetMic(uint16_t txPacketCounter); /** * \brief Enabled or disables the duty cycle @@ -798,7 +808,7 @@ public: // Test interface * * \param [in] enable - Enabled or disables the duty cycle */ - void LoRaMacTestSetDutyCycleOn( bool enable ); + void LoRaMacTestSetDutyCycleOn(bool enable); /** * \brief Sets the channel index @@ -808,7 +818,7 @@ public: // Test interface * * \param [in] channel - Channel index */ - void LoRaMacTestSetChannel( uint8_t channel ); + void LoRaMacTestSetChannel(uint8_t channel); private: /** diff --git a/features/lorawan/lorastack/phy/LoRaPHY.cpp b/features/lorawan/lorastack/phy/LoRaPHY.cpp index b0bbb6b2c1..61416a42a2 100644 --- a/features/lorawan/lorastack/phy/LoRaPHY.cpp +++ b/features/lorawan/lorastack/phy/LoRaPHY.cpp @@ -47,30 +47,35 @@ LoRaPHY::~LoRaPHY() _radio = NULL; } -bool LoRaPHY::mask_bit_test(const uint16_t *mask, unsigned bit) { - return mask[bit/16] & (1U << (bit % 16)); +bool LoRaPHY::mask_bit_test(const uint16_t *mask, unsigned bit) +{ + return mask[bit / 16] & (1U << (bit % 16)); } -void LoRaPHY::mask_bit_set(uint16_t *mask, unsigned bit) { - mask[bit/16] |= (1U << (bit % 16)); +void LoRaPHY::mask_bit_set(uint16_t *mask, unsigned bit) +{ + mask[bit / 16] |= (1U << (bit % 16)); } -void LoRaPHY::mask_bit_clear(uint16_t *mask, unsigned bit) { - mask[bit/16] &= ~(1U << (bit % 16)); +void LoRaPHY::mask_bit_clear(uint16_t *mask, unsigned bit) +{ + mask[bit / 16] &= ~(1U << (bit % 16)); } -void LoRaPHY::set_radio_instance(LoRaRadio& radio) +void LoRaPHY::set_radio_instance(LoRaRadio &radio) { _radio = &radio; } -void LoRaPHY::put_radio_to_sleep() { +void LoRaPHY::put_radio_to_sleep() +{ _radio->lock(); _radio->sleep(); _radio->unlock(); } -void LoRaPHY::put_radio_to_standby() { +void LoRaPHY::put_radio_to_standby() +{ _radio->lock(); _radio->standby(); _radio->unlock(); @@ -100,7 +105,7 @@ uint32_t LoRaPHY::get_radio_rng() uint32_t rand; _radio->lock(); - rand =_radio->random(); + rand = _radio->random(); _radio->unlock(); return rand; @@ -113,7 +118,7 @@ void LoRaPHY::handle_send(uint8_t *buf, uint8_t size) _radio->unlock(); } -uint8_t LoRaPHY::request_new_channel(int8_t channel_id, channel_params_t* new_channel) +uint8_t LoRaPHY::request_new_channel(int8_t channel_id, channel_params_t *new_channel) { if (!phy_params.custom_channelplans_supported) { return 0; @@ -129,27 +134,22 @@ uint8_t LoRaPHY::request_new_channel(int8_t channel_id, channel_params_t* new_ch } else { new_channel->band = lookup_band_for_frequency(new_channel->frequency); switch (add_channel(new_channel, channel_id)) { - case LORAWAN_STATUS_OK: - { + case LORAWAN_STATUS_OK: { break; } - case LORAWAN_STATUS_FREQUENCY_INVALID: - { + case LORAWAN_STATUS_FREQUENCY_INVALID: { status &= 0xFE; break; } - case LORAWAN_STATUS_DATARATE_INVALID: - { + case LORAWAN_STATUS_DATARATE_INVALID: { status &= 0xFD; break; } - case LORAWAN_STATUS_FREQ_AND_DR_INVALID: - { + case LORAWAN_STATUS_FREQ_AND_DR_INVALID: { status &= 0xFC; break; } - default: - { + default: { status &= 0xFC; break; } @@ -164,9 +164,9 @@ int32_t LoRaPHY::get_random(int32_t min, int32_t max) return (int32_t) rand() % (max - min + 1) + min; } -bool LoRaPHY::verify_channel_DR(uint8_t nb_channels, uint16_t* channel_mask, +bool LoRaPHY::verify_channel_DR(uint8_t nb_channels, uint16_t *channel_mask, int8_t dr, int8_t min_dr, int8_t max_dr, - channel_params_t* channels) + channel_params_t *channels) { if (val_in_range(dr, min_dr, max_dr) == 0) { return false; @@ -186,7 +186,7 @@ bool LoRaPHY::verify_channel_DR(uint8_t nb_channels, uint16_t* channel_mask, return false; } -bool LoRaPHY::val_in_range( int8_t value, int8_t min, int8_t max ) +bool LoRaPHY::val_in_range(int8_t value, int8_t min, int8_t max) { if ((value >= min) && (value <= max)) { return true; @@ -195,7 +195,7 @@ bool LoRaPHY::val_in_range( int8_t value, int8_t min, int8_t max ) return false; } -bool LoRaPHY::disable_channel(uint16_t* channel_mask, uint8_t id, +bool LoRaPHY::disable_channel(uint16_t *channel_mask, uint8_t id, uint8_t max_channels_num) { uint8_t index = id / 16; @@ -214,7 +214,7 @@ uint8_t LoRaPHY::count_bits(uint16_t mask, uint8_t nbBits) { uint8_t nbActiveBits = 0; - for(uint8_t j = 0; j < nbBits; j++) { + for (uint8_t j = 0; j < nbBits; j++) { if (mask_bit_test(&mask, j)) { nbActiveBits++; } @@ -223,7 +223,7 @@ uint8_t LoRaPHY::count_bits(uint16_t mask, uint8_t nbBits) return nbActiveBits; } -uint8_t LoRaPHY::num_active_channels(uint16_t* channel_mask, uint8_t start_idx, +uint8_t LoRaPHY::num_active_channels(uint16_t *channel_mask, uint8_t start_idx, uint8_t stop_idx) { uint8_t nb_channels = 0; @@ -239,10 +239,10 @@ uint8_t LoRaPHY::num_active_channels(uint16_t* channel_mask, uint8_t start_idx, return nb_channels; } -void LoRaPHY::copy_channel_mask(uint16_t* dest_mask, uint16_t* src_mask, uint8_t len) +void LoRaPHY::copy_channel_mask(uint16_t *dest_mask, uint16_t *src_mask, uint8_t len) { if ((dest_mask != NULL) && (src_mask != NULL)) { - for( uint8_t i = 0; i < len; i++ ) { + for (uint8_t i = 0; i < len; i++) { dest_mask[i] = src_mask[i]; } } @@ -264,37 +264,37 @@ void LoRaPHY::set_last_tx_done(uint8_t channel, bool joined, lorawan_time_t last } lorawan_time_t LoRaPHY::update_band_timeoff(bool joined, bool duty_cycle, - band_t* bands, uint8_t nb_bands) + band_t *bands, uint8_t nb_bands) { - lorawan_time_t next_tx_delay = (lorawan_time_t) (-1); + lorawan_time_t next_tx_delay = (lorawan_time_t)(-1); // Update bands Time OFF for (uint8_t i = 0; i < nb_bands; i++) { if (joined == false) { uint32_t txDoneTime = MAX(_lora_time.get_elapsed_time(bands[i].last_join_tx_time), - (duty_cycle == true) ? - _lora_time.get_elapsed_time(bands[i].last_tx_time) : 0); + (duty_cycle == true) ? + _lora_time.get_elapsed_time(bands[i].last_tx_time) : 0); if (bands[i].off_time <= txDoneTime) { bands[i].off_time = 0; } if (bands[i].off_time != 0) { - next_tx_delay = MIN( bands[i].off_time - txDoneTime, next_tx_delay ); + next_tx_delay = MIN(bands[i].off_time - txDoneTime, next_tx_delay); } } else { // if network has been joined if (duty_cycle == true) { - if( bands[i].off_time <= _lora_time.get_elapsed_time(bands[i].last_tx_time)) { + if (bands[i].off_time <= _lora_time.get_elapsed_time(bands[i].last_tx_time)) { bands[i].off_time = 0; } - if(bands[i].off_time != 0 ) { + if (bands[i].off_time != 0) { next_tx_delay = MIN(bands[i].off_time - _lora_time.get_elapsed_time(bands[i].last_tx_time), - next_tx_delay); + next_tx_delay); } } else { // if duty cycle is not on @@ -307,7 +307,8 @@ lorawan_time_t LoRaPHY::update_band_timeoff(bool joined, bool duty_cycle, return next_tx_delay; } -uint8_t LoRaPHY::parse_link_ADR_req(const uint8_t* payload, link_adr_params_t* params) +uint8_t LoRaPHY::parse_link_ADR_req(const uint8_t *payload, + link_adr_params_t *params) { uint8_t ret_index = 0; @@ -324,7 +325,7 @@ uint8_t LoRaPHY::parse_link_ADR_req(const uint8_t* payload, link_adr_params_t* p // Parse ChMaskCtrl and nbRep params->nb_rep = payload[4]; - params->ch_mask_ctrl = ( params->nb_rep >> 4 ) & 0x07; + params->ch_mask_ctrl = (params->nb_rep >> 4) & 0x07; params->nb_rep &= 0x0F; // LinkAdrReq has 4 bytes length + 1 byte CMD @@ -334,8 +335,8 @@ uint8_t LoRaPHY::parse_link_ADR_req(const uint8_t* payload, link_adr_params_t* p return ret_index; } -uint8_t LoRaPHY::verify_link_ADR_req(verify_adr_params_t* verify_params, - int8_t* dr, int8_t* tx_pow, uint8_t* nb_rep) +uint8_t LoRaPHY::verify_link_ADR_req(verify_adr_params_t *verify_params, + int8_t *dr, int8_t *tx_pow, uint8_t *nb_rep) { uint8_t status = verify_params->status; int8_t datarate = verify_params->datarate; @@ -404,10 +405,10 @@ double LoRaPHY::compute_symb_timeout_fsk(uint8_t phy_dr) 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) + uint32_t *window_timeout, int32_t *window_offset) { // 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_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); } @@ -430,7 +431,7 @@ int8_t LoRaPHY::get_next_lower_dr(int8_t dr, int8_t min_dr) if (next_lower_dr != min_dr) { next_lower_dr -= 1; } - } while((next_lower_dr != min_dr) && !is_datarate_supported(next_lower_dr)); + } while ((next_lower_dr != min_dr) && !is_datarate_supported(next_lower_dr)); return next_lower_dr; } @@ -439,7 +440,7 @@ uint8_t LoRaPHY::get_bandwidth(uint8_t dr) { uint32_t *bandwidths = (uint32_t *) phy_params.bandwidths.table; - switch(bandwidths[dr]) { + switch (bandwidths[dr]) { default: case 125000: return 0; @@ -462,7 +463,7 @@ uint8_t LoRaPHY::enabled_channel_count(bool joined, uint8_t datarate, if (mask_bit_test(channel_mask, i)) { if (val_in_range(datarate, phy_params.channels.channel_list[i].dr_range.fields.min, - phy_params.channels.channel_list[i].dr_range.fields.max ) == 0) { + phy_params.channels.channel_list[i].dr_range.fields.max) == 0) { // data rate range invalid for this channel continue; } @@ -602,7 +603,7 @@ uint8_t LoRaPHY::get_default_rx2_datarate() return phy_params.rx_window2_datarate; } -uint16_t* LoRaPHY::get_channel_mask(bool get_default) +uint16_t *LoRaPHY::get_channel_mask(bool get_default) { if (get_default) { return phy_params.channels.default_mask; @@ -615,7 +616,7 @@ uint8_t LoRaPHY::get_max_nb_channels() return phy_params.max_channel_cnt; } -channel_params_t* LoRaPHY::get_phy_channels() +channel_params_t *LoRaPHY::get_phy_channels() { return phy_params.channels.channel_list; } @@ -628,7 +629,7 @@ bool LoRaPHY::is_custom_channel_plan_supported() void LoRaPHY::restore_default_channels() { // Restore channels default mask - for (uint8_t i=0; i < phy_params.channels.mask_size; i++) { + for (uint8_t i = 0; i < phy_params.channels.mask_size; i++) { phy_params.channels.mask[i] |= phy_params.channels.default_mask[i]; } } @@ -644,7 +645,7 @@ bool LoRaPHY::verify_rx_datarate(uint8_t datarate) } else { return val_in_range(datarate, phy_params.dwell_limit_datarate, - phy_params.max_rx_datarate ); + phy_params.max_rx_datarate); } } return false; @@ -690,7 +691,7 @@ bool LoRaPHY::verify_nb_join_trials(uint8_t nb_join_trials) return true; } -void LoRaPHY::apply_cf_list(const uint8_t* payload, uint8_t size) +void LoRaPHY::apply_cf_list(const uint8_t *payload, uint8_t size) { // if the underlying PHY doesn't support CF-List, ignore the request if (!phy_params.cflist_supported) { @@ -700,8 +701,8 @@ void LoRaPHY::apply_cf_list(const uint8_t* payload, uint8_t size) channel_params_t new_channel; // Setup default datarate range - new_channel.dr_range.value = (phy_params.default_max_datarate << 4) - | phy_params.default_datarate; + new_channel.dr_range.value = (phy_params.default_max_datarate << 4) | + phy_params.default_datarate; // Size of the optional CF list if (size != 16) { @@ -716,7 +717,7 @@ void LoRaPHY::apply_cf_list(const uint8_t* payload, uint8_t size) // should override this function in the implementation of that particular // PHY. for (uint8_t i = 0, channel_id = phy_params.default_channel_cnt; - channel_id < phy_params.max_channel_cnt; i+=3, channel_id++) { + channel_id < phy_params.max_channel_cnt; i += 3, channel_id++) { if (channel_id < (phy_params.cflist_channel_cnt + phy_params.default_channel_cnt)) { // Channel frequency new_channel.frequency = (uint32_t) payload[i]; @@ -745,8 +746,8 @@ void LoRaPHY::apply_cf_list(const uint8_t* payload, uint8_t size) } -bool LoRaPHY::get_next_ADR(bool restore_channel_mask, int8_t& dr_out, - int8_t& tx_power_out, uint32_t& adr_ack_cnt) +bool LoRaPHY::get_next_ADR(bool restore_channel_mask, int8_t &dr_out, + int8_t &tx_power_out, uint32_t &adr_ack_cnt) { bool set_adr_ack_bit = false; @@ -791,7 +792,7 @@ void LoRaPHY::compute_rx_win_params(int8_t datarate, uint8_t min_rx_symbols, double t_symbol = 0.0; // Get the datarate, perform a boundary check - rx_conf_params->datarate = MIN( datarate, phy_params.max_rx_datarate); + rx_conf_params->datarate = MIN(datarate, phy_params.max_rx_datarate); rx_conf_params->bandwidth = get_bandwidth(rx_conf_params->datarate); @@ -801,14 +802,14 @@ void LoRaPHY::compute_rx_win_params(int8_t datarate, uint8_t min_rx_symbols, } else { // LoRa t_symbol = compute_symb_timeout_lora(((uint8_t *)phy_params.datarates.table)[rx_conf_params->datarate], - ((uint32_t *)phy_params.bandwidths.table)[rx_conf_params->datarate]); + ((uint32_t *)phy_params.bandwidths.table)[rx_conf_params->datarate]); } get_rx_window_params(t_symbol, min_rx_symbols, rx_error, RADIO_WAKEUP_TIME, &rx_conf_params->window_timeout, &rx_conf_params->window_offset); } -bool LoRaPHY::rx_config(rx_config_params_t* rx_conf) +bool LoRaPHY::rx_config(rx_config_params_t *rx_conf) { radio_modems_t modem; uint8_t dr = rx_conf->datarate; @@ -871,8 +872,8 @@ bool LoRaPHY::rx_config(rx_config_params_t* rx_conf) return true; } -bool LoRaPHY::tx_config(tx_config_params_t* tx_conf, int8_t* tx_power, - lorawan_time_t* tx_toa) +bool LoRaPHY::tx_config(tx_config_params_t *tx_conf, int8_t *tx_power, + lorawan_time_t *tx_toa) { radio_modems_t modem; int8_t phy_dr = ((uint8_t *)phy_params.datarates.table)[tx_conf->datarate]; @@ -895,7 +896,7 @@ bool LoRaPHY::tx_config(tx_config_params_t* tx_conf, int8_t* tx_power, // Setup the radio frequency _radio->set_channel(list[tx_conf->channel].frequency); - if( tx_conf->datarate == phy_params.max_tx_datarate ) { + if (tx_conf->datarate == phy_params.max_tx_datarate) { // High Speed FSK channel modem = MODEM_FSK; _radio->set_tx_config(modem, phy_tx_power, 25000, bandwidth, @@ -904,11 +905,11 @@ bool LoRaPHY::tx_config(tx_config_params_t* tx_conf, int8_t* tx_power, } else { modem = MODEM_LORA; _radio->set_tx_config(modem, phy_tx_power, 0, bandwidth, phy_dr, 1, 8, - false, true, 0, 0, false, 3000 ); + false, true, 0, 0, false, 3000); } // Setup maximum payload lenght of the radio driver - _radio->set_max_payload_length( modem, tx_conf->pkt_len); + _radio->set_max_payload_length(modem, tx_conf->pkt_len); // Get the time-on-air of the next tx frame *tx_toa = _radio->time_on_air(modem, tx_conf->pkt_len); @@ -919,9 +920,9 @@ bool LoRaPHY::tx_config(tx_config_params_t* tx_conf, int8_t* tx_power, return true; } -uint8_t LoRaPHY::link_ADR_request(adr_req_params_t* link_adr_req, - int8_t* dr_out, int8_t* tx_power_out, - uint8_t* nb_rep_out, uint8_t* nb_bytes_processed) +uint8_t LoRaPHY::link_ADR_request(adr_req_params_t *link_adr_req, + int8_t *dr_out, int8_t *tx_power_out, + uint8_t *nb_rep_out, uint8_t *nb_bytes_processed) { uint8_t status = 0x07; link_adr_params_t adr_settings; @@ -939,7 +940,7 @@ uint8_t LoRaPHY::link_ADR_request(adr_req_params_t* link_adr_req, while (bytes_processed < link_adr_req->payload_size) { // Get ADR request parameters next_index = parse_link_ADR_req(&(link_adr_req->payload[bytes_processed]), - &adr_settings); + &adr_settings); if (next_index == 0) { break; // break loop, since no more request has been found @@ -960,8 +961,7 @@ uint8_t LoRaPHY::link_ADR_request(adr_req_params_t* link_adr_req, } // channel mask applies to first 16 channels - if (adr_settings.ch_mask_ctrl == 0 || - adr_settings.ch_mask_ctrl == 6) { + if (adr_settings.ch_mask_ctrl == 0 || adr_settings.ch_mask_ctrl == 6) { for (uint8_t i = 0; i < phy_params.max_channel_cnt; i++) { @@ -977,7 +977,7 @@ uint8_t LoRaPHY::link_ADR_request(adr_req_params_t* link_adr_req, // if channel mask control is 0, we test the bits and // frequencies and change the status if we find a discrepancy if ((mask_bit_test(temp_channel_mask, i)) && - (phy_params.channels.channel_list[i].frequency == 0)) { + (phy_params.channels.channel_list[i].frequency == 0)) { // Trying to enable an undefined channel status &= 0xFE; // Channel mask KO } @@ -1030,10 +1030,14 @@ uint8_t LoRaPHY::link_ADR_request(adr_req_params_t* link_adr_req, return status; } -uint8_t LoRaPHY::accept_rx_param_setup_req(rx_param_setup_req_t* params) +uint8_t LoRaPHY::accept_rx_param_setup_req(rx_param_setup_req_t *params) { uint8_t status = 0x07; + if (lookup_band_for_frequency(params->frequency) < 0) { + status &= 0xFE; + } + // Verify radio frequency if (_radio->check_rf_frequency(params->frequency) == false) { status &= 0xFE; // Channel frequency KO @@ -1069,7 +1073,7 @@ int LoRaPHY::lookup_band_for_frequency(uint32_t freq) const // check all sub bands (if there are sub-bands) to check if the given // frequency falls into any of the frequency ranges - for (int band=0; bandjoined, - params->dc_enabled, - band_table, phy_params.bands.size); + params->dc_enabled, + band_table, phy_params.bands.size); // Search how many channels are enabled channel_count = enabled_channel_count(params->joined, params->current_datarate, - phy_params.channels.mask, - enabled_channels, &delay_tx); + phy_params.channels.mask, + enabled_channels, &delay_tx); } else { delay_tx++; - next_tx_delay = params->aggregate_timeoff - - _lora_time.get_elapsed_time(params->last_aggregate_tx_time); + next_tx_delay = params->aggregate_timeoff - + _lora_time.get_elapsed_time(params->last_aggregate_tx_time); } if (channel_count > 0) { @@ -1272,7 +1275,8 @@ lorawan_status_t LoRaPHY::set_next_channel(channel_selection_params_t* params, return LORAWAN_STATUS_NO_CHANNEL_FOUND; } -lorawan_status_t LoRaPHY::add_channel(const channel_params_t* new_channel, uint8_t id) +lorawan_status_t LoRaPHY::add_channel(const channel_params_t *new_channel, + uint8_t id) { bool dr_invalid = false; bool freq_invalid = false; @@ -1367,7 +1371,7 @@ bool LoRaPHY::remove_channel(uint8_t channel_id) phy_params.max_channel_cnt); } -void LoRaPHY::set_tx_cont_mode(cw_mode_params_t* params, uint32_t given_frequency) +void LoRaPHY::set_tx_cont_mode(cw_mode_params_t *params, uint32_t given_frequency) { band_t *bands_table = (band_t *) phy_params.bands.table; channel_params_t *channels = phy_params.channels.channel_list; @@ -1380,7 +1384,7 @@ void LoRaPHY::set_tx_cont_mode(cw_mode_params_t* params, uint32_t given_frequenc uint32_t frequency = 0; if (given_frequency == 0) { - frequency = channels[params->channel].frequency; + frequency = channels[params->channel].frequency; } else { frequency = given_frequency; } @@ -1388,7 +1392,7 @@ void LoRaPHY::set_tx_cont_mode(cw_mode_params_t* params, uint32_t given_frequenc // Calculate physical TX power if (params->max_eirp > 0 && params->antenna_gain > 0) { phy_tx_power = compute_tx_power(params->tx_power, params->max_eirp, - params->antenna_gain ); + params->antenna_gain); } else { phy_tx_power = params->tx_power; }