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() 00208 { 00209 static const uint16_t fsb_mask[] = MBED_CONF_LORA_FSB_MASK_CHINA; 00210 00211 bands[0] = CN470_BAND0 ; 00212 00213 // Channels 00214 // 125 kHz channels 00215 for( uint8_t i = 0; i < CN470_MAX_NB_CHANNELS; i++ ) 00216 { 00217 channels[i].frequency = 470300000 + i * 200000; 00218 channels[i].dr_range.value = ( DR_5 << 4 ) | DR_0; 00219 channels[i].band = 0; 00220 } 00221 00222 // Initialize the channels default mask 00223 for (uint8_t i = 0; i < CN470_CHANNEL_MASK_SIZE; i++) { 00224 default_channel_mask[i] = 0xFFFF & fsb_mask[i]; 00225 } 00226 00227 // Update the channels mask 00228 copy_channel_mask(channel_mask, default_channel_mask, CN470_CHANNEL_MASK_SIZE); 00229 00230 // set default channels 00231 phy_params.channels.channel_list = channels; 00232 phy_params.channels.channel_list_size = CN470_MAX_NB_CHANNELS; 00233 phy_params.channels.mask = channel_mask; 00234 phy_params.channels.default_mask = default_channel_mask; 00235 phy_params.channels.mask_size = CN470_CHANNEL_MASK_SIZE; 00236 00237 // set bands for CN470 spectrum 00238 phy_params.bands.table = (void *) bands; 00239 phy_params.bands.size = CN470_MAX_NB_BANDS; 00240 00241 // set bandwidths available in CN470 spectrum 00242 phy_params.bandwidths.table = (void *) bandwidths_CN470 ; 00243 phy_params.bandwidths.size = 6; 00244 00245 // set data rates available in CN470 spectrum 00246 phy_params.datarates.table = (void *) datarates_CN470 ; 00247 phy_params.datarates.size = 6; 00248 00249 // set payload sizes with respect to data rates 00250 phy_params.payloads.table = (void *) max_payloads_CN470 ; 00251 phy_params.payloads.size = 6; 00252 phy_params.payloads_with_repeater.table = (void *)max_payloads_with_repeater_CN470 ; 00253 phy_params.payloads_with_repeater.size = 6; 00254 00255 // dwell time setting 00256 phy_params.ul_dwell_time_setting = 0; 00257 phy_params.dl_dwell_time_setting = 0; 00258 00259 // set initial and default parameters 00260 phy_params.duty_cycle_enabled = CN470_DUTY_CYCLE_ENABLED; 00261 00262 phy_params.accept_tx_param_setup_req = false; 00263 phy_params.fsk_supported = false; 00264 phy_params.cflist_supported = false; 00265 phy_params.dl_channel_req_supported = false; 00266 phy_params.custom_channelplans_supported = false; 00267 00268 phy_params.default_channel_cnt = CN470_MAX_NB_CHANNELS; 00269 phy_params.max_channel_cnt = CN470_MAX_NB_CHANNELS; 00270 phy_params.cflist_channel_cnt = 0; 00271 phy_params.min_tx_datarate = CN470_TX_MIN_DATARATE; 00272 phy_params.max_tx_datarate = CN470_TX_MAX_DATARATE; 00273 phy_params.min_rx_datarate = CN470_RX_MIN_DATARATE; 00274 phy_params.max_rx_datarate = CN470_RX_MAX_DATARATE; 00275 phy_params.default_datarate = CN470_DEFAULT_DATARATE; 00276 phy_params.default_max_datarate = CN470_TX_MAX_DATARATE; 00277 phy_params.min_rx1_dr_offset = CN470_MIN_RX1_DR_OFFSET; 00278 phy_params.max_rx1_dr_offset = CN470_MAX_RX1_DR_OFFSET; 00279 phy_params.default_rx1_dr_offset = CN470_DEFAULT_RX1_DR_OFFSET; 00280 phy_params.min_tx_power = CN470_MIN_TX_POWER; 00281 phy_params.max_tx_power = CN470_MAX_TX_POWER; 00282 phy_params.default_tx_power = CN470_DEFAULT_TX_POWER; 00283 phy_params.default_max_eirp = CN470_DEFAULT_MAX_EIRP; 00284 phy_params.default_antenna_gain = CN470_DEFAULT_ANTENNA_GAIN; 00285 phy_params.adr_ack_limit = CN470_ADR_ACK_LIMIT; 00286 phy_params.adr_ack_delay = CN470_ADR_ACK_DELAY; 00287 phy_params.max_rx_window = CN470_MAX_RX_WINDOW; 00288 phy_params.recv_delay1 = CN470_RECEIVE_DELAY1; 00289 phy_params.recv_delay2 = CN470_RECEIVE_DELAY2; 00290 00291 phy_params.join_accept_delay1 = CN470_JOIN_ACCEPT_DELAY1; 00292 phy_params.join_accept_delay2 = CN470_JOIN_ACCEPT_DELAY2; 00293 phy_params.max_fcnt_gap = CN470_MAX_FCNT_GAP; 00294 phy_params.ack_timeout = CN470_ACKTIMEOUT; 00295 phy_params.ack_timeout_rnd = CN470_ACK_TIMEOUT_RND; 00296 phy_params.rx_window2_datarate = CN470_RX_WND_2_DR; 00297 phy_params.rx_window2_frequency = CN470_RX_WND_2_FREQ; 00298 } 00299 00300 LoRaPHYCN470::~LoRaPHYCN470() 00301 { 00302 } 00303 00304 lorawan_status_t LoRaPHYCN470::set_next_channel(channel_selection_params_t *params, 00305 uint8_t *channel, lorawan_time_t *time, 00306 lorawan_time_t *aggregate_timeoff) 00307 { 00308 uint8_t channel_count = 0; 00309 uint8_t delay_tx = 0; 00310 00311 uint8_t enabled_channels[CN470_MAX_NB_CHANNELS] = {0}; 00312 00313 lorawan_time_t next_tx_delay = 0; 00314 band_t *band_table = (band_t *) phy_params.bands.table; 00315 00316 if (num_active_channels(phy_params.channels.mask, 0, 00317 phy_params.channels.mask_size) == 0) { 00318 00319 // Reactivate default channels 00320 copy_channel_mask(phy_params.channels.mask, 00321 phy_params.channels.default_mask, 00322 phy_params.channels.mask_size); 00323 } 00324 00325 if (params->aggregate_timeoff 00326 <= _lora_time->get_elapsed_time(params->last_aggregate_tx_time)) { 00327 // Reset Aggregated time off 00328 *aggregate_timeoff = 0; 00329 00330 // Update bands Time OFF 00331 next_tx_delay = update_band_timeoff(params->joined, 00332 params->dc_enabled, 00333 band_table, phy_params.bands.size); 00334 00335 // Search how many channels are enabled 00336 channel_count = enabled_channel_count(params->current_datarate, 00337 phy_params.channels.mask, 00338 enabled_channels, &delay_tx); 00339 } else { 00340 delay_tx++; 00341 next_tx_delay = params->aggregate_timeoff - 00342 _lora_time->get_elapsed_time(params->last_aggregate_tx_time); 00343 } 00344 00345 if (channel_count > 0) { 00346 // We found a valid channel 00347 *channel = enabled_channels[get_random(0, channel_count - 1)]; 00348 *time = 0; 00349 return LORAWAN_STATUS_OK; 00350 } 00351 00352 if (delay_tx > 0) { 00353 // Delay transmission due to AggregatedTimeOff or to a band time off 00354 *time = next_tx_delay; 00355 return LORAWAN_STATUS_DUTYCYCLE_RESTRICTED; 00356 } 00357 00358 *time = 0; 00359 return LORAWAN_STATUS_NO_CHANNEL_FOUND; 00360 } 00361 00362 bool LoRaPHYCN470::rx_config(rx_config_params_t * config) 00363 { 00364 int8_t dr = config->datarate ; 00365 uint8_t max_payload = 0; 00366 int8_t phy_dr = 0; 00367 uint32_t frequency = config->frequency ; 00368 00369 _radio->lock(); 00370 00371 if (_radio->get_status() != RF_IDLE) { 00372 _radio->unlock(); 00373 return false; 00374 } 00375 00376 _radio->unlock(); 00377 00378 if( config->rx_slot == RX_SLOT_WIN_1 ) 00379 { 00380 // Apply window 1 frequency 00381 frequency = CN470_FIRST_RX1_CHANNEL + (config->channel % 48) * CN470_STEPWIDTH_RX1_CHANNEL; 00382 } 00383 00384 // Read the physical datarate from the datarates table 00385 phy_dr = datarates_CN470 [dr]; 00386 00387 _radio->lock(); 00388 00389 _radio->set_channel(frequency); 00390 00391 // Radio configuration 00392 _radio->set_rx_config(MODEM_LORA, config->bandwidth , phy_dr, 1, 0, 00393 MBED_CONF_LORA_DOWNLINK_PREAMBLE_LENGTH, 00394 config->window_timeout , false, 0, false, 0, 0, true, 00395 config->is_rx_continuous ); 00396 00397 _radio->unlock(); 00398 00399 if (config->is_repeater_supported == true) { 00400 max_payload = max_payloads_with_repeater_CN470 [dr]; 00401 } else { 00402 max_payload = max_payloads_CN470 [dr]; 00403 } 00404 00405 _radio->lock(); 00406 _radio->set_max_payload_length(MODEM_LORA, max_payload + LORA_MAC_FRMPAYLOAD_OVERHEAD); 00407 _radio->unlock(); 00408 00409 return true; 00410 } 00411 00412 bool LoRaPHYCN470::tx_config(tx_config_params_t* config, int8_t* tx_power, 00413 lorawan_time_t* tx_toa) 00414 { 00415 int8_t phy_dr = datarates_CN470 [config->datarate]; 00416 00417 if (config->tx_power > bands[channels[config->channel].band].max_tx_pwr) { 00418 config->tx_power = bands[channels[config->channel].band].max_tx_pwr; 00419 } 00420 00421 int8_t phy_tx_power = 0; 00422 00423 // Calculate physical TX power 00424 phy_tx_power = compute_tx_power(config->tx_power, config->max_eirp, 00425 config->antenna_gain); 00426 00427 // acquire lock to radio 00428 _radio->lock(); 00429 00430 _radio->set_channel(channels[config->channel].frequency); 00431 00432 _radio->set_tx_config(MODEM_LORA, phy_tx_power, 0, 0, phy_dr, 1, 00433 MBED_CONF_LORA_UPLINK_PREAMBLE_LENGTH, false, true, 00434 0, 0, false, 3000); 00435 // Setup maximum payload lenght of the radio driver 00436 _radio->set_max_payload_length(MODEM_LORA, config->pkt_len); 00437 00438 // Get the time-on-air of the next tx frame 00439 *tx_toa = _radio->time_on_air(MODEM_LORA, config->pkt_len); 00440 00441 // release lock to radio 00442 _radio->unlock(); 00443 00444 *tx_power = config->tx_power; 00445 00446 return true; 00447 } 00448 00449 uint8_t LoRaPHYCN470::link_ADR_request(adr_req_params_t* params, 00450 int8_t* dr_out, int8_t* tx_power_out, 00451 uint8_t* nb_rep_out, 00452 uint8_t* nb_bytes_parsed) 00453 { 00454 uint8_t status = 0x07; 00455 link_adr_params_t adr_settings; 00456 uint8_t next_index = 0; 00457 uint8_t bytes_processed = 0; 00458 uint16_t temp_channel_masks[CN470_CHANNEL_MASK_SIZE] = {0, 0, 0, 0, 0, 0}; 00459 00460 verify_adr_params_t verify_params; 00461 00462 // Initialize local copy of channels mask 00463 copy_channel_mask(temp_channel_masks, channel_mask, CN470_CHANNEL_MASK_SIZE); 00464 00465 while(bytes_processed < params->payload_size) { 00466 00467 // Get ADR request parameters 00468 next_index = parse_link_ADR_req(&(params->payload [bytes_processed]), &adr_settings); 00469 00470 if (next_index == 0) { 00471 break; // break loop, since no more request has been found 00472 } 00473 00474 // Update bytes processed 00475 bytes_processed += next_index; 00476 00477 // Revert status, as we only check the last ADR request for the channel mask KO 00478 status = 0x07; 00479 00480 if (adr_settings.ch_mask_ctrl == 6) { 00481 00482 // Enable all 125 kHz channels 00483 for (uint8_t i = 0; i < CN470_CHANNEL_MASK_SIZE; i++) { 00484 temp_channel_masks[i] = 0xFFFF; 00485 } 00486 00487 } else if( adr_settings.ch_mask_ctrl == 7 ) { 00488 00489 status &= 0xFE; // Channel mask KO 00490 00491 } else { 00492 00493 for (uint8_t i = 0; i < 16; i++) { 00494 00495 if (((adr_settings.channel_mask & (1 << i)) != 0 ) && 00496 (channels[adr_settings.ch_mask_ctrl * 16 + i].frequency == 0)) { 00497 // Trying to enable an undefined channel 00498 status &= 0xFE; // Channel mask KO 00499 } 00500 } 00501 00502 temp_channel_masks[adr_settings.ch_mask_ctrl] = adr_settings.channel_mask; 00503 } 00504 } 00505 00506 verify_params.status = status; 00507 verify_params.adr_enabled = params->adr_enabled ; 00508 verify_params.datarate = adr_settings.datarate; 00509 verify_params.tx_power = adr_settings.tx_power; 00510 verify_params.nb_rep = adr_settings.nb_rep; 00511 verify_params.current_datarate = params->current_datarate ; 00512 verify_params.current_tx_power = params->current_tx_power ; 00513 verify_params.current_nb_rep = params->current_nb_rep ; 00514 verify_params.channel_mask = temp_channel_masks; 00515 00516 00517 // Verify the parameters and update, if necessary 00518 status = verify_link_ADR_req(&verify_params, &adr_settings.datarate, 00519 &adr_settings.tx_power, &adr_settings.nb_rep); 00520 00521 // Update channelsMask if everything is correct 00522 if (status == 0x07) { 00523 // Copy Mask 00524 copy_channel_mask(channel_mask, temp_channel_masks, CN470_CHANNEL_MASK_SIZE); 00525 } 00526 00527 // Update status variables 00528 *dr_out = adr_settings.datarate; 00529 *tx_power_out = adr_settings.tx_power; 00530 *nb_rep_out = adr_settings.nb_rep; 00531 *nb_bytes_parsed = bytes_processed; 00532 00533 return status; 00534 } 00535 00536 uint8_t LoRaPHYCN470::accept_rx_param_setup_req(rx_param_setup_req_t* params) 00537 { 00538 uint8_t status = 0x07; 00539 uint32_t freq = params->frequency; 00540 00541 // acquire radio lock 00542 _radio->lock(); 00543 00544 if ((_radio->check_rf_frequency(freq) == false) 00545 || (freq < CN470_FIRST_RX1_CHANNEL) 00546 || (freq > CN470_LAST_RX1_CHANNEL) 00547 || (((freq - (uint32_t) CN470_FIRST_RX1_CHANNEL) % (uint32_t) CN470_STEPWIDTH_RX1_CHANNEL) != 0)) { 00548 00549 status &= 0xFE; // Channel frequency KO 00550 } 00551 00552 // release radio lock 00553 _radio->unlock(); 00554 00555 // Verify datarate 00556 if (val_in_range(params->datarate, CN470_RX_MIN_DATARATE, CN470_RX_MAX_DATARATE) == 0) { 00557 status &= 0xFD; // Datarate KO 00558 } 00559 00560 // Verify datarate offset 00561 if (val_in_range(params->dr_offset, CN470_MIN_RX1_DR_OFFSET, CN470_MAX_RX1_DR_OFFSET) == 0) { 00562 status &= 0xFB; // Rx1DrOffset range KO 00563 } 00564 00565 return status; 00566 }
Generated on Tue Aug 9 2022 00:37:09 by
1.7.2