mirror of https://github.com/ARMmbed/mbed-os.git
[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.pull/6059/head
parent
34c034dfff
commit
6ea541c054
|
@ -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.
|
||||
|
|
|
@ -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<<i)) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// skip any channels which are not currently enabled
|
||||
if ((channel_masks[0] & (1U<<i)) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
status = error_type_converter(_loramac.LoRaMacChannelRemove(i));
|
||||
|
||||
if (status != LORA_MAC_STATUS_OK) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
return error_type_converter(_loramac.RemoveChannelPlan());
|
||||
}
|
||||
|
||||
lora_mac_status_t LoRaWANStack::remove_a_channel(uint8_t channel_id)
|
||||
|
@ -566,38 +494,7 @@ lora_mac_status_t LoRaWANStack::remove_a_channel(uint8_t channel_id)
|
|||
return LORA_MAC_STATUS_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
GetPhyParams_t get_phy;
|
||||
PhyParam_t phy_param;
|
||||
uint8_t max_num_channels;
|
||||
uint16_t *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;
|
||||
|
||||
// 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 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)
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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<<i)) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// skip any channels which are not currently enabled
|
||||
if ((channel_masks[0] & (1U<<i)) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
status = remove_single_channel(i);
|
||||
|
||||
if (status != LORAMAC_STATUS_OK) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
LoRaMacStatus_t LoRaMacChannelPlan::remove_single_channel(uint8_t channel_id)
|
||||
{
|
||||
GetPhyParams_t get_phy;
|
||||
PhyParam_t phy_param;
|
||||
uint8_t max_num_channels;
|
||||
uint16_t *channel_masks;
|
||||
ChannelRemoveParams_t channelRemove;
|
||||
|
||||
// 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;
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
|
@ -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_ */
|
Loading…
Reference in New Issue