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_with_repeater.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 uint16_t ack_limit_plus_delay = phy_params.adr_ack_limit + phy_params.adr_ack_delay; 00338 00339 if (dr_out == phy_params.min_tx_datarate) { 00340 adr_ack_cnt = 0; 00341 return adrAckReq; 00342 } 00343 00344 if (adr_ack_cnt < phy_params.adr_ack_limit) { 00345 return adrAckReq; 00346 } 00347 00348 // ADR ack counter is larger than ADR-ACK-LIMIT 00349 adrAckReq = true; 00350 tx_power_out = phy_params.max_tx_power; 00351 00352 00353 if (adr_ack_cnt >= ack_limit_plus_delay) { 00354 if ((adr_ack_cnt % phy_params.adr_ack_delay) == 1) { 00355 // Decrease the datarate 00356 dr_out = get_next_lower_tx_datarate(dr_out); 00357 00358 if (dr_out == phy_params.min_tx_datarate) { 00359 // We must set adrAckReq to false as soon as we reach the lowest datarate 00360 adrAckReq = false; 00361 if (restore_channel_mask) { 00362 // Re-enable default channels 00363 reenable_500khz_channels(channel_mask[4], channel_mask); 00364 } 00365 } 00366 } 00367 } 00368 00369 return adrAckReq; 00370 } 00371 00372 bool LoRaPHYUS915Hybrid::rx_config(rx_config_params_t * config, int8_t* datarate) 00373 { 00374 int8_t dr = config->datarate ; 00375 uint8_t max_payload = 0; 00376 int8_t phy_dr = 0; 00377 uint32_t frequency = config->frequency ; 00378 00379 _radio->lock(); 00380 00381 if (_radio->get_status() != RF_IDLE) { 00382 00383 _radio->unlock(); 00384 return false; 00385 00386 } 00387 00388 _radio->unlock(); 00389 00390 if (config->rx_slot == RX_SLOT_WIN_1 ) { 00391 // Apply window 1 frequency 00392 frequency = US915_HYBRID_FIRST_RX1_CHANNEL + (config->channel % 8) * US915_HYBRID_STEPWIDTH_RX1_CHANNEL; 00393 } 00394 00395 // Read the physical datarate from the datarates table 00396 phy_dr = datarates_US915_HYBRID [dr]; 00397 00398 _radio->lock(); 00399 00400 _radio->set_channel( frequency ); 00401 00402 // Radio configuration 00403 _radio->set_rx_config(MODEM_LORA, config->bandwidth , phy_dr, 1, 0, 8, 00404 config->window_timeout , false, 0, false, 0, 0, true, 00405 config->is_rx_continuous ); 00406 00407 _radio->unlock(); 00408 00409 if (config->is_repeater_supported == true) { 00410 max_payload = max_payloads_with_repeater_US915_HYBRID [dr]; 00411 } else { 00412 max_payload = max_payloads_US915_HYBRID [dr]; 00413 } 00414 00415 _radio->lock(); 00416 _radio->set_max_payload_length(MODEM_LORA, max_payload + LORA_MAC_FRMPAYLOAD_OVERHEAD); 00417 _radio->unlock(); 00418 00419 *datarate = (uint8_t) dr; 00420 return true; 00421 } 00422 00423 bool LoRaPHYUS915Hybrid::tx_config(tx_config_params_t* config, int8_t* tx_power, 00424 lorawan_time_t* tx_toa) 00425 { 00426 int8_t phy_dr = datarates_US915_HYBRID [config->datarate]; 00427 00428 int8_t tx_power_limited = limit_tx_power(config->tx_power, 00429 bands[channels[config->channel].band].max_tx_pwr, 00430 config->datarate); 00431 00432 uint32_t bandwidth = get_bandwidth (config->datarate); 00433 int8_t phy_tx_power = 0; 00434 00435 // Calculate physical TX power 00436 phy_tx_power = compute_tx_power(tx_power_limited, US915_HYBRID_DEFAULT_MAX_ERP, 0); 00437 00438 _radio->lock(); 00439 00440 _radio->set_channel( channels[config->channel].frequency ); 00441 00442 _radio->set_tx_config(MODEM_LORA, phy_tx_power, 0, bandwidth, phy_dr, 1, 8, 00443 false, true, 0, 0, false, 3000); 00444 00445 // Setup maximum payload lenght of the radio driver 00446 _radio->set_max_payload_length(MODEM_LORA, config->pkt_len); 00447 00448 // Get the time-on-air of the next tx frame 00449 *tx_toa = _radio->time_on_air(MODEM_LORA, config->pkt_len); 00450 00451 _radio->unlock(); 00452 *tx_power = tx_power_limited; 00453 00454 return true; 00455 } 00456 00457 uint8_t LoRaPHYUS915Hybrid::link_ADR_request(adr_req_params_t* params, 00458 int8_t* dr_out, int8_t* tx_power_out, 00459 uint8_t* nb_rep_out, 00460 uint8_t* nb_bytes_parsed) 00461 { 00462 uint8_t status = 0x07; 00463 link_adr_params_t adr_settings; 00464 uint8_t next_idx = 0; 00465 uint8_t bytes_processed = 0; 00466 uint16_t temp_channel_mask[US915_HYBRID_CHANNEL_MASK_SIZE] = {0, 0, 0, 0, 0}; 00467 00468 verify_adr_params_t verify_params; 00469 00470 // Initialize local copy of channels mask 00471 copy_channel_mask(temp_channel_mask, channel_mask, US915_HYBRID_CHANNEL_MASK_SIZE); 00472 00473 while (bytes_processed < params->payload_size) { 00474 next_idx = parse_link_ADR_req(&(params->payload [bytes_processed]), 00475 &adr_settings); 00476 00477 if (next_idx == 0) { 00478 break; // break loop, since no more request has been found 00479 } 00480 00481 // Update bytes processed 00482 bytes_processed += next_idx; 00483 00484 // Revert status, as we only check the last ADR request for the channel mask KO 00485 status = 0x07; 00486 00487 if (adr_settings.ch_mask_ctrl == 6) { 00488 // Enable all 125 kHz channels 00489 temp_channel_mask[0] = 0xFFFF; 00490 temp_channel_mask[1] = 0xFFFF; 00491 temp_channel_mask[2] = 0xFFFF; 00492 temp_channel_mask[3] = 0xFFFF; 00493 // Apply chMask to channels 64 to 71 00494 temp_channel_mask[4] = adr_settings.channel_mask; 00495 } else if( adr_settings.ch_mask_ctrl == 7 ) { 00496 // Disable all 125 kHz channels 00497 temp_channel_mask[0] = 0x0000; 00498 temp_channel_mask[1] = 0x0000; 00499 temp_channel_mask[2] = 0x0000; 00500 temp_channel_mask[3] = 0x0000; 00501 // Apply chMask to channels 64 to 71 00502 temp_channel_mask[4] = adr_settings.channel_mask; 00503 } else if( adr_settings.ch_mask_ctrl == 5 ) { 00504 // RFU 00505 status &= 0xFE; // Channel mask KO 00506 } else { 00507 temp_channel_mask[adr_settings.ch_mask_ctrl] = adr_settings.channel_mask; 00508 } 00509 } 00510 00511 // FCC 15.247 paragraph F mandates to hop on at least 2 125 kHz channels 00512 if ((adr_settings.datarate < DR_4) && 00513 (num_active_channels( temp_channel_mask, 0, 4 ) < 2)) { 00514 status &= 0xFE; // Channel mask KO 00515 } 00516 00517 if( validate_channel_mask(temp_channel_mask ) == false) { 00518 status &= 0xFE; // Channel mask KO 00519 } 00520 00521 verify_params.status = status; 00522 verify_params.adr_enabled = params->adr_enabled ; 00523 verify_params.datarate = adr_settings.datarate; 00524 verify_params.tx_power = adr_settings.tx_power; 00525 verify_params.nb_rep = adr_settings.nb_rep; 00526 verify_params.current_datarate = params->current_datarate ; 00527 verify_params.current_tx_power = params->current_tx_power ; 00528 verify_params.current_nb_rep = params->current_nb_rep ; 00529 verify_params.channel_mask = temp_channel_mask; 00530 00531 00532 // Verify the parameters and update, if necessary 00533 status = verify_link_ADR_req(&verify_params, &adr_settings.datarate, 00534 &adr_settings.tx_power, &adr_settings.nb_rep); 00535 00536 // Update channelsMask if everything is correct 00537 if (status == 0x07) { 00538 // Copy Mask 00539 copy_channel_mask(channel_mask, temp_channel_mask, US915_HYBRID_CHANNEL_MASK_SIZE); 00540 00541 current_channel_mask[0] &= channel_mask[0]; 00542 current_channel_mask[1] &= channel_mask[1]; 00543 current_channel_mask[2] &= channel_mask[2]; 00544 current_channel_mask[3] &= channel_mask[3]; 00545 current_channel_mask[4] = channel_mask[4]; 00546 } 00547 00548 // Update status variables 00549 *dr_out = adr_settings.datarate; 00550 *tx_power_out = adr_settings.tx_power; 00551 *nb_rep_out = adr_settings.nb_rep; 00552 *nb_bytes_parsed = bytes_processed; 00553 00554 return status; 00555 } 00556 00557 uint8_t LoRaPHYUS915Hybrid::accept_rx_param_setup_req(rx_param_setup_req_t* params) 00558 { 00559 uint8_t status = 0x07; 00560 uint32_t freq = params->frequency; 00561 00562 // Verify radio frequency 00563 if ((_radio->check_rf_frequency(freq) == false) 00564 || (freq < US915_HYBRID_FIRST_RX1_CHANNEL) 00565 || (freq > US915_HYBRID_LAST_RX1_CHANNEL) 00566 || (((freq - ( uint32_t ) US915_HYBRID_FIRST_RX1_CHANNEL) % (uint32_t) US915_HYBRID_STEPWIDTH_RX1_CHANNEL) != 0)) { 00567 status &= 0xFE; // Channel frequency KO 00568 } 00569 00570 // Verify datarate 00571 if (val_in_range(params->datarate, US915_HYBRID_RX_MIN_DATARATE, US915_HYBRID_RX_MAX_DATARATE) == 0) { 00572 status &= 0xFD; // Datarate KO 00573 } 00574 00575 if ((val_in_range(params->datarate, DR_5, DR_7) == 1) 00576 || (params->datarate > DR_13)) { 00577 status &= 0xFD; // Datarate KO 00578 } 00579 00580 // Verify datarate offset 00581 if (val_in_range(params->dr_offset, US915_HYBRID_MIN_RX1_DR_OFFSET, US915_HYBRID_MAX_RX1_DR_OFFSET) == 0) { 00582 status &= 0xFB; // Rx1DrOffset range KO 00583 } 00584 00585 return status; 00586 } 00587 00588 int8_t LoRaPHYUS915Hybrid::get_alternate_DR(uint8_t nb_trials) 00589 { 00590 int8_t datarate = 0; 00591 00592 // Re-enable 500 kHz default channels 00593 reenable_500khz_channels(channel_mask[4], channel_mask); 00594 00595 if ((nb_trials & 0x01) == 0x01) { 00596 datarate = DR_4; 00597 } else { 00598 datarate = DR_0; 00599 } 00600 00601 return datarate; 00602 } 00603 00604 lorawan_status_t LoRaPHYUS915Hybrid::set_next_channel(channel_selection_params_t* params, 00605 uint8_t* channel, lorawan_time_t* time, 00606 lorawan_time_t* aggregate_timeOff) 00607 { 00608 uint8_t nb_enabled_channels = 0; 00609 uint8_t delay_tx = 0; 00610 uint8_t enabled_channels[US915_HYBRID_MAX_NB_CHANNELS] = {0}; 00611 lorawan_time_t next_tx_delay = 0; 00612 00613 // Count 125kHz channels 00614 if (num_active_channels(current_channel_mask, 0, 4) == 0) { 00615 // Reactivate default channels 00616 copy_channel_mask(current_channel_mask, channel_mask, 4); 00617 } 00618 00619 // Check other channels 00620 if (params->current_datarate >= DR_4) { 00621 if ((current_channel_mask[4] & 0x00FF ) == 0) { 00622 current_channel_mask[4] = channel_mask[4]; 00623 } 00624 } 00625 00626 if (params->aggregate_timeoff <= _lora_time.get_elapsed_time( params->last_aggregate_tx_time)) { 00627 // Reset Aggregated time off 00628 *aggregate_timeOff = 0; 00629 00630 // Update bands Time OFF 00631 next_tx_delay = update_band_timeoff(params->joined, 00632 params->dc_enabled, bands, 00633 US915_HYBRID_MAX_NB_BANDS); 00634 00635 // Search how many channels are enabled 00636 nb_enabled_channels = enabled_channel_count(params->joined, 00637 params->current_datarate, 00638 current_channel_mask, 00639 enabled_channels, &delay_tx); 00640 } else { 00641 delay_tx++; 00642 next_tx_delay = params->aggregate_timeoff - _lora_time.get_elapsed_time(params->last_aggregate_tx_time); 00643 } 00644 00645 if (nb_enabled_channels > 0) { 00646 00647 // We found a valid channel 00648 *channel = enabled_channels[get_random(0, nb_enabled_channels - 1)]; 00649 // Disable the channel in the mask 00650 disable_channel(current_channel_mask, *channel, US915_HYBRID_MAX_NB_CHANNELS - 8); 00651 00652 *time = 0; 00653 return LORAWAN_STATUS_OK; 00654 00655 } else { 00656 00657 if (delay_tx > 0) { 00658 // Delay transmission due to AggregatedTimeOff or to a band time off 00659 *time = next_tx_delay; 00660 return LORAWAN_STATUS_DUTYCYCLE_RESTRICTED; 00661 } 00662 00663 // Datarate not supported by any channel 00664 *time = 0; 00665 return LORAWAN_STATUS_NO_CHANNEL_FOUND; 00666 } 00667 } 00668 00669 void LoRaPHYUS915Hybrid::set_tx_cont_mode(cw_mode_params_t * params, uint32_t given_frequency) 00670 { 00671 (void)given_frequency; 00672 00673 int8_t tx_power_limited = limit_tx_power(params->tx_power , 00674 bands[channels[params->channel ].band].max_tx_pwr, 00675 params->datarate ); 00676 00677 int8_t phy_tx_power = 0; 00678 uint32_t frequency = channels[params->channel ].frequency; 00679 00680 // Calculate physical TX power 00681 phy_tx_power = compute_tx_power(tx_power_limited, US915_HYBRID_DEFAULT_MAX_ERP, 0); 00682 00683 _radio->lock(); 00684 _radio->set_tx_continuous_wave(frequency, phy_tx_power, params->timeout ); 00685 _radio->unlock(); 00686 } 00687 00688 uint8_t LoRaPHYUS915Hybrid::apply_DR_offset(int8_t dr, int8_t drOffset) 00689 { 00690 int8_t datarate = datarate_offsets_US915_HYBRID [dr][drOffset]; 00691 00692 if (datarate < 0) { 00693 datarate = DR_0; 00694 } 00695 00696 return datarate; 00697 } 00698 00699 00700 void LoRaPHYUS915Hybrid::reenable_500khz_channels(uint16_t mask, uint16_t* channelsMask) 00701 { 00702 uint16_t blockMask = mask; 00703 00704 for (uint8_t i = 0, j = 0; i < 4; i++, j += 2) { 00705 channelsMask[i] = 0; 00706 if ((blockMask & (1 << j)) != 0) { 00707 channelsMask[i] |= 0x00FF; 00708 } 00709 00710 if ((blockMask & (1 << (j + 1))) != 0) { 00711 channelsMask[i] |= 0xFF00; 00712 } 00713 } 00714 00715 channelsMask[4] = blockMask; 00716 } 00717 00718 int8_t LoRaPHYUS915Hybrid::limit_tx_power(int8_t txPower, int8_t maxBandTxPower, 00719 int8_t datarate) 00720 { 00721 int8_t txPowerResult = txPower; 00722 00723 // Limit tx power to the band max 00724 txPowerResult = MAX(txPower, maxBandTxPower); 00725 00726 if (datarate == DR_4) { 00727 00728 // Limit tx power to max 26dBm 00729 txPowerResult = MAX(txPower, TX_POWER_2); 00730 00731 } else { 00732 00733 if (num_active_channels(channel_mask, 0, 4) < 50) { 00734 // Limit tx power to max 21dBm 00735 txPowerResult = MAX(txPower, TX_POWER_5); 00736 } 00737 } 00738 00739 return txPowerResult; 00740 } 00741 00742 bool LoRaPHYUS915Hybrid::validate_channel_mask(uint16_t* channel_masks) 00743 { 00744 bool mask_state = false; 00745 00746 uint16_t block1 = 0; 00747 uint16_t block2 = 0; 00748 uint8_t index = 0; 00749 uint16_t temp_channel_masks[US915_HYBRID_CHANNEL_MASK_SIZE]; 00750 00751 // Copy channels mask to not change the input 00752 for (uint8_t i = 0; i < 4; i++) { 00753 temp_channel_masks[i] = channel_masks[i]; 00754 } 00755 00756 for(uint8_t i = 0; i < 4; i++) { 00757 block1 = temp_channel_masks[i] & 0x00FF; 00758 block2 = temp_channel_masks[i] & 0xFF00; 00759 00760 if (count_bits(block1, 16) > 1) { 00761 00762 temp_channel_masks[i] &= block1; 00763 temp_channel_masks[4] = 1 << ( i * 2 ); 00764 mask_state = true; 00765 index = i; 00766 break; 00767 00768 } else if( count_bits( block2, 16 ) > 1 ) { 00769 00770 temp_channel_masks[i] &= block2; 00771 temp_channel_masks[4] = 1 << ( i * 2 + 1 ); 00772 mask_state = true; 00773 index = i; 00774 break; 00775 00776 } 00777 } 00778 00779 // Do change the channel mask, if we have found a valid block. 00780 if (mask_state == true) { 00781 // Copy channels mask back again 00782 for (uint8_t i = 0; i < 4; i++) { 00783 channel_masks[i] = temp_channel_masks[i]; 00784 00785 if (i != index) { 00786 channel_masks[i] = 0; 00787 } 00788 } 00789 00790 channel_masks[4] = temp_channel_masks[4]; 00791 } 00792 00793 return mask_state; 00794 }
Generated on Tue Jul 12 2022 14:23:52 by
