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