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