From 6ea541c0540222b7282bea53a609a7efd1e70135 Mon Sep 17 00:00:00 2001 From: Hasnain Virk Date: Thu, 11 Jan 2018 13:55:08 +0200 Subject: [PATCH] [IOTCELL-286] Adding Channel Plan subsystem Channel planning was distributed over LoRaWANStack and LoRaMac previously. We now centralize it by allocating the service to its own class. Thus making the workflow consistent, i.e., Request for channel plan = Application->Interface->stack->Mac->ChannelPlan Major change apart from adding the channel plan subsystem are the API changes in LoRaMac class. --- features/lorawan/LoRaWANInterface.h | 3 + features/lorawan/LoRaWANStack.cpp | 157 +----------- features/lorawan/lorastack/mac/LoRaMac.cpp | 38 +-- features/lorawan/lorastack/mac/LoRaMac.h | 59 ++++- .../lorastack/mac/LoRaMacChannelPlan.cpp | 236 ++++++++++++++++++ .../lorastack/mac/LoRaMacChannelPlan.h | 115 +++++++++ 6 files changed, 429 insertions(+), 179 deletions(-) create mode 100644 features/lorawan/lorastack/mac/LoRaMacChannelPlan.cpp create mode 100644 features/lorawan/lorastack/mac/LoRaMacChannelPlan.h diff --git a/features/lorawan/LoRaWANInterface.h b/features/lorawan/LoRaWANInterface.h index 49c36678eb..ba722e50dd 100644 --- a/features/lorawan/LoRaWANInterface.h +++ b/features/lorawan/LoRaWANInterface.h @@ -226,6 +226,9 @@ public: * is already active, the request is silently ignored. A negative error * code is returned if there is any problem with parameters. * + * Please note that this API can also be used to add a single channel to the + * existing channel plan. + * * There is no reverse mechanism in the 1.0.2 specification for a node to request * a particular channel. Only the network server can initiate such a request. * You need to ensure that the corresponding base station supports the channel or channels being added. diff --git a/features/lorawan/LoRaWANStack.cpp b/features/lorawan/LoRaWANStack.cpp index 106c3784aa..fac53a1141 100644 --- a/features/lorawan/LoRaWANStack.cpp +++ b/features/lorawan/LoRaWANStack.cpp @@ -471,91 +471,19 @@ lora_mac_status_t LoRaWANStack::add_channels(const lora_channelplan_t &channel_p return LORA_MAC_STATUS_NOT_INITIALIZED; } - ChannelParams_t mac_layer_ch_params; - LoRaMacStatus_t status; + LoRaMacStatus_t status = _loramac.AddChannelPlan(channel_plan); - GetPhyParams_t get_phy; - PhyParam_t phy_param; - uint8_t max_num_channels; - - // Check first how many channels the selected PHY layer supports - get_phy.Attribute = PHY_MAX_NB_CHANNELS; - phy_param = _lora_phy.get_phy_params(&get_phy); - max_num_channels = (uint8_t) phy_param.Value; - - // check if user is setting more channels than supported - if (channel_plan.nb_channels > max_num_channels) { - return LORA_MAC_STATUS_PARAMETER_INVALID; - } - - for (uint8_t i = 0; i < channel_plan.nb_channels; i++) { - mac_layer_ch_params.Band = channel_plan.channels[i].ch_param.band; - mac_layer_ch_params.DrRange.Fields.Max = channel_plan.channels[i].ch_param.dr_range.lora_mac_fields_s.max; - mac_layer_ch_params.DrRange.Fields.Min = channel_plan.channels[i].ch_param.dr_range.lora_mac_fields_s.min; - mac_layer_ch_params.DrRange.Value = channel_plan.channels[i].ch_param.dr_range.value; - mac_layer_ch_params.Frequency = channel_plan.channels[i].ch_param.frequency; - mac_layer_ch_params.Rx1Frequency =channel_plan.channels[i].ch_param.rx1_frequency; - - status = _loramac.LoRaMacChannelAdd(channel_plan.channels[i].id, mac_layer_ch_params); - - if (status != LORAMAC_STATUS_OK) { - return error_type_converter(status); - } - } - - return LORA_MAC_STATUS_OK; + return error_type_converter(status); } lora_mac_status_t LoRaWANStack::drop_channel_list() { - if (_device_current_state == DEVICE_STATE_NOT_INITIALIZED ) - { + if (_device_current_state == DEVICE_STATE_NOT_INITIALIZED) { tr_error("Stack not initialized!"); return LORA_MAC_STATUS_NOT_INITIALIZED; } - lora_mac_status_t status = LORA_MAC_STATUS_OK; - - GetPhyParams_t get_phy; - PhyParam_t phy_param; - uint8_t max_num_channels; - uint16_t *channel_masks; - uint16_t *default_channel_masks; - - // Check first how many channels the selected PHY layer supports - get_phy.Attribute = PHY_MAX_NB_CHANNELS; - phy_param = _lora_phy.get_phy_params(&get_phy); - max_num_channels = (uint8_t) phy_param.Value; - - // Now check the channel mask for enabled channels - get_phy.Attribute = PHY_CHANNELS_MASK; - phy_param = _lora_phy.get_phy_params(&get_phy); - channel_masks = phy_param.ChannelsMask; - - // Now check the channel mask for default channels - get_phy.Attribute = PHY_CHANNELS_DEFAULT_MASK; - phy_param = _lora_phy.get_phy_params(&get_phy); - default_channel_masks = phy_param.ChannelsMask; - - for (uint8_t i = 0; i < max_num_channels; i++) { - // skip any default channels - if ((default_channel_masks[0] & (1U<= max_num_channels) { - return LORA_MAC_STATUS_PARAMETER_INVALID; - } - - // Now check the Default channel mask - get_phy.Attribute = PHY_CHANNELS_DEFAULT_MASK; - phy_param = _lora_phy.get_phy_params(&get_phy); - channel_masks = phy_param.ChannelsMask; - - // check if the channel ID give belongs to a default channel - // Mostly the default channels are in the first mask if the region - // have multiple channel masks for various sub-bands. So we check the first - // mask only and return an error code if user sent a default channel id - if ((channel_masks[0] & (1U << channel_id)) != 0) { - tr_error("Not allowed to remove a Default Channel."); - return LORA_MAC_STATUS_PARAMETER_INVALID; - } - - return error_type_converter(_loramac.LoRaMacChannelRemove(channel_id)); + return error_type_converter(_loramac.RemoveSingleChannel(channel_id)); } lora_mac_status_t LoRaWANStack::get_enabled_channels(lora_channelplan_t& channel_plan) @@ -610,49 +507,7 @@ lora_mac_status_t LoRaWANStack::get_enabled_channels(lora_channelplan_t& channel return LORA_MAC_STATUS_BUSY; } - lora_mac_mib_request_confirm_t mib_params; - - GetPhyParams_t get_phy; - PhyParam_t phy_param; - uint8_t max_num_channels; - uint16_t *channel_masks; - uint8_t count = 0; - - // Check first how many channels the selected PHY layer supports - get_phy.Attribute = PHY_MAX_NB_CHANNELS; - phy_param = _lora_phy.get_phy_params(&get_phy); - max_num_channels = (uint8_t) phy_param.Value; - - // Now check the Default channel mask - get_phy.Attribute = PHY_CHANNELS_MASK; - phy_param = _lora_phy.get_phy_params(&get_phy); - channel_masks = phy_param.ChannelsMask; - - // Request Mib to get channels - memset(&mib_params, 0, sizeof(mib_params)); - mib_params.type = LORA_MIB_CHANNELS; - mib_get_request(&mib_params); - - for (uint8_t i = 0; i < max_num_channels; i++) { - // skip the channels which are not enabled - if ((channel_masks[0] & (1U << i)) == 0) { - continue; - } - - // otherwise add them to the channel_plan struct - channel_plan.channels[count].id = i; - channel_plan.channels[count].ch_param.frequency = mib_params.param.channel_list[i].frequency; - channel_plan.channels[count].ch_param.dr_range.value = mib_params.param.channel_list[i].dr_range.value; - channel_plan.channels[count].ch_param.dr_range.lora_mac_fields_s.min = mib_params.param.channel_list[i].dr_range.lora_mac_fields_s.min; - channel_plan.channels[count].ch_param.dr_range.lora_mac_fields_s.max = mib_params.param.channel_list[i].dr_range.lora_mac_fields_s.max; - channel_plan.channels[count].ch_param.band = mib_params.param.channel_list[i].band; - channel_plan.channels[count].ch_param.rx1_frequency = mib_params.param.channel_list[i].rx1_frequency; - count++; - } - - channel_plan.nb_channels = count; - - return LORA_MAC_STATUS_OK; + return error_type_converter(_loramac.GetChannelPlan(channel_plan)); } lora_mac_status_t LoRaWANStack::enable_adaptive_datarate(bool adr_enabled) diff --git a/features/lorawan/lorastack/mac/LoRaMac.cpp b/features/lorawan/lorastack/mac/LoRaMac.cpp index f1b5c28cec..03201fa84d 100644 --- a/features/lorawan/lorastack/mac/LoRaMac.cpp +++ b/features/lorawan/lorastack/mac/LoRaMac.cpp @@ -1704,6 +1704,9 @@ LoRaMacStatus_t LoRaMac::LoRaMacInitialization(LoRaMacPrimitives_t *primitives, // Activate MIB subsystem mib.activate_mib_subsystem(this, lora_phy); + // Activate channel planning subsystem + ch_plan.activate_channelplan_subsystem(lora_phy, &mib); + LoRaMacPrimitives = primitives; LoRaMacCallbacks = callbacks; @@ -1889,10 +1892,8 @@ LoRaMacStatus_t LoRaMac::LoRaMacQueryTxPossible( uint8_t size, LoRaMacTxInfo_t* return LORAMAC_STATUS_OK; } -LoRaMacStatus_t LoRaMac::LoRaMacChannelAdd( uint8_t id, ChannelParams_t params ) +LoRaMacStatus_t LoRaMac::AddChannelPlan(const lora_channelplan_t& plan) { - ChannelAddParams_t channelAdd; - // Validate if the MAC is in a correct state if( ( _params.LoRaMacState & LORAMAC_TX_RUNNING ) == LORAMAC_TX_RUNNING ) { @@ -1902,16 +1903,11 @@ LoRaMacStatus_t LoRaMac::LoRaMacChannelAdd( uint8_t id, ChannelParams_t params ) } } - channelAdd.NewChannel = ¶ms; - channelAdd.ChannelId = id; - - return lora_phy->add_channel(&channelAdd); + return ch_plan.set_plan(plan); } -LoRaMacStatus_t LoRaMac::LoRaMacChannelRemove( uint8_t id ) +LoRaMacStatus_t LoRaMac::RemoveChannelPlan() { - ChannelRemoveParams_t channelRemove; - if( ( _params.LoRaMacState & LORAMAC_TX_RUNNING ) == LORAMAC_TX_RUNNING ) { if( ( _params.LoRaMacState & LORAMAC_TX_CONFIG ) != LORAMAC_TX_CONFIG ) @@ -1920,16 +1916,26 @@ LoRaMacStatus_t LoRaMac::LoRaMacChannelRemove( uint8_t id ) } } - channelRemove.ChannelId = id; + return ch_plan.remove_plan(); - if(lora_phy->remove_channel(&channelRemove) == false) +} + +LoRaMacStatus_t LoRaMac::GetChannelPlan(lora_channelplan_t& plan) +{ + return ch_plan.get_plan(plan, &_params); +} + +LoRaMacStatus_t LoRaMac::RemoveSingleChannel(uint8_t id) +{ + if( ( _params.LoRaMacState & LORAMAC_TX_RUNNING ) == LORAMAC_TX_RUNNING ) { - return LORAMAC_STATUS_PARAMETER_INVALID; + if( ( _params.LoRaMacState & LORAMAC_TX_CONFIG ) != LORAMAC_TX_CONFIG ) + { + return LORAMAC_STATUS_BUSY; + } } - lora_phy->put_radio_to_sleep(); - - return LORAMAC_STATUS_OK; + return ch_plan.remove_single_channel(id); } LoRaMacStatus_t LoRaMac::LoRaMacMulticastChannelLink( MulticastParams_t *channelParam ) diff --git a/features/lorawan/lorastack/mac/LoRaMac.h b/features/lorawan/lorastack/mac/LoRaMac.h index 21580a1447..031ada4a2e 100644 --- a/features/lorawan/lorastack/mac/LoRaMac.h +++ b/features/lorawan/lorastack/mac/LoRaMac.h @@ -49,7 +49,7 @@ #include "lorastack/mac/LoRaMacMlme.h" #include "lorastack/mac/LoRaMacMcps.h" #include "lorastack/mac/LoRaMacMib.h" - +#include "lorastack/mac/LoRaMacChannelPlan.h" class LoRaMac { @@ -117,27 +117,57 @@ public: LoRaMacStatus_t LoRaMacQueryTxPossible( uint8_t size, LoRaMacTxInfo_t* txInfo ); /*! - * \brief LoRaMAC channel add service. + * \brief Adds a channel plan to the system. * - * \details Adds a new channel to the channel list and activates the ID in - * the channel mask. Please note that this functionality is not available - * in all regions. Information on the allowed ranges is available at the LoRaWAN Regional Parameters V1.0.2rB. + * \details Adds a whole channel plan or a single new channel to the. + * Please note that this functionality is not available in all regions. + * Information on the allowed ranges is available at the + * LoRaWAN Regional Parameters V1.0.2rB. * - * \param id [in] - The ID of the channel. - * - * \param params [in] - The channel parameters to set. + * \param plan [in] - A reference to application provided channel plan. * * \retval `LoRaMacStatus_t` The status of the operation. The possible values are: * \ref LORAMAC_STATUS_OK * \ref LORAMAC_STATUS_BUSY * \ref LORAMAC_STATUS_PARAMETER_INVALID */ - LoRaMacStatus_t LoRaMacChannelAdd( uint8_t id, ChannelParams_t params ); + LoRaMacStatus_t AddChannelPlan(const lora_channelplan_t& plan); /*! - * \brief LoRaMAC channel remove service. + * \brief Removes a channel plan from the system. * - * \details Deactivates the ID in the channel mask. + * \details Removes the whole active channel plan except the 'Default Channels'.. + * Please note that this functionality is not available in all regions. + * Information on the allowed ranges is available at the + * LoRaWAN Regional Parameters V1.0.2rB. + * + * \retval `LoRaMacStatus_t` The status of the operation. The possible values are: + * \ref LORAMAC_STATUS_OK + * \ref LORAMAC_STATUS_BUSY + * \ref LORAMAC_STATUS_PARAMETER_INVALID + */ + LoRaMacStatus_t RemoveChannelPlan(); + + /*! + * \brief Access active channel plan. + * + * \details Provides access to the current active channel plan. + * + * \param plan [out] - A reference to application provided channel plan data + * structure which will be filled in with active channel + * plan. + * + * \retval `LoRaMacStatus_t` The status of the operation. The possible values are: + * \ref LORAMAC_STATUS_OK + * \ref LORAMAC_STATUS_BUSY + * \ref LORAMAC_STATUS_PARAMETER_INVALID + */ + LoRaMacStatus_t GetChannelPlan(lora_channelplan_t& plan); + + /*! + * \brief Remove a given channel from the active plan. + * + * \details Deactivates the given channel. * * \param id - Id of the channel. * @@ -146,7 +176,7 @@ public: * \ref LORAMAC_STATUS_BUSY * \ref LORAMAC_STATUS_PARAMETER_INVALID */ - LoRaMacStatus_t LoRaMacChannelRemove( uint8_t id ); + LoRaMacStatus_t RemoveSingleChannel( uint8_t id ); /*! * \brief LoRaMAC multicast channel link service. @@ -626,6 +656,11 @@ private: */ LoRaMacMib mib; + /** + * Channel planning subsystem + */ + LoRaMacChannelPlan ch_plan; + /** * Timer subsystem handle */ diff --git a/features/lorawan/lorastack/mac/LoRaMacChannelPlan.cpp b/features/lorawan/lorastack/mac/LoRaMacChannelPlan.cpp new file mode 100644 index 0000000000..6f576b98b3 --- /dev/null +++ b/features/lorawan/lorastack/mac/LoRaMacChannelPlan.cpp @@ -0,0 +1,236 @@ +/** + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2013 Semtech + ___ _____ _ ___ _ _____ ___ ___ ___ ___ +/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __| +\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _| +|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___| +embedded.connectivity.solutions=============== + +Description: LoRaWAN stack layer that controls both MAC and PHY underneath + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE ) + + +Copyright (c) 2017, Arm Limited and affiliates. + +SPDX-License-Identifier: BSD-3-Clause +*/ + +#include "lorastack/mac/LoRaMacChannelPlan.h" + +LoRaMacChannelPlan::LoRaMacChannelPlan() : _lora_phy(NULL), _mib(NULL) +{ +} + +LoRaMacChannelPlan::~LoRaMacChannelPlan() +{ +} + +void LoRaMacChannelPlan::activate_channelplan_subsystem(LoRaPHY *phy, LoRaMacMib *mib) +{ + _lora_phy = phy; + _mib = mib; +} + +LoRaMacStatus_t LoRaMacChannelPlan::set_plan(const lora_channelplan_t& plan) +{ + ChannelAddParams_t channelAdd; + ChannelParams_t mac_layer_ch_params; + LoRaMacStatus_t status; + + GetPhyParams_t get_phy; + PhyParam_t phy_param; + uint8_t max_num_channels; + + // Check first how many channels the selected PHY layer supports + get_phy.Attribute = PHY_MAX_NB_CHANNELS; + phy_param = _lora_phy->get_phy_params(&get_phy); + max_num_channels = (uint8_t) phy_param.Value; + + // check if user is setting more channels than supported + if (plan.nb_channels > max_num_channels) { + return LORAMAC_STATUS_PARAMETER_INVALID; + } + + for (uint8_t i = 0; i < plan.nb_channels; i++) { + mac_layer_ch_params.Band = plan.channels[i].ch_param.band; + mac_layer_ch_params.DrRange.Fields.Max = + plan.channels[i].ch_param.dr_range.lora_mac_fields_s.max; + mac_layer_ch_params.DrRange.Fields.Min = + plan.channels[i].ch_param.dr_range.lora_mac_fields_s.min; + mac_layer_ch_params.DrRange.Value = + plan.channels[i].ch_param.dr_range.value; + mac_layer_ch_params.Frequency = + plan.channels[i].ch_param.frequency; + mac_layer_ch_params.Rx1Frequency = + plan.channels[i].ch_param.rx1_frequency; + + channelAdd.ChannelId = plan.channels[i].id; + channelAdd.NewChannel = &mac_layer_ch_params; + + status = _lora_phy->add_channel(&channelAdd); + + if (status != LORAMAC_STATUS_OK) { + return status; + } + } + + return LORAMAC_STATUS_OK; +} + +LoRaMacStatus_t LoRaMacChannelPlan::get_plan(lora_channelplan_t& plan, + lora_mac_protocol_params *params) +{ + if (params == NULL) { + return LORAMAC_STATUS_PARAMETER_INVALID; + } + + MibRequestConfirm_t mib_params; + LoRaMacStatus_t status; + + GetPhyParams_t get_phy; + PhyParam_t phy_param; + uint8_t max_num_channels; + uint16_t *channel_masks; + uint8_t count = 0; + + // Check first how many channels the selected PHY layer supports + get_phy.Attribute = PHY_MAX_NB_CHANNELS; + phy_param = _lora_phy->get_phy_params(&get_phy); + max_num_channels = (uint8_t) phy_param.Value; + + // Now check the Default channel mask + get_phy.Attribute = PHY_CHANNELS_MASK; + phy_param = _lora_phy->get_phy_params(&get_phy); + channel_masks = phy_param.ChannelsMask; + + // Request Mib to get channels + memset(&mib_params, 0, sizeof(mib_params)); + mib_params.Type = MIB_CHANNELS; + + status = _mib->get_request(&mib_params, params); + + if (status != LORAMAC_STATUS_OK) { + return status; + } + + for (uint8_t i = 0; i < max_num_channels; i++) { + // skip the channels which are not enabled + if ((channel_masks[0] & (1U << i)) == 0) { + continue; + } + + // otherwise add them to the channel_plan struct + plan.channels[count].id = i; + plan.channels[count].ch_param.frequency = mib_params.Param.ChannelList[i].Frequency; + plan.channels[count].ch_param.dr_range.value = mib_params.Param.ChannelList[i].DrRange.Value; + plan.channels[count].ch_param.dr_range.lora_mac_fields_s.min = mib_params.Param.ChannelList[i].DrRange.Fields.Min; + plan.channels[count].ch_param.dr_range.lora_mac_fields_s.max = mib_params.Param.ChannelList[i].DrRange.Fields.Max; + plan.channels[count].ch_param.band = mib_params.Param.ChannelList[i].Band; + plan.channels[count].ch_param.rx1_frequency = mib_params.Param.ChannelList[i].Rx1Frequency; + count++; + } + + plan.nb_channels = count; + + return LORAMAC_STATUS_OK; +} + +LoRaMacStatus_t LoRaMacChannelPlan::remove_plan() +{ + LoRaMacStatus_t status = LORAMAC_STATUS_OK; + + GetPhyParams_t get_phy; + PhyParam_t phy_param; + uint8_t max_num_channels; + uint16_t *channel_masks; + uint16_t *default_channel_masks; + + // Check first how many channels the selected PHY layer supports + get_phy.Attribute = PHY_MAX_NB_CHANNELS; + phy_param = _lora_phy->get_phy_params(&get_phy); + max_num_channels = (uint8_t) phy_param.Value; + + // Now check the channel mask for enabled channels + get_phy.Attribute = PHY_CHANNELS_MASK; + phy_param = _lora_phy->get_phy_params(&get_phy); + channel_masks = phy_param.ChannelsMask; + + // Now check the channel mask for default channels + get_phy.Attribute = PHY_CHANNELS_DEFAULT_MASK; + phy_param = _lora_phy->get_phy_params(&get_phy); + default_channel_masks = phy_param.ChannelsMask; + + for (uint8_t i = 0; i < max_num_channels; i++) { + // skip any default channels + if ((default_channel_masks[0] & (1U<get_phy_params(&get_phy); + max_num_channels = (uint8_t) phy_param.Value; + + // According to specification channel IDs start from 0 and last valid + // channel ID is N-1 where N=MAX_NUM_CHANNELS. + // So any ID which is larger or equal to the Max number of channels is invalid + if (channel_id >= max_num_channels) { + return LORAMAC_STATUS_PARAMETER_INVALID; + } + + // Now check the Default channel mask + get_phy.Attribute = PHY_CHANNELS_DEFAULT_MASK; + phy_param = _lora_phy->get_phy_params(&get_phy); + channel_masks = phy_param.ChannelsMask; + + // check if the channel ID give belongs to a default channel + // Mostly the default channels are in the first mask if the region + // have multiple channel masks for various sub-bands. So we check the first + // mask only and return an error code if user sent a default channel id + if ((channel_masks[0] & (1U << channel_id)) != 0) { + return LORAMAC_STATUS_PARAMETER_INVALID; + } + + channelRemove.ChannelId = channel_id; + + if(_lora_phy->remove_channel(&channelRemove) == false) + { + return LORAMAC_STATUS_PARAMETER_INVALID; + } + + _lora_phy->put_radio_to_sleep(); + + return LORAMAC_STATUS_OK; +} + diff --git a/features/lorawan/lorastack/mac/LoRaMacChannelPlan.h b/features/lorawan/lorastack/mac/LoRaMacChannelPlan.h new file mode 100644 index 0000000000..e57d37d951 --- /dev/null +++ b/features/lorawan/lorastack/mac/LoRaMacChannelPlan.h @@ -0,0 +1,115 @@ +/** + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2013 Semtech + ___ _____ _ ___ _ _____ ___ ___ ___ ___ +/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __| +\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _| +|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___| +embedded.connectivity.solutions=============== + +Description: LoRaWAN stack layer that controls both MAC and PHY underneath + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE ) + + +Copyright (c) 2017, Arm Limited and affiliates. + +SPDX-License-Identifier: BSD-3-Clause +*/ + +#ifndef MBED_LORAWAN_LORAMACCHANNELPLAN_H_ +#define MBED_LORAWAN_LORAMACCHANNELPLAN_H_ + +#include "lorawan/system/lorawan_data_structures.h" +#include "lorastack/phy/LoRaPHY.h" +#include "lorastack/mac/LoRaMacMib.h" + +class LoRaMacChannelPlan { + +public: + + /** Constructor + * + * Sets local handles to NULL. These handles will be set when the subsystem + * is activated by the MAC layer. + */ + LoRaMacChannelPlan(); + + /** Destructor + * + * Does nothing + */ + ~LoRaMacChannelPlan(); + + /** Activates Channel Planning subsystem + * + * Stores pointers to PHY layer MIB subsystem + * + * @param phy pointer to PHY layer + * @param mib pointer to MIB subsystem + */ + void activate_channelplan_subsystem(LoRaPHY *phy,LoRaMacMib *mib); + + /** Set a given channel plan + * + * Used to set application provided channel plan. This API can be used to + * set a single channel as well to the existing channel plan. + * + * @param plan a reference to application channel plan. PHY layer takes a + * copy of the channel parameters provided within. + * + * @return LORA_MAC_STATUS_OK if everything goes well otherwise + * a negative error code is returned. + */ + LoRaMacStatus_t set_plan(const lora_channelplan_t& plan); + + /** Access the active channel plan + * + * Used to get active channel plan. + * + * @param plan a reference to application provided channel plan structure + * which gets filled in with active channel plan data. + * + * @param params pointer to active MAC layer parameters. + * + * @return LORA_MAC_STATUS_OK if everything goes well otherwise + * a negative error code is returned. + */ + LoRaMacStatus_t get_plan(lora_channelplan_t& plan, lora_mac_protocol_params *params); + + /** Remove the active channel plan + * + * Drops the whole channel list except the 'Default Channels' ofcourse. + * + * @return LORA_MAC_STATUS_OK if everything goes well otherwise + * a negative error code is returned. + */ + LoRaMacStatus_t remove_plan(); + + /** Remove a single channel from the plan + * + * @param id the channel id which needs to be removed + * + * @return LORA_MAC_STATUS_OK if everything goes well otherwise + * a negative error code is returned. + */ + LoRaMacStatus_t remove_single_channel(uint8_t id); + +private: + + /** + * Local handles + */ + LoRaPHY *_lora_phy; + LoRaMacMib * _mib; +}; + + + +#endif /* MBED_LORAWAN_LORAMACCHANNELPLAN_H_ */