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