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.
LoRaPHY.cpp
00001 /** 00002 / _____) _ | | 00003 ( (____ _____ ____ _| |_ _____ ____| |__ 00004 \____ \| ___ | (_ _) ___ |/ ___) _ \ 00005 _____) ) ____| | | || |_| ____( (___| | | | 00006 (______/|_____)_|_|_| \__)_____)\____)_| |_| 00007 (C)2013 Semtech 00008 ___ _____ _ ___ _ _____ ___ ___ ___ ___ 00009 / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __| 00010 \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _| 00011 |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___| 00012 embedded.connectivity.solutions=============== 00013 00014 License: Revised BSD License, see LICENSE.TXT file include in the project 00015 00016 Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE ) 00017 00018 00019 Copyright (c) 2017, Arm Limited and affiliates. 00020 00021 SPDX-License-Identifier: BSD-3-Clause 00022 */ 00023 00024 #include <stdbool.h> 00025 #include <stdlib.h> 00026 #include <string.h> 00027 #include <stdint.h> 00028 #include <math.h> 00029 #include "lorawan/lorastack/phy/LoRaPHY.h" 00030 00031 #define BACKOFF_DC_1_HOUR 100 00032 #define BACKOFF_DC_10_HOURS 1000 00033 #define BACKOFF_DC_24_HOURS 10000 00034 00035 #define CHANNELS_IN_MASK 16 00036 00037 LoRaPHY::LoRaPHY(LoRaWANTimeHandler &lora_time) 00038 : _radio(NULL), 00039 _lora_time(lora_time) 00040 { 00041 memset(&phy_params, 0, sizeof(phy_params)); 00042 } 00043 00044 LoRaPHY::~LoRaPHY() 00045 { 00046 _radio = NULL; 00047 } 00048 00049 void LoRaPHY::set_radio_instance(LoRaRadio& radio) 00050 { 00051 _radio = &radio; 00052 } 00053 00054 void LoRaPHY::put_radio_to_sleep() { 00055 _radio->lock(); 00056 _radio->sleep(); 00057 _radio->unlock(); 00058 } 00059 00060 void LoRaPHY::put_radio_to_standby() { 00061 _radio->lock(); 00062 _radio->standby(); 00063 _radio->unlock(); 00064 } 00065 00066 void LoRaPHY::setup_public_network_mode(bool set) 00067 { 00068 _radio->lock(); 00069 _radio->set_public_network(set); 00070 _radio->unlock(); 00071 } 00072 00073 void LoRaPHY::setup_rx_window(bool rx_continuous, uint32_t max_rx_window) 00074 { 00075 _radio->lock(); 00076 if (!rx_continuous) { 00077 _radio->receive(max_rx_window); 00078 } else { 00079 _radio->receive(0); // Continuous mode 00080 } 00081 _radio->unlock(); 00082 } 00083 00084 // For DevNonce for example 00085 uint32_t LoRaPHY::get_radio_rng() 00086 { 00087 uint32_t rand; 00088 00089 _radio->lock(); 00090 rand =_radio->random(); 00091 _radio->unlock(); 00092 00093 return rand; 00094 } 00095 00096 void LoRaPHY::handle_send(uint8_t *buf, uint8_t size) 00097 { 00098 _radio->lock(); 00099 _radio->send(buf, size); 00100 _radio->unlock(); 00101 } 00102 00103 uint8_t LoRaPHY::request_new_channel(new_channel_req_params_t* params) 00104 { 00105 if (!phy_params.custom_channelplans_supported) { 00106 return 0; 00107 } 00108 00109 uint8_t status = 0x03; 00110 00111 if (params->new_channel->frequency == 0) { 00112 // Remove 00113 if (remove_channel(params->channel_id) == false) { 00114 status &= 0xFC; 00115 } 00116 } else { 00117 00118 switch (add_channel(params->new_channel, params->channel_id)) { 00119 case LORAWAN_STATUS_OK: 00120 { 00121 break; 00122 } 00123 case LORAWAN_STATUS_FREQUENCY_INVALID: 00124 { 00125 status &= 0xFE; 00126 break; 00127 } 00128 case LORAWAN_STATUS_DATARATE_INVALID: 00129 { 00130 status &= 0xFD; 00131 break; 00132 } 00133 case LORAWAN_STATUS_FREQ_AND_DR_INVALID: 00134 { 00135 status &= 0xFC; 00136 break; 00137 } 00138 default: 00139 { 00140 status &= 0xFC; 00141 break; 00142 } 00143 } 00144 } 00145 00146 return status; 00147 } 00148 00149 int32_t LoRaPHY::get_random(int32_t min, int32_t max) 00150 { 00151 return (int32_t) rand() % (max - min + 1) + min; 00152 } 00153 00154 bool LoRaPHY::verify_channel_DR(uint8_t nb_channels, uint16_t* channel_mask, 00155 int8_t dr, int8_t min_dr, int8_t max_dr, 00156 channel_params_t * channels) 00157 { 00158 if (val_in_range(dr, min_dr, max_dr) == 0) { 00159 return false; 00160 } 00161 00162 for (uint8_t i = 0; i < phy_params.max_channel_cnt; i++) { 00163 if (mask_bit_test(channel_mask, i)) { 00164 // Check datarate validity for enabled channels 00165 if (val_in_range(dr, (channels[i].dr_range.fields.min & 0x0F), 00166 (channels[i].dr_range .fields.max & 0x0F))) { 00167 // At least 1 channel has been found we can return OK. 00168 return true; 00169 } 00170 } 00171 } 00172 00173 return false; 00174 } 00175 00176 uint8_t LoRaPHY::val_in_range( int8_t value, int8_t min, int8_t max ) 00177 { 00178 if ((value >= min) && (value <= max)) { 00179 return 1; 00180 } 00181 00182 return 0; 00183 } 00184 00185 bool LoRaPHY::disable_channel(uint16_t* channel_mask, uint8_t id, 00186 uint8_t max_channels_num) 00187 { 00188 uint8_t index = id / 16; 00189 00190 if ((index > phy_params.channels.mask_size) || (id >= max_channels_num)) { 00191 return false; 00192 } 00193 00194 // Deactivate channel 00195 mask_bit_clear(channel_mask, id); 00196 00197 return true; 00198 } 00199 00200 uint8_t LoRaPHY::count_bits(uint16_t mask, uint8_t nbBits) 00201 { 00202 uint8_t nbActiveBits = 0; 00203 00204 for(uint8_t j = 0; j < nbBits; j++) { 00205 if (mask_bit_test(&mask, j)) { 00206 nbActiveBits++; 00207 } 00208 } 00209 00210 return nbActiveBits; 00211 } 00212 00213 uint8_t LoRaPHY::num_active_channels(uint16_t* channel_mask, uint8_t start_idx, 00214 uint8_t stop_idx) 00215 { 00216 uint8_t nb_channels = 0; 00217 00218 if (channel_mask == NULL) { 00219 return 0; 00220 } 00221 00222 for (uint8_t i = start_idx; i < stop_idx; i++) { 00223 nb_channels += count_bits(channel_mask[i], 16); 00224 } 00225 00226 return nb_channels; 00227 } 00228 00229 void LoRaPHY::copy_channel_mask(uint16_t* dest_mask, uint16_t* src_mask, uint8_t len) 00230 { 00231 if ((dest_mask != NULL) && (src_mask != NULL)) { 00232 for( uint8_t i = 0; i < len; i++ ) { 00233 dest_mask[i] = src_mask[i]; 00234 } 00235 } 00236 } 00237 00238 void LoRaPHY::set_last_tx_done(set_band_txdone_params_t* last_tx_params) 00239 { 00240 if (!last_tx_params) { 00241 return; 00242 } 00243 00244 band_t *band_table = (band_t *) phy_params.bands.table; 00245 channel_params_t *channel_list = phy_params.channels.channel_list; 00246 00247 if (last_tx_params->joined == true) { 00248 band_table[channel_list[last_tx_params->channel].band].last_tx_time = last_tx_params->last_tx_done_time; 00249 return; 00250 } 00251 00252 band_table[channel_list[last_tx_params->channel].band].last_tx_time = last_tx_params->last_tx_done_time; 00253 band_table[channel_list[last_tx_params->channel].band].last_join_tx_time = last_tx_params->last_tx_done_time; 00254 00255 } 00256 00257 lorawan_time_t LoRaPHY::update_band_timeoff(bool joined, bool duty_cycle, 00258 band_t * bands, uint8_t nb_bands) 00259 { 00260 lorawan_time_t next_tx_delay = (lorawan_time_t) (-1); 00261 00262 // Update bands Time OFF 00263 for (uint8_t i = 0; i < nb_bands; i++) { 00264 00265 if (joined == false) { 00266 uint32_t txDoneTime = MAX(_lora_time.get_elapsed_time(bands[i].last_join_tx_time ), 00267 (duty_cycle == true) ? 00268 _lora_time.get_elapsed_time(bands[i].last_tx_time ) : 0); 00269 00270 if (bands[i].off_time <= txDoneTime) { 00271 bands[i].off_time = 0; 00272 } 00273 00274 if (bands[i].off_time != 0) { 00275 next_tx_delay = MIN( bands[i].off_time - txDoneTime, next_tx_delay ); 00276 } 00277 00278 } else { 00279 // if network has been joined 00280 if (duty_cycle == true) { 00281 00282 if( bands[i].off_time <= _lora_time.get_elapsed_time(bands[i].last_tx_time )) { 00283 bands[i].off_time = 0; 00284 } 00285 00286 if(bands[i].off_time != 0 ) { 00287 next_tx_delay = MIN(bands[i].off_time - _lora_time.get_elapsed_time(bands[i].last_tx_time ), 00288 next_tx_delay); 00289 } 00290 } else { 00291 // if duty cycle is not on 00292 next_tx_delay = 0; 00293 bands[i].off_time = 0; 00294 } 00295 } 00296 } 00297 00298 return next_tx_delay; 00299 } 00300 00301 uint8_t LoRaPHY::parse_link_ADR_req(uint8_t* payload, link_adr_params_t* params) 00302 { 00303 uint8_t ret_index = 0; 00304 00305 if (payload[0] == SRV_MAC_LINK_ADR_REQ ) { 00306 00307 // Parse datarate and tx power 00308 params->datarate = payload[1]; 00309 params->tx_power = params->datarate & 0x0F; 00310 params->datarate = (params->datarate >> 4) & 0x0F; 00311 00312 // Parse ChMask 00313 params->channel_mask = (uint16_t) payload[2]; 00314 params->channel_mask |= (uint16_t) payload[3] << 8; 00315 00316 // Parse ChMaskCtrl and nbRep 00317 params->nb_rep = payload[4]; 00318 params->ch_mask_ctrl = ( params->nb_rep >> 4 ) & 0x07; 00319 params->nb_rep &= 0x0F; 00320 00321 // LinkAdrReq has 4 bytes length + 1 byte CMD 00322 ret_index = 5; 00323 } 00324 00325 return ret_index; 00326 } 00327 00328 uint8_t LoRaPHY::verify_link_ADR_req(verify_adr_params_t* verify_params, 00329 int8_t* dr, int8_t* tx_pow, uint8_t* nb_rep) 00330 { 00331 uint8_t status = verify_params->status ; 00332 int8_t datarate = verify_params->datarate ; 00333 int8_t tx_power = verify_params->tx_power ; 00334 int8_t nb_repetitions = verify_params->nb_rep ; 00335 00336 // Handle the case when ADR is off. 00337 if (verify_params->adr_enabled == false) { 00338 // When ADR is off, we are allowed to change the channels mask and the NbRep, 00339 // if the datarate and the TX power of the LinkAdrReq are set to 0x0F. 00340 if ((verify_params->datarate != 0x0F) || (verify_params->tx_power != 0x0F)) { 00341 status = 0; 00342 nb_repetitions = verify_params->current_nb_rep ; 00343 } 00344 00345 // Get the current datarate and tx power 00346 datarate = verify_params->current_datarate ; 00347 tx_power = verify_params->current_tx_power ; 00348 } 00349 00350 if (status != 0) { 00351 // Verify channel datarate 00352 if (verify_channel_DR(phy_params.max_channel_cnt, verify_params->channel_mask , 00353 datarate, phy_params.min_tx_datarate, 00354 phy_params.max_tx_datarate, phy_params.channels.channel_list) 00355 == false) { 00356 status &= 0xFD; // Datarate KO 00357 } 00358 00359 // Verify tx power 00360 if (val_in_range(tx_power, phy_params.max_tx_power, 00361 phy_params.min_tx_power) == 0) { 00362 // Verify if the maximum TX power is exceeded 00363 if (phy_params.max_tx_power > tx_power) { 00364 // Apply maximum TX power. Accept TX power. 00365 tx_power = phy_params.max_tx_power; 00366 } else { 00367 status &= 0xFB; // TxPower KO 00368 } 00369 } 00370 } 00371 00372 // If the status is ok, verify the NbRep 00373 if (status == 0x07 && nb_repetitions == 0) { 00374 // Restore the default value according to the LoRaWAN specification 00375 nb_repetitions = 1; 00376 } 00377 00378 // Apply changes 00379 *dr = datarate; 00380 *tx_pow = tx_power; 00381 *nb_rep = nb_repetitions; 00382 00383 return status; 00384 } 00385 00386 double LoRaPHY::compute_symb_timeout_lora(uint8_t phy_dr, uint32_t bandwidth) 00387 { 00388 return ((double)(1 << phy_dr) / (double) bandwidth) * 1000; 00389 } 00390 00391 double LoRaPHY::compute_symb_timeout_fsk(uint8_t phy_dr) 00392 { 00393 return (8.0 / (double) phy_dr); // 1 symbol equals 1 byte 00394 } 00395 00396 void LoRaPHY::get_rx_window_params(double t_symb, uint8_t min_rx_symb, 00397 uint32_t rx_error, uint32_t wakeup_time, 00398 uint32_t* window_timeout, int32_t* window_offset) 00399 { 00400 // Computed number of symbols 00401 *window_timeout = MAX ((uint32_t) ceil(((2 * min_rx_symb - 8) * t_symb + 2 * rx_error) / t_symb), min_rx_symb ); 00402 *window_offset = (int32_t) ceil((4.0 * t_symb) - ((*window_timeout * t_symb) / 2.0 ) - wakeup_time); 00403 } 00404 00405 int8_t LoRaPHY::compute_tx_power(int8_t tx_power_idx, float max_eirp, 00406 float antenna_gain) 00407 { 00408 int8_t phy_tx_power = 0; 00409 00410 phy_tx_power = (int8_t) floor((max_eirp - (tx_power_idx * 2U)) - antenna_gain); 00411 00412 return phy_tx_power; 00413 } 00414 00415 00416 int8_t LoRaPHY::get_next_lower_dr(int8_t dr, int8_t min_dr) 00417 { 00418 uint8_t next_lower_dr = 0; 00419 00420 if (dr == min_dr) { 00421 next_lower_dr = min_dr; 00422 } else { 00423 next_lower_dr = dr - 1; 00424 } 00425 00426 return next_lower_dr; 00427 } 00428 00429 uint8_t LoRaPHY::get_bandwidth(uint8_t dr) 00430 { 00431 uint32_t *bandwidths = (uint32_t *) phy_params.bandwidths.table; 00432 00433 switch(bandwidths[dr]) { 00434 default: 00435 case 125000: 00436 return 0; 00437 case 250000: 00438 return 1; 00439 case 500000: 00440 return 2; 00441 } 00442 } 00443 00444 uint8_t LoRaPHY::enabled_channel_count(bool joined, uint8_t datarate, 00445 const uint16_t *channel_mask, 00446 uint8_t *channel_indices, 00447 uint8_t *delayTx) 00448 { 00449 uint8_t count = 0; 00450 uint8_t delay_transmission = 0; 00451 00452 for (uint8_t i = 0; i < phy_params.max_channel_cnt; i++) { 00453 if (mask_bit_test(channel_mask, i)) { 00454 00455 if (val_in_range(datarate, phy_params.channels.channel_list[i].dr_range.fields.min, 00456 phy_params.channels.channel_list[i].dr_range.fields.max ) == 0) { 00457 // data rate range invalid for this channel 00458 continue; 00459 } 00460 00461 band_t *band_table = (band_t *) phy_params.bands.table; 00462 if (band_table[phy_params.channels.channel_list[i].band].off_time > 0) { 00463 // Check if the band is available for transmission 00464 delay_transmission++; 00465 continue; 00466 } 00467 00468 // otherwise count the channel as enabled 00469 channel_indices[count++] = i; 00470 } 00471 } 00472 00473 *delayTx = delay_transmission; 00474 00475 return count; 00476 } 00477 00478 phy_param_t LoRaPHY::get_phy_params(get_phy_params_t* getPhy) 00479 { 00480 phy_param_t phyParam = { 0 }; 00481 00482 switch (getPhy->attribute) { 00483 case PHY_MIN_RX_DR : { 00484 if (phy_params.dl_dwell_time_setting == 0) { 00485 phyParam.value = phy_params.min_rx_datarate; 00486 } else { 00487 phyParam.value = phy_params.dwell_limit_datarate; 00488 } 00489 break; 00490 } 00491 case PHY_MIN_TX_DR : { 00492 if (phy_params.ul_dwell_time_setting == 0) { 00493 phyParam.value = phy_params.min_tx_datarate; 00494 } else { 00495 phyParam.value = phy_params.dwell_limit_datarate; 00496 } 00497 break; 00498 } 00499 case PHY_DEF_TX_DR : { 00500 phyParam.value = phy_params.default_datarate; 00501 break; 00502 } 00503 case PHY_NEXT_LOWER_TX_DR : { 00504 if (phy_params.ul_dwell_time_setting == 0) { 00505 phyParam.value = get_next_lower_dr(getPhy->datarate, 00506 phy_params.min_tx_datarate); 00507 } else { 00508 phyParam.value = get_next_lower_dr( 00509 getPhy->datarate, phy_params.dwell_limit_datarate); 00510 } 00511 break; 00512 } 00513 case PHY_DEF_TX_POWER : { 00514 phyParam.value = phy_params.default_tx_power; 00515 break; 00516 } 00517 case PHY_MAX_PAYLOAD : { 00518 uint8_t *payload_table = (uint8_t *) phy_params.payloads.table; 00519 phyParam.value = payload_table[getPhy->datarate]; 00520 break; 00521 } 00522 case PHY_MAX_PAYLOAD_REPEATER : { 00523 uint8_t *payload_table = (uint8_t *) phy_params.payloads_with_repeater.table; 00524 phyParam.value = payload_table[getPhy->datarate]; 00525 break; 00526 } 00527 case PHY_DUTY_CYCLE : { 00528 phyParam.value = phy_params.duty_cycle_enabled; 00529 break; 00530 } 00531 case PHY_MAX_RX_WINDOW : { 00532 phyParam.value = phy_params.max_rx_window; 00533 break; 00534 } 00535 case PHY_RECEIVE_DELAY1 : { 00536 phyParam.value = phy_params.recv_delay1; 00537 break; 00538 } 00539 case PHY_RECEIVE_DELAY2 : { 00540 phyParam.value = phy_params.recv_delay2; 00541 break; 00542 } 00543 case PHY_JOIN_ACCEPT_DELAY1 : { 00544 phyParam.value = phy_params.join_accept_delay1; 00545 break; 00546 } 00547 case PHY_JOIN_ACCEPT_DELAY2 : { 00548 phyParam.value = phy_params.join_accept_delay2; 00549 break; 00550 } 00551 case PHY_MAX_FCNT_GAP : { 00552 phyParam.value = phy_params.max_fcnt_gap; 00553 break; 00554 } 00555 case PHY_ACK_TIMEOUT : { 00556 uint16_t ack_timeout = phy_params.ack_timeout; 00557 uint16_t ack_timeout_rnd = phy_params.ack_timeout_rnd; 00558 phyParam.value = (ack_timeout 00559 + get_random(-ack_timeout_rnd, ack_timeout_rnd)); 00560 break; 00561 } 00562 case PHY_DEF_DR1_OFFSET : { 00563 phyParam.value = phy_params.default_rx1_dr_offset; 00564 break; 00565 } 00566 case PHY_DEF_RX2_FREQUENCY : { 00567 phyParam.value = phy_params.rx_window2_frequency; 00568 break; 00569 } 00570 case PHY_DEF_RX2_DR : { 00571 phyParam.value = phy_params.rx_window2_datarate; 00572 break; 00573 } 00574 case PHY_CHANNEL_MASK : { 00575 phyParam.channel_mask = phy_params.channels.mask; 00576 break; 00577 } 00578 case PHY_DEFAULT_CHANNEL_MASK : { 00579 phyParam.channel_mask = phy_params.channels.default_mask; 00580 break; 00581 } 00582 case PHY_MAX_NB_CHANNELS : { 00583 phyParam.value = phy_params.max_channel_cnt; 00584 break; 00585 } 00586 case PHY_CHANNELS : { 00587 phyParam.channel_params = phy_params.channels.channel_list; 00588 break; 00589 } 00590 case PHY_CUSTOM_CHANNEL_PLAN_SUPPORT : 00591 // 0 if custom channel plans are not supported (in LoRaWAN terms 00592 // the regions who do not support custom channels are called as 00593 // regions with dynamic channel plans) 00594 phyParam.value = (uint32_t) phy_params.custom_channelplans_supported; 00595 break; 00596 case PHY_DEF_UPLINK_DWELL_TIME : { 00597 phyParam.value = phy_params.ul_dwell_time_setting; 00598 break; 00599 } 00600 case PHY_DEF_DOWNLINK_DWELL_TIME : { 00601 phyParam.value = phy_params.dl_dwell_time_setting; 00602 break; 00603 } 00604 case PHY_DEF_MAX_EIRP : { 00605 phyParam.f_value = phy_params.default_max_eirp; 00606 break; 00607 } 00608 case PHY_DEF_ANTENNA_GAIN : { 00609 phyParam.f_value = phy_params.default_antenna_gain; 00610 break; 00611 } 00612 case PHY_NB_JOIN_TRIALS : 00613 case PHY_DEF_NB_JOIN_TRIALS : { 00614 phyParam.value = MBED_CONF_LORA_NB_TRIALS; 00615 break; 00616 } 00617 default: { 00618 break; 00619 } 00620 } 00621 00622 return phyParam; 00623 } 00624 00625 void LoRaPHY::restore_default_channels() 00626 { 00627 // Restore channels default mask 00628 for (uint8_t i=0; i < phy_params.channels.mask_size; i++) { 00629 phy_params.channels.mask[i] |= phy_params.channels.default_mask[i]; 00630 } 00631 } 00632 00633 bool LoRaPHY::verify(verification_params_t* verify, phy_attributes_t phy_attribute) 00634 { 00635 switch(phy_attribute) { 00636 case PHY_TX_DR : 00637 { 00638 if (phy_params.ul_dwell_time_setting == 0) { 00639 return val_in_range(verify->datarate, 00640 phy_params.min_tx_datarate, 00641 phy_params.max_tx_datarate); 00642 } else { 00643 return val_in_range(verify->datarate, 00644 phy_params.dwell_limit_datarate, 00645 phy_params.max_tx_datarate); 00646 } 00647 00648 } 00649 case PHY_DEF_TX_DR : 00650 { 00651 return val_in_range(verify->datarate, 00652 phy_params.default_datarate, 00653 phy_params.default_max_datarate); 00654 } 00655 case PHY_RX_DR : 00656 { 00657 if (phy_params.dl_dwell_time_setting == 0) { 00658 return val_in_range(verify->datarate, 00659 phy_params.min_rx_datarate, 00660 phy_params.min_rx_datarate); 00661 } else { 00662 return val_in_range(verify->datarate, 00663 phy_params.dwell_limit_datarate, 00664 phy_params.min_rx_datarate ); 00665 } 00666 } 00667 case PHY_DEF_TX_POWER : 00668 case PHY_TX_POWER : 00669 { 00670 // Remark: switched min and max! 00671 return val_in_range(verify->tx_power, phy_params.max_tx_power, 00672 phy_params.min_tx_power); 00673 } 00674 case PHY_DUTY_CYCLE : 00675 { 00676 if (verify->duty_cycle == phy_params.duty_cycle_enabled) { 00677 return true; 00678 } 00679 00680 return false; 00681 } 00682 case PHY_NB_JOIN_TRIALS : 00683 { 00684 if (verify->nb_join_trials < MBED_CONF_LORA_NB_TRIALS) { 00685 return false; 00686 } 00687 break; 00688 } 00689 default: 00690 return false; 00691 } 00692 00693 return true; 00694 } 00695 00696 void LoRaPHY::apply_cf_list(cflist_params_t* cf_list) 00697 { 00698 // if the underlying PHY doesn't support CF-List, ignore the request 00699 if (!phy_params.cflist_supported) { 00700 return; 00701 } 00702 00703 channel_params_t new_channel; 00704 00705 // Setup default datarate range 00706 new_channel.dr_range .value = (phy_params.default_max_datarate << 4) 00707 | phy_params.default_datarate; 00708 00709 // Size of the optional CF list 00710 if (cf_list->size != 16) { 00711 return; 00712 } 00713 00714 // Last byte is RFU, don't take it into account 00715 // NOTE: Currently the PHY layers supported by LoRaWAN who accept a CF-List 00716 // define first 2 or 3 channels as default channels. this function is 00717 // written keeping that in mind. If there would be a PHY in the future that 00718 // accepts CF-list but have haphazard allocation of default channels, we 00719 // should override this function in the implementation of that particular 00720 // PHY. 00721 for (uint8_t i = 0, channel_id = phy_params.default_channel_cnt; 00722 channel_id < phy_params.max_channel_cnt; i+=phy_params.default_channel_cnt, channel_id++) { 00723 if (channel_id < (phy_params.cflist_channel_cnt + phy_params.default_channel_cnt)) { 00724 // Channel frequency 00725 new_channel.frequency = (uint32_t) cf_list->payload[i]; 00726 new_channel.frequency |= ((uint32_t) cf_list->payload[i + 1] << 8); 00727 new_channel.frequency |= ((uint32_t) cf_list->payload[i + 2] << 16); 00728 new_channel.frequency *= 100; 00729 00730 // Initialize alternative frequency to 0 00731 new_channel.rx1_frequency = 0; 00732 } else { 00733 new_channel.frequency = 0; 00734 new_channel.dr_range .value = 0; 00735 new_channel.rx1_frequency = 0; 00736 } 00737 00738 if (new_channel.frequency != 0) { 00739 // Try to add channel 00740 add_channel(&new_channel, channel_id); 00741 } else { 00742 remove_channel(channel_id); 00743 } 00744 } 00745 } 00746 00747 00748 bool LoRaPHY::get_next_ADR(bool restore_channel_mask, int8_t& dr_out, 00749 int8_t& tx_power_out, uint32_t& adr_ack_cnt) 00750 { 00751 bool set_adr_ack_bit = false; 00752 00753 get_phy_params_t get_phy; 00754 phy_param_t phy_param; 00755 uint16_t ack_limit_plus_delay = phy_params.adr_ack_limit + phy_params.adr_ack_delay; 00756 00757 if (dr_out == phy_params.min_tx_datarate) { 00758 adr_ack_cnt = 0; 00759 return set_adr_ack_bit; 00760 } 00761 00762 if (adr_ack_cnt < phy_params.adr_ack_limit) { 00763 return set_adr_ack_bit; 00764 } 00765 00766 // ADR ack counter is larger than ADR-ACK-LIMIT 00767 set_adr_ack_bit = true; 00768 tx_power_out = phy_params.max_tx_power; 00769 00770 if (adr_ack_cnt >= ack_limit_plus_delay) { 00771 if ((adr_ack_cnt % phy_params.adr_ack_delay) == 1) { 00772 // Decrease the datarate 00773 get_phy.attribute = PHY_NEXT_LOWER_TX_DR ; 00774 get_phy.datarate = dr_out; 00775 phy_param = get_phy_params(&get_phy); 00776 dr_out = phy_param.value ; 00777 00778 if (dr_out == phy_params.min_tx_datarate) { 00779 // We must set adrAckReq to false as soon as we reach the lowest datarate 00780 set_adr_ack_bit = false; 00781 if (restore_channel_mask) { 00782 // Re-enable default channels 00783 restore_default_channels(); 00784 } 00785 } 00786 } 00787 } 00788 00789 return set_adr_ack_bit; 00790 } 00791 00792 void LoRaPHY::compute_rx_win_params(int8_t datarate, uint8_t min_rx_symbols, 00793 uint32_t rx_error, 00794 rx_config_params_t *rx_conf_params) 00795 { 00796 double t_symbol = 0.0; 00797 00798 // Get the datarate, perform a boundary check 00799 rx_conf_params->datarate = MIN( datarate, phy_params.max_rx_datarate); 00800 00801 rx_conf_params->bandwidth = get_bandwidth(rx_conf_params->datarate ); 00802 00803 if (phy_params.fsk_supported && rx_conf_params->datarate == phy_params.max_rx_datarate) { 00804 // FSK 00805 t_symbol = compute_symb_timeout_fsk(((uint8_t *)phy_params.datarates.table)[rx_conf_params->datarate ]); 00806 } else { 00807 // LoRa 00808 t_symbol = compute_symb_timeout_lora(((uint8_t *)phy_params.datarates.table)[rx_conf_params->datarate ], 00809 ((uint32_t *)phy_params.bandwidths.table)[rx_conf_params->datarate ]); 00810 } 00811 00812 get_rx_window_params(t_symbol, min_rx_symbols, rx_error, RADIO_WAKEUP_TIME, 00813 &rx_conf_params->window_timeout , &rx_conf_params->window_offset ); 00814 } 00815 00816 bool LoRaPHY::rx_config(rx_config_params_t * rx_conf, int8_t* datarate) 00817 { 00818 radio_modems_t modem; 00819 uint8_t dr = rx_conf->datarate ; 00820 uint8_t max_payload = 0; 00821 uint8_t phy_dr = 0; 00822 uint32_t frequency = rx_conf->frequency ; 00823 00824 _radio->lock(); 00825 00826 if (_radio->get_status() != RF_IDLE) { 00827 _radio->unlock(); 00828 return false; 00829 } 00830 00831 _radio->unlock(); 00832 00833 if (rx_conf->rx_slot == RX_SLOT_WIN_1 ) { 00834 // Apply window 1 frequency 00835 frequency = phy_params.channels.channel_list[rx_conf->channel ].frequency; 00836 // Apply the alternative RX 1 window frequency, if it is available 00837 if (phy_params.channels.channel_list[rx_conf->channel ].rx1_frequency != 0) { 00838 frequency = phy_params.channels.channel_list[rx_conf->channel ].rx1_frequency; 00839 } 00840 } 00841 00842 // Read the physical datarate from the datarates table 00843 uint8_t *datarate_table = (uint8_t *) phy_params.datarates.table; 00844 uint8_t *payload_table = (uint8_t *) phy_params.payloads.table; 00845 uint8_t *payload_with_repeater_table = (uint8_t *) phy_params.payloads_with_repeater.table; 00846 00847 phy_dr = datarate_table[dr]; 00848 00849 _radio->lock(); 00850 00851 _radio->set_channel(frequency); 00852 00853 // Radio configuration 00854 if (dr == DR_7 && phy_params.fsk_supported) { 00855 modem = MODEM_FSK; 00856 _radio->set_rx_config(modem, 50000, phy_dr * 1000, 0, 83333, 5, 00857 rx_conf->window_timeout , false, 0, true, 0, 0, 00858 false, rx_conf->is_rx_continuous ); 00859 } else { 00860 modem = MODEM_LORA; 00861 _radio->set_rx_config(modem, rx_conf->bandwidth , phy_dr, 1, 0, 8, 00862 rx_conf->window_timeout , false, 0, false, 0, 0, 00863 true, rx_conf->is_rx_continuous ); 00864 } 00865 00866 if (rx_conf->is_repeater_supported ) { 00867 max_payload = payload_with_repeater_table[dr]; 00868 } else { 00869 max_payload = payload_table[dr]; 00870 } 00871 00872 _radio->set_max_payload_length(modem, max_payload + LORA_MAC_FRMPAYLOAD_OVERHEAD); 00873 00874 _radio->unlock(); 00875 00876 *datarate = phy_dr; 00877 00878 return true; 00879 } 00880 00881 bool LoRaPHY::tx_config(tx_config_params_t* tx_conf, int8_t* tx_power, 00882 lorawan_time_t* tx_toa) 00883 { 00884 radio_modems_t modem; 00885 int8_t phy_dr = ((uint8_t *)phy_params.datarates.table)[tx_conf->datarate]; 00886 channel_params_t *list = phy_params.channels.channel_list; 00887 uint8_t band_idx = list[tx_conf->channel].band ; 00888 band_t *bands = (band_t *)phy_params.bands.table; 00889 00890 // limit TX power if set to too much 00891 if (tx_conf->tx_power > bands[band_idx].max_tx_pwr ) { 00892 tx_conf->tx_power = bands[band_idx].max_tx_pwr ; 00893 } 00894 00895 uint8_t bandwidth = get_bandwidth(tx_conf->datarate); 00896 int8_t phy_tx_power = 0; 00897 00898 // Calculate physical TX power 00899 phy_tx_power = compute_tx_power(tx_conf->tx_power, tx_conf->max_eirp, 00900 tx_conf->antenna_gain); 00901 00902 _radio->lock(); 00903 00904 // Setup the radio frequency 00905 _radio->set_channel(list[tx_conf->channel].frequency ); 00906 00907 if( tx_conf->datarate == phy_params.max_tx_datarate ) { 00908 // High Speed FSK channel 00909 modem = MODEM_FSK; 00910 _radio->set_tx_config(modem, phy_tx_power, 25000, bandwidth, 00911 phy_dr * 1000, 0, 5, false, true, 0, 0, false, 00912 3000); 00913 } else { 00914 modem = MODEM_LORA; 00915 _radio->set_tx_config(modem, phy_tx_power, 0, bandwidth, phy_dr, 1, 8, 00916 false, true, 0, 0, false, 3000 ); 00917 } 00918 00919 // Setup maximum payload lenght of the radio driver 00920 _radio->set_max_payload_length( modem, tx_conf->pkt_len); 00921 // Get the time-on-air of the next tx frame 00922 *tx_toa = _radio->time_on_air(modem, tx_conf->pkt_len); 00923 00924 _radio->unlock(); 00925 00926 *tx_power = tx_conf->tx_power; 00927 00928 return true; 00929 } 00930 00931 uint8_t LoRaPHY::link_ADR_request(adr_req_params_t* link_adr_req, 00932 int8_t* dr_out, int8_t* tx_power_out, 00933 uint8_t* nb_rep_out, uint8_t* nb_bytes_processed) 00934 { 00935 uint8_t status = 0x07; 00936 link_adr_params_t adr_settings; 00937 uint8_t next_index = 0; 00938 uint8_t bytes_processed = 0; 00939 00940 // rather than dynamically allocating memory, we choose to set 00941 // a channel mask list size of unity here as we know that all 00942 // the PHY layer implementations who have more than 16 channels, i.e., 00943 // have channel mask list size more than unity, override this method. 00944 uint16_t temp_channel_mask[1] = {0}; 00945 00946 verify_adr_params_t verify_params; 00947 00948 while (bytes_processed < link_adr_req->payload_size) { 00949 // Get ADR request parameters 00950 next_index = parse_link_ADR_req(&(link_adr_req->payload [bytes_processed]), 00951 &adr_settings); 00952 00953 if (next_index == 0) { 00954 break; // break loop, since no more request has been found 00955 } 00956 00957 // Update bytes processed 00958 bytes_processed += next_index; 00959 00960 // Revert status, as we only check the last ADR request for the channel mask KO 00961 status = 0x07; 00962 00963 // Setup temporary channels mask 00964 temp_channel_mask[0] = adr_settings.channel_mask; 00965 00966 // Verify channels mask 00967 if (adr_settings.ch_mask_ctrl == 0 && temp_channel_mask[0] == 0) { 00968 status &= 0xFE; // Channel mask KO 00969 } 00970 00971 // channel mask applies to first 16 channels 00972 if (adr_settings.ch_mask_ctrl == 0 || 00973 adr_settings.ch_mask_ctrl == 6) { 00974 00975 for (uint8_t i = 0; i < phy_params.max_channel_cnt; i++) { 00976 00977 // turn on all channels if channel mask control is 6 00978 if (adr_settings.ch_mask_ctrl == 6) { 00979 if (phy_params.channels.channel_list[i].frequency != 0) { 00980 mask_bit_set(temp_channel_mask, i); 00981 } 00982 00983 continue; 00984 } 00985 00986 // if channel mask control is 0, we test the bits and 00987 // frequencies and change the status if we find a discrepancy 00988 if ((mask_bit_test(temp_channel_mask, i)) && 00989 (phy_params.channels.channel_list[i].frequency == 0)) { 00990 // Trying to enable an undefined channel 00991 status &= 0xFE; // Channel mask KO 00992 } 00993 } 00994 } else { 00995 // Channel mask control applies to RFUs 00996 status &= 0xFE; // Channel mask KO 00997 } 00998 } 00999 01000 verify_params.status = status; 01001 01002 verify_params.adr_enabled = link_adr_req->adr_enabled ; 01003 verify_params.current_datarate = link_adr_req->current_datarate ; 01004 verify_params.current_tx_power = link_adr_req->current_tx_power ; 01005 verify_params.current_nb_rep = link_adr_req->current_nb_rep ; 01006 01007 verify_params.datarate = adr_settings.datarate; 01008 verify_params.tx_power = adr_settings.tx_power; 01009 verify_params.nb_rep = adr_settings.nb_rep; 01010 01011 01012 verify_params.channel_mask = temp_channel_mask; 01013 01014 // Verify the parameters and update, if necessary 01015 status = verify_link_ADR_req(&verify_params, &adr_settings.datarate, 01016 &adr_settings.tx_power, &adr_settings.nb_rep); 01017 01018 // Update channelsMask if everything is correct 01019 if (status == 0x07) { 01020 // Set the channels mask to a default value 01021 memset(phy_params.channels.mask, 0, 01022 sizeof(uint16_t)*phy_params.channels.mask_size); 01023 01024 // Update the channels mask 01025 copy_channel_mask(phy_params.channels.mask, temp_channel_mask, 01026 phy_params.channels.mask_size); 01027 } 01028 01029 // Update status variables 01030 *dr_out = adr_settings.datarate; 01031 *tx_power_out = adr_settings.tx_power; 01032 *nb_rep_out = adr_settings.nb_rep; 01033 *nb_bytes_processed = bytes_processed; 01034 01035 return status; 01036 } 01037 01038 uint8_t LoRaPHY::accept_rx_param_setup_req(rx_param_setup_req_t* params) 01039 { 01040 uint8_t status = 0x07; 01041 01042 // Verify radio frequency 01043 if (_radio->check_rf_frequency(params->frequency) == false) { 01044 status &= 0xFE; // Channel frequency KO 01045 } 01046 01047 // Verify datarate 01048 if (val_in_range(params->datarate, phy_params.min_rx_datarate, 01049 phy_params.max_rx_datarate) == 0) { 01050 status &= 0xFD; // Datarate KO 01051 } 01052 01053 // Verify datarate offset 01054 if (val_in_range(params->dr_offset, phy_params.min_rx1_dr_offset, 01055 phy_params.max_rx1_dr_offset) == 0) { 01056 status &= 0xFB; // Rx1DrOffset range KO 01057 } 01058 01059 return status; 01060 } 01061 01062 bool LoRaPHY::accept_tx_param_setup_req(tx_param_setup_req_t *params) 01063 { 01064 if (phy_params.accept_tx_param_setup_req) { 01065 phy_params.ul_dwell_time_setting = params->ul_dwell_time; 01066 phy_params.dl_dwell_time_setting = params->dl_dwell_time; 01067 } 01068 01069 return phy_params.accept_tx_param_setup_req; 01070 } 01071 01072 bool LoRaPHY::verify_frequency(uint32_t freq) 01073 { 01074 band_t *bands_table = (band_t *)phy_params.bands.table; 01075 01076 // check all sub bands (if there are sub-bands) to check if the given 01077 // frequency falls into any of the frequency ranges 01078 01079 for (uint8_t i=0; i<phy_params.bands.size; i++) { 01080 if (freq <= bands_table[i].higher_band_freq 01081 && freq >= bands_table[i].lower_band_freq) { 01082 return true; 01083 } 01084 } 01085 01086 return false; 01087 } 01088 01089 uint8_t LoRaPHY::dl_channel_request(dl_channel_req_params_t* params) 01090 { 01091 if (!phy_params.dl_channel_req_supported) { 01092 return 0; 01093 } 01094 01095 uint8_t status = 0x03; 01096 01097 // Verify if the frequency is supported 01098 if (verify_frequency(params->rx1_frequency) == false) { 01099 status &= 0xFE; 01100 } 01101 01102 // Verify if an uplink frequency exists 01103 if (phy_params.channels.channel_list[params->channel_id].frequency == 0) { 01104 status &= 0xFD; 01105 } 01106 01107 // Apply Rx1 frequency, if the status is OK 01108 if (status == 0x03) { 01109 phy_params.channels.channel_list[params->channel_id].rx1_frequency = params->rx1_frequency; 01110 } 01111 01112 return status; 01113 } 01114 01115 /** 01116 * Alternate datarate algorithm for join requests. 01117 * - We check from the PHY and take note of total 01118 * number of data rates available upto the default data rate for 01119 * default channels. 01120 * 01121 * - Application sets a total number of re-trials for a Join Request, i.e., 01122 * MBED_CONF_LORA_NB_TRIALS. So MAC layer will send us a counter 01123 * nb_trials < MBED_CONF_LORA_NB_TRIALS which is the current number of trial. 01124 * 01125 * - We roll over total available datarates and pick one according to the 01126 * number of trial sequentially. 01127 * 01128 * - We always start from the Default Data rate and and set the next lower 01129 * data rate for every iteration. 01130 * 01131 * - MAC layer will stop when maximum number of re-trials, i.e., 01132 * MBED_CONF_LORA_NB_TRIALS is achieved. 01133 * 01134 * So essentially MBED_CONF_LORA_NB_TRIALS should be a multiple of range of 01135 * data rates available. For example, in EU868 band, default max. data rate is 01136 * DR_5 and min. data rate is DR_0, so total data rates available are 6. 01137 * 01138 * Hence MBED_CONF_LORA_NB_TRIALS should be a multiple of 6. Setting, 01139 * MBED_CONF_LORA_NB_TRIALS = 6 would mean that every data rate will be tried 01140 * exactly once starting from the largest and finishing at the smallest. 01141 * 01142 * PHY layers which do not have datarates scheme similar to EU band will ofcourse 01143 * override this method. 01144 */ 01145 int8_t LoRaPHY::get_alternate_DR(uint8_t nb_trials) 01146 { 01147 int8_t datarate = 0; 01148 uint8_t total_nb_datrates = (phy_params.default_max_datarate - phy_params.min_tx_datarate) + 1; 01149 01150 uint8_t res = nb_trials % total_nb_datrates; 01151 01152 if (res == 0) { 01153 datarate = phy_params.min_tx_datarate; 01154 } else if (res == 1) { 01155 datarate = phy_params.default_max_datarate; 01156 } else { 01157 datarate = (phy_params.default_max_datarate - res) + 1; 01158 } 01159 01160 return datarate; 01161 } 01162 01163 void LoRaPHY::calculate_backoff(backoff_params_t * calc_backoff) 01164 { 01165 band_t *band_table = (band_t *) phy_params.bands.table; 01166 channel_params_t *channel_list = phy_params.channels.channel_list; 01167 01168 uint8_t band_idx = channel_list[calc_backoff->channel].band ; 01169 uint16_t duty_cycle = band_table[band_idx].duty_cycle ; 01170 uint16_t join_duty_cycle = 0; 01171 01172 // Reset time-off to initial value. 01173 band_table[band_idx].off_time = 0; 01174 01175 if (calc_backoff->joined == false) { 01176 // Get the join duty cycle 01177 if (calc_backoff->elapsed_time < 3600000) { 01178 join_duty_cycle = BACKOFF_DC_1_HOUR; 01179 } else if (calc_backoff->elapsed_time < (3600000 + 36000000)) { 01180 join_duty_cycle = BACKOFF_DC_10_HOURS; 01181 } else { 01182 join_duty_cycle = BACKOFF_DC_24_HOURS; 01183 } 01184 01185 // Apply the most restricting duty cycle 01186 duty_cycle = MAX(duty_cycle, join_duty_cycle); 01187 } 01188 01189 // No back-off if the last frame was not a join request and when the 01190 // duty cycle is not enabled 01191 if (calc_backoff->dc_enabled == false && 01192 calc_backoff->last_tx_was_join_req == false) { 01193 band_table[band_idx].off_time = 0; 01194 } else { 01195 // Apply band time-off. 01196 band_table[band_idx].off_time = calc_backoff->tx_toa * duty_cycle - calc_backoff->tx_toa; 01197 } 01198 } 01199 01200 bool LoRaPHY::set_next_channel(channel_selection_params_t* params, 01201 uint8_t* channel, lorawan_time_t* time, 01202 lorawan_time_t* aggregate_timeoff) 01203 { 01204 uint8_t channel_count = 0; 01205 uint8_t delay_tx = 0; 01206 01207 // Note here that the PHY layer implementations which have more than 01208 // 16 channels at their disposal, override this function. That's why 01209 // it is safe to assume that we are dealing with a block of 16 channels 01210 // i.e., EU like implementations. So rather than dynamically allocating 01211 // memory we chose to use a magic number of 16 01212 uint8_t enabled_channels[16]; 01213 01214 memset(enabled_channels, 0xFF, sizeof(uint8_t)*16); 01215 01216 lorawan_time_t next_tx_delay = 0; 01217 band_t *band_table = (band_t *) phy_params.bands.table; 01218 01219 if (num_active_channels(phy_params.channels.mask, 0, 01220 phy_params.channels.mask_size) == 0) { 01221 01222 // Reactivate default channels 01223 copy_channel_mask(phy_params.channels.mask, 01224 phy_params.channels.default_mask, 01225 phy_params.channels.mask_size); 01226 } 01227 01228 if (params->aggregate_timeoff 01229 <= _lora_time.get_elapsed_time(params->last_aggregate_tx_time)) { 01230 // Reset Aggregated time off 01231 *aggregate_timeoff = 0; 01232 01233 // Update bands Time OFF 01234 next_tx_delay = update_band_timeoff(params->joined, 01235 params->dc_enabled, 01236 band_table, phy_params.bands.size); 01237 01238 // Search how many channels are enabled 01239 channel_count = enabled_channel_count(params->joined, params->current_datarate, 01240 phy_params.channels.mask, 01241 enabled_channels, &delay_tx); 01242 } else { 01243 delay_tx++; 01244 next_tx_delay = params->aggregate_timeoff 01245 - _lora_time.get_elapsed_time(params->last_aggregate_tx_time); 01246 } 01247 01248 if (channel_count > 0) { 01249 // We found a valid channel 01250 *channel = enabled_channels[get_random(0, channel_count - 1)]; 01251 *time = 0; 01252 return true; 01253 } 01254 01255 if (delay_tx > 0) { 01256 // Delay transmission due to AggregatedTimeOff or to a band time off 01257 *time = next_tx_delay; 01258 return true; 01259 } 01260 01261 // Datarate not supported by any channel, restore defaults 01262 copy_channel_mask(phy_params.channels.mask, 01263 phy_params.channels.default_mask, 01264 phy_params.channels.mask_size); 01265 *time = 0; 01266 return false; 01267 } 01268 01269 lorawan_status_t LoRaPHY::add_channel(channel_params_t * new_channel, uint8_t id) 01270 { 01271 bool dr_invalid = false; 01272 bool freq_invalid = false; 01273 01274 if (!phy_params.custom_channelplans_supported 01275 || id >= phy_params.max_channel_cnt) { 01276 01277 return LORAWAN_STATUS_PARAMETER_INVALID; 01278 } 01279 01280 // Validate the datarate range 01281 if (val_in_range(new_channel->dr_range .fields.min , 01282 phy_params.min_tx_datarate, 01283 phy_params.max_tx_datarate) == 0) { 01284 dr_invalid = true; 01285 } 01286 01287 if (val_in_range(new_channel->dr_range .fields.max , phy_params.min_tx_datarate, 01288 phy_params.max_tx_datarate) == 0) { 01289 dr_invalid = true; 01290 } 01291 01292 if (new_channel->dr_range .fields.min > new_channel->dr_range .fields.max ) { 01293 dr_invalid = true; 01294 } 01295 01296 // Default channels don't accept all values 01297 if (id < phy_params.default_channel_cnt) { 01298 // Validate the datarate range for min: must be DR_0 01299 if (new_channel->dr_range .fields.min > phy_params.min_tx_datarate) { 01300 dr_invalid = true; 01301 } 01302 01303 // Validate the datarate range for max: must be DR_5 <= Max <= TX_MAX_DATARATE 01304 if (val_in_range(new_channel->dr_range .fields.max , 01305 phy_params.default_max_datarate, 01306 phy_params.max_tx_datarate) == 0) { 01307 dr_invalid = true; 01308 } 01309 01310 // We are not allowed to change the frequency 01311 if (new_channel->frequency != phy_params.channels.channel_list[id].frequency) { 01312 freq_invalid = true; 01313 } 01314 } 01315 01316 // Check frequency 01317 if (!freq_invalid) { 01318 if (verify_frequency(new_channel->frequency ) == false) { 01319 freq_invalid = true; 01320 } 01321 } 01322 01323 // Check status 01324 if (dr_invalid && freq_invalid) { 01325 return LORAWAN_STATUS_FREQ_AND_DR_INVALID; 01326 } 01327 01328 if (dr_invalid) { 01329 return LORAWAN_STATUS_DATARATE_INVALID; 01330 } 01331 01332 if (freq_invalid) { 01333 return LORAWAN_STATUS_FREQUENCY_INVALID; 01334 } 01335 01336 memcpy(&(phy_params.channels.channel_list[id]), new_channel, sizeof(channel_params_t )); 01337 01338 phy_params.channels.channel_list[id].band = new_channel->band ; 01339 01340 mask_bit_set(phy_params.channels.mask, id); 01341 01342 return LORAWAN_STATUS_OK; 01343 } 01344 01345 bool LoRaPHY::remove_channel(uint8_t channel_id) 01346 { 01347 // upper layers are checking if the custom channel planning is supported or 01348 // not. So we don't need to worry about that 01349 if (mask_bit_test(phy_params.channels.default_mask, channel_id)) { 01350 return false; 01351 } 01352 01353 01354 // Remove the channel from the list of channels 01355 const channel_params_t empty_channel = { 0, 0, { 0 }, 0 }; 01356 phy_params.channels.channel_list[channel_id] = empty_channel; 01357 01358 return disable_channel(phy_params.channels.mask, channel_id, 01359 phy_params.max_channel_cnt); 01360 } 01361 01362 void LoRaPHY::set_tx_cont_mode(cw_mode_params_t * params, uint32_t given_frequency) 01363 { 01364 band_t *bands_table = (band_t *) phy_params.bands.table; 01365 channel_params_t *channels = phy_params.channels.channel_list; 01366 01367 if (params->tx_power > bands_table[channels[params->channel ].band ].max_tx_pwr ) { 01368 params->tx_power = bands_table[channels[params->channel ].band].max_tx_pwr ; 01369 } 01370 01371 int8_t phy_tx_power = 0; 01372 uint32_t frequency = 0; 01373 01374 if (given_frequency == 0) { 01375 frequency = channels[params->channel ].frequency; 01376 } else { 01377 frequency = given_frequency; 01378 } 01379 01380 // Calculate physical TX power 01381 if (params->max_eirp > 0 && params->antenna_gain > 0) { 01382 phy_tx_power = compute_tx_power(params->tx_power , params->max_eirp , 01383 params->antenna_gain ); 01384 } else { 01385 phy_tx_power = params->tx_power ; 01386 } 01387 01388 _radio->lock(); 01389 _radio->set_tx_continuous_wave(frequency, phy_tx_power, params->timeout ); 01390 _radio->unlock(); 01391 } 01392 01393 uint8_t LoRaPHY::apply_DR_offset(int8_t dr, int8_t dr_offset) 01394 { 01395 int8_t datarate = dr - dr_offset; 01396 01397 if (datarate < 0) { 01398 datarate = phy_params.min_tx_datarate; 01399 } 01400 01401 return datarate; 01402 } 01403 01404
Generated on Tue Jul 12 2022 13:30:22 by
