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

« Back to documentation index

Show/hide line numbers LoRaMacChannelPlan.cpp Source File

LoRaMacChannelPlan.cpp

00001 /**
00002  / _____)             _              | |
00003 ( (____  _____ ____ _| |_ _____  ____| |__
00004  \____ \| ___ |    (_   _) ___ |/ ___)  _ \
00005  _____) ) ____| | | || |_| ____( (___| | | |
00006 (______/|_____)_|_|_| \__)_____)\____)_| |_|
00007     (C)2013 Semtech
00008  ___ _____ _   ___ _  _____ ___  ___  ___ ___
00009 / __|_   _/_\ / __| |/ / __/ _ \| _ \/ __| __|
00010 \__ \ | |/ _ \ (__| ' <| _| (_) |   / (__| _|
00011 |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
00012 embedded.connectivity.solutions===============
00013 
00014 Description: LoRaWAN stack layer that controls both MAC and PHY underneath
00015 
00016 License: Revised BSD License, see LICENSE.TXT file include in the project
00017 
00018 Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )
00019 
00020 
00021 Copyright (c) 2017, Arm Limited and affiliates.
00022 
00023 SPDX-License-Identifier: BSD-3-Clause
00024 */
00025 
00026 #include "lorastack/mac/LoRaMacChannelPlan.h"
00027 
00028 LoRaMacChannelPlan::LoRaMacChannelPlan() : _lora_phy(NULL), _mib(NULL)
00029 {
00030 }
00031 
00032 LoRaMacChannelPlan::~LoRaMacChannelPlan()
00033 {
00034 }
00035 
00036 void LoRaMacChannelPlan::activate_channelplan_subsystem(LoRaPHY *phy, LoRaMacMib *mib)
00037 {
00038     _lora_phy = phy;
00039     _mib = mib;
00040 }
00041 
00042 lorawan_status_t LoRaMacChannelPlan::set_plan(const lorawan_channelplan_t& plan)
00043 {
00044     channel_params_t  mac_layer_ch_params;
00045     lorawan_status_t status;
00046 
00047     get_phy_params_t get_phy;
00048     phy_param_t  phy_param;
00049     uint8_t max_num_channels;
00050 
00051     // Check if the PHY layer supports custom channel plans or not.
00052     get_phy.attribute = PHY_CUSTOM_CHANNEL_PLAN_SUPPORT ;
00053     phy_param = _lora_phy->get_phy_params(&get_phy);
00054 
00055     if (!phy_param.value ) {
00056         return LORAWAN_STATUS_SERVICE_UNKNOWN;
00057     }
00058 
00059     // Check first how many channels the selected PHY layer supports
00060     get_phy.attribute = PHY_MAX_NB_CHANNELS ;
00061     phy_param = _lora_phy->get_phy_params(&get_phy);
00062     max_num_channels = (uint8_t) phy_param.value ;
00063 
00064     // check if user is setting more channels than supported
00065     if (plan.nb_channels > max_num_channels) {
00066         return LORAWAN_STATUS_PARAMETER_INVALID;
00067     }
00068 
00069     for (uint8_t i = 0; i < plan.nb_channels; i++) {
00070 
00071         mac_layer_ch_params.band  = plan.channels[i].ch_param.band;
00072 
00073         mac_layer_ch_params.dr_range .fields.max  = plan.channels[i].ch_param.dr_range.fields.max;
00074         mac_layer_ch_params.dr_range .fields.min  = plan.channels[i].ch_param.dr_range.fields.min;
00075         mac_layer_ch_params.dr_range .value  = plan.channels[i].ch_param.dr_range.value;
00076         mac_layer_ch_params.frequency  = plan.channels[i].ch_param.frequency;
00077         mac_layer_ch_params.rx1_frequency  = plan.channels[i].ch_param.rx1_frequency;
00078 
00079         status = _lora_phy->add_channel(&mac_layer_ch_params, plan.channels[i].id);
00080 
00081         if (status != LORAWAN_STATUS_OK) {
00082             return status;
00083         }
00084     }
00085 
00086     return LORAWAN_STATUS_OK;
00087 }
00088 
00089 lorawan_status_t LoRaMacChannelPlan::get_plan(lorawan_channelplan_t& plan,
00090                                              loramac_protocol_params *params)
00091 {
00092     if (params == NULL) {
00093         return LORAWAN_STATUS_PARAMETER_INVALID;
00094     }
00095 
00096     loramac_mib_req_confirm_t  mib_confirm;
00097     lorawan_status_t status;
00098 
00099     get_phy_params_t get_phy;
00100     phy_param_t  phy_param;
00101     uint8_t max_num_channels;
00102     uint16_t *channel_mask;
00103     uint8_t count = 0;
00104 
00105     // Check if the PHY layer supports custom channel plans or not.
00106     get_phy.attribute = PHY_CUSTOM_CHANNEL_PLAN_SUPPORT ;
00107     phy_param = _lora_phy->get_phy_params(&get_phy);
00108 
00109     if (!phy_param.value ) {
00110         return LORAWAN_STATUS_SERVICE_UNKNOWN;
00111     }
00112 
00113     // Check first how many channels the selected PHY layer supports
00114     get_phy.attribute = PHY_MAX_NB_CHANNELS ;
00115     phy_param = _lora_phy->get_phy_params(&get_phy);
00116     max_num_channels = (uint8_t) phy_param.value ;
00117 
00118     // Now check the Default channel mask
00119     get_phy.attribute = PHY_CHANNEL_MASK ;
00120     phy_param = _lora_phy->get_phy_params(&get_phy);
00121     channel_mask = phy_param.channel_mask ;
00122 
00123     // Request Mib to get channels
00124     memset(&mib_confirm, 0, sizeof(mib_confirm));
00125     mib_confirm.type  = MIB_CHANNELS ;
00126 
00127     status = _mib->get_request(&mib_confirm, params);
00128 
00129     if (status != LORAWAN_STATUS_OK) {
00130         return status;
00131     }
00132 
00133     for (uint8_t i = 0; i < max_num_channels; i++) {
00134         // skip the channels which are not enabled
00135         if (_lora_phy->mask_bit_test(channel_mask, i) == 0) {
00136             continue;
00137         }
00138 
00139         // otherwise add them to the channel_plan struct
00140         plan.channels[count].id = i;
00141         plan.channels[count].ch_param.frequency = mib_confirm.param .channel_list [i].frequency ;
00142         plan.channels[count].ch_param.dr_range.value = mib_confirm.param .channel_list [i].dr_range .value ;
00143         plan.channels[count].ch_param.dr_range.fields.min = mib_confirm.param .channel_list [i].dr_range .fields.min ;
00144         plan.channels[count].ch_param.dr_range.fields.max = mib_confirm.param .channel_list [i].dr_range .fields.max ;
00145         plan.channels[count].ch_param.band = mib_confirm.param .channel_list [i].band ;
00146         plan.channels[count].ch_param.rx1_frequency = mib_confirm.param .channel_list [i].rx1_frequency ;
00147         count++;
00148     }
00149 
00150     plan.nb_channels = count;
00151 
00152     return LORAWAN_STATUS_OK;
00153 }
00154 
00155 lorawan_status_t LoRaMacChannelPlan::remove_plan()
00156 {
00157     lorawan_status_t status = LORAWAN_STATUS_OK;
00158 
00159     get_phy_params_t get_phy;
00160     phy_param_t  phy_param;
00161     uint8_t max_num_channels;
00162     uint16_t *channel_mask;
00163     uint16_t *default_channel_mask;
00164 
00165     // Check if the PHY layer supports custom channel plans or not.
00166     get_phy.attribute = PHY_CUSTOM_CHANNEL_PLAN_SUPPORT ;
00167     phy_param = _lora_phy->get_phy_params(&get_phy);
00168 
00169     if (!phy_param.value ) {
00170         return LORAWAN_STATUS_SERVICE_UNKNOWN;
00171     }
00172 
00173     // Check first how many channels the selected PHY layer supports
00174     get_phy.attribute = PHY_MAX_NB_CHANNELS ;
00175     phy_param = _lora_phy->get_phy_params(&get_phy);
00176     max_num_channels = (uint8_t) phy_param.value ;
00177 
00178     // Now check the channel mask for enabled channels
00179     get_phy.attribute = PHY_CHANNEL_MASK ;
00180     phy_param = _lora_phy->get_phy_params(&get_phy);
00181     channel_mask = phy_param.channel_mask ;
00182 
00183     // Now check the channel mask for default channels
00184     get_phy.attribute = PHY_DEFAULT_CHANNEL_MASK ;
00185     phy_param = _lora_phy->get_phy_params(&get_phy);
00186     default_channel_mask = phy_param.channel_mask ;
00187 
00188     for (uint8_t i = 0; i < max_num_channels; i++) {
00189         // skip any default channels
00190         if (_lora_phy->mask_bit_test(default_channel_mask, i) != 0) {
00191             continue;
00192         }
00193 
00194         // skip any channels which are not currently enabled
00195         if (_lora_phy->mask_bit_test(channel_mask, i) == 0) {
00196             continue;
00197         }
00198 
00199         status = remove_single_channel(i);
00200 
00201         if (status != LORAWAN_STATUS_OK) {
00202             return status;
00203         }
00204     }
00205 
00206     return status;
00207 }
00208 
00209 lorawan_status_t LoRaMacChannelPlan::remove_single_channel(uint8_t channel_id)
00210 {
00211     get_phy_params_t get_phy;
00212     phy_param_t  phy_param;
00213     uint8_t max_num_channels;
00214 
00215     // Check if the PHY layer supports custom channel plans or not.
00216     get_phy.attribute = PHY_CUSTOM_CHANNEL_PLAN_SUPPORT ;
00217     phy_param = _lora_phy->get_phy_params(&get_phy);
00218 
00219     if (!phy_param.value ) {
00220         return LORAWAN_STATUS_SERVICE_UNKNOWN;
00221     }
00222 
00223     // Check first how many channels the selected PHY layer supports
00224     get_phy.attribute = PHY_MAX_NB_CHANNELS ;
00225     phy_param = _lora_phy->get_phy_params(&get_phy);
00226     max_num_channels = (uint8_t) phy_param.value ;
00227 
00228     // According to specification channel IDs start from 0 and last valid
00229     // channel ID is N-1 where N=MAX_NUM_CHANNELS.
00230     // So any ID which is larger or equal to the Max number of channels is invalid
00231     if (channel_id >= max_num_channels) {
00232         return LORAWAN_STATUS_PARAMETER_INVALID;
00233     }
00234 
00235     if (_lora_phy->remove_channel(channel_id) == false) {
00236         return LORAWAN_STATUS_PARAMETER_INVALID;
00237     }
00238 
00239     _lora_phy->put_radio_to_sleep();
00240 
00241     return LORAWAN_STATUS_OK;
00242 }
00243