Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
LoRaPHYUS915Hybrid.cpp
00001 /** 00002 * @file LoRaPHYUS915Hybrid.cpp 00003 * 00004 * @brief Implements LoRaPHY for US 915 MHz Hybrid band 00005 * 00006 * \code 00007 * ______ _ 00008 * / _____) _ | | 00009 * ( (____ _____ ____ _| |_ _____ ____| |__ 00010 * \____ \| ___ | (_ _) ___ |/ ___) _ \ 00011 * _____) ) ____| | | || |_| ____( (___| | | | 00012 * (______/|_____)_|_|_| \__)_____)\____)_| |_| 00013 * (C)2013 Semtech 00014 * ___ _____ _ ___ _ _____ ___ ___ ___ ___ 00015 * / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __| 00016 * \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _| 00017 * |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___| 00018 * embedded.connectivity.solutions=============== 00019 * 00020 * \endcode 00021 * 00022 * 00023 * License: Revised BSD License, see LICENSE.TXT file include in the project 00024 * 00025 * Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE ) 00026 * 00027 * Copyright (c) 2017, Arm Limited and affiliates. 00028 * SPDX-License-Identifier: BSD-3-Clause 00029 * 00030 */ 00031 00032 #include "LoRaPHYUS915Hybrid.h" 00033 #include "lora_phy_ds.h" 00034 00035 /*! 00036 * Minimal datarate that can be used by the node 00037 */ 00038 #define US915_HYBRID_TX_MIN_DATARATE DR_0 00039 00040 /*! 00041 * Maximal datarate that can be used by the node 00042 */ 00043 #define US915_HYBRID_TX_MAX_DATARATE DR_4 00044 00045 /*! 00046 * Minimal datarate that can be used by the node 00047 */ 00048 #define US915_HYBRID_RX_MIN_DATARATE DR_8 00049 00050 /*! 00051 * Maximal datarate that can be used by the node 00052 */ 00053 #define US915_HYBRID_RX_MAX_DATARATE DR_13 00054 00055 /*! 00056 * Default datarate used by the node 00057 */ 00058 #define US915_HYBRID_DEFAULT_DATARATE DR_0 00059 00060 /*! 00061 * Minimal Rx1 receive datarate offset 00062 */ 00063 #define US915_HYBRID_MIN_RX1_DR_OFFSET 0 00064 00065 /*! 00066 * Maximal Rx1 receive datarate offset 00067 */ 00068 #define US915_HYBRID_MAX_RX1_DR_OFFSET 3 00069 00070 /*! 00071 * Default Rx1 receive datarate offset 00072 */ 00073 #define US915_HYBRID_DEFAULT_RX1_DR_OFFSET 0 00074 00075 /*! 00076 * Minimal Tx output power that can be used by the node 00077 */ 00078 #define US915_HYBRID_MIN_TX_POWER TX_POWER_10 00079 00080 /*! 00081 * Maximal Tx output power that can be used by the node 00082 */ 00083 #define US915_HYBRID_MAX_TX_POWER TX_POWER_0 00084 00085 /*! 00086 * Default Tx output power used by the node 00087 */ 00088 #define US915_HYBRID_DEFAULT_TX_POWER TX_POWER_0 00089 00090 /*! 00091 * Default Max ERP 00092 */ 00093 #define US915_HYBRID_DEFAULT_MAX_ERP 30.0f 00094 00095 /*! 00096 * ADR Ack limit 00097 */ 00098 #define US915_HYBRID_ADR_ACK_LIMIT 64 00099 00100 /*! 00101 * ADR Ack delay 00102 */ 00103 #define US915_HYBRID_ADR_ACK_DELAY 32 00104 00105 /*! 00106 * Enabled or disabled the duty cycle 00107 */ 00108 #define US915_HYBRID_DUTY_CYCLE_ENABLED 0 00109 00110 /*! 00111 * Maximum RX window duration 00112 */ 00113 #define US915_HYBRID_MAX_RX_WINDOW 3000 00114 00115 /*! 00116 * Receive delay 1 00117 */ 00118 #define US915_HYBRID_RECEIVE_DELAY1 1000 00119 00120 /*! 00121 * Receive delay 2 00122 */ 00123 #define US915_HYBRID_RECEIVE_DELAY2 2000 00124 00125 /*! 00126 * Join accept delay 1 00127 */ 00128 #define US915_HYBRID_JOIN_ACCEPT_DELAY1 5000 00129 00130 /*! 00131 * Join accept delay 2 00132 */ 00133 #define US915_HYBRID_JOIN_ACCEPT_DELAY2 6000 00134 00135 /*! 00136 * Maximum frame counter gap 00137 */ 00138 #define US915_HYBRID_MAX_FCNT_GAP 16384 00139 00140 /*! 00141 * Ack timeout 00142 */ 00143 #define US915_HYBRID_ACKTIMEOUT 2000 00144 00145 /*! 00146 * Random ack timeout limits 00147 */ 00148 #define US915_HYBRID_ACK_TIMEOUT_RND 1000 00149 00150 /*! 00151 * Second reception window channel frequency definition. 00152 */ 00153 #define US915_HYBRID_RX_WND_2_FREQ 923300000 00154 00155 /*! 00156 * Second reception window channel datarate definition. 00157 */ 00158 #define US915_HYBRID_RX_WND_2_DR DR_8 00159 00160 /*! 00161 * Band 0 definition 00162 * { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff } 00163 */ 00164 static const band_t US915_HYBRID_BAND0 = { 1, US915_HYBRID_MAX_TX_POWER, 0, 0, 0 }; // 100.0 % 00165 00166 /*! 00167 * Defines the first channel for RX window 1 for US band 00168 */ 00169 #define US915_HYBRID_FIRST_RX1_CHANNEL ( (uint32_t) 923300000 ) 00170 00171 /*! 00172 * Defines the last channel for RX window 1 for US band 00173 */ 00174 #define US915_HYBRID_LAST_RX1_CHANNEL ( (uint32_t) 927500000 ) 00175 00176 /*! 00177 * Defines the step width of the channels for RX window 1 00178 */ 00179 #define US915_HYBRID_STEPWIDTH_RX1_CHANNEL ( (uint32_t) 600000 ) 00180 00181 /*! 00182 * Data rates table definition 00183 */ 00184 static const uint8_t datarates_US915_HYBRID [] = { 10, 9, 8, 7, 8, 0, 0, 0, 12, 11, 10, 9, 8, 7, 0, 0 }; 00185 00186 /*! 00187 * Bandwidths table definition in Hz 00188 */ 00189 static const uint32_t bandwidths_US915_HYBRID [] = { 125000, 125000, 125000, 125000, 500000, 0, 0, 0, 500000, 500000, 500000, 500000, 500000, 500000, 0, 0 }; 00190 00191 /*! 00192 * Up/Down link data rates offset definition 00193 */ 00194 static const int8_t datarate_offsets_US915_HYBRID [5][4] = 00195 { 00196 { DR_10, DR_9 , DR_8 , DR_8 }, // DR_0 00197 { DR_11, DR_10, DR_9 , DR_8 }, // DR_1 00198 { DR_12, DR_11, DR_10, DR_9 }, // DR_2 00199 { DR_13, DR_12, DR_11, DR_10 }, // DR_3 00200 { DR_13, DR_13, DR_12, DR_11 }, // DR_4 00201 }; 00202 00203 /*! 00204 * Maximum payload with respect to the datarate index. Cannot operate with repeater. 00205 */ 00206 static const uint8_t max_payloads_US915_HYBRID [] = { 11, 53, 125, 242, 242, 0, 0, 0, 53, 129, 242, 242, 242, 242, 0, 0 }; 00207 00208 /*! 00209 * Maximum payload with respect to the datarate index. Can operate with repeater. 00210 */ 00211 static const uint8_t max_payloads_with_repeater_US915_HYBRID [] = { 11, 53, 125, 242, 242, 0, 0, 0, 33, 109, 222, 222, 222, 222, 0, 0 }; 00212 00213 LoRaPHYUS915Hybrid::LoRaPHYUS915Hybrid(LoRaWANTimeHandler &lora_time) 00214 : LoRaPHY(lora_time) 00215 { 00216 bands[0] = US915_HYBRID_BAND0 ; 00217 00218 // Channels 00219 // 125 kHz channels 00220 for (uint8_t i = 0; i < US915_HYBRID_MAX_NB_CHANNELS - 8; i++) { 00221 channels[i].frequency = 902300000 + i * 200000; 00222 channels[i].dr_range.value = ( DR_3 << 4 ) | DR_0; 00223 channels[i].band = 0; 00224 } 00225 00226 // 500 kHz channels 00227 for (uint8_t i = US915_HYBRID_MAX_NB_CHANNELS - 8; i < US915_HYBRID_MAX_NB_CHANNELS; i++) { 00228 channels[i].frequency = 903000000 + (i - (US915_HYBRID_MAX_NB_CHANNELS - 8)) * 1600000; 00229 channels[i].dr_range.value = ( DR_4 << 4 ) | DR_4; 00230 channels[i].band = 0; 00231 } 00232 00233 // ChannelsMask 00234 default_channel_mask[0] = 0x00FF; 00235 default_channel_mask[1] = 0x0000; 00236 default_channel_mask[2] = 0x0000; 00237 default_channel_mask[3] = 0x0000; 00238 default_channel_mask[4] = 0x0001; 00239 00240 memset(channel_mask, 0, sizeof(channel_mask)); 00241 memset(current_channel_mask, 0, sizeof(current_channel_mask)); 00242 00243 // Copy channels default mask 00244 copy_channel_mask(channel_mask, default_channel_mask, US915_HYBRID_CHANNEL_MASK_SIZE); 00245 00246 // Copy into channels mask remaining 00247 copy_channel_mask(current_channel_mask, channel_mask, US915_HYBRID_CHANNEL_MASK_SIZE); 00248 00249 // set default channels 00250 phy_params.channels.channel_list = channels; 00251 phy_params.channels.channel_list_size = US915_HYBRID_MAX_NB_CHANNELS; 00252 phy_params.channels.mask = channel_mask; 00253 phy_params.channels.default_mask = default_channel_mask; 00254 phy_params.channels.mask_size = US915_HYBRID_CHANNEL_MASK_SIZE; 00255 00256 // set bands for US915_HYBRID spectrum 00257 phy_params.bands.table = (void *) bands; 00258 phy_params.bands.size = US915_HYBRID_MAX_NB_BANDS; 00259 00260 // set bandwidths available in US915_HYBRID spectrum 00261 phy_params.bandwidths.table = (void *) bandwidths_US915_HYBRID ; 00262 phy_params.bandwidths.size = 16; 00263 00264 // set data rates available in US915_HYBRID spectrum 00265 phy_params.datarates.table = (void *) datarates_US915_HYBRID ; 00266 phy_params.datarates.size = 16; 00267 00268 // set payload sizes with respect to data rates 00269 phy_params.payloads.table = (void *) max_payloads_US915_HYBRID ; 00270 phy_params.payloads.size = 16; 00271 phy_params.payloads_with_repeater.table = (void *) max_payloads_with_repeater_US915_HYBRID ; 00272 phy_params.payloads.size = 16; 00273 00274 // dwell time setting 00275 phy_params.ul_dwell_time_setting = 0; 00276 phy_params.dl_dwell_time_setting = 0; 00277 00278 // set initial and default parameters 00279 phy_params.duty_cycle_enabled = US915_HYBRID_DUTY_CYCLE_ENABLED; 00280 phy_params.accept_tx_param_setup_req = false; 00281 phy_params.fsk_supported = false; 00282 phy_params.cflist_supported = false; 00283 phy_params.dl_channel_req_supported = false; 00284 phy_params.custom_channelplans_supported = false; 00285 phy_params.default_channel_cnt = US915_HYBRID_MAX_NB_CHANNELS; 00286 phy_params.max_channel_cnt = US915_HYBRID_MAX_NB_CHANNELS; 00287 phy_params.cflist_channel_cnt = 0; 00288 phy_params.min_tx_datarate = US915_HYBRID_TX_MIN_DATARATE; 00289 phy_params.max_tx_datarate = US915_HYBRID_TX_MAX_DATARATE; 00290 phy_params.min_rx_datarate = US915_HYBRID_RX_MIN_DATARATE; 00291 phy_params.max_rx_datarate = US915_HYBRID_RX_MAX_DATARATE; 00292 phy_params.default_datarate = US915_HYBRID_DEFAULT_DATARATE; 00293 phy_params.default_max_datarate = US915_HYBRID_TX_MAX_DATARATE; 00294 phy_params.min_rx1_dr_offset = US915_HYBRID_MIN_RX1_DR_OFFSET; 00295 phy_params.max_rx1_dr_offset = US915_HYBRID_MAX_RX1_DR_OFFSET; 00296 phy_params.default_rx1_dr_offset = US915_HYBRID_DEFAULT_RX1_DR_OFFSET; 00297 phy_params.min_tx_power = US915_HYBRID_MIN_TX_POWER; 00298 phy_params.max_tx_power = US915_HYBRID_MAX_TX_POWER; 00299 phy_params.default_tx_power = US915_HYBRID_DEFAULT_TX_POWER; 00300 phy_params.default_max_eirp = 0; 00301 phy_params.default_antenna_gain = 0; 00302 phy_params.adr_ack_limit = US915_HYBRID_ADR_ACK_LIMIT; 00303 phy_params.adr_ack_delay = US915_HYBRID_ADR_ACK_DELAY; 00304 phy_params.max_rx_window = US915_HYBRID_MAX_RX_WINDOW; 00305 phy_params.recv_delay1 = US915_HYBRID_RECEIVE_DELAY1; 00306 phy_params.recv_delay2 = US915_HYBRID_RECEIVE_DELAY2; 00307 00308 phy_params.join_accept_delay1 = US915_HYBRID_JOIN_ACCEPT_DELAY1; 00309 phy_params.join_accept_delay2 = US915_HYBRID_JOIN_ACCEPT_DELAY2; 00310 phy_params.max_fcnt_gap = US915_HYBRID_MAX_FCNT_GAP; 00311 phy_params.ack_timeout = US915_HYBRID_ACKTIMEOUT; 00312 phy_params.ack_timeout_rnd = US915_HYBRID_ACK_TIMEOUT_RND; 00313 phy_params.rx_window2_datarate = US915_HYBRID_RX_WND_2_DR; 00314 phy_params.rx_window2_frequency = US915_HYBRID_RX_WND_2_FREQ; 00315 } 00316 00317 LoRaPHYUS915Hybrid::~LoRaPHYUS915Hybrid() 00318 { 00319 } 00320 00321 void LoRaPHYUS915Hybrid::restore_default_channels() 00322 { 00323 // Copy channels default mask 00324 copy_channel_mask(channel_mask, default_channel_mask, US915_HYBRID_CHANNEL_MASK_SIZE); 00325 00326 for (uint8_t i = 0; i < US915_HYBRID_CHANNEL_MASK_SIZE; i++) { 00327 // Copy-And the channels mask 00328 current_channel_mask[i] &= channel_mask[i]; 00329 } 00330 } 00331 00332 bool LoRaPHYUS915Hybrid::get_next_ADR(bool restore_channel_mask, int8_t& dr_out, 00333 int8_t& tx_power_out, uint32_t& adr_ack_cnt) 00334 { 00335 bool adrAckReq = false; 00336 00337 get_phy_params_t get_phy; 00338 phy_param_t phy_param; 00339 00340 uint16_t ack_limit_plus_delay = phy_params.adr_ack_limit + phy_params.adr_ack_delay; 00341 00342 if (dr_out == phy_params.min_tx_datarate) { 00343 adr_ack_cnt = 0; 00344 return adrAckReq; 00345 } 00346 00347 if (adr_ack_cnt < phy_params.adr_ack_limit) { 00348 return adrAckReq; 00349 } 00350 00351 // ADR ack counter is larger than ADR-ACK-LIMIT 00352 adrAckReq = true; 00353 tx_power_out = phy_params.max_tx_power; 00354 00355 00356 if (adr_ack_cnt >= ack_limit_plus_delay) { 00357 if ((adr_ack_cnt % phy_params.adr_ack_delay) == 1) { 00358 // Decrease the datarate 00359 get_phy.attribute = PHY_NEXT_LOWER_TX_DR ; 00360 get_phy.datarate = dr_out; 00361 phy_param = get_phy_params(&get_phy); 00362 dr_out = phy_param.value ; 00363 00364 if (dr_out == phy_params.min_tx_datarate) { 00365 // We must set adrAckReq to false as soon as we reach the lowest datarate 00366 adrAckReq = false; 00367 if (restore_channel_mask) { 00368 // Re-enable default channels 00369 reenable_500khz_channels(channel_mask[4], channel_mask); 00370 } 00371 } 00372 } 00373 } 00374 00375 return adrAckReq; 00376 } 00377 00378 bool LoRaPHYUS915Hybrid::rx_config(rx_config_params_t * config, int8_t* datarate) 00379 { 00380 int8_t dr = config->datarate ; 00381 uint8_t max_payload = 0; 00382 int8_t phy_dr = 0; 00383 uint32_t frequency = config->frequency ; 00384 00385 _radio->lock(); 00386 00387 if (_radio->get_status() != RF_IDLE) { 00388 00389 _radio->unlock(); 00390 return false; 00391 00392 } 00393 00394 _radio->unlock(); 00395 00396 if (config->rx_slot == RX_SLOT_WIN_1 ) { 00397 // Apply window 1 frequency 00398 frequency = US915_HYBRID_FIRST_RX1_CHANNEL + (config->channel % 8) * US915_HYBRID_STEPWIDTH_RX1_CHANNEL; 00399 } 00400 00401 // Read the physical datarate from the datarates table 00402 phy_dr = datarates_US915_HYBRID [dr]; 00403 00404 _radio->lock(); 00405 00406 _radio->set_channel( frequency ); 00407 00408 // Radio configuration 00409 _radio->set_rx_config(MODEM_LORA, config->bandwidth , phy_dr, 1, 0, 8, 00410 config->window_timeout , false, 0, false, 0, 0, true, 00411 config->is_rx_continuous ); 00412 00413 _radio->unlock(); 00414 00415 if (config->is_repeater_supported == true) { 00416 max_payload = max_payloads_with_repeater_US915_HYBRID [dr]; 00417 } else { 00418 max_payload = max_payloads_US915_HYBRID [dr]; 00419 } 00420 00421 _radio->lock(); 00422 _radio->set_max_payload_length(MODEM_LORA, max_payload + LORA_MAC_FRMPAYLOAD_OVERHEAD); 00423 _radio->unlock(); 00424 00425 *datarate = (uint8_t) dr; 00426 return true; 00427 } 00428 00429 bool LoRaPHYUS915Hybrid::tx_config(tx_config_params_t* config, int8_t* tx_power, 00430 lorawan_time_t* tx_toa) 00431 { 00432 int8_t phy_dr = datarates_US915_HYBRID [config->datarate]; 00433 00434 int8_t tx_power_limited = limit_tx_power(config->tx_power, 00435 bands[channels[config->channel].band].max_tx_pwr, 00436 config->datarate); 00437 00438 uint32_t bandwidth = get_bandwidth (config->datarate); 00439 int8_t phy_tx_power = 0; 00440 00441 // Calculate physical TX power 00442 phy_tx_power = compute_tx_power(tx_power_limited, US915_HYBRID_DEFAULT_MAX_ERP, 0); 00443 00444 _radio->lock(); 00445 00446 _radio->set_channel( channels[config->channel].frequency ); 00447 00448 _radio->set_tx_config(MODEM_LORA, phy_tx_power, 0, bandwidth, phy_dr, 1, 8, 00449 false, true, 0, 0, false, 3000); 00450 00451 // Setup maximum payload lenght of the radio driver 00452 _radio->set_max_payload_length(MODEM_LORA, config->pkt_len); 00453 00454 // Get the time-on-air of the next tx frame 00455 *tx_toa = _radio->time_on_air(MODEM_LORA, config->pkt_len); 00456 00457 _radio->unlock(); 00458 *tx_power = tx_power_limited; 00459 00460 return true; 00461 } 00462 00463 uint8_t LoRaPHYUS915Hybrid::link_ADR_request(adr_req_params_t* params, 00464 int8_t* dr_out, int8_t* tx_power_out, 00465 uint8_t* nb_rep_out, 00466 uint8_t* nb_bytes_parsed) 00467 { 00468 uint8_t status = 0x07; 00469 link_adr_params_t adr_settings; 00470 uint8_t next_idx = 0; 00471 uint8_t bytes_processed = 0; 00472 uint16_t temp_channel_mask[US915_HYBRID_CHANNEL_MASK_SIZE] = {0, 0, 0, 0, 0}; 00473 00474 verify_adr_params_t verify_params; 00475 00476 // Initialize local copy of channels mask 00477 copy_channel_mask(temp_channel_mask, channel_mask, US915_HYBRID_CHANNEL_MASK_SIZE); 00478 00479 while (bytes_processed < params->payload_size) { 00480 next_idx = parse_link_ADR_req(&(params->payload [bytes_processed]), 00481 &adr_settings); 00482 00483 if (next_idx == 0) { 00484 break; // break loop, since no more request has been found 00485 } 00486 00487 // Update bytes processed 00488 bytes_processed += next_idx; 00489 00490 // Revert status, as we only check the last ADR request for the channel mask KO 00491 status = 0x07; 00492 00493 if (adr_settings.ch_mask_ctrl == 6) { 00494 // Enable all 125 kHz channels 00495 temp_channel_mask[0] = 0xFFFF; 00496 temp_channel_mask[1] = 0xFFFF; 00497 temp_channel_mask[2] = 0xFFFF; 00498 temp_channel_mask[3] = 0xFFFF; 00499 // Apply chMask to channels 64 to 71 00500 temp_channel_mask[4] = adr_settings.channel_mask; 00501 } else if( adr_settings.ch_mask_ctrl == 7 ) { 00502 // Disable all 125 kHz channels 00503 temp_channel_mask[0] = 0x0000; 00504 temp_channel_mask[1] = 0x0000; 00505 temp_channel_mask[2] = 0x0000; 00506 temp_channel_mask[3] = 0x0000; 00507 // Apply chMask to channels 64 to 71 00508 temp_channel_mask[4] = adr_settings.channel_mask; 00509 } else if( adr_settings.ch_mask_ctrl == 5 ) { 00510 // RFU 00511 status &= 0xFE; // Channel mask KO 00512 } else { 00513 temp_channel_mask[adr_settings.ch_mask_ctrl] = adr_settings.channel_mask; 00514 } 00515 } 00516 00517 // FCC 15.247 paragraph F mandates to hop on at least 2 125 kHz channels 00518 if ((adr_settings.datarate < DR_4) && 00519 (num_active_channels( temp_channel_mask, 0, 4 ) < 2)) { 00520 status &= 0xFE; // Channel mask KO 00521 } 00522 00523 if( validate_channel_mask(temp_channel_mask ) == false) { 00524 status &= 0xFE; // Channel mask KO 00525 } 00526 00527 verify_params.status = status; 00528 verify_params.adr_enabled = params->adr_enabled ; 00529 verify_params.datarate = adr_settings.datarate; 00530 verify_params.tx_power = adr_settings.tx_power; 00531 verify_params.nb_rep = adr_settings.nb_rep; 00532 verify_params.current_datarate = params->current_datarate ; 00533 verify_params.current_tx_power = params->current_tx_power ; 00534 verify_params.current_nb_rep = params->current_nb_rep ; 00535 verify_params.channel_mask = temp_channel_mask; 00536 00537 00538 // Verify the parameters and update, if necessary 00539 status = verify_link_ADR_req(&verify_params, &adr_settings.datarate, 00540 &adr_settings.tx_power, &adr_settings.nb_rep); 00541 00542 // Update channelsMask if everything is correct 00543 if (status == 0x07) { 00544 // Copy Mask 00545 copy_channel_mask(channel_mask, temp_channel_mask, US915_HYBRID_CHANNEL_MASK_SIZE); 00546 00547 current_channel_mask[0] &= channel_mask[0]; 00548 current_channel_mask[1] &= channel_mask[1]; 00549 current_channel_mask[2] &= channel_mask[2]; 00550 current_channel_mask[3] &= channel_mask[3]; 00551 current_channel_mask[4] = channel_mask[4]; 00552 } 00553 00554 // Update status variables 00555 *dr_out = adr_settings.datarate; 00556 *tx_power_out = adr_settings.tx_power; 00557 *nb_rep_out = adr_settings.nb_rep; 00558 *nb_bytes_parsed = bytes_processed; 00559 00560 return status; 00561 } 00562 00563 uint8_t LoRaPHYUS915Hybrid::accept_rx_param_setup_req(rx_param_setup_req_t* params) 00564 { 00565 uint8_t status = 0x07; 00566 uint32_t freq = params->frequency; 00567 00568 // Verify radio frequency 00569 if ((_radio->check_rf_frequency(freq) == false) 00570 || (freq < US915_HYBRID_FIRST_RX1_CHANNEL) 00571 || (freq > US915_HYBRID_LAST_RX1_CHANNEL) 00572 || (((freq - ( uint32_t ) US915_HYBRID_FIRST_RX1_CHANNEL) % (uint32_t) US915_HYBRID_STEPWIDTH_RX1_CHANNEL) != 0)) { 00573 status &= 0xFE; // Channel frequency KO 00574 } 00575 00576 // Verify datarate 00577 if (val_in_range(params->datarate, US915_HYBRID_RX_MIN_DATARATE, US915_HYBRID_RX_MAX_DATARATE) == 0) { 00578 status &= 0xFD; // Datarate KO 00579 } 00580 00581 if ((val_in_range(params->datarate, DR_5, DR_7) == 1) 00582 || (params->datarate > DR_13)) { 00583 status &= 0xFD; // Datarate KO 00584 } 00585 00586 // Verify datarate offset 00587 if (val_in_range(params->dr_offset, US915_HYBRID_MIN_RX1_DR_OFFSET, US915_HYBRID_MAX_RX1_DR_OFFSET) == 0) { 00588 status &= 0xFB; // Rx1DrOffset range KO 00589 } 00590 00591 return status; 00592 } 00593 00594 int8_t LoRaPHYUS915Hybrid::get_alternate_DR(uint8_t nb_trials) 00595 { 00596 int8_t datarate = 0; 00597 00598 // Re-enable 500 kHz default channels 00599 reenable_500khz_channels(channel_mask[4], channel_mask); 00600 00601 if ((nb_trials & 0x01) == 0x01) { 00602 datarate = DR_4; 00603 } else { 00604 datarate = DR_0; 00605 } 00606 00607 return datarate; 00608 } 00609 00610 bool LoRaPHYUS915Hybrid::set_next_channel(channel_selection_params_t* params, 00611 uint8_t* channel, lorawan_time_t* time, 00612 lorawan_time_t* aggregate_timeOff) 00613 { 00614 uint8_t nb_enabled_channels = 0; 00615 uint8_t delay_tx = 0; 00616 uint8_t enabled_channels[US915_HYBRID_MAX_NB_CHANNELS] = {0}; 00617 lorawan_time_t next_tx_delay = 0; 00618 00619 // Count 125kHz channels 00620 if (num_active_channels(current_channel_mask, 0, 4) == 0) { 00621 // Reactivate default channels 00622 copy_channel_mask(current_channel_mask, channel_mask, 4); 00623 } 00624 00625 // Check other channels 00626 if (params->current_datarate >= DR_4) { 00627 if ((current_channel_mask[4] & 0x00FF ) == 0) { 00628 current_channel_mask[4] = channel_mask[4]; 00629 } 00630 } 00631 00632 if (params->aggregate_timeoff <= _lora_time.get_elapsed_time( params->last_aggregate_tx_time)) { 00633 // Reset Aggregated time off 00634 *aggregate_timeOff = 0; 00635 00636 // Update bands Time OFF 00637 next_tx_delay = update_band_timeoff(params->joined, 00638 params->dc_enabled, bands, 00639 US915_HYBRID_MAX_NB_BANDS); 00640 00641 // Search how many channels are enabled 00642 nb_enabled_channels = enabled_channel_count(params->joined, 00643 params->current_datarate, 00644 current_channel_mask, 00645 enabled_channels, &delay_tx); 00646 } else { 00647 delay_tx++; 00648 next_tx_delay = params->aggregate_timeoff - _lora_time.get_elapsed_time(params->last_aggregate_tx_time); 00649 } 00650 00651 if (nb_enabled_channels > 0) { 00652 00653 // We found a valid channel 00654 *channel = enabled_channels[get_random(0, nb_enabled_channels - 1)]; 00655 // Disable the channel in the mask 00656 disable_channel(current_channel_mask, *channel, US915_HYBRID_MAX_NB_CHANNELS - 8); 00657 00658 *time = 0; 00659 return true; 00660 00661 } else { 00662 00663 if (delay_tx > 0) { 00664 // Delay transmission due to AggregatedTimeOff or to a band time off 00665 *time = next_tx_delay; 00666 return true; 00667 } 00668 00669 // Datarate not supported by any channel 00670 *time = 0; 00671 return false; 00672 } 00673 } 00674 00675 void LoRaPHYUS915Hybrid::set_tx_cont_mode(cw_mode_params_t * params, uint32_t given_frequency) 00676 { 00677 (void)given_frequency; 00678 00679 int8_t tx_power_limited = limit_tx_power(params->tx_power , 00680 bands[channels[params->channel ].band].max_tx_pwr, 00681 params->datarate ); 00682 00683 int8_t phy_tx_power = 0; 00684 uint32_t frequency = channels[params->channel ].frequency; 00685 00686 // Calculate physical TX power 00687 phy_tx_power = compute_tx_power(tx_power_limited, US915_HYBRID_DEFAULT_MAX_ERP, 0); 00688 00689 _radio->lock(); 00690 _radio->set_tx_continuous_wave(frequency, phy_tx_power, params->timeout ); 00691 _radio->unlock(); 00692 } 00693 00694 uint8_t LoRaPHYUS915Hybrid::apply_DR_offset(int8_t dr, int8_t drOffset) 00695 { 00696 int8_t datarate = datarate_offsets_US915_HYBRID [dr][drOffset]; 00697 00698 if (datarate < 0) { 00699 datarate = DR_0; 00700 } 00701 00702 return datarate; 00703 } 00704 00705 00706 void LoRaPHYUS915Hybrid::reenable_500khz_channels(uint16_t mask, uint16_t* channelsMask) 00707 { 00708 uint16_t blockMask = mask; 00709 00710 for (uint8_t i = 0, j = 0; i < 4; i++, j += 2) { 00711 channelsMask[i] = 0; 00712 if ((blockMask & (1 << j)) != 0) { 00713 channelsMask[i] |= 0x00FF; 00714 } 00715 00716 if ((blockMask & (1 << (j + 1))) != 0) { 00717 channelsMask[i] |= 0xFF00; 00718 } 00719 } 00720 00721 channelsMask[4] = blockMask; 00722 } 00723 00724 int8_t LoRaPHYUS915Hybrid::limit_tx_power(int8_t txPower, int8_t maxBandTxPower, 00725 int8_t datarate) 00726 { 00727 int8_t txPowerResult = txPower; 00728 00729 // Limit tx power to the band max 00730 txPowerResult = MAX(txPower, maxBandTxPower); 00731 00732 if (datarate == DR_4) { 00733 00734 // Limit tx power to max 26dBm 00735 txPowerResult = MAX(txPower, TX_POWER_2); 00736 00737 } else { 00738 00739 if (num_active_channels(channel_mask, 0, 4) < 50) { 00740 // Limit tx power to max 21dBm 00741 txPowerResult = MAX(txPower, TX_POWER_5); 00742 } 00743 } 00744 00745 return txPowerResult; 00746 } 00747 00748 bool LoRaPHYUS915Hybrid::validate_channel_mask(uint16_t* channel_masks) 00749 { 00750 bool mask_state = false; 00751 00752 uint16_t block1 = 0; 00753 uint16_t block2 = 0; 00754 uint8_t index = 0; 00755 uint16_t temp_channel_masks[US915_HYBRID_CHANNEL_MASK_SIZE]; 00756 00757 // Copy channels mask to not change the input 00758 for (uint8_t i = 0; i < 4; i++) { 00759 temp_channel_masks[i] = channel_masks[i]; 00760 } 00761 00762 for(uint8_t i = 0; i < 4; i++) { 00763 block1 = temp_channel_masks[i] & 0x00FF; 00764 block2 = temp_channel_masks[i] & 0xFF00; 00765 00766 if (count_bits(block1, 16) > 5) { 00767 00768 temp_channel_masks[i] &= block1; 00769 temp_channel_masks[4] = 1 << ( i * 2 ); 00770 mask_state = true; 00771 index = i; 00772 break; 00773 00774 } else if( count_bits( block2, 16 ) > 5 ) { 00775 00776 temp_channel_masks[i] &= block2; 00777 temp_channel_masks[4] = 1 << ( i * 2 + 1 ); 00778 mask_state = true; 00779 index = i; 00780 break; 00781 00782 } 00783 } 00784 00785 // Do change the channel mask, if we have found a valid block. 00786 if (mask_state == true) { 00787 // Copy channels mask back again 00788 for (uint8_t i = 0; i < 4; i++) { 00789 channel_masks[i] = temp_channel_masks[i]; 00790 00791 if (i != index) { 00792 channel_masks[i] = 0; 00793 } 00794 } 00795 00796 channel_masks[4] = temp_channel_masks[4]; 00797 } 00798 00799 return mask_state; 00800 }
Generated on Tue Jul 12 2022 13:24:48 by
1.7.2