mirror of https://github.com/ARMmbed/mbed-os.git
244 lines
7.7 KiB
C++
244 lines
7.7 KiB
C++
/**
|
|
/ _____) _ | |
|
|
( (____ _____ ____ _| |_ _____ ____| |__
|
|
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
|
_____) ) ____| | | || |_| ____( (___| | | |
|
|
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
|
(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;
|
|
}
|
|
|
|
lorawan_status_t LoRaMacChannelPlan::set_plan(const lorawan_channelplan_t& plan)
|
|
{
|
|
channel_params_t mac_layer_ch_params;
|
|
lorawan_status_t status;
|
|
|
|
get_phy_params_t get_phy;
|
|
phy_param_t phy_param;
|
|
uint8_t max_num_channels;
|
|
|
|
// Check if the PHY layer supports custom channel plans or not.
|
|
get_phy.attribute = PHY_CUSTOM_CHANNEL_PLAN_SUPPORT;
|
|
phy_param = _lora_phy->get_phy_params(&get_phy);
|
|
|
|
if (!phy_param.value) {
|
|
return LORAWAN_STATUS_SERVICE_UNKNOWN;
|
|
}
|
|
|
|
// 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 LORAWAN_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.dr_range.fields.max = plan.channels[i].ch_param.dr_range.fields.max;
|
|
mac_layer_ch_params.dr_range.fields.min = plan.channels[i].ch_param.dr_range.fields.min;
|
|
mac_layer_ch_params.dr_range.value = plan.channels[i].ch_param.dr_range.value;
|
|
mac_layer_ch_params.frequency = plan.channels[i].ch_param.frequency;
|
|
mac_layer_ch_params.rx1_frequency = plan.channels[i].ch_param.rx1_frequency;
|
|
|
|
status = _lora_phy->add_channel(&mac_layer_ch_params, plan.channels[i].id);
|
|
|
|
if (status != LORAWAN_STATUS_OK) {
|
|
return status;
|
|
}
|
|
}
|
|
|
|
return LORAWAN_STATUS_OK;
|
|
}
|
|
|
|
lorawan_status_t LoRaMacChannelPlan::get_plan(lorawan_channelplan_t& plan,
|
|
loramac_protocol_params *params)
|
|
{
|
|
if (params == NULL) {
|
|
return LORAWAN_STATUS_PARAMETER_INVALID;
|
|
}
|
|
|
|
loramac_mib_req_confirm_t mib_confirm;
|
|
lorawan_status_t status;
|
|
|
|
get_phy_params_t get_phy;
|
|
phy_param_t phy_param;
|
|
uint8_t max_num_channels;
|
|
uint16_t *channel_mask;
|
|
uint8_t count = 0;
|
|
|
|
// Check if the PHY layer supports custom channel plans or not.
|
|
get_phy.attribute = PHY_CUSTOM_CHANNEL_PLAN_SUPPORT;
|
|
phy_param = _lora_phy->get_phy_params(&get_phy);
|
|
|
|
if (!phy_param.value) {
|
|
return LORAWAN_STATUS_SERVICE_UNKNOWN;
|
|
}
|
|
|
|
// 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_CHANNEL_MASK;
|
|
phy_param = _lora_phy->get_phy_params(&get_phy);
|
|
channel_mask = phy_param.channel_mask;
|
|
|
|
// Request Mib to get channels
|
|
memset(&mib_confirm, 0, sizeof(mib_confirm));
|
|
mib_confirm.type = MIB_CHANNELS;
|
|
|
|
status = _mib->get_request(&mib_confirm, params);
|
|
|
|
if (status != LORAWAN_STATUS_OK) {
|
|
return status;
|
|
}
|
|
|
|
for (uint8_t i = 0; i < max_num_channels; i++) {
|
|
// skip the channels which are not enabled
|
|
if (_lora_phy->mask_bit_test(channel_mask, i) == 0) {
|
|
continue;
|
|
}
|
|
|
|
// otherwise add them to the channel_plan struct
|
|
plan.channels[count].id = i;
|
|
plan.channels[count].ch_param.frequency = mib_confirm.param.channel_list[i].frequency;
|
|
plan.channels[count].ch_param.dr_range.value = mib_confirm.param.channel_list[i].dr_range.value;
|
|
plan.channels[count].ch_param.dr_range.fields.min = mib_confirm.param.channel_list[i].dr_range.fields.min;
|
|
plan.channels[count].ch_param.dr_range.fields.max = mib_confirm.param.channel_list[i].dr_range.fields.max;
|
|
plan.channels[count].ch_param.band = mib_confirm.param.channel_list[i].band;
|
|
plan.channels[count].ch_param.rx1_frequency = mib_confirm.param.channel_list[i].rx1_frequency;
|
|
count++;
|
|
}
|
|
|
|
plan.nb_channels = count;
|
|
|
|
return LORAWAN_STATUS_OK;
|
|
}
|
|
|
|
lorawan_status_t LoRaMacChannelPlan::remove_plan()
|
|
{
|
|
lorawan_status_t status = LORAWAN_STATUS_OK;
|
|
|
|
get_phy_params_t get_phy;
|
|
phy_param_t phy_param;
|
|
uint8_t max_num_channels;
|
|
uint16_t *channel_mask;
|
|
uint16_t *default_channel_mask;
|
|
|
|
// Check if the PHY layer supports custom channel plans or not.
|
|
get_phy.attribute = PHY_CUSTOM_CHANNEL_PLAN_SUPPORT;
|
|
phy_param = _lora_phy->get_phy_params(&get_phy);
|
|
|
|
if (!phy_param.value) {
|
|
return LORAWAN_STATUS_SERVICE_UNKNOWN;
|
|
}
|
|
|
|
// 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_CHANNEL_MASK;
|
|
phy_param = _lora_phy->get_phy_params(&get_phy);
|
|
channel_mask = phy_param.channel_mask;
|
|
|
|
// Now check the channel mask for default channels
|
|
get_phy.attribute = PHY_DEFAULT_CHANNEL_MASK;
|
|
phy_param = _lora_phy->get_phy_params(&get_phy);
|
|
default_channel_mask = phy_param.channel_mask;
|
|
|
|
for (uint8_t i = 0; i < max_num_channels; i++) {
|
|
// skip any default channels
|
|
if (_lora_phy->mask_bit_test(default_channel_mask, i) != 0) {
|
|
continue;
|
|
}
|
|
|
|
// skip any channels which are not currently enabled
|
|
if (_lora_phy->mask_bit_test(channel_mask, i) == 0) {
|
|
continue;
|
|
}
|
|
|
|
status = remove_single_channel(i);
|
|
|
|
if (status != LORAWAN_STATUS_OK) {
|
|
return status;
|
|
}
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
lorawan_status_t LoRaMacChannelPlan::remove_single_channel(uint8_t channel_id)
|
|
{
|
|
get_phy_params_t get_phy;
|
|
phy_param_t phy_param;
|
|
uint8_t max_num_channels;
|
|
|
|
// Check if the PHY layer supports custom channel plans or not.
|
|
get_phy.attribute = PHY_CUSTOM_CHANNEL_PLAN_SUPPORT;
|
|
phy_param = _lora_phy->get_phy_params(&get_phy);
|
|
|
|
if (!phy_param.value) {
|
|
return LORAWAN_STATUS_SERVICE_UNKNOWN;
|
|
}
|
|
|
|
// 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 LORAWAN_STATUS_PARAMETER_INVALID;
|
|
}
|
|
|
|
if (_lora_phy->remove_channel(channel_id) == false) {
|
|
return LORAWAN_STATUS_PARAMETER_INVALID;
|
|
}
|
|
|
|
_lora_phy->put_radio_to_sleep();
|
|
|
|
return LORAWAN_STATUS_OK;
|
|
}
|
|
|