Denislam Valeev / Mbed OS Nucleo_rtos_basic
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers LoRaPHY.cpp Source File

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