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.
LoRaPHYCN470.cpp
00001 /** 00002 * @file LoRaPHYCN470.cpp 00003 * 00004 * @brief Implements LoRaPHY for Chinese 470 MHz 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 "LoRaPHYCN470.h" 00033 #include "lora_phy_ds.h" 00034 00035 /*! 00036 * Minimal datarate that can be used by the node 00037 */ 00038 #define CN470_TX_MIN_DATARATE DR_0 00039 00040 /*! 00041 * Maximal datarate that can be used by the node 00042 */ 00043 #define CN470_TX_MAX_DATARATE DR_5 00044 00045 /*! 00046 * Minimal datarate that can be used by the node 00047 */ 00048 #define CN470_RX_MIN_DATARATE DR_0 00049 00050 /*! 00051 * Maximal datarate that can be used by the node 00052 */ 00053 #define CN470_RX_MAX_DATARATE DR_5 00054 00055 /*! 00056 * Default datarate used by the node 00057 */ 00058 #define CN470_DEFAULT_DATARATE DR_0 00059 00060 /*! 00061 * Minimal Rx1 receive datarate offset 00062 */ 00063 #define CN470_MIN_RX1_DR_OFFSET 0 00064 00065 /*! 00066 * Maximal Rx1 receive datarate offset 00067 */ 00068 #define CN470_MAX_RX1_DR_OFFSET 3 00069 00070 /*! 00071 * Default Rx1 receive datarate offset 00072 */ 00073 #define CN470_DEFAULT_RX1_DR_OFFSET 0 00074 00075 /*! 00076 * Minimal Tx output power that can be used by the node 00077 */ 00078 #define CN470_MIN_TX_POWER TX_POWER_7 00079 00080 /*! 00081 * Maximal Tx output power that can be used by the node 00082 */ 00083 #define CN470_MAX_TX_POWER TX_POWER_0 00084 00085 /*! 00086 * Default Tx output power used by the node 00087 */ 00088 #define CN470_DEFAULT_TX_POWER TX_POWER_0 00089 00090 /*! 00091 * Default Max EIRP 00092 */ 00093 #define CN470_DEFAULT_MAX_EIRP 19.15f 00094 00095 /*! 00096 * Default antenna gain 00097 */ 00098 #define CN470_DEFAULT_ANTENNA_GAIN 2.15f 00099 00100 /*! 00101 * ADR Ack limit 00102 */ 00103 #define CN470_ADR_ACK_LIMIT 64 00104 00105 /*! 00106 * ADR Ack delay 00107 */ 00108 #define CN470_ADR_ACK_DELAY 32 00109 00110 /*! 00111 * Enabled or disabled the duty cycle 00112 */ 00113 #define CN470_DUTY_CYCLE_ENABLED 0 00114 00115 /*! 00116 * Maximum RX window duration 00117 */ 00118 #define CN470_MAX_RX_WINDOW 3000 00119 00120 /*! 00121 * Receive delay 1 00122 */ 00123 #define CN470_RECEIVE_DELAY1 1000 00124 00125 /*! 00126 * Receive delay 2 00127 */ 00128 #define CN470_RECEIVE_DELAY2 2000 00129 00130 /*! 00131 * Join accept delay 1 00132 */ 00133 #define CN470_JOIN_ACCEPT_DELAY1 5000 00134 00135 /*! 00136 * Join accept delay 2 00137 */ 00138 #define CN470_JOIN_ACCEPT_DELAY2 6000 00139 00140 /*! 00141 * Maximum frame counter gap 00142 */ 00143 #define CN470_MAX_FCNT_GAP 16384 00144 00145 /*! 00146 * Ack timeout 00147 */ 00148 #define CN470_ACKTIMEOUT 2000 00149 00150 /*! 00151 * Random ack timeout limits 00152 */ 00153 #define CN470_ACK_TIMEOUT_RND 1000 00154 00155 /*! 00156 * Second reception window channel frequency definition. 00157 */ 00158 #define CN470_RX_WND_2_FREQ 505300000 00159 00160 /*! 00161 * Second reception window channel datarate definition. 00162 */ 00163 #define CN470_RX_WND_2_DR DR_0 00164 00165 /*! 00166 * Band 0 definition 00167 * { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff } 00168 */ 00169 static const band_t CN470_BAND0 = {1, CN470_MAX_TX_POWER, 0, 0, 0}; // 100.0 % 00170 00171 /*! 00172 * Defines the first channel for RX window 1 for CN470 band 00173 */ 00174 #define CN470_FIRST_RX1_CHANNEL ((uint32_t) 500300000) 00175 00176 /*! 00177 * Defines the last channel for RX window 1 for CN470 band 00178 */ 00179 #define CN470_LAST_RX1_CHANNEL ((uint32_t) 509700000) 00180 00181 /*! 00182 * Defines the step width of the channels for RX window 1 00183 */ 00184 #define CN470_STEPWIDTH_RX1_CHANNEL ((uint32_t) 200000) 00185 00186 /*! 00187 * Data rates table definition 00188 */ 00189 static const uint8_t datarates_CN470 [] = {12, 11, 10, 9, 8, 7}; 00190 00191 /*! 00192 * Bandwidths table definition in Hz 00193 */ 00194 static const uint32_t bandwidths_CN470 [] = {125000, 125000, 125000, 125000, 125000, 125000}; 00195 00196 /*! 00197 * Maximum payload with respect to the datarate index. Cannot operate with repeater. 00198 */ 00199 static const uint8_t max_payloads_CN470 [] = {51, 51, 51, 115, 222, 222}; 00200 00201 /*! 00202 * Maximum payload with respect to the datarate index. Can operate with repeater. 00203 */ 00204 static const uint8_t max_payloads_with_repeater_CN470 [] = {51, 51, 51, 115, 222, 222}; 00205 00206 00207 LoRaPHYCN470::LoRaPHYCN470(LoRaWANTimeHandler &lora_time) 00208 : LoRaPHY(lora_time) 00209 { 00210 bands[0] = CN470_BAND0 ; 00211 00212 // Channels 00213 // 125 kHz channels 00214 for( uint8_t i = 0; i < CN470_MAX_NB_CHANNELS; i++ ) 00215 { 00216 channels[i].frequency = 470300000 + i * 200000; 00217 channels[i].dr_range.value = ( DR_5 << 4 ) | DR_0; 00218 channels[i].band = 0; 00219 } 00220 00221 // Initialize the channels default mask 00222 default_channel_mask[0] = 0xFFFF; 00223 default_channel_mask[1] = 0xFFFF; 00224 default_channel_mask[2] = 0xFFFF; 00225 default_channel_mask[3] = 0xFFFF; 00226 default_channel_mask[4] = 0xFFFF; 00227 default_channel_mask[5] = 0xFFFF; 00228 00229 // Update the channels mask 00230 copy_channel_mask(channel_mask, default_channel_mask, CN470_CHANNEL_MASK_SIZE); 00231 00232 // set default channels 00233 phy_params.channels.channel_list = channels; 00234 phy_params.channels.channel_list_size = CN470_MAX_NB_CHANNELS; 00235 phy_params.channels.mask = channel_mask; 00236 phy_params.channels.default_mask = default_channel_mask; 00237 phy_params.channels.mask_size = CN470_CHANNEL_MASK_SIZE; 00238 00239 // set bands for CN470 spectrum 00240 phy_params.bands.table = (void *) bands; 00241 phy_params.bands.size = CN470_MAX_NB_BANDS; 00242 00243 // set bandwidths available in CN470 spectrum 00244 phy_params.bandwidths.table = (void *) bandwidths_CN470 ; 00245 phy_params.bandwidths.size = 6; 00246 00247 // set data rates available in CN470 spectrum 00248 phy_params.datarates.table = (void *) datarates_CN470 ; 00249 phy_params.datarates.size = 6; 00250 00251 // set payload sizes with respect to data rates 00252 phy_params.payloads.table = (void *) max_payloads_CN470 ; 00253 phy_params.payloads.size = 6; 00254 phy_params.payloads_with_repeater.table = (void *)max_payloads_with_repeater_CN470 ; 00255 phy_params.payloads_with_repeater.size = 6; 00256 00257 // dwell time setting 00258 phy_params.ul_dwell_time_setting = 0; 00259 phy_params.dl_dwell_time_setting = 0; 00260 00261 // set initial and default parameters 00262 phy_params.duty_cycle_enabled = CN470_DUTY_CYCLE_ENABLED; 00263 00264 phy_params.accept_tx_param_setup_req = false; 00265 phy_params.fsk_supported = false; 00266 phy_params.cflist_supported = false; 00267 phy_params.dl_channel_req_supported = false; 00268 phy_params.custom_channelplans_supported = false; 00269 00270 phy_params.default_channel_cnt = CN470_MAX_NB_CHANNELS; 00271 phy_params.max_channel_cnt = CN470_MAX_NB_CHANNELS; 00272 phy_params.cflist_channel_cnt = 0; 00273 phy_params.min_tx_datarate = CN470_TX_MIN_DATARATE; 00274 phy_params.max_tx_datarate = CN470_TX_MAX_DATARATE; 00275 phy_params.min_rx_datarate = CN470_RX_MIN_DATARATE; 00276 phy_params.max_rx_datarate = CN470_RX_MAX_DATARATE; 00277 phy_params.default_datarate = CN470_DEFAULT_DATARATE; 00278 phy_params.default_max_datarate = CN470_TX_MAX_DATARATE; 00279 phy_params.min_rx1_dr_offset = CN470_MIN_RX1_DR_OFFSET; 00280 phy_params.max_rx1_dr_offset = CN470_MAX_RX1_DR_OFFSET; 00281 phy_params.default_rx1_dr_offset = CN470_DEFAULT_RX1_DR_OFFSET; 00282 phy_params.min_tx_power = CN470_MIN_TX_POWER; 00283 phy_params.max_tx_power = CN470_MAX_TX_POWER; 00284 phy_params.default_tx_power = CN470_DEFAULT_TX_POWER; 00285 phy_params.default_max_eirp = CN470_DEFAULT_MAX_EIRP; 00286 phy_params.default_antenna_gain = CN470_DEFAULT_ANTENNA_GAIN; 00287 phy_params.adr_ack_limit = CN470_ADR_ACK_LIMIT; 00288 phy_params.adr_ack_delay = CN470_ADR_ACK_DELAY; 00289 phy_params.max_rx_window = CN470_MAX_RX_WINDOW; 00290 phy_params.recv_delay1 = CN470_RECEIVE_DELAY1; 00291 phy_params.recv_delay2 = CN470_RECEIVE_DELAY2; 00292 00293 phy_params.join_accept_delay1 = CN470_JOIN_ACCEPT_DELAY1; 00294 phy_params.join_accept_delay2 = CN470_JOIN_ACCEPT_DELAY2; 00295 phy_params.max_fcnt_gap = CN470_MAX_FCNT_GAP; 00296 phy_params.ack_timeout = CN470_ACKTIMEOUT; 00297 phy_params.ack_timeout_rnd = CN470_ACK_TIMEOUT_RND; 00298 phy_params.rx_window2_datarate = CN470_RX_WND_2_DR; 00299 phy_params.rx_window2_frequency = CN470_RX_WND_2_FREQ; 00300 } 00301 00302 LoRaPHYCN470::~LoRaPHYCN470() 00303 { 00304 } 00305 00306 bool LoRaPHYCN470::rx_config(rx_config_params_t * config) 00307 { 00308 int8_t dr = config->datarate ; 00309 uint8_t max_payload = 0; 00310 int8_t phy_dr = 0; 00311 uint32_t frequency = config->frequency ; 00312 00313 _radio->lock(); 00314 00315 if (_radio->get_status() != RF_IDLE) { 00316 _radio->unlock(); 00317 return false; 00318 } 00319 00320 _radio->unlock(); 00321 00322 if( config->rx_slot == RX_SLOT_WIN_1 ) 00323 { 00324 // Apply window 1 frequency 00325 frequency = CN470_FIRST_RX1_CHANNEL + (config->channel % 48) * CN470_STEPWIDTH_RX1_CHANNEL; 00326 } 00327 00328 // Read the physical datarate from the datarates table 00329 phy_dr = datarates_CN470 [dr]; 00330 00331 _radio->lock(); 00332 00333 _radio->set_channel(frequency); 00334 00335 // Radio configuration 00336 _radio->set_rx_config(MODEM_LORA, config->bandwidth , phy_dr, 1, 0, 8, 00337 config->window_timeout , false, 0, false, 0, 0, true, 00338 config->is_rx_continuous ); 00339 00340 _radio->unlock(); 00341 00342 if (config->is_repeater_supported == true) { 00343 max_payload = max_payloads_with_repeater_CN470 [dr]; 00344 } else { 00345 max_payload = max_payloads_CN470 [dr]; 00346 } 00347 00348 _radio->lock(); 00349 _radio->set_max_payload_length(MODEM_LORA, max_payload + LORA_MAC_FRMPAYLOAD_OVERHEAD); 00350 _radio->unlock(); 00351 00352 return true; 00353 } 00354 00355 bool LoRaPHYCN470::tx_config(tx_config_params_t* config, int8_t* tx_power, 00356 lorawan_time_t* tx_toa) 00357 { 00358 int8_t phy_dr = datarates_CN470 [config->datarate]; 00359 00360 if (config->tx_power > bands[channels[config->channel].band].max_tx_pwr) { 00361 config->tx_power = bands[channels[config->channel].band].max_tx_pwr; 00362 } 00363 00364 int8_t phy_tx_power = 0; 00365 00366 // Calculate physical TX power 00367 phy_tx_power = compute_tx_power(config->tx_power, config->max_eirp, 00368 config->antenna_gain); 00369 00370 // acquire lock to radio 00371 _radio->lock(); 00372 00373 _radio->set_channel(channels[config->channel].frequency); 00374 00375 _radio->set_tx_config(MODEM_LORA, phy_tx_power, 0, 0, phy_dr, 1, 8, false, true, 00376 0, 0, false, 3000); 00377 // Setup maximum payload lenght of the radio driver 00378 _radio->set_max_payload_length(MODEM_LORA, config->pkt_len); 00379 00380 // Get the time-on-air of the next tx frame 00381 *tx_toa = _radio->time_on_air(MODEM_LORA, config->pkt_len); 00382 00383 // release lock to radio 00384 _radio->unlock(); 00385 00386 *tx_power = config->tx_power; 00387 00388 return true; 00389 } 00390 00391 uint8_t LoRaPHYCN470::link_ADR_request(adr_req_params_t* params, 00392 int8_t* dr_out, int8_t* tx_power_out, 00393 uint8_t* nb_rep_out, 00394 uint8_t* nb_bytes_parsed) 00395 { 00396 uint8_t status = 0x07; 00397 link_adr_params_t adr_settings; 00398 uint8_t next_index = 0; 00399 uint8_t bytes_processed = 0; 00400 uint16_t temp_channel_masks[CN470_CHANNEL_MASK_SIZE] = {0, 0, 0, 0, 0, 0}; 00401 00402 verify_adr_params_t verify_params; 00403 00404 // Initialize local copy of channels mask 00405 copy_channel_mask(temp_channel_masks, channel_mask, CN470_CHANNEL_MASK_SIZE); 00406 00407 while(bytes_processed < params->payload_size) { 00408 00409 // Get ADR request parameters 00410 next_index = parse_link_ADR_req(&(params->payload [bytes_processed]), &adr_settings); 00411 00412 if (next_index == 0) { 00413 break; // break loop, since no more request has been found 00414 } 00415 00416 // Update bytes processed 00417 bytes_processed += next_index; 00418 00419 // Revert status, as we only check the last ADR request for the channel mask KO 00420 status = 0x07; 00421 00422 if (adr_settings.ch_mask_ctrl == 6) { 00423 00424 // Enable all 125 kHz channels 00425 temp_channel_masks[0] = 0xFFFF; 00426 temp_channel_masks[1] = 0xFFFF; 00427 temp_channel_masks[2] = 0xFFFF; 00428 temp_channel_masks[3] = 0xFFFF; 00429 temp_channel_masks[4] = 0xFFFF; 00430 temp_channel_masks[5] = 0xFFFF; 00431 00432 } else if( adr_settings.ch_mask_ctrl == 7 ) { 00433 00434 status &= 0xFE; // Channel mask KO 00435 00436 } else { 00437 00438 for (uint8_t i = 0; i < 16; i++) { 00439 00440 if (((adr_settings.channel_mask & (1 << i)) != 0 ) && 00441 (channels[adr_settings.ch_mask_ctrl * 16 + i].frequency == 0)) { 00442 // Trying to enable an undefined channel 00443 status &= 0xFE; // Channel mask KO 00444 } 00445 } 00446 00447 temp_channel_masks[adr_settings.ch_mask_ctrl] = adr_settings.channel_mask; 00448 } 00449 } 00450 00451 verify_params.status = status; 00452 verify_params.adr_enabled = params->adr_enabled ; 00453 verify_params.datarate = adr_settings.datarate; 00454 verify_params.tx_power = adr_settings.tx_power; 00455 verify_params.nb_rep = adr_settings.nb_rep; 00456 verify_params.current_datarate = params->current_datarate ; 00457 verify_params.current_tx_power = params->current_tx_power ; 00458 verify_params.current_nb_rep = params->current_nb_rep ; 00459 verify_params.channel_mask = temp_channel_masks; 00460 00461 00462 // Verify the parameters and update, if necessary 00463 status = verify_link_ADR_req(&verify_params, &adr_settings.datarate, 00464 &adr_settings.tx_power, &adr_settings.nb_rep); 00465 00466 // Update channelsMask if everything is correct 00467 if (status == 0x07) { 00468 // Copy Mask 00469 copy_channel_mask(channel_mask, temp_channel_masks, CN470_CHANNEL_MASK_SIZE); 00470 } 00471 00472 // Update status variables 00473 *dr_out = adr_settings.datarate; 00474 *tx_power_out = adr_settings.tx_power; 00475 *nb_rep_out = adr_settings.nb_rep; 00476 *nb_bytes_parsed = bytes_processed; 00477 00478 return status; 00479 } 00480 00481 uint8_t LoRaPHYCN470::accept_rx_param_setup_req(rx_param_setup_req_t* params) 00482 { 00483 uint8_t status = 0x07; 00484 uint32_t freq = params->frequency; 00485 00486 // acquire radio lock 00487 _radio->lock(); 00488 00489 if ((_radio->check_rf_frequency(freq) == false) 00490 || (freq < CN470_FIRST_RX1_CHANNEL) 00491 || (freq > CN470_LAST_RX1_CHANNEL) 00492 || (((freq - (uint32_t) CN470_FIRST_RX1_CHANNEL) % (uint32_t) CN470_STEPWIDTH_RX1_CHANNEL) != 0)) { 00493 00494 status &= 0xFE; // Channel frequency KO 00495 } 00496 00497 // release radio lock 00498 _radio->unlock(); 00499 00500 // Verify datarate 00501 if (val_in_range(params->datarate, CN470_RX_MIN_DATARATE, CN470_RX_MAX_DATARATE) == 0) { 00502 status &= 0xFD; // Datarate KO 00503 } 00504 00505 // Verify datarate offset 00506 if (val_in_range(params->dr_offset, CN470_MIN_RX1_DR_OFFSET, CN470_MAX_RX1_DR_OFFSET) == 0) { 00507 status &= 0xFB; // Rx1DrOffset range KO 00508 } 00509 00510 return status; 00511 }
Generated on Tue Jul 12 2022 18:18:38 by
