mbed-os/features/lorawan/lorastack/mac/LoRaMacMcps.cpp

147 lines
4.5 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 "LoRaMac.h"
#include "lorastack/mac/LoRaMacMcps.h"
LoRaMacMcps::LoRaMacMcps()
: _lora_mac(NULL), _lora_phy(NULL)
{
}
LoRaMacMcps::~LoRaMacMcps()
{
}
void LoRaMacMcps::activate_mcps_subsystem(LoRaMac *mac, LoRaPHY *phy)
{
_lora_mac = mac;
_lora_phy = phy;
}
lorawan_status_t LoRaMacMcps::set_request(loramac_mcps_req_t *mcpsRequest,
loramac_protocol_params *params)
{
if (mcpsRequest == NULL || _lora_phy == NULL || _lora_mac == NULL) {
return LORAWAN_STATUS_PARAMETER_INVALID;
}
get_phy_params_t get_phy;
phy_param_t phyParam;
lorawan_status_t status = LORAWAN_STATUS_SERVICE_UNKNOWN;
loramac_mhdr_t machdr;
verification_params_t verify;
uint8_t fport = 0;
void *fbuffer;
uint16_t fbuffer_size;
int8_t datarate = DR_0;
bool ready_to_send = false;
machdr.value = 0;
// Before performing any MCPS request, clear the confirmation structure
memset((uint8_t*) &confirmation, 0, sizeof(confirmation));
confirmation.status = LORAMAC_EVENT_INFO_STATUS_ERROR;
// ack_timeout_retry_counter must be reset every time a new request (unconfirmed or confirmed) is performed.
params->ack_timeout_retry_counter = 1;
switch (mcpsRequest->type) {
case MCPS_UNCONFIRMED: {
ready_to_send = true;
params->max_ack_timeout_retries = 1;
machdr.bits.mtype = FRAME_TYPE_DATA_UNCONFIRMED_UP;
fport = mcpsRequest->req.unconfirmed.fport;
fbuffer = mcpsRequest->f_buffer;
fbuffer_size = mcpsRequest->f_buffer_size;
datarate = mcpsRequest->req.unconfirmed.data_rate;
break;
}
case MCPS_CONFIRMED: {
ready_to_send = true;
params->max_ack_timeout_retries = mcpsRequest->req.confirmed.nb_trials;
machdr.bits.mtype = FRAME_TYPE_DATA_CONFIRMED_UP;
fport = mcpsRequest->req.confirmed.fport;
fbuffer = mcpsRequest->f_buffer;
fbuffer_size = mcpsRequest->f_buffer_size;
datarate = mcpsRequest->req.confirmed.data_rate;
break;
}
case MCPS_PROPRIETARY: {
ready_to_send = true;
params->max_ack_timeout_retries = 1;
machdr.bits.mtype = FRAME_TYPE_PROPRIETARY;
fbuffer = mcpsRequest->f_buffer;
fbuffer_size = mcpsRequest->f_buffer_size;
datarate = mcpsRequest->req.proprietary.data_rate;
break;
}
default:
break;
}
// Filter fPorts
// TODO: Does not work with PROPRIETARY messages
// if( IsFPortAllowed( fPort ) == false )
// {
// return LORAWAN_STATUS_PARAMETER_INVALID;
// }
// Get the minimum possible datarate
get_phy.attribute = PHY_MIN_TX_DR;
phyParam = _lora_phy->get_phy_params(&get_phy);
// Apply the minimum possible datarate.
// Some regions have limitations for the minimum datarate.
datarate = MAX(datarate, (int8_t)phyParam.value);
if (ready_to_send == true) {
if (params->sys_params.adr_on == false) {
verify.datarate = datarate;
if (_lora_phy->verify(&verify, PHY_TX_DR) == true) {
params->sys_params.channel_data_rate = verify.datarate;
} else {
return LORAWAN_STATUS_PARAMETER_INVALID;
}
}
status = _lora_mac->send(&machdr, fport, fbuffer, fbuffer_size);
if (status == LORAWAN_STATUS_OK) {
confirmation.req_type = mcpsRequest->type;
params->flags.bits.mcps_req = 1;
} else {
params->is_node_ack_requested = false;
}
}
return status;
}