mirror of https://github.com/ARMmbed/mbed-os.git
Architecture rework, bug fixing & missing features
MAC layer is now a class rather than being a blob. In addition to that Mac commands are now being handled in a seperate subsystem (a class of its own). In future we will do the same with othe sublayers of MAC like MLME, MCPS etc. The drive behind this exercise is to make MAC and supporting layers into an object oriented system. Major bug fixes include: - last join time inclusion in band parameters - disabling rx2 window if we missed the slot already - MLME uplink schdule hook - nbRep according to spec - maintaining datarate after successful joining - suppressing MLME requests if MAC is in TX_DELAYED state - Uplink dwell time verification Some missing features are implemented. Details are as follows. Support for LinkCheckRequet: An application API is added, add_link_check_request() to delegate a request for Link Check Request MAC command. * Application provides a callback function that needs to be called on reception of link check response. * Mac command is piggybacked with data frames. This API makes the sticky MAC command stick with the application payloads until/unless the application un-sticks the said mac command using remove_link_check_request() API. Handling fPending bit: If in the Downlink, we get the fPending bit set in fctrl octet, we attempt to send an empty message back to Network Server to open additional Receive windows. This operation is independent of the application. An RX_DONE event is queued bedore generating the said empty message. Specification does not mention what can be the type of that empty message. We have decided it to be of CONFIRMED type as it gives us an added benefit of retries if the corresponding RX slots are missed. Radio event callbacks as Mbed callbacks: radio_events_t structure has been carrying C-style callbacks which was inherited from the legacy code. These callbacks has now been changed to Mbed Callbacks that makes sure that we can be object oriented from now on.pull/6059/head
parent
1eedadd52d
commit
b634ca49dd
|
@ -28,7 +28,7 @@ inline LoRaWANStack& stk_obj()
|
|||
return LoRaWANStack::get_lorawan_stack();
|
||||
}
|
||||
|
||||
LoRaWANInterface::LoRaWANInterface(LoRaRadio& radio)
|
||||
LoRaWANInterface::LoRaWANInterface(LoRaRadio& radio) : _link_check_requested(false)
|
||||
{
|
||||
// Pass mac_handlers to radio to the radio driver after
|
||||
// binding radio driver to PHY layer
|
||||
|
@ -117,6 +117,17 @@ lora_mac_status_t LoRaWANInterface::disconnect()
|
|||
return LORA_MAC_STATUS_OK;
|
||||
}
|
||||
|
||||
lora_mac_status_t LoRaWANInterface::add_link_check_request()
|
||||
{
|
||||
_link_check_requested = true;
|
||||
return stk_obj().set_link_check_request();
|
||||
}
|
||||
|
||||
void LoRaWANInterface::remove_link_check_request()
|
||||
{
|
||||
_link_check_requested = false;
|
||||
}
|
||||
|
||||
lora_mac_status_t LoRaWANInterface::set_datarate(uint8_t data_rate)
|
||||
{
|
||||
return stk_obj().set_channel_data_rate(data_rate);
|
||||
|
@ -160,6 +171,12 @@ lora_mac_status_t LoRaWANInterface::remove_channel_plan()
|
|||
int16_t LoRaWANInterface::send(uint8_t port, const uint8_t* data,
|
||||
uint16_t length, int flags)
|
||||
{
|
||||
if (_link_check_requested) {
|
||||
// add a link check request with normal data, until the application
|
||||
// explicitly removes it.
|
||||
add_link_check_request();
|
||||
}
|
||||
|
||||
if (data) {
|
||||
return stk_obj().handle_tx(port, data, length, flags);
|
||||
} else {
|
||||
|
|
|
@ -130,6 +130,44 @@ public:
|
|||
*/
|
||||
virtual lora_mac_status_t disconnect();
|
||||
|
||||
/** Validate the connectivity with the network.
|
||||
*
|
||||
* Application may use this API to submit a request to the stack for
|
||||
* validation of its connectivity to a Network Server. Under the hood, this
|
||||
* API schedules a Link Check Request command (LinkCheckReq) for the network
|
||||
* server and once the response, i.e., LinkCheckAns MAC command is received
|
||||
* from the Network Server, user provided method is called.
|
||||
*
|
||||
* One way to use this API may be the validation of connectivity after a long
|
||||
* deep sleep. Mbed LoRaWANStack piggy-backs the MAC commands with data
|
||||
* frame payload so the application needs to try sending something and the Network
|
||||
* Server may respond during the RX slots.
|
||||
*
|
||||
* This API is usable only when the 'link_check_resp' callback is set by
|
||||
* the application. See add_lora_app_callbacks API. If the above mentioned
|
||||
* callback is not set, a LORA_MAC_STATUS_PARAMETER_INVALID error is thrown.
|
||||
*
|
||||
* First parameter to callback function is the demodulation margin and
|
||||
* the second parameter is the number of gateways that successfully received
|
||||
* the last request.
|
||||
*
|
||||
* A 'Link Check Request' MAC command remains set for every subsequent
|
||||
* transmission, until/unless application explicitly turns it off using
|
||||
* remove_link_check_request() API.
|
||||
*
|
||||
* @return LORA_MAC_STATUS_OK on successfully queuing a request, or
|
||||
* a negative error code on failure.
|
||||
*
|
||||
*/
|
||||
virtual lora_mac_status_t add_link_check_request();
|
||||
|
||||
/** Removes link check request sticky MAC command.
|
||||
*
|
||||
* Any already queued request may still get entertained. However, no new
|
||||
* requests will be made.
|
||||
*/
|
||||
virtual void remove_link_check_request();
|
||||
|
||||
/** Sets up a particular data rate
|
||||
*
|
||||
* `set_datarate()` first verifies whether the data rate given is valid or not.
|
||||
|
@ -361,7 +399,7 @@ public:
|
|||
* int main()
|
||||
* {
|
||||
* lorawan.initialize(&queue);
|
||||
* cbs.lorawan_events = mbed::callback(my_event_handler);
|
||||
* cbs.events = mbed::callback(my_event_handler);
|
||||
* lorawan.add_app_callbacks(&cbs);
|
||||
* lorawan.connect();
|
||||
* }
|
||||
|
@ -387,6 +425,9 @@ public:
|
|||
* callbacks.
|
||||
*/
|
||||
virtual lora_mac_status_t add_app_callbacks(lorawan_app_callbacks_t *callbacks);
|
||||
|
||||
private:
|
||||
bool _link_check_requested;
|
||||
};
|
||||
|
||||
#endif /* LORAWANINTERFACE_H_ */
|
||||
|
|
|
@ -168,7 +168,7 @@ LoRaWANStack& LoRaWANStack::get_lorawan_stack()
|
|||
radio_events_t *LoRaWANStack::bind_radio_driver(LoRaRadio& radio)
|
||||
{
|
||||
// Store pointer to callback routines inside MAC layer (non-IRQ safe)
|
||||
_mac_handlers = GetPhyEventHandlers();
|
||||
_mac_handlers = _loramac.GetPhyEventHandlers();
|
||||
// passes the reference to radio driver down to PHY layer
|
||||
lora_phy.get()->set_radio_instance(radio);
|
||||
return _mac_handlers;
|
||||
|
@ -204,7 +204,8 @@ lora_mac_status_t LoRaWANStack::initialize_mac_layer(EventQueue *queue)
|
|||
LoRaMacPrimitives.MacMcpsConfirm = callback(this, &LoRaWANStack::mcps_confirm);
|
||||
LoRaMacPrimitives.MacMcpsIndication = callback(this, &LoRaWANStack::mcps_indication);
|
||||
LoRaMacPrimitives.MacMlmeConfirm = callback(this, &LoRaWANStack::mlme_confirm);
|
||||
LoRaMacInitialization(&LoRaMacPrimitives, &LoRaMacCallbacks, lora_phy.get(), queue);
|
||||
LoRaMacPrimitives.MacMlmeIndication = callback(this, &LoRaWANStack::mlme_indication);
|
||||
_loramac.LoRaMacInitialization(&LoRaMacPrimitives, &LoRaMacCallbacks, lora_phy.get(), queue);
|
||||
|
||||
mib_req.type = LORA_MIB_ADR;
|
||||
mib_req.param.adr_enable = LORAWAN_ADR_ON;
|
||||
|
@ -315,7 +316,7 @@ lora_mac_status_t LoRaWANStack::send_compliance_test_frame_to_mac()
|
|||
uint16_t LoRaWANStack::check_possible_tx_size(uint16_t size)
|
||||
{
|
||||
LoRaMacTxInfo_t txInfo;
|
||||
if (LoRaMacQueryTxPossible(size, &txInfo) == LORAMAC_STATUS_LENGTH_ERROR) {
|
||||
if (_loramac.LoRaMacQueryTxPossible(size, &txInfo) == LORAMAC_STATUS_LENGTH_ERROR) {
|
||||
// Cannot transmit this much. Return how much data can be sent
|
||||
// at the moment
|
||||
return txInfo.MaxPossiblePayload;
|
||||
|
@ -461,9 +462,30 @@ void LoRaWANStack::mlme_confirm(MlmeConfirm_t *mlme_confirm)
|
|||
mlme_confirm_handler(&lora_mlme_confirm);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief MLME-Indication event function
|
||||
*
|
||||
* \param [IN] mlmeIndication - Pointer to the indication structure.
|
||||
*/
|
||||
void LoRaWANStack::mlme_indication( MlmeIndication_t *mlmeIndication )
|
||||
{
|
||||
switch( mlmeIndication->MlmeIndication )
|
||||
{
|
||||
case MLME_SCHEDULE_UPLINK:
|
||||
{// The MAC signals that we shall provide an uplink as soon as possible
|
||||
// TODO: Sending implementation missing and will be implemented using
|
||||
// another task.
|
||||
//OnTxNextPacketTimerEvent( );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LoRaWANStack::set_lora_callbacks(lorawan_app_callbacks_t *cbs)
|
||||
{
|
||||
|
||||
if (cbs) {
|
||||
if (cbs->events) {
|
||||
_callbacks.events = cbs->events;
|
||||
|
@ -508,7 +530,7 @@ lora_mac_status_t LoRaWANStack::add_channels(const lora_channelplan_t &channel_p
|
|||
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 = LoRaMacChannelAdd(channel_plan.channels[i].id, mac_layer_ch_params);
|
||||
status = _loramac.LoRaMacChannelAdd(channel_plan.channels[i].id, mac_layer_ch_params);
|
||||
|
||||
if (status != LORAMAC_STATUS_OK) {
|
||||
return error_type_converter(status);
|
||||
|
@ -560,7 +582,7 @@ lora_mac_status_t LoRaWANStack::drop_channel_list()
|
|||
continue;
|
||||
}
|
||||
|
||||
status = error_type_converter(LoRaMacChannelRemove(i));
|
||||
status = error_type_converter(_loramac.LoRaMacChannelRemove(i));
|
||||
|
||||
if (status != LORA_MAC_STATUS_OK) {
|
||||
return status;
|
||||
|
@ -609,7 +631,7 @@ lora_mac_status_t LoRaWANStack::remove_a_channel(uint8_t channel_id)
|
|||
return LORA_MAC_STATUS_PARAMETER_INVALID;
|
||||
}
|
||||
|
||||
return error_type_converter(LoRaMacChannelRemove(channel_id));
|
||||
return error_type_converter(_loramac.LoRaMacChannelRemove(channel_id));
|
||||
}
|
||||
|
||||
lora_mac_status_t LoRaWANStack::get_enabled_channels(lora_channelplan_t& channel_plan)
|
||||
|
@ -872,8 +894,10 @@ int16_t LoRaWANStack::handle_tx(uint8_t port, const uint8_t* data,
|
|||
_tx_msg.f_buffer_size = length;
|
||||
_tx_msg.pending_size = 0;
|
||||
// copy user buffer upto the max_possible_size
|
||||
if (data && length > 0) {
|
||||
memcpy(_tx_msg.f_buffer, data, length);
|
||||
}
|
||||
}
|
||||
|
||||
// Handles all unconfirmed messages, including proprietary and multicast
|
||||
if ((flags & MSG_FLAG_MASK) == MSG_UNCONFIRMED_FLAG
|
||||
|
@ -1018,7 +1042,7 @@ lora_mac_status_t LoRaWANStack::mlme_request_handler(lora_mac_mlme_req_t *mlme_r
|
|||
break;
|
||||
}
|
||||
|
||||
return error_type_converter(LoRaMacMlmeRequest(&request));
|
||||
return error_type_converter(_loramac.LoRaMacMlmeRequest(&request));
|
||||
}
|
||||
|
||||
/** MLME-Confirm event function
|
||||
|
@ -1057,8 +1081,15 @@ void LoRaWANStack::mlme_confirm_handler(lora_mac_mlme_confirm_t *mlme_confirm)
|
|||
_compliance_test.link_check = true;
|
||||
_compliance_test.demod_margin = mlme_confirm->demod_margin;
|
||||
_compliance_test.nb_gateways = mlme_confirm->nb_gateways;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
// normal operation as oppose to compliance testing
|
||||
if (_callbacks.link_check_resp) {
|
||||
_queue->call(_callbacks.link_check_resp, mlme_confirm->demod_margin,
|
||||
mlme_confirm->nb_gateways);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -1101,7 +1132,7 @@ lora_mac_status_t LoRaWANStack::mcps_request_handler(lora_mac_mcps_req_t *mcps_r
|
|||
break;
|
||||
}
|
||||
|
||||
return error_type_converter(LoRaMacMcpsRequest(&request));
|
||||
return error_type_converter(_loramac.LoRaMacMcpsRequest(&request));
|
||||
}
|
||||
|
||||
/** MCPS-Confirm event function
|
||||
|
@ -1253,6 +1284,14 @@ void LoRaWANStack::mcps_indication_handler(lora_mac_mcps_indication_t *mcps_indi
|
|||
if (_callbacks.events) {
|
||||
_queue->call(_callbacks.events, RX_DONE);
|
||||
}
|
||||
|
||||
// If fPending bit is set we try to generate an empty packet
|
||||
// with CONFIRMED flag set. We always set a CONFIRMED flag so
|
||||
// that we could retry a certain number of times if the uplink
|
||||
// failed for some reason
|
||||
if (mcps_indication->frame_pending) {
|
||||
handle_tx(mcps_indication->port, NULL, 0, MSG_CONFIRMED_FLAG);
|
||||
}
|
||||
} else {
|
||||
// Invalid port, ports 0, 224 and 225-255 are reserved.
|
||||
}
|
||||
|
@ -1292,10 +1331,10 @@ void LoRaWANStack::compliance_test_handler(lora_mac_mcps_indication_t *mcps_indi
|
|||
mib_set_request(&mib_req);
|
||||
|
||||
#if MBED_CONF_LORA_PHY == 0
|
||||
LoRaMacTestSetDutyCycleOn(false);
|
||||
_loramac.LoRaMacTestSetDutyCycleOn(false);
|
||||
#endif
|
||||
//5000ms
|
||||
LoRaMacSetTxTimer(5000);
|
||||
_loramac.LoRaMacSetTxTimer(5000);
|
||||
set_device_state(DEVICE_STATE_COMPLIANCE_TEST);
|
||||
tr_debug("Compliance test activated.");
|
||||
}
|
||||
|
@ -1314,11 +1353,11 @@ void LoRaWANStack::compliance_test_handler(lora_mac_mcps_indication_t *mcps_indi
|
|||
mib_req.param.adr_enable = LORAWAN_ADR_ON;
|
||||
mib_set_request(&mib_req);
|
||||
#if MBED_CONF_LORA_PHY == 0
|
||||
LoRaMacTestSetDutyCycleOn(LORAWAN_DUTYCYCLE_ON);
|
||||
_loramac.LoRaMacTestSetDutyCycleOn(LORAWAN_DUTYCYCLE_ON);
|
||||
#endif
|
||||
// Go to idle state after compliance test mode.
|
||||
tr_debug("Compliance test disabled.");
|
||||
LoRaMacStopTxTimer();
|
||||
_loramac.LoRaMacStopTxTimer();
|
||||
|
||||
// Clear any compliance test message stuff before going back to normal operation.
|
||||
memset(&_tx_msg, 0, sizeof(_tx_msg));
|
||||
|
@ -1366,7 +1405,7 @@ void LoRaWANStack::compliance_test_handler(lora_mac_mcps_indication_t *mcps_indi
|
|||
mib_request.param.adr_enable = LORAWAN_ADR_ON;
|
||||
mib_set_request(&mib_request);
|
||||
#if MBED_CONF_LORA_PHY == 0
|
||||
LoRaMacTestSetDutyCycleOn(LORAWAN_DUTYCYCLE_ON);
|
||||
_loramac.LoRaMacTestSetDutyCycleOn(LORAWAN_DUTYCYCLE_ON);
|
||||
#endif
|
||||
mlme_request.type = LORA_MLME_JOIN;
|
||||
mlme_request.req.join.dev_eui = _lw_session.connection.connection_u.otaa.dev_eui;
|
||||
|
@ -1569,7 +1608,7 @@ lora_mac_status_t LoRaWANStack::mib_set_request(lora_mac_mib_request_confirm_t *
|
|||
/*
|
||||
* Set MIB data to LoRa stack
|
||||
*/
|
||||
status = error_type_converter(LoRaMacMibSetRequestConfirm(&stack_mib_set));
|
||||
status = error_type_converter(_loramac.LoRaMacMibSetRequestConfirm(&stack_mib_set));
|
||||
/*
|
||||
* Release memory if reserved by multicast list
|
||||
*/
|
||||
|
@ -1598,7 +1637,7 @@ lora_mac_status_t LoRaWANStack::mib_get_request(lora_mac_mib_request_confirm_t *
|
|||
|
||||
// Interprets from lora_mac_mib_t to Mib_t
|
||||
stack_mib_get.Type = interpret_mib_req_confirm_type(mib_get_params->type);
|
||||
mac_status = error_type_converter(LoRaMacMibGetRequestConfirm(&stack_mib_get));
|
||||
mac_status = error_type_converter(_loramac.LoRaMacMibGetRequestConfirm(&stack_mib_get));
|
||||
|
||||
if (LORA_MAC_STATUS_OK != mac_status) {
|
||||
return LORA_MAC_STATUS_SERVICE_UNKNOWN;
|
||||
|
@ -1782,6 +1821,19 @@ lora_mac_status_t LoRaWANStack::error_type_converter(LoRaMacStatus_t type)
|
|||
}
|
||||
}
|
||||
|
||||
lora_mac_status_t LoRaWANStack::set_link_check_request()
|
||||
{
|
||||
if (!_callbacks.link_check_resp) {
|
||||
tr_error("Must assign a callback function for link check request. ");
|
||||
return LORA_MAC_STATUS_PARAMETER_INVALID;
|
||||
}
|
||||
|
||||
lora_mac_mlme_req_t mlme_req;
|
||||
|
||||
mlme_req.type = LORA_MLME_LINK_CHECK;
|
||||
return mlme_request_handler(&mlme_req);
|
||||
}
|
||||
|
||||
void LoRaWANStack::shutdown()
|
||||
{
|
||||
set_device_state(DEVICE_STATE_SHUTDOWN);
|
||||
|
@ -1944,7 +1996,7 @@ lora_mac_status_t LoRaWANStack::lora_state_machine()
|
|||
tr_debug("Device is in compliance test mode.");
|
||||
|
||||
//5000ms
|
||||
LoRaMacSetTxTimer(5000);
|
||||
_loramac.LoRaMacSetTxTimer(5000);
|
||||
if (_compliance_test.running == true) {
|
||||
send_compliance_test_frame_to_mac();
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ public:
|
|||
|
||||
/** Sets all callbacks for the application.
|
||||
*
|
||||
* \param callbacks A pointer to the structure carrying callbacks.
|
||||
* @param callbacks A pointer to the structure carrying callbacks.
|
||||
*/
|
||||
void set_lora_callbacks(lorawan_app_callbacks_t *callbacks);
|
||||
|
||||
|
@ -267,6 +267,22 @@ public:
|
|||
int16_t handle_rx(const uint8_t port, uint8_t* data,
|
||||
uint16_t length, uint8_t flags);
|
||||
|
||||
/** Send Link Check Request MAC command.
|
||||
*
|
||||
*
|
||||
* This API schedules a Link Check Request command (LinkCheckReq) for the network
|
||||
* server and once the response, i.e., LinkCheckAns MAC command is received
|
||||
* from the Network Server, an event is generated.
|
||||
*
|
||||
* A callback function for the link check response must be set prior to using
|
||||
* this API, otherwise a LORA_MAC_STATUS_PARAMETER_INVALID error is thrown.
|
||||
*
|
||||
* @return LORA_MAC_STATUS_OK on successfully queuing a request, or
|
||||
* a negative error code on failure.
|
||||
*
|
||||
*/
|
||||
lora_mac_status_t set_link_check_request();
|
||||
|
||||
/** Shuts down the LoRaWAN protocol.
|
||||
*
|
||||
* In response to the user call for disconnection, the stack shuts down itself.
|
||||
|
@ -296,11 +312,6 @@ private:
|
|||
*/
|
||||
void set_device_state(device_states_t new_state);
|
||||
|
||||
/**
|
||||
* This function is used only for compliance testing
|
||||
*/
|
||||
void prepare_special_tx_frame(uint8_t port);
|
||||
|
||||
/**
|
||||
* Hands over the packet to Mac layer by posting an MCPS request.
|
||||
*/
|
||||
|
@ -327,6 +338,13 @@ private:
|
|||
*/
|
||||
void mlme_confirm(MlmeConfirm_t *mlme_confirm);
|
||||
|
||||
/**
|
||||
* Callback function for MLME indication. Mac layer calls this function once
|
||||
* an MLME indication is received. This method translates Mac layer data
|
||||
* structure into stack layer data structure.
|
||||
*/
|
||||
void mlme_indication( MlmeIndication_t *mlmeIndication );
|
||||
|
||||
/**
|
||||
* Handles an MLME request coming from the upper layers and delegates
|
||||
* it to the Mac layer, for example, a Join request goes as an MLME request
|
||||
|
@ -389,6 +407,12 @@ private:
|
|||
*/
|
||||
uint16_t check_possible_tx_size(uint16_t size);
|
||||
|
||||
#if defined(LORAWAN_COMPLIANCE_TEST)
|
||||
/**
|
||||
* This function is used only for compliance testing
|
||||
*/
|
||||
void prepare_special_tx_frame(uint8_t port);
|
||||
|
||||
/**
|
||||
* Used only for compliance testing
|
||||
*/
|
||||
|
@ -398,12 +422,15 @@ private:
|
|||
* Used only for compliance testing
|
||||
*/
|
||||
lora_mac_status_t send_compliance_test_frame_to_mac();
|
||||
#endif
|
||||
|
||||
/**
|
||||
* converts error codes from Mac layer to controller layer
|
||||
*/
|
||||
lora_mac_status_t error_type_converter(LoRaMacStatus_t type);
|
||||
|
||||
LoRaMac _loramac;
|
||||
|
||||
#if defined(LORAWAN_COMPLIANCE_TEST)
|
||||
compliance_test_t _compliance_test;
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -44,35 +44,30 @@
|
|||
#include "netsocket/LoRaRadio.h"
|
||||
#include "lorastack/phy/LoRaPHY.h"
|
||||
#include "lorawan/system/lorawan_data_structures.h"
|
||||
#include "LoRaMacCommand.h"
|
||||
#include "events/EventQueue.h"
|
||||
|
||||
|
||||
/*!
|
||||
* Check the MAC layer state every MAC_STATE_CHECK_TIMEOUT in ms.
|
||||
* Maximum PHY layer payload size
|
||||
*/
|
||||
#define MAC_STATE_CHECK_TIMEOUT 1000
|
||||
#define LORAMAC_PHY_MAXPAYLOAD 255
|
||||
|
||||
/*!
|
||||
* The maximum number of times the MAC layer tries to get an acknowledge.
|
||||
|
||||
class LoRaMac
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
* \brief Constructor
|
||||
*/
|
||||
#define MAX_ACK_RETRIES 8
|
||||
LoRaMac();
|
||||
|
||||
/*!
|
||||
* The frame direction definition for uplink communications.
|
||||
/*!
|
||||
* \brief Destructor
|
||||
*/
|
||||
#define UP_LINK 0
|
||||
~LoRaMac();
|
||||
|
||||
/*!
|
||||
* The frame direction definition for downlink communications.
|
||||
*/
|
||||
#define DOWN_LINK 1
|
||||
|
||||
|
||||
/*!
|
||||
* LoRaMAC max EIRP (dBm) table.
|
||||
*/
|
||||
static const uint8_t LoRaMacMaxEirpTable[] = { 8, 10, 12, 13, 14, 16, 18, 20, 21, 24, 26, 27, 29, 30, 33, 36 };
|
||||
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* \brief LoRaMAC layer initialization
|
||||
*
|
||||
* \details In addition to the initialization of the LoRaMAC layer, this
|
||||
|
@ -95,12 +90,12 @@ static const uint8_t LoRaMacMaxEirpTable[] = { 8, 10, 12, 13, 14, 16, 18, 20, 21
|
|||
* \ref LORAMAC_STATUS_PARAMETER_INVALID
|
||||
* \ref LORAMAC_STATUS_REGION_NOT_SUPPORTED.
|
||||
*/
|
||||
LoRaMacStatus_t LoRaMacInitialization(LoRaMacPrimitives_t *primitives,
|
||||
LoRaMacStatus_t LoRaMacInitialization(LoRaMacPrimitives_t *primitives,
|
||||
LoRaMacCallback_t *callbacks,
|
||||
LoRaPHY *phy,
|
||||
events::EventQueue *queue);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* \brief Queries the LoRaMAC whether it is possible to send the next frame with
|
||||
* a given payload size. The LoRaMAC takes the scheduled MAC commands into
|
||||
* account and reports when the frame can be sent.
|
||||
|
@ -122,9 +117,9 @@ LoRaMacStatus_t LoRaMacInitialization(LoRaMacPrimitives_t *primitives,
|
|||
* If the query is valid, and the LoRaMAC is able to send the frame,
|
||||
* the function returns \ref LORAMAC_STATUS_OK.
|
||||
*/
|
||||
LoRaMacStatus_t LoRaMacQueryTxPossible( uint8_t size, LoRaMacTxInfo_t* txInfo );
|
||||
LoRaMacStatus_t LoRaMacQueryTxPossible( uint8_t size, LoRaMacTxInfo_t* txInfo );
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* \brief LoRaMAC channel add service.
|
||||
*
|
||||
* \details Adds a new channel to the channel list and activates the ID in
|
||||
|
@ -140,9 +135,9 @@ LoRaMacStatus_t LoRaMacQueryTxPossible( uint8_t size, LoRaMacTxInfo_t* txInfo );
|
|||
* \ref LORAMAC_STATUS_BUSY
|
||||
* \ref LORAMAC_STATUS_PARAMETER_INVALID
|
||||
*/
|
||||
LoRaMacStatus_t LoRaMacChannelAdd( uint8_t id, ChannelParams_t params );
|
||||
LoRaMacStatus_t LoRaMacChannelAdd( uint8_t id, ChannelParams_t params );
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* \brief LoRaMAC channel remove service.
|
||||
*
|
||||
* \details Deactivates the ID in the channel mask.
|
||||
|
@ -154,9 +149,9 @@ LoRaMacStatus_t LoRaMacChannelAdd( uint8_t id, ChannelParams_t params );
|
|||
* \ref LORAMAC_STATUS_BUSY
|
||||
* \ref LORAMAC_STATUS_PARAMETER_INVALID
|
||||
*/
|
||||
LoRaMacStatus_t LoRaMacChannelRemove( uint8_t id );
|
||||
LoRaMacStatus_t LoRaMacChannelRemove( uint8_t id );
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* \brief LoRaMAC multicast channel link service.
|
||||
*
|
||||
* \details Links a multicast channel into the linked list.
|
||||
|
@ -168,9 +163,9 @@ LoRaMacStatus_t LoRaMacChannelRemove( uint8_t id );
|
|||
* \ref LORAMAC_STATUS_BUSY
|
||||
* \ref LORAMAC_STATUS_PARAMETER_INVALID
|
||||
*/
|
||||
LoRaMacStatus_t LoRaMacMulticastChannelLink( MulticastParams_t *channelParam );
|
||||
LoRaMacStatus_t LoRaMacMulticastChannelLink( MulticastParams_t *channelParam );
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* \brief LoRaMAC multicast channel unlink service.
|
||||
*
|
||||
* \details Unlinks a multicast channel from the linked list.
|
||||
|
@ -182,9 +177,9 @@ LoRaMacStatus_t LoRaMacMulticastChannelLink( MulticastParams_t *channelParam );
|
|||
* \ref LORAMAC_STATUS_BUSY
|
||||
* \ref LORAMAC_STATUS_PARAMETER_INVALID
|
||||
*/
|
||||
LoRaMacStatus_t LoRaMacMulticastChannelUnlink( MulticastParams_t *channelParam );
|
||||
LoRaMacStatus_t LoRaMacMulticastChannelUnlink( MulticastParams_t *channelParam );
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* \brief LoRaMAC MIB-GET.
|
||||
*
|
||||
* \details The MAC information base service to get the attributes of the LoRaMac layer.
|
||||
|
@ -209,9 +204,9 @@ LoRaMacStatus_t LoRaMacMulticastChannelUnlink( MulticastParams_t *channelParam )
|
|||
* \ref LORAMAC_STATUS_SERVICE_UNKNOWN
|
||||
* \ref LORAMAC_STATUS_PARAMETER_INVALID
|
||||
*/
|
||||
LoRaMacStatus_t LoRaMacMibGetRequestConfirm( MibRequestConfirm_t *mibGet );
|
||||
LoRaMacStatus_t LoRaMacMibGetRequestConfirm( MibRequestConfirm_t *mibGet );
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* \brief LoRaMAC MIB-SET.
|
||||
*
|
||||
* \details The MAC information base service to set the attributes of the LoRaMac layer.
|
||||
|
@ -239,9 +234,9 @@ LoRaMacStatus_t LoRaMacMibGetRequestConfirm( MibRequestConfirm_t *mibGet );
|
|||
* \ref LORAMAC_STATUS_SERVICE_UNKNOWN
|
||||
* \ref LORAMAC_STATUS_PARAMETER_INVALID
|
||||
*/
|
||||
LoRaMacStatus_t LoRaMacMibSetRequestConfirm( MibRequestConfirm_t *mibSet );
|
||||
LoRaMacStatus_t LoRaMacMibSetRequestConfirm( MibRequestConfirm_t *mibSet );
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* \brief LoRaMAC MLME request
|
||||
*
|
||||
* \details The MAC layer management entity handles the management services. The
|
||||
|
@ -286,9 +281,9 @@ LoRaMacStatus_t LoRaMacMibSetRequestConfirm( MibRequestConfirm_t *mibSet );
|
|||
* \ref LORAMAC_STATUS_LENGTH_ERROR
|
||||
* \ref LORAMAC_STATUS_DEVICE_OFF
|
||||
*/
|
||||
LoRaMacStatus_t LoRaMacMlmeRequest( MlmeReq_t *mlmeRequest );
|
||||
LoRaMacStatus_t LoRaMacMlmeRequest( MlmeReq_t *mlmeRequest );
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* \brief LoRaMAC MCPS request
|
||||
*
|
||||
* \details The MAC Common Part Sublayer handles the data services. The following
|
||||
|
@ -321,18 +316,26 @@ LoRaMacStatus_t LoRaMacMlmeRequest( MlmeReq_t *mlmeRequest );
|
|||
* \ref LORAMAC_STATUS_LENGTH_ERROR
|
||||
* \ref LORAMAC_STATUS_DEVICE_OFF
|
||||
*/
|
||||
LoRaMacStatus_t LoRaMacMcpsRequest( McpsReq_t *mcpsRequest );
|
||||
LoRaMacStatus_t LoRaMacMcpsRequest( McpsReq_t *mcpsRequest );
|
||||
|
||||
/**
|
||||
/**
|
||||
* \brief LoRaMAC layer provides its callback functions for
|
||||
* PHY layer
|
||||
*
|
||||
* \return Pointer to callback functions for radio events
|
||||
*/
|
||||
radio_events_t *GetPhyEventHandlers();
|
||||
radio_events_t *GetPhyEventHandlers();
|
||||
|
||||
/*!
|
||||
* \brief Configures the events to trigger an MLME-Indication with
|
||||
* a MLME type of MLME_SCHEDULE_UPLINK.
|
||||
*/
|
||||
void SetMlmeScheduleUplinkIndication( void );
|
||||
|
||||
#if defined(LORAWAN_COMPLIANCE_TEST)
|
||||
/**
|
||||
public: // Test interface
|
||||
|
||||
/**
|
||||
* \brief LoRaMAC set tx timer.
|
||||
*
|
||||
* \details Sets up a timer for next transmission (application specific timers).
|
||||
|
@ -343,9 +346,9 @@ radio_events_t *GetPhyEventHandlers();
|
|||
* \ref LORAMAC_STATUS_OK
|
||||
* \ref LORAMAC_STATUS_PARAMETER_INVALID
|
||||
*/
|
||||
LoRaMacStatus_t LoRaMacSetTxTimer( uint32_t NextTxTime );
|
||||
LoRaMacStatus_t LoRaMacSetTxTimer( uint32_t NextTxTime );
|
||||
|
||||
/**
|
||||
/**
|
||||
* \brief LoRaMAC stop tx timer.
|
||||
*
|
||||
* \details Stops the next tx timer.
|
||||
|
@ -354,7 +357,566 @@ LoRaMacStatus_t LoRaMacSetTxTimer( uint32_t NextTxTime );
|
|||
* \ref LORAMAC_STATUS_OK
|
||||
* \ref LORAMAC_STATUS_PARAMETER_INVALID
|
||||
*/
|
||||
LoRaMacStatus_t LoRaMacStopTxTimer( );
|
||||
LoRaMacStatus_t LoRaMacStopTxTimer( );
|
||||
|
||||
/**
|
||||
* \brief Enabled or disables the reception windows
|
||||
*
|
||||
* \details This is a test function. It shall be used for testing purposes only.
|
||||
* Changing this attribute may lead to a non-conformance LoRaMac operation.
|
||||
*
|
||||
* \param [in] enable - Enabled or disables the reception windows
|
||||
*/
|
||||
void LoRaMacTestRxWindowsOn( bool enable );
|
||||
|
||||
/**
|
||||
* \brief Enables the MIC field test
|
||||
*
|
||||
* \details This is a test function. It shall be used for testing purposes only.
|
||||
* Changing this attribute may lead to a non-conformance LoRaMac operation.
|
||||
*
|
||||
* \param [in] txPacketCounter - Fixed Tx packet counter value
|
||||
*/
|
||||
void LoRaMacTestSetMic( uint16_t txPacketCounter );
|
||||
|
||||
/**
|
||||
* \brief Enabled or disables the duty cycle
|
||||
*
|
||||
* \details This is a test function. It shall be used for testing purposes only.
|
||||
* Changing this attribute may lead to a non-conformance LoRaMac operation.
|
||||
*
|
||||
* \param [in] enable - Enabled or disables the duty cycle
|
||||
*/
|
||||
void LoRaMacTestSetDutyCycleOn( bool enable );
|
||||
|
||||
/**
|
||||
* \brief Sets the channel index
|
||||
*
|
||||
* \details This is a test function. It shall be used for testing purposes only.
|
||||
* Changing this attribute may lead to a non-conformance LoRaMac operation.
|
||||
*
|
||||
* \param [in] channel - Channel index
|
||||
*/
|
||||
void LoRaMacTestSetChannel( uint8_t channel );
|
||||
|
||||
private:
|
||||
/**
|
||||
* Timer to handle the application data transmission duty cycle
|
||||
*/
|
||||
TimerEvent_t TxNextPacketTimer;
|
||||
#endif
|
||||
|
||||
private:
|
||||
/*!
|
||||
* \brief Function to be executed on Radio Tx Done event
|
||||
*/
|
||||
void OnRadioTxDone( void );
|
||||
|
||||
/*!
|
||||
* \brief This function prepares the MAC to abort the execution of function
|
||||
* OnRadioRxDone in case of a reception error.
|
||||
*/
|
||||
void PrepareRxDoneAbort( void );
|
||||
|
||||
/*!
|
||||
* \brief Function to be executed on Radio Rx Done event
|
||||
*/
|
||||
void OnRadioRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr );
|
||||
|
||||
/*!
|
||||
* \brief Function executed on Radio Tx Timeout event
|
||||
*/
|
||||
void OnRadioTxTimeout( void );
|
||||
|
||||
/*!
|
||||
* \brief Function executed on Radio Rx error event
|
||||
*/
|
||||
void OnRadioRxError( void );
|
||||
|
||||
/*!
|
||||
* \brief Function executed on Radio Rx Timeout event
|
||||
*/
|
||||
void OnRadioRxTimeout( void );
|
||||
|
||||
/*!
|
||||
* \brief Function executed on Resend Frame timer event.
|
||||
*/
|
||||
void OnMacStateCheckTimerEvent( void );
|
||||
|
||||
/*!
|
||||
* \brief Function executed on duty cycle delayed Tx timer event
|
||||
*/
|
||||
void OnTxDelayedTimerEvent( void );
|
||||
|
||||
/**
|
||||
* \brief Function to be executed when next Tx is possible
|
||||
*/
|
||||
void OnNextTx( void );
|
||||
|
||||
/*!
|
||||
* \brief Function executed on first Rx window timer event
|
||||
*/
|
||||
void OnRxWindow1TimerEvent( void );
|
||||
|
||||
/*!
|
||||
* \brief Function executed on second Rx window timer event
|
||||
*/
|
||||
void OnRxWindow2TimerEvent( void );
|
||||
|
||||
/*!
|
||||
* \brief Function executed on AckTimeout timer event
|
||||
*/
|
||||
void OnAckTimeoutTimerEvent( void );
|
||||
|
||||
/*!
|
||||
* \brief Initializes and opens the reception window
|
||||
*
|
||||
* \param [IN] rxContinuous Set to true, if the RX is in continuous mode
|
||||
* \param [IN] maxRxWindow Maximum RX window timeout
|
||||
*/
|
||||
void RxWindowSetup( bool rxContinuous, uint32_t maxRxWindow );
|
||||
|
||||
/*!
|
||||
* \brief Validates if the payload fits into the frame, taking the datarate
|
||||
* into account.
|
||||
*
|
||||
* \details Refer to chapter 4.3.2 of the LoRaWAN specification, v1.0
|
||||
*
|
||||
* \param lenN Length of the application payload. The length depends on the
|
||||
* datarate and is region specific
|
||||
*
|
||||
* \param datarate Current datarate
|
||||
*
|
||||
* \param fOptsLen Length of the fOpts field
|
||||
*
|
||||
* \retval [false: payload does not fit into the frame, true: payload fits into
|
||||
* the frame]
|
||||
*/
|
||||
bool ValidatePayloadLength( uint8_t lenN, int8_t datarate, uint8_t fOptsLen );
|
||||
|
||||
/*!
|
||||
* \brief LoRaMAC layer generic send frame
|
||||
*
|
||||
* \param [IN] macHdr MAC header field
|
||||
* \param [IN] fPort MAC payload port
|
||||
* \param [IN] fBuffer MAC data buffer to be sent
|
||||
* \param [IN] fBufferSize MAC data buffer size
|
||||
* \retval status Status of the operation.
|
||||
*/
|
||||
LoRaMacStatus_t Send( LoRaMacHeader_t *macHdr, uint8_t fPort, void *fBuffer, uint16_t fBufferSize );
|
||||
|
||||
/*!
|
||||
* \brief LoRaMAC layer frame buffer initialization
|
||||
*
|
||||
* \param [IN] macHdr MAC header field
|
||||
* \param [IN] fCtrl MAC frame control field
|
||||
* \param [IN] fOpts MAC commands buffer
|
||||
* \param [IN] fPort MAC payload port
|
||||
* \param [IN] fBuffer MAC data buffer to be sent
|
||||
* \param [IN] fBufferSize MAC data buffer size
|
||||
* \retval status Status of the operation.
|
||||
*/
|
||||
LoRaMacStatus_t PrepareFrame( LoRaMacHeader_t *macHdr, LoRaMacFrameCtrl_t *fCtrl, uint8_t fPort, void *fBuffer, uint16_t fBufferSize );
|
||||
|
||||
/*
|
||||
* \brief Schedules the frame according to the duty cycle
|
||||
*
|
||||
* \retval Status of the operation
|
||||
*/
|
||||
LoRaMacStatus_t ScheduleTx( void );
|
||||
|
||||
/*
|
||||
* \brief Calculates the back-off time for the band of a channel.
|
||||
*
|
||||
* \param [IN] channel The last Tx channel index
|
||||
*/
|
||||
void CalculateBackOff( uint8_t channel );
|
||||
|
||||
/*!
|
||||
* \brief LoRaMAC layer prepared frame buffer transmission with channel specification
|
||||
*
|
||||
* \remark PrepareFrame must be called at least once before calling this
|
||||
* function.
|
||||
*
|
||||
* \param [IN] channel Channel to transmit on
|
||||
* \retval status Status of the operation.
|
||||
*/
|
||||
LoRaMacStatus_t SendFrameOnChannel( uint8_t channel );
|
||||
|
||||
/*!
|
||||
* \brief Sets the radio in continuous transmission mode
|
||||
*
|
||||
* \remark Uses the radio parameters set on the previous transmission.
|
||||
*
|
||||
* \param [IN] timeout Time in seconds while the radio is kept in continuous wave mode
|
||||
* \retval status Status of the operation.
|
||||
*/
|
||||
LoRaMacStatus_t SetTxContinuousWave( uint16_t timeout );
|
||||
|
||||
/*!
|
||||
* \brief Sets the radio in continuous transmission mode
|
||||
*
|
||||
* \remark Uses the radio parameters set on the previous transmission.
|
||||
*
|
||||
* \param [IN] timeout Time in seconds while the radio is kept in continuous wave mode
|
||||
* \param [IN] frequency RF frequency to be set.
|
||||
* \param [IN] power RF output power to be set.
|
||||
* \retval status Status of the operation.
|
||||
*/
|
||||
LoRaMacStatus_t SetTxContinuousWave1( uint16_t timeout, uint32_t frequency, uint8_t power );
|
||||
|
||||
/*!
|
||||
* \brief Resets MAC specific parameters to default
|
||||
*/
|
||||
void ResetMacParameters( void );
|
||||
|
||||
/*!
|
||||
* \brief Resets MAC specific parameters to default
|
||||
*
|
||||
* \param [IN] fPort The fPort
|
||||
*
|
||||
* \retval [false: fPort not allowed, true: fPort allowed]
|
||||
*/
|
||||
bool IsFPortAllowed( uint8_t fPort );
|
||||
|
||||
/*!
|
||||
* \brief Opens up a continuous RX 2 window. This is used for
|
||||
* class c devices.
|
||||
*/
|
||||
void OpenContinuousRx2Window( void );
|
||||
|
||||
/**
|
||||
* Prototypes for ISR handlers
|
||||
*/
|
||||
static void handle_cad_done(bool cad);
|
||||
static void handle_tx_done(void);
|
||||
static void handle_rx_done(uint8_t *payload, uint16_t size, int16_t rssi,
|
||||
int8_t snr);
|
||||
static void handle_rx_error(void);
|
||||
static void handle_rx_timeout(void);
|
||||
static void handle_tx_timeout(void);
|
||||
static void handle_fhss_change_channel(uint8_t cur_channel);
|
||||
static void handle_rx1_timer_event(void);
|
||||
static void handle_rx2_timer_event(void);
|
||||
static void handle_ack_timeout(void);
|
||||
static void handle_delayed_tx_timer_event(void);
|
||||
static void handle_mac_state_check_timer_event(void);
|
||||
static void handle_next_tx_timer_event(void);
|
||||
|
||||
private:
|
||||
/**
|
||||
* LoRa PHY layer object storage
|
||||
*/
|
||||
LoRaPHY *lora_phy;
|
||||
|
||||
LoRaMacCommand mac_commands;
|
||||
|
||||
|
||||
/**
|
||||
* Radio event callback handlers for MAC
|
||||
*/
|
||||
radio_events_t RadioEvents;
|
||||
|
||||
|
||||
/*!
|
||||
* Device IEEE EUI
|
||||
*/
|
||||
uint8_t *LoRaMacDevEui;
|
||||
|
||||
/*!
|
||||
* Application IEEE EUI
|
||||
*/
|
||||
uint8_t *LoRaMacAppEui;
|
||||
|
||||
/*!
|
||||
* AES encryption/decryption cipher application key
|
||||
*/
|
||||
uint8_t *LoRaMacAppKey;
|
||||
|
||||
/*!
|
||||
* AES encryption/decryption cipher network session key
|
||||
*/
|
||||
uint8_t LoRaMacNwkSKey[16];
|
||||
|
||||
/*!
|
||||
* AES encryption/decryption cipher application session key
|
||||
*/
|
||||
uint8_t LoRaMacAppSKey[16];
|
||||
|
||||
/*!
|
||||
* Device nonce is a random value extracted by issuing a sequence of RSSI
|
||||
* measurements
|
||||
*/
|
||||
uint16_t LoRaMacDevNonce;
|
||||
|
||||
/*!
|
||||
* Network ID ( 3 bytes )
|
||||
*/
|
||||
uint32_t LoRaMacNetID;
|
||||
|
||||
/*!
|
||||
* Mote Address
|
||||
*/
|
||||
uint32_t LoRaMacDevAddr;
|
||||
|
||||
/*!
|
||||
* Multicast channels linked list
|
||||
*/
|
||||
MulticastParams_t *MulticastChannels;
|
||||
|
||||
/*!
|
||||
* Actual device class
|
||||
*/
|
||||
DeviceClass_t LoRaMacDeviceClass;
|
||||
|
||||
/*!
|
||||
* Indicates if the node is connected to a private or public network
|
||||
*/
|
||||
bool PublicNetwork;
|
||||
|
||||
/*!
|
||||
* Indicates if the node supports repeaters
|
||||
*/
|
||||
bool RepeaterSupport;
|
||||
|
||||
/*!
|
||||
* Buffer containing the data to be sent or received.
|
||||
*/
|
||||
uint8_t LoRaMacBuffer[LORAMAC_PHY_MAXPAYLOAD];
|
||||
|
||||
/*!
|
||||
* Length of packet in LoRaMacBuffer
|
||||
*/
|
||||
uint16_t LoRaMacBufferPktLen;
|
||||
|
||||
/*!
|
||||
* Length of the payload in LoRaMacBuffer
|
||||
*/
|
||||
uint8_t LoRaMacTxPayloadLen;
|
||||
|
||||
/*!
|
||||
* Buffer containing the upper layer data.
|
||||
*/
|
||||
uint8_t LoRaMacRxPayload[LORAMAC_PHY_MAXPAYLOAD];
|
||||
|
||||
/*!
|
||||
* LoRaMAC frame counter. Each time a packet is sent the counter is incremented.
|
||||
* Only the 16 LSB bits are sent
|
||||
*/
|
||||
uint32_t UpLinkCounter;
|
||||
|
||||
/*!
|
||||
* LoRaMAC frame counter. Each time a packet is received the counter is incremented.
|
||||
* Only the 16 LSB bits are received
|
||||
*/
|
||||
uint32_t DownLinkCounter;
|
||||
|
||||
/*!
|
||||
* IsPacketCounterFixed enables the MIC field tests by fixing the
|
||||
* UpLinkCounter value
|
||||
*/
|
||||
bool IsUpLinkCounterFixed;
|
||||
|
||||
/*!
|
||||
* Used for test purposes. Disables the opening of the reception windows.
|
||||
*/
|
||||
bool IsRxWindowsEnabled;
|
||||
|
||||
/*!
|
||||
* Indicates if the MAC layer has already joined a network.
|
||||
*/
|
||||
bool IsLoRaMacNetworkJoined;
|
||||
|
||||
/*!
|
||||
* Counts the number of missed ADR acknowledgements
|
||||
*/
|
||||
uint32_t AdrAckCounter;
|
||||
|
||||
/*!
|
||||
* If the node has sent a FRAME_TYPE_DATA_CONFIRMED_UP this variable indicates
|
||||
* if the nodes needs to manage the server acknowledgement.
|
||||
*/
|
||||
bool NodeAckRequested;
|
||||
|
||||
/*!
|
||||
* If the server has sent a FRAME_TYPE_DATA_CONFIRMED_DOWN this variable indicates
|
||||
* if the ACK bit must be set for the next transmission
|
||||
*/
|
||||
bool SrvAckRequested;
|
||||
|
||||
/*!
|
||||
* LoRaMac parameters
|
||||
*/
|
||||
LoRaMacParams_t LoRaMacParams;
|
||||
|
||||
/*!
|
||||
* LoRaMac default parameters
|
||||
*/
|
||||
LoRaMacParams_t LoRaMacParamsDefaults;
|
||||
|
||||
/*!
|
||||
* Uplink messages repetitions counter
|
||||
*/
|
||||
uint8_t ChannelsNbRepCounter;
|
||||
|
||||
/*!
|
||||
* Aggregated duty cycle management
|
||||
*/
|
||||
TimerTime_t AggregatedLastTxDoneTime;
|
||||
TimerTime_t AggregatedTimeOff;
|
||||
|
||||
/*!
|
||||
* Enables/Disables duty cycle management (Test only)
|
||||
*/
|
||||
bool DutyCycleOn;
|
||||
|
||||
/*!
|
||||
* Current channel index
|
||||
*/
|
||||
uint8_t Channel;
|
||||
|
||||
/*!
|
||||
* Current channel index
|
||||
*/
|
||||
uint8_t LastTxChannel;
|
||||
|
||||
/*!
|
||||
* Set to true, if the last uplink was a join request
|
||||
*/
|
||||
bool LastTxIsJoinRequest;
|
||||
|
||||
/*!
|
||||
* Stores the time at LoRaMac initialization.
|
||||
*
|
||||
* \remark Used for the BACKOFF_DC computation.
|
||||
*/
|
||||
TimerTime_t LoRaMacInitializationTime;
|
||||
|
||||
/*!
|
||||
* LoRaMac internal states
|
||||
*/
|
||||
enum eLoRaMacState
|
||||
{
|
||||
LORAMAC_IDLE = 0x00000000,
|
||||
LORAMAC_TX_RUNNING = 0x00000001,
|
||||
LORAMAC_RX = 0x00000002,
|
||||
LORAMAC_ACK_REQ = 0x00000004,
|
||||
LORAMAC_ACK_RETRY = 0x00000008,
|
||||
LORAMAC_TX_DELAYED = 0x00000010,
|
||||
LORAMAC_TX_CONFIG = 0x00000020,
|
||||
LORAMAC_RX_ABORT = 0x00000040,
|
||||
};
|
||||
|
||||
/*!
|
||||
* LoRaMac internal state
|
||||
*/
|
||||
uint32_t LoRaMacState;
|
||||
|
||||
/*!
|
||||
* LoRaMac timer used to check the LoRaMacState (runs every second)
|
||||
*/
|
||||
TimerEvent_t MacStateCheckTimer;
|
||||
|
||||
/*!
|
||||
* LoRaMac upper layer event functions
|
||||
*/
|
||||
LoRaMacPrimitives_t *LoRaMacPrimitives;
|
||||
|
||||
/*!
|
||||
* LoRaMac upper layer callback functions
|
||||
*/
|
||||
LoRaMacCallback_t *LoRaMacCallbacks;
|
||||
|
||||
/*!
|
||||
* LoRaMac duty cycle delayed Tx timer
|
||||
*/
|
||||
TimerEvent_t TxDelayedTimer;
|
||||
|
||||
/*!
|
||||
* LoRaMac reception windows timers
|
||||
*/
|
||||
TimerEvent_t RxWindowTimer1;
|
||||
TimerEvent_t RxWindowTimer2;
|
||||
|
||||
/*!
|
||||
* LoRaMac reception windows delay
|
||||
* \remark normal frame: RxWindowXDelay = ReceiveDelayX - RADIO_WAKEUP_TIME
|
||||
* join frame : RxWindowXDelay = JoinAcceptDelayX - RADIO_WAKEUP_TIME
|
||||
*/
|
||||
uint32_t RxWindow1Delay;
|
||||
uint32_t RxWindow2Delay;
|
||||
|
||||
/*!
|
||||
* LoRaMac Rx windows configuration
|
||||
*/
|
||||
RxConfigParams_t RxWindow1Config;
|
||||
RxConfigParams_t RxWindow2Config;
|
||||
|
||||
/*!
|
||||
* Acknowledge timeout timer. Used for packet retransmissions.
|
||||
*/
|
||||
TimerEvent_t AckTimeoutTimer;
|
||||
|
||||
/*!
|
||||
* Number of trials to get a frame acknowledged
|
||||
*/
|
||||
uint8_t AckTimeoutRetries;
|
||||
|
||||
/*!
|
||||
* Number of trials to get a frame acknowledged
|
||||
*/
|
||||
uint8_t AckTimeoutRetriesCounter;
|
||||
|
||||
/*!
|
||||
* Indicates if the AckTimeout timer has expired or not
|
||||
*/
|
||||
bool AckTimeoutRetry;
|
||||
|
||||
/*!
|
||||
* Last transmission time on air
|
||||
*/
|
||||
TimerTime_t TxTimeOnAir;
|
||||
|
||||
/*!
|
||||
* Number of trials for the Join Request
|
||||
*/
|
||||
uint8_t JoinRequestTrials;
|
||||
|
||||
/*!
|
||||
* Maximum number of trials for the Join Request
|
||||
*/
|
||||
uint8_t MaxJoinRequestTrials;
|
||||
|
||||
/*!
|
||||
* Structure to hold MCPS indication data.
|
||||
*/
|
||||
McpsIndication_t McpsIndication;
|
||||
|
||||
/*!
|
||||
* Structure to hold MCPS confirm data.
|
||||
*/
|
||||
McpsConfirm_t McpsConfirm;
|
||||
|
||||
/*!
|
||||
* Structure to hold MLME indication data.
|
||||
*/
|
||||
MlmeIndication_t MlmeIndication;
|
||||
|
||||
/*!
|
||||
* Structure to hold MLME confirm data.
|
||||
*/
|
||||
MlmeConfirm_t MlmeConfirm;
|
||||
|
||||
/*!
|
||||
* Holds the current rx window slot
|
||||
*/
|
||||
LoRaMacRxSlot_t RxSlot;
|
||||
|
||||
/*!
|
||||
* LoRaMac tx/rx operation state
|
||||
*/
|
||||
LoRaMacFlags_t LoRaMacFlags;
|
||||
|
||||
};
|
||||
|
||||
#endif // __LORAMAC_H__
|
||||
|
|
|
@ -0,0 +1,444 @@
|
|||
/**
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2013 Semtech
|
||||
___ _____ _ ___ _ _____ ___ ___ ___ ___
|
||||
/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
|
||||
\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|
||||
|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
|
||||
embedded.connectivity.solutions===============
|
||||
|
||||
Description: LoRa MAC layer implementation
|
||||
|
||||
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 "LoRaMacCommand.h"
|
||||
#include "LoRaMac.h"
|
||||
|
||||
#if defined(FEATURE_COMMON_PAL)
|
||||
#include "mbed_trace.h"
|
||||
#define TRACE_GROUP "LMACC"
|
||||
#else
|
||||
#define tr_debug(...) (void(0)) //dummies if feature common pal is not added
|
||||
#define tr_info(...) (void(0)) //dummies if feature common pal is not added
|
||||
#define tr_error(...) (void(0)) //dummies if feature common pal is not added
|
||||
#endif //defined(FEATURE_COMMON_PAL)
|
||||
|
||||
/*!
|
||||
* LoRaMAC max EIRP (dBm) table.
|
||||
*/
|
||||
static const uint8_t LoRaMacMaxEirpTable[] = { 8, 10, 12, 13, 14, 16, 18, 20, 21, 24, 26, 27, 29, 30, 33, 36 };
|
||||
|
||||
|
||||
LoRaMacCommand::LoRaMacCommand(LoRaMac& lora_mac)
|
||||
: _lora_mac(lora_mac)
|
||||
{
|
||||
MacCommandsInNextTx = false;
|
||||
MacCommandsBufferIndex = 0;
|
||||
MacCommandsBufferToRepeatIndex = 0;
|
||||
//uint8_t MacCommandsBuffer[LORA_MAC_COMMAND_MAX_LENGTH];
|
||||
//uint8_t MacCommandsBufferToRepeat[LORA_MAC_COMMAND_MAX_LENGTH];
|
||||
}
|
||||
|
||||
LoRaMacCommand::~LoRaMacCommand()
|
||||
{
|
||||
}
|
||||
|
||||
LoRaMacStatus_t LoRaMacCommand::AddMacCommand(uint8_t cmd, uint8_t p1, uint8_t p2)
|
||||
{
|
||||
LoRaMacStatus_t status = LORAMAC_STATUS_BUSY;
|
||||
// The maximum buffer length must take MAC commands to re-send into account.
|
||||
const uint8_t bufLen = LORA_MAC_COMMAND_MAX_LENGTH - MacCommandsBufferToRepeatIndex;
|
||||
|
||||
switch( cmd )
|
||||
{
|
||||
case MOTE_MAC_LINK_CHECK_REQ:
|
||||
if( MacCommandsBufferIndex < bufLen )
|
||||
{
|
||||
MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
|
||||
// No payload for this command
|
||||
status = LORAMAC_STATUS_OK;
|
||||
}
|
||||
break;
|
||||
case MOTE_MAC_LINK_ADR_ANS:
|
||||
if( MacCommandsBufferIndex < ( bufLen - 1 ) )
|
||||
{
|
||||
MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
|
||||
// Margin
|
||||
MacCommandsBuffer[MacCommandsBufferIndex++] = p1;
|
||||
status = LORAMAC_STATUS_OK;
|
||||
}
|
||||
break;
|
||||
case MOTE_MAC_DUTY_CYCLE_ANS:
|
||||
if( MacCommandsBufferIndex < bufLen )
|
||||
{
|
||||
MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
|
||||
// No payload for this answer
|
||||
status = LORAMAC_STATUS_OK;
|
||||
}
|
||||
break;
|
||||
case MOTE_MAC_RX_PARAM_SETUP_ANS:
|
||||
if( MacCommandsBufferIndex < ( bufLen - 1 ) )
|
||||
{
|
||||
MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
|
||||
// Status: Datarate ACK, Channel ACK
|
||||
MacCommandsBuffer[MacCommandsBufferIndex++] = p1;
|
||||
// This is a sticky MAC command answer. Setup indication
|
||||
_lora_mac.SetMlmeScheduleUplinkIndication();
|
||||
status = LORAMAC_STATUS_OK;
|
||||
}
|
||||
break;
|
||||
case MOTE_MAC_DEV_STATUS_ANS:
|
||||
if( MacCommandsBufferIndex < ( bufLen - 2 ) )
|
||||
{
|
||||
MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
|
||||
// 1st byte Battery
|
||||
// 2nd byte Margin
|
||||
MacCommandsBuffer[MacCommandsBufferIndex++] = p1;
|
||||
MacCommandsBuffer[MacCommandsBufferIndex++] = p2;
|
||||
status = LORAMAC_STATUS_OK;
|
||||
}
|
||||
break;
|
||||
case MOTE_MAC_NEW_CHANNEL_ANS:
|
||||
if( MacCommandsBufferIndex < ( bufLen - 1 ) )
|
||||
{
|
||||
MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
|
||||
// Status: Datarate range OK, Channel frequency OK
|
||||
MacCommandsBuffer[MacCommandsBufferIndex++] = p1;
|
||||
status = LORAMAC_STATUS_OK;
|
||||
}
|
||||
break;
|
||||
case MOTE_MAC_RX_TIMING_SETUP_ANS:
|
||||
if( MacCommandsBufferIndex < bufLen )
|
||||
{
|
||||
MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
|
||||
// No payload for this answer
|
||||
// This is a sticky MAC command answer. Setup indication
|
||||
_lora_mac.SetMlmeScheduleUplinkIndication();
|
||||
status = LORAMAC_STATUS_OK;
|
||||
}
|
||||
break;
|
||||
case MOTE_MAC_TX_PARAM_SETUP_ANS:
|
||||
if( MacCommandsBufferIndex < bufLen )
|
||||
{
|
||||
MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
|
||||
// No payload for this answer
|
||||
status = LORAMAC_STATUS_OK;
|
||||
}
|
||||
break;
|
||||
case MOTE_MAC_DL_CHANNEL_ANS:
|
||||
if( MacCommandsBufferIndex < bufLen )
|
||||
{
|
||||
MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
|
||||
// Status: Uplink frequency exists, Channel frequency OK
|
||||
MacCommandsBuffer[MacCommandsBufferIndex++] = p1;
|
||||
// This is a sticky MAC command answer. Setup indication
|
||||
_lora_mac.SetMlmeScheduleUplinkIndication();
|
||||
status = LORAMAC_STATUS_OK;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return LORAMAC_STATUS_SERVICE_UNKNOWN;
|
||||
}
|
||||
if( status == LORAMAC_STATUS_OK )
|
||||
{
|
||||
MacCommandsInNextTx = true;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
void LoRaMacCommand::ClearCommandBuffer()
|
||||
{
|
||||
MacCommandsBufferIndex = 0;
|
||||
}
|
||||
|
||||
uint8_t LoRaMacCommand::GetLength() const
|
||||
{
|
||||
return MacCommandsBufferIndex;
|
||||
}
|
||||
|
||||
uint8_t *LoRaMacCommand::GetMacCommandsBuffer()
|
||||
{
|
||||
return MacCommandsBuffer;
|
||||
}
|
||||
|
||||
void LoRaMacCommand::ParseMacCommandsToRepeat()
|
||||
{
|
||||
uint8_t i = 0;
|
||||
uint8_t cmdCount = 0;
|
||||
|
||||
for( i = 0; i < MacCommandsBufferIndex; i++ )
|
||||
{
|
||||
switch( MacCommandsBuffer[i] )
|
||||
{
|
||||
// STICKY
|
||||
case MOTE_MAC_DL_CHANNEL_ANS:
|
||||
case MOTE_MAC_RX_PARAM_SETUP_ANS:
|
||||
{ // 1 byte payload
|
||||
MacCommandsBufferToRepeat[cmdCount++] = MacCommandsBuffer[i++];
|
||||
MacCommandsBufferToRepeat[cmdCount++] = MacCommandsBuffer[i];
|
||||
break;
|
||||
}
|
||||
case MOTE_MAC_RX_TIMING_SETUP_ANS:
|
||||
{ // 0 byte payload
|
||||
MacCommandsBufferToRepeat[cmdCount++] = MacCommandsBuffer[i];
|
||||
break;
|
||||
}
|
||||
// NON-STICKY
|
||||
case MOTE_MAC_DEV_STATUS_ANS:
|
||||
{ // 2 bytes payload
|
||||
i += 2;
|
||||
break;
|
||||
}
|
||||
case MOTE_MAC_LINK_ADR_ANS:
|
||||
case MOTE_MAC_NEW_CHANNEL_ANS:
|
||||
{ // 1 byte payload
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
case MOTE_MAC_TX_PARAM_SETUP_ANS:
|
||||
case MOTE_MAC_DUTY_CYCLE_ANS:
|
||||
case MOTE_MAC_LINK_CHECK_REQ:
|
||||
{ // 0 byte payload
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( cmdCount > 0 ) {
|
||||
MacCommandsInNextTx = true;
|
||||
} else {
|
||||
MacCommandsInNextTx = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LoRaMacCommand::ClearRepeatBuffer()
|
||||
{
|
||||
MacCommandsBufferToRepeatIndex = 0;
|
||||
}
|
||||
|
||||
void LoRaMacCommand::CopyRepeatCommandsToBuffer()
|
||||
{
|
||||
// Copy the MAC commands which must be re-send into the MAC command buffer
|
||||
memcpy(&MacCommandsBuffer[MacCommandsBufferIndex], MacCommandsBufferToRepeat, MacCommandsBufferToRepeatIndex);
|
||||
MacCommandsBufferIndex += MacCommandsBufferToRepeatIndex;
|
||||
}
|
||||
|
||||
uint8_t LoRaMacCommand::GetRepeatLength() const
|
||||
{
|
||||
return MacCommandsBufferToRepeatIndex;
|
||||
}
|
||||
|
||||
void LoRaMacCommand::ClearMacCommandsInNextTx()
|
||||
{
|
||||
MacCommandsInNextTx = false;
|
||||
}
|
||||
|
||||
bool LoRaMacCommand::IsMacCommandsInNextTx() const
|
||||
{
|
||||
return MacCommandsInNextTx;
|
||||
}
|
||||
|
||||
void LoRaMacCommand::ProcessMacCommands(uint8_t *payload, uint8_t macIndex, uint8_t commandsSize, uint8_t snr,
|
||||
MlmeConfirm_t &MlmeConfirm, LoRaMacCallback_t *LoRaMacCallbacks,
|
||||
LoRaMacParams_t &LoRaMacParams, LoRaPHY &lora_phy)
|
||||
{
|
||||
uint8_t status = 0;
|
||||
|
||||
while( macIndex < commandsSize )
|
||||
{
|
||||
// Decode Frame MAC commands
|
||||
switch( payload[macIndex++] )
|
||||
{
|
||||
case SRV_MAC_LINK_CHECK_ANS:
|
||||
MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK;
|
||||
MlmeConfirm.DemodMargin = payload[macIndex++];
|
||||
MlmeConfirm.NbGateways = payload[macIndex++];
|
||||
break;
|
||||
case SRV_MAC_LINK_ADR_REQ:
|
||||
{
|
||||
LinkAdrReqParams_t linkAdrReq;
|
||||
int8_t linkAdrDatarate = DR_0;
|
||||
int8_t linkAdrTxPower = TX_POWER_0;
|
||||
uint8_t linkAdrNbRep = 0;
|
||||
uint8_t linkAdrNbBytesParsed = 0;
|
||||
|
||||
// Fill parameter structure
|
||||
linkAdrReq.Payload = &payload[macIndex - 1];
|
||||
linkAdrReq.PayloadSize = commandsSize - ( macIndex - 1 );
|
||||
linkAdrReq.AdrEnabled = LoRaMacParams.AdrCtrlOn;
|
||||
linkAdrReq.UplinkDwellTime = LoRaMacParams.UplinkDwellTime;
|
||||
linkAdrReq.CurrentDatarate = LoRaMacParams.ChannelsDatarate;
|
||||
linkAdrReq.CurrentTxPower = LoRaMacParams.ChannelsTxPower;
|
||||
linkAdrReq.CurrentNbRep = LoRaMacParams.ChannelsNbRep;
|
||||
|
||||
// Process the ADR requests
|
||||
status = lora_phy.link_ADR_request(&linkAdrReq, &linkAdrDatarate,
|
||||
&linkAdrTxPower, &linkAdrNbRep,
|
||||
&linkAdrNbBytesParsed);
|
||||
|
||||
if( ( status & 0x07 ) == 0x07 )
|
||||
{
|
||||
LoRaMacParams.ChannelsDatarate = linkAdrDatarate;
|
||||
LoRaMacParams.ChannelsTxPower = linkAdrTxPower;
|
||||
LoRaMacParams.ChannelsNbRep = linkAdrNbRep;
|
||||
}
|
||||
|
||||
// Add the answers to the buffer
|
||||
for( uint8_t i = 0; i < ( linkAdrNbBytesParsed / 5 ); i++ )
|
||||
{
|
||||
AddMacCommand( MOTE_MAC_LINK_ADR_ANS, status, 0 );
|
||||
}
|
||||
// Update MAC index
|
||||
macIndex += linkAdrNbBytesParsed - 1;
|
||||
}
|
||||
break;
|
||||
case SRV_MAC_DUTY_CYCLE_REQ:
|
||||
LoRaMacParams.MaxDCycle = payload[macIndex++];
|
||||
LoRaMacParams.AggregatedDCycle = 1 << LoRaMacParams.MaxDCycle;
|
||||
AddMacCommand( MOTE_MAC_DUTY_CYCLE_ANS, 0, 0 );
|
||||
break;
|
||||
case SRV_MAC_RX_PARAM_SETUP_REQ:
|
||||
{
|
||||
RxParamSetupReqParams_t rxParamSetupReq;
|
||||
status = 0x07;
|
||||
|
||||
rxParamSetupReq.DrOffset = ( payload[macIndex] >> 4 ) & 0x07;
|
||||
rxParamSetupReq.Datarate = payload[macIndex] & 0x0F;
|
||||
macIndex++;
|
||||
|
||||
rxParamSetupReq.Frequency = ( uint32_t )payload[macIndex++];
|
||||
rxParamSetupReq.Frequency |= ( uint32_t )payload[macIndex++] << 8;
|
||||
rxParamSetupReq.Frequency |= ( uint32_t )payload[macIndex++] << 16;
|
||||
rxParamSetupReq.Frequency *= 100;
|
||||
|
||||
// Perform request on region
|
||||
status = lora_phy.setup_rx_params(&rxParamSetupReq);
|
||||
|
||||
if( ( status & 0x07 ) == 0x07 )
|
||||
{
|
||||
LoRaMacParams.Rx2Channel.Datarate = rxParamSetupReq.Datarate;
|
||||
LoRaMacParams.Rx2Channel.Frequency = rxParamSetupReq.Frequency;
|
||||
LoRaMacParams.Rx1DrOffset = rxParamSetupReq.DrOffset;
|
||||
}
|
||||
AddMacCommand( MOTE_MAC_RX_PARAM_SETUP_ANS, status, 0 );
|
||||
}
|
||||
break;
|
||||
case SRV_MAC_DEV_STATUS_REQ:
|
||||
{
|
||||
uint8_t batteryLevel = BAT_LEVEL_NO_MEASURE;
|
||||
if( ( LoRaMacCallbacks != NULL ) && ( LoRaMacCallbacks->GetBatteryLevel != NULL ) )
|
||||
{
|
||||
batteryLevel = LoRaMacCallbacks->GetBatteryLevel( );
|
||||
}
|
||||
AddMacCommand( MOTE_MAC_DEV_STATUS_ANS, batteryLevel, snr );
|
||||
break;
|
||||
}
|
||||
case SRV_MAC_NEW_CHANNEL_REQ:
|
||||
{
|
||||
NewChannelReqParams_t newChannelReq;
|
||||
ChannelParams_t chParam;
|
||||
status = 0x03;
|
||||
|
||||
newChannelReq.ChannelId = payload[macIndex++];
|
||||
newChannelReq.NewChannel = &chParam;
|
||||
|
||||
chParam.Frequency = ( uint32_t )payload[macIndex++];
|
||||
chParam.Frequency |= ( uint32_t )payload[macIndex++] << 8;
|
||||
chParam.Frequency |= ( uint32_t )payload[macIndex++] << 16;
|
||||
chParam.Frequency *= 100;
|
||||
chParam.Rx1Frequency = 0;
|
||||
chParam.DrRange.Value = payload[macIndex++];
|
||||
|
||||
status = lora_phy.request_new_channel(&newChannelReq);
|
||||
|
||||
AddMacCommand( MOTE_MAC_NEW_CHANNEL_ANS, status, 0 );
|
||||
}
|
||||
break;
|
||||
case SRV_MAC_RX_TIMING_SETUP_REQ:
|
||||
{
|
||||
uint8_t delay = payload[macIndex++] & 0x0F;
|
||||
|
||||
if( delay == 0 )
|
||||
{
|
||||
delay++;
|
||||
}
|
||||
LoRaMacParams.ReceiveDelay1 = delay * 1000;
|
||||
LoRaMacParams.ReceiveDelay2 = LoRaMacParams.ReceiveDelay1 + 1000;
|
||||
AddMacCommand( MOTE_MAC_RX_TIMING_SETUP_ANS, 0, 0 );
|
||||
}
|
||||
break;
|
||||
case SRV_MAC_TX_PARAM_SETUP_REQ:
|
||||
{
|
||||
TxParamSetupReqParams_t txParamSetupReq;
|
||||
uint8_t eirpDwellTime = payload[macIndex++];
|
||||
|
||||
txParamSetupReq.UplinkDwellTime = 0;
|
||||
txParamSetupReq.DownlinkDwellTime = 0;
|
||||
|
||||
if( ( eirpDwellTime & 0x20 ) == 0x20 )
|
||||
{
|
||||
txParamSetupReq.DownlinkDwellTime = 1;
|
||||
}
|
||||
if( ( eirpDwellTime & 0x10 ) == 0x10 )
|
||||
{
|
||||
txParamSetupReq.UplinkDwellTime = 1;
|
||||
}
|
||||
txParamSetupReq.MaxEirp = eirpDwellTime & 0x0F;
|
||||
|
||||
// Check the status for correctness
|
||||
if( lora_phy.setup_tx_params(&txParamSetupReq ) != -1 )
|
||||
{
|
||||
// Accept command
|
||||
LoRaMacParams.UplinkDwellTime = txParamSetupReq.UplinkDwellTime;
|
||||
LoRaMacParams.DownlinkDwellTime = txParamSetupReq.DownlinkDwellTime;
|
||||
LoRaMacParams.MaxEirp = LoRaMacMaxEirpTable[txParamSetupReq.MaxEirp];
|
||||
// Add command response
|
||||
AddMacCommand( MOTE_MAC_TX_PARAM_SETUP_ANS, 0, 0 );
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SRV_MAC_DL_CHANNEL_REQ:
|
||||
{
|
||||
DlChannelReqParams_t dlChannelReq;
|
||||
status = 0x03;
|
||||
|
||||
dlChannelReq.ChannelId = payload[macIndex++];
|
||||
dlChannelReq.Rx1Frequency = ( uint32_t )payload[macIndex++];
|
||||
dlChannelReq.Rx1Frequency |= ( uint32_t )payload[macIndex++] << 8;
|
||||
dlChannelReq.Rx1Frequency |= ( uint32_t )payload[macIndex++] << 16;
|
||||
dlChannelReq.Rx1Frequency *= 100;
|
||||
|
||||
status = lora_phy.dl_channel_request(&dlChannelReq);
|
||||
|
||||
AddMacCommand( MOTE_MAC_DL_CHANNEL_ANS, status, 0 );
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Unknown command. ABORT MAC commands processing
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool LoRaMacCommand::IsStickyMacCommandPending()
|
||||
{
|
||||
if( MacCommandsBufferToRepeatIndex > 0 )
|
||||
{
|
||||
// Sticky MAC commands pending
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
|
@ -0,0 +1,175 @@
|
|||
/**
|
||||
* \file LoRaMacCommand.h
|
||||
*
|
||||
* \brief LoRa MAC layer implementation
|
||||
*
|
||||
* \copyright Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*
|
||||
* \code
|
||||
* ______ _
|
||||
* / _____) _ | |
|
||||
* ( (____ _____ ____ _| |_ _____ ____| |__
|
||||
* \____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
* _____) ) ____| | | || |_| ____( (___| | | |
|
||||
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
* (C)2013 Semtech
|
||||
*
|
||||
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
|
||||
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
|
||||
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|
||||
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
|
||||
* embedded.connectivity.solutions===============
|
||||
*
|
||||
* \endcode
|
||||
*
|
||||
* \author Miguel Luis ( Semtech )
|
||||
*
|
||||
* \author Gregory Cristian ( Semtech )
|
||||
*
|
||||
* \author Daniel Jaeckle ( STACKFORCE )
|
||||
*
|
||||
* \defgroup LORAMAC LoRa MAC layer implementation
|
||||
* This module specifies the API implementation of the LoRaMAC layer.
|
||||
* This is a placeholder for a detailed description of the LoRaMac
|
||||
* layer and the supported features.
|
||||
*
|
||||
* Copyright (c) 2017, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
#ifndef __LORAMACCOMMAND_H__
|
||||
#define __LORAMACCOMMAND_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "lorawan/system/lorawan_data_structures.h"
|
||||
#include "lorawan/lorastack/phy/LoRaPHY.h"
|
||||
|
||||
/*!
|
||||
* Maximum MAC commands buffer size
|
||||
*/
|
||||
#define LORA_MAC_COMMAND_MAX_LENGTH 128
|
||||
|
||||
class LoRaMac;
|
||||
|
||||
class LoRaMacCommand
|
||||
{
|
||||
public:
|
||||
LoRaMacCommand(LoRaMac &lora_mac);
|
||||
~LoRaMacCommand();
|
||||
|
||||
/*!
|
||||
* \brief Adds a new MAC command to be sent.
|
||||
*
|
||||
* \Remark MAC layer internal function
|
||||
*
|
||||
* \param [in] cmd MAC command to be added
|
||||
* [MOTE_MAC_LINK_CHECK_REQ,
|
||||
* MOTE_MAC_LINK_ADR_ANS,
|
||||
* MOTE_MAC_DUTY_CYCLE_ANS,
|
||||
* MOTE_MAC_RX2_PARAM_SET_ANS,
|
||||
* MOTE_MAC_DEV_STATUS_ANS
|
||||
* MOTE_MAC_NEW_CHANNEL_ANS]
|
||||
* \param [in] p1 1st parameter ( optional depends on the command )
|
||||
* \param [in] p2 2nd parameter ( optional depends on the command )
|
||||
*
|
||||
* \retval status Function status [0: OK, 1: Unknown command, 2: Buffer full]
|
||||
*/
|
||||
LoRaMacStatus_t AddMacCommand(uint8_t cmd, uint8_t p1, uint8_t p2);
|
||||
|
||||
/*!
|
||||
* \brief Clear MAC command buffer.
|
||||
*/
|
||||
void ClearCommandBuffer();
|
||||
|
||||
/*!
|
||||
* \brief Get the length of MAC commands
|
||||
*
|
||||
* \retval status Length of used MAC buffer (bytes)
|
||||
*/
|
||||
uint8_t GetLength() const;
|
||||
|
||||
/*!
|
||||
* \brief Get MAC command buffer
|
||||
*
|
||||
* \retval Pointer to MAC command buffer
|
||||
*/
|
||||
uint8_t *GetMacCommandsBuffer();
|
||||
|
||||
/*!
|
||||
* \brief Parses the MAC commands which must be resent.
|
||||
*/
|
||||
void ParseMacCommandsToRepeat();
|
||||
|
||||
/*!
|
||||
* \brief Clear MAC command repeat buffer.
|
||||
*/
|
||||
void ClearRepeatBuffer();
|
||||
|
||||
/*!
|
||||
* \brief Copy MAC commands from repeat buffer to actual MAC command buffer.
|
||||
*/
|
||||
void CopyRepeatCommandsToBuffer();
|
||||
|
||||
/*!
|
||||
* \brief Get the length of MAC commands in repeat buffer
|
||||
*
|
||||
* \retval status Length of used MAC Repeat buffer (bytes)
|
||||
*/
|
||||
uint8_t GetRepeatLength() const;
|
||||
|
||||
/*!
|
||||
* \brief Clear MAC commands in next TX.
|
||||
*/
|
||||
void ClearMacCommandsInNextTx();
|
||||
|
||||
/*!
|
||||
* \brief Check if MAC command buffer has commands to be sent in next TX
|
||||
*
|
||||
* \retval status True: buffer has MAC commands to be sent, false: no commands in buffer]
|
||||
*/
|
||||
bool IsMacCommandsInNextTx() const;
|
||||
|
||||
/*!
|
||||
* \brief Decodes MAC commands in the fOpts field and in the payload
|
||||
*/
|
||||
void ProcessMacCommands(uint8_t *payload, uint8_t macIndex, uint8_t commandsSize, uint8_t snr,
|
||||
MlmeConfirm_t &MlmeConfirm, LoRaMacCallback_t *LoRaMacCallbacks,
|
||||
LoRaMacParams_t &LoRaMacParams, LoRaPHY &lora_phy);
|
||||
|
||||
/*!
|
||||
* \brief Verifies if sticky MAC commands are pending.
|
||||
*
|
||||
* \retval [true: sticky MAC commands pending, false: No MAC commands pending]
|
||||
*/
|
||||
bool IsStickyMacCommandPending();
|
||||
|
||||
private:
|
||||
LoRaMac& _lora_mac;
|
||||
|
||||
/*!
|
||||
* Indicates if the MAC layer wants to send MAC commands
|
||||
*/
|
||||
bool MacCommandsInNextTx;
|
||||
|
||||
/*!
|
||||
* Contains the current MacCommandsBuffer index
|
||||
*/
|
||||
uint8_t MacCommandsBufferIndex;
|
||||
|
||||
/*!
|
||||
* Contains the current MacCommandsBuffer index for MAC commands to repeat
|
||||
*/
|
||||
uint8_t MacCommandsBufferToRepeatIndex;
|
||||
|
||||
/*!
|
||||
* Buffer containing the MAC layer commands
|
||||
*/
|
||||
uint8_t MacCommandsBuffer[LORA_MAC_COMMAND_MAX_LENGTH];
|
||||
|
||||
/*!
|
||||
* Buffer containing the MAC layer commands which must be repeated
|
||||
*/
|
||||
uint8_t MacCommandsBufferToRepeat[LORA_MAC_COMMAND_MAX_LENGTH];
|
||||
};
|
||||
|
||||
#endif //__LORAMACCOMMAND_H__
|
|
@ -1,68 +0,0 @@
|
|||
/**
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2013 Semtech
|
||||
___ _____ _ ___ _ _____ ___ ___ ___ ___
|
||||
/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
|
||||
\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|
||||
|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
|
||||
embedded.connectivity.solutions===============
|
||||
|
||||
Description: LoRa MAC layer test function implementation
|
||||
|
||||
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 __LORAMACTEST_H__
|
||||
#define __LORAMACTEST_H__
|
||||
|
||||
/**
|
||||
* \brief Enabled or disables the reception windows
|
||||
*
|
||||
* \details This is a test function. It shall be used for testing purposes only.
|
||||
* Changing this attribute may lead to a non-conformance LoRaMac operation.
|
||||
*
|
||||
* \param [in] enable - Enabled or disables the reception windows
|
||||
*/
|
||||
void LoRaMacTestRxWindowsOn( bool enable );
|
||||
|
||||
/**
|
||||
* \brief Enables the MIC field test
|
||||
*
|
||||
* \details This is a test function. It shall be used for testing purposes only.
|
||||
* Changing this attribute may lead to a non-conformance LoRaMac operation.
|
||||
*
|
||||
* \param [in] txPacketCounter - Fixed Tx packet counter value
|
||||
*/
|
||||
void LoRaMacTestSetMic( uint16_t txPacketCounter );
|
||||
|
||||
/**
|
||||
* \brief Enabled or disables the duty cycle
|
||||
*
|
||||
* \details This is a test function. It shall be used for testing purposes only.
|
||||
* Changing this attribute may lead to a non-conformance LoRaMac operation.
|
||||
*
|
||||
* \param [in] enable - Enabled or disables the duty cycle
|
||||
*/
|
||||
void LoRaMacTestSetDutyCycleOn( bool enable );
|
||||
|
||||
/**
|
||||
* \brief Sets the channel index
|
||||
*
|
||||
* \details This is a test function. It shall be used for testing purposes only.
|
||||
* Changing this attribute may lead to a non-conformance LoRaMac operation.
|
||||
*
|
||||
* \param [in] channel - Channel index
|
||||
*/
|
||||
void LoRaMacTestSetChannel( uint8_t channel );
|
||||
|
||||
#endif // __LORAMACTEST_H__
|
|
@ -355,8 +355,8 @@ uint8_t LoRaPHY::verify_link_ADR_req( RegionCommonLinkAdrReqVerifyParams_t* veri
|
|||
if( status == 0x07 )
|
||||
{
|
||||
if( nbRepetitions == 0 )
|
||||
{ // Keep the current one
|
||||
nbRepetitions = verifyParams->CurrentNbRep;
|
||||
{ // Restore the default value according to the LoRaWAN specification
|
||||
nbRepetitions = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -196,9 +196,9 @@
|
|||
|
||||
/*!
|
||||
* Band 0 definition
|
||||
* { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
|
||||
* { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
|
||||
*/
|
||||
#define AS923_BAND0 { 100, AS923_MAX_TX_POWER, 0, 0 } // 1.0 %
|
||||
#define AS923_BAND0 { 100, AS923_MAX_TX_POWER, 0, 0, 0 } // 1.0 %
|
||||
|
||||
/*!
|
||||
* LoRaMac default channel 1
|
||||
|
@ -823,7 +823,7 @@ bool LoRaPHYAS923::rx_config(RxConfigParams_t* rxConfig, int8_t* datarate)
|
|||
return false;
|
||||
}
|
||||
|
||||
if( rxConfig->Window == 0 )
|
||||
if( rxConfig->RxSlot == RX_SLOT_WIN_1 )
|
||||
{
|
||||
// Apply window 1 frequency
|
||||
frequency = Channels[rxConfig->Channel].Frequency;
|
||||
|
|
|
@ -166,9 +166,9 @@
|
|||
|
||||
/*!
|
||||
* Band 0 definition
|
||||
* { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
|
||||
* { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
|
||||
*/
|
||||
#define AU915_BAND0 { 1, AU915_MAX_TX_POWER, 0, 0 } // 100.0 %
|
||||
#define AU915_BAND0 { 1, AU915_MAX_TX_POWER, 0, 0, 0 } // 100.0 %
|
||||
|
||||
/*!
|
||||
* Defines the first channel for RX window 1 for US band
|
||||
|
@ -638,7 +638,7 @@ bool LoRaPHYAU915::rx_config(RxConfigParams_t* rxConfig, int8_t* datarate)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (rxConfig->Window == 0) {
|
||||
if (rxConfig->RxSlot == RX_SLOT_WIN_1) {
|
||||
// Apply window 1 frequency
|
||||
frequency = AU915_FIRST_RX1_CHANNEL
|
||||
+ (rxConfig->Channel % 8) * AU915_STEPWIDTH_RX1_CHANNEL;
|
||||
|
|
|
@ -166,9 +166,9 @@
|
|||
|
||||
/*!
|
||||
* Band 0 definition
|
||||
* { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
|
||||
* { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
|
||||
*/
|
||||
#define CN470_BAND0 { 1, CN470_MAX_TX_POWER, 0, 0 } // 100.0 %
|
||||
#define CN470_BAND0 { 1, CN470_MAX_TX_POWER, 0, 0, 0 } // 100.0 %
|
||||
|
||||
/*!
|
||||
* Defines the first channel for RX window 1 for CN470 band
|
||||
|
@ -636,7 +636,7 @@ bool LoRaPHYCN470::rx_config(RxConfigParams_t* rxConfig, int8_t* datarate)
|
|||
return false;
|
||||
}
|
||||
|
||||
if( rxConfig->Window == 0 )
|
||||
if( rxConfig->RxSlot == RX_SLOT_WIN_1 )
|
||||
{
|
||||
// Apply window 1 frequency
|
||||
frequency = CN470_FIRST_RX1_CHANNEL + ( rxConfig->Channel % 48 ) * CN470_STEPWIDTH_RX1_CHANNEL;
|
||||
|
|
|
@ -184,9 +184,9 @@
|
|||
|
||||
/*!
|
||||
* Band 0 definition
|
||||
* { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
|
||||
* { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
|
||||
*/
|
||||
#define CN779_BAND0 { 100, CN779_MAX_TX_POWER, 0, 0 } // 1.0 %
|
||||
#define CN779_BAND0 { 100, CN779_MAX_TX_POWER, 0, 0, 0 } // 1.0 %
|
||||
|
||||
/*!
|
||||
* LoRaMac default channel 1
|
||||
|
@ -730,7 +730,7 @@ bool LoRaPHYCN779::rx_config(RxConfigParams_t* rxConfig, int8_t* datarate)
|
|||
return false;
|
||||
}
|
||||
|
||||
if( rxConfig->Window == 0 )
|
||||
if( rxConfig->RxSlot == RX_SLOT_WIN_1)
|
||||
{
|
||||
// Apply window 1 frequency
|
||||
frequency = Channels[rxConfig->Channel].Frequency;
|
||||
|
|
|
@ -183,9 +183,9 @@
|
|||
|
||||
/*!
|
||||
* Band 0 definition
|
||||
* { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
|
||||
* { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
|
||||
*/
|
||||
#define EU433_BAND0 { 100, EU433_MAX_TX_POWER, 0, 0 } // 1.0 %
|
||||
#define EU433_BAND0 { 100, EU433_MAX_TX_POWER, 0, 0, 0 } // 1.0 %
|
||||
|
||||
/*!
|
||||
* LoRaMac default channel 1
|
||||
|
@ -731,7 +731,7 @@ bool LoRaPHYEU433::rx_config(RxConfigParams_t* rxConfig, int8_t* datarate)
|
|||
return false;
|
||||
}
|
||||
|
||||
if( rxConfig->Window == 0 )
|
||||
if( rxConfig->RxSlot == RX_SLOT_WIN_1 )
|
||||
{
|
||||
// Apply window 1 frequency
|
||||
frequency = Channels[rxConfig->Channel].Frequency;
|
||||
|
|
|
@ -179,33 +179,33 @@
|
|||
|
||||
/*!
|
||||
* Band 0 definition
|
||||
* { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
|
||||
* { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
|
||||
*/
|
||||
#define EU868_BAND0 { 100 , EU868_MAX_TX_POWER, 0, 0 } // 1.0 %
|
||||
#define EU868_BAND0 { 100 , EU868_MAX_TX_POWER, 0, 0, 0 } // 1.0 %
|
||||
|
||||
/*!
|
||||
* Band 1 definition
|
||||
* { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
|
||||
* { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
|
||||
*/
|
||||
#define EU868_BAND1 { 100 , EU868_MAX_TX_POWER, 0, 0 } // 1.0 %
|
||||
#define EU868_BAND1 { 100 , EU868_MAX_TX_POWER, 0, 0, 0 } // 1.0 %
|
||||
|
||||
/*!
|
||||
* Band 2 definition
|
||||
* Band = { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
|
||||
* Band = { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
|
||||
*/
|
||||
#define EU868_BAND2 { 1000, EU868_MAX_TX_POWER, 0, 0 } // 0.1 %
|
||||
#define EU868_BAND2 { 1000, EU868_MAX_TX_POWER, 0, 0, 0 } // 0.1 %
|
||||
|
||||
/*!
|
||||
* Band 2 definition
|
||||
* Band = { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
|
||||
* Band 3 definition
|
||||
* Band = { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
|
||||
*/
|
||||
#define EU868_BAND3 { 10 , EU868_MAX_TX_POWER, 0, 0 } // 10.0 %
|
||||
#define EU868_BAND3 { 10 , EU868_MAX_TX_POWER, 0, 0, 0 } // 10.0 %
|
||||
|
||||
/*!
|
||||
* Band 2 definition
|
||||
* Band = { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
|
||||
* Band 4 definition
|
||||
* Band = { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
|
||||
*/
|
||||
#define EU868_BAND4 { 100 , EU868_MAX_TX_POWER, 0, 0 } // 1.0 %
|
||||
#define EU868_BAND4 { 100 , EU868_MAX_TX_POWER, 0, 0, 0 } // 1.0 %
|
||||
|
||||
/*!
|
||||
* LoRaMac default channel 1
|
||||
|
@ -785,7 +785,7 @@ bool LoRaPHYEU868::rx_config(RxConfigParams_t* rxConfig, int8_t* datarate)
|
|||
return false;
|
||||
}
|
||||
|
||||
if( rxConfig->Window == 0 )
|
||||
if( rxConfig->RxSlot == RX_SLOT_WIN_1 )
|
||||
{
|
||||
// Apply window 1 frequency
|
||||
frequency = Channels[rxConfig->Channel].Frequency;
|
||||
|
|
|
@ -181,9 +181,9 @@
|
|||
|
||||
/*!
|
||||
* Band 0 definition
|
||||
* { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
|
||||
* { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
|
||||
*/
|
||||
#define IN865_BAND0 { 1 , IN865_MAX_TX_POWER, 0, 0 } // 100.0 %
|
||||
#define IN865_BAND0 { 1 , IN865_MAX_TX_POWER, 0, 0, 0 } // 100.0 %
|
||||
|
||||
/*!
|
||||
* LoRaMac default channel 1
|
||||
|
@ -738,7 +738,7 @@ bool LoRaPHYIN865::rx_config(RxConfigParams_t* rxConfig, int8_t* datarate)
|
|||
return false;
|
||||
}
|
||||
|
||||
if( rxConfig->Window == 0 )
|
||||
if( rxConfig->RxSlot == RX_SLOT_WIN_1 )
|
||||
{
|
||||
// Apply window 1 frequency
|
||||
frequency = Channels[rxConfig->Channel].Frequency;
|
||||
|
|
|
@ -186,9 +186,9 @@
|
|||
|
||||
/*!
|
||||
* Band 0 definition
|
||||
* { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
|
||||
* { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
|
||||
*/
|
||||
#define KR920_BAND0 { 1 , KR920_MAX_TX_POWER, 0, 0 } // 100.0 %
|
||||
#define KR920_BAND0 { 1 , KR920_MAX_TX_POWER, 0, 0, 0 } // 100.0 %
|
||||
|
||||
/*!
|
||||
* LoRaMac default channel 1
|
||||
|
@ -759,7 +759,7 @@ bool LoRaPHYKR920::rx_config(RxConfigParams_t* rxConfig, int8_t* datarate)
|
|||
return false;
|
||||
}
|
||||
|
||||
if( rxConfig->Window == 0 )
|
||||
if( rxConfig->RxSlot == RX_SLOT_WIN_1 )
|
||||
{
|
||||
// Apply window 1 frequency
|
||||
frequency = Channels[rxConfig->Channel].Frequency;
|
||||
|
|
|
@ -161,9 +161,9 @@
|
|||
|
||||
/*!
|
||||
* Band 0 definition
|
||||
* { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
|
||||
* { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
|
||||
*/
|
||||
#define US915_BAND0 { 1, US915_MAX_TX_POWER, 0, 0 } // 100.0 %
|
||||
#define US915_BAND0 { 1, US915_MAX_TX_POWER, 0, 0, 0 } // 100.0 %
|
||||
|
||||
/*!
|
||||
* Defines the first channel for RX window 1 for US band
|
||||
|
@ -683,7 +683,7 @@ bool LoRaPHYUS915::rx_config(RxConfigParams_t* rxConfig, int8_t* datarate)
|
|||
return false;
|
||||
}
|
||||
|
||||
if( rxConfig->Window == 0 )
|
||||
if( rxConfig->RxSlot == RX_SLOT_WIN_1 )
|
||||
{
|
||||
// Apply window 1 frequency
|
||||
frequency = US915_FIRST_RX1_CHANNEL + ( rxConfig->Channel % 8 ) * US915_STEPWIDTH_RX1_CHANNEL;
|
||||
|
|
|
@ -162,9 +162,9 @@
|
|||
|
||||
/*!
|
||||
* Band 0 definition
|
||||
* { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
|
||||
* { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
|
||||
*/
|
||||
#define US915_HYBRID_BAND0 { 1, US915_HYBRID_MAX_TX_POWER, 0, 0 } // 100.0 %
|
||||
#define US915_HYBRID_BAND0 { 1, US915_HYBRID_MAX_TX_POWER, 0, 0, 0 } // 100.0 %
|
||||
|
||||
/*!
|
||||
* Defines the first channel for RX window 1 for US band
|
||||
|
@ -771,7 +771,7 @@ bool LoRaPHYUS915Hybrid::rx_config(RxConfigParams_t* rxConfig, int8_t* datarate)
|
|||
return false;
|
||||
}
|
||||
|
||||
if( rxConfig->Window == 0 )
|
||||
if( rxConfig->RxSlot == RX_SLOT_WIN_1 )
|
||||
{
|
||||
// Apply window 1 frequency
|
||||
frequency = US915_HYBRID_FIRST_RX1_CHANNEL + ( rxConfig->Channel % 8 ) * US915_HYBRID_STEPWIDTH_RX1_CHANNEL;
|
||||
|
|
|
@ -908,9 +908,9 @@ typedef struct sRxConfigParams
|
|||
*/
|
||||
bool RxContinuous;
|
||||
/*!
|
||||
* Sets the RX window. 0: RX window 1, 1: RX window 2.
|
||||
* Sets the RX window.
|
||||
*/
|
||||
bool Window;
|
||||
LoRaMacRxSlot_t RxSlot;
|
||||
}RxConfigParams_t;
|
||||
|
||||
/*!
|
||||
|
|
|
@ -101,12 +101,4 @@ TimerTime_t TimerGetCurrentTime( void );
|
|||
*/
|
||||
TimerTime_t TimerGetElapsedTime( TimerTime_t savedTime );
|
||||
|
||||
/*!
|
||||
* \brief Return the time elapsed since a fixed moment in time.
|
||||
*
|
||||
* \param [in] eventInFuture The fixed moment in the future.
|
||||
* \retval time The difference between now and a future event.
|
||||
*/
|
||||
TimerTime_t TimerGetFutureTime( TimerTime_t eventInFuture );
|
||||
|
||||
#endif // MBED_LORAWAN_SYS_TIMER_H__
|
||||
|
|
|
@ -218,6 +218,29 @@ typedef struct sRx2ChannelParams
|
|||
uint8_t Datarate;
|
||||
}Rx2ChannelParams_t;
|
||||
|
||||
/*!
|
||||
* LoRaMAC receive window enumeration
|
||||
*/
|
||||
typedef enum eLoRaMacRxSlot
|
||||
{
|
||||
/*!
|
||||
* LoRaMAC receive window 1
|
||||
*/
|
||||
RX_SLOT_WIN_1,
|
||||
/*!
|
||||
* LoRaMAC receive window 2
|
||||
*/
|
||||
RX_SLOT_WIN_2,
|
||||
/*!
|
||||
* LoRaMAC receive window 2 for class c - continuous listening
|
||||
*/
|
||||
RX_SLOT_WIN_CLASS_C,
|
||||
/*!
|
||||
* LoRaMAC class b ping slot window
|
||||
*/
|
||||
RX_SLOT_WIN_PING_SLOT
|
||||
}LoRaMacRxSlot_t;
|
||||
|
||||
/*!
|
||||
* The global MAC layer parameters.
|
||||
*/
|
||||
|
@ -290,6 +313,21 @@ typedef struct sLoRaMacParams
|
|||
* The antenna gain of the node.
|
||||
*/
|
||||
float AntennaGain;
|
||||
|
||||
/*!
|
||||
* Maximum duty cycle
|
||||
* \remark Possibility to shutdown the device.
|
||||
*/
|
||||
uint8_t MaxDCycle;
|
||||
/*!
|
||||
* Aggregated duty cycle management
|
||||
*/
|
||||
uint16_t AggregatedDCycle;
|
||||
|
||||
/*!
|
||||
* LoRaMac ADR control status
|
||||
*/
|
||||
bool AdrCtrlOn;
|
||||
}LoRaMacParams_t;
|
||||
|
||||
/*!
|
||||
|
@ -639,6 +677,10 @@ typedef union eLoRaMacFlags_t
|
|||
* MLME-Req pending
|
||||
*/
|
||||
uint8_t MlmeReq : 1;
|
||||
/*!
|
||||
* MLME-Ind pending
|
||||
*/
|
||||
uint8_t MlmeInd : 1;
|
||||
/*!
|
||||
* MAC cycle done
|
||||
*/
|
||||
|
@ -908,7 +950,7 @@ typedef struct sMcpsIndication
|
|||
*
|
||||
* [0: Rx window 1, 1: Rx window 2]
|
||||
*/
|
||||
uint8_t RxSlot;
|
||||
LoRaMacRxSlot_t RxSlot;
|
||||
/*!
|
||||
* Set if an acknowledgement was received.
|
||||
*/
|
||||
|
@ -926,10 +968,11 @@ typedef struct sMcpsIndication
|
|||
* specific MAC management service:
|
||||
*
|
||||
* Name | Request | Indication | Response | Confirm
|
||||
* --------------------- | :-----: | :--------: | :------: | :-----:
|
||||
* ---------------------------- | :-----: | :--------: | :------: | :-----:
|
||||
* \ref MLME_JOIN | YES | NO | NO | YES
|
||||
* \ref MLME_LINK_CHECK | YES | NO | NO | YES
|
||||
* \ref MLME_TXCW | YES | NO | NO | YES
|
||||
* \ref MLME_SCHEDULE_UPLINK | NO | YES | NO | NO
|
||||
*
|
||||
* The following table provides links to the function implementations of the
|
||||
* related MLME primitives.
|
||||
|
@ -938,6 +981,7 @@ typedef struct sMcpsIndication
|
|||
* ---------------- | :---------------------:
|
||||
* MLME-Request | \ref LoRaMacMlmeRequest
|
||||
* MLME-Confirm | MacMlmeConfirm in \ref LoRaMacPrimitives_t
|
||||
* MLME-Indication | MacMlmeIndication in \ref LoRaMacPrimitives_t
|
||||
*/
|
||||
typedef enum eMlme
|
||||
{
|
||||
|
@ -965,6 +1009,11 @@ typedef enum eMlme
|
|||
* LoRaWAN end-device certification.
|
||||
*/
|
||||
MLME_TXCW_1,
|
||||
/*!
|
||||
* Indicates that the application shall perform an uplink as
|
||||
* soon as possible.
|
||||
*/
|
||||
MLME_SCHEDULE_UPLINK
|
||||
}Mlme_t;
|
||||
|
||||
/*!
|
||||
|
@ -1073,6 +1122,17 @@ typedef struct sMlmeConfirm
|
|||
uint8_t NbRetries;
|
||||
}MlmeConfirm_t;
|
||||
|
||||
/*!
|
||||
* LoRaMAC MLME-Indication primitive
|
||||
*/
|
||||
typedef struct sMlmeIndication
|
||||
{
|
||||
/*!
|
||||
* MLME-Indication type
|
||||
*/
|
||||
Mlme_t MlmeIndication;
|
||||
}MlmeIndication_t;
|
||||
|
||||
/*!
|
||||
* LoRa MAC Information Base (MIB).
|
||||
*
|
||||
|
@ -1618,6 +1678,13 @@ typedef struct sLoRaMacPrimitives
|
|||
* \param [OUT] MLME-Confirm parameters.
|
||||
*/
|
||||
mbed::Callback<void(MlmeConfirm_t*)> MacMlmeConfirm;
|
||||
|
||||
/*!
|
||||
* \brief MLME-Indication primitive
|
||||
*
|
||||
* \param [OUT] MLME-Indication parameters
|
||||
*/
|
||||
mbed::Callback<void(MlmeIndication_t*)> MacMlmeIndication;
|
||||
}LoRaMacPrimitives_t;
|
||||
|
||||
/*!
|
||||
|
|
|
@ -131,17 +131,18 @@ typedef struct radio_settings {
|
|||
*
|
||||
*/
|
||||
typedef struct radio_events {
|
||||
/* Tx Done callback prototype.
|
||||
*
|
||||
/**
|
||||
* Callback when Transmission is done
|
||||
*/
|
||||
void (*tx_done) (void);
|
||||
mbed::Callback<void()> tx_done;
|
||||
|
||||
/* Tx Timeout callback prototype.
|
||||
*
|
||||
/**
|
||||
* Callback when Transmission is timed out
|
||||
*/
|
||||
void (*tx_timeout) (void);
|
||||
mbed::Callback<void()> tx_timeout;
|
||||
|
||||
/* Rx Done callback prototype.
|
||||
/**
|
||||
* Rx Done callback prototype.
|
||||
*
|
||||
* @param payload Received buffer pointer.
|
||||
* @param size Received buffer size.
|
||||
|
@ -150,29 +151,31 @@ typedef struct radio_events {
|
|||
* FSK : N/A (set to 0)
|
||||
* LoRa: SNR value in dB
|
||||
*/
|
||||
void (*rx_done) (uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr);
|
||||
mbed::Callback<void(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr)> rx_done;
|
||||
|
||||
/* Rx Timeout callback prototype.
|
||||
*
|
||||
/**
|
||||
* Callback when Reception is timed out
|
||||
*/
|
||||
void (*rx_timeout) (void);
|
||||
mbed::Callback<void()> rx_timeout;
|
||||
|
||||
/* Rx Error callback prototype.
|
||||
*
|
||||
/**
|
||||
* Callback when Reception ends up in error
|
||||
*/
|
||||
void (*rx_error) (void);
|
||||
mbed::Callback<void()> rx_error;
|
||||
|
||||
/* FHSS Change Channel callback prototype.
|
||||
/**
|
||||
* FHSS Change Channel callback prototype.
|
||||
*
|
||||
* @param current_channel The index number of the current channel.
|
||||
*/
|
||||
void (*fhss_change_channel) (uint8_t current_channel);
|
||||
mbed::Callback<void(uint8_t current_channel)> fhss_change_channel;
|
||||
|
||||
/* CAD Done callback prototype.
|
||||
/**
|
||||
* CAD Done callback prototype.
|
||||
*
|
||||
* @param channel_activity_detected Channel activity detected during the CAD.
|
||||
* @param channel_busy True, if Channel activity detected.
|
||||
*/
|
||||
void (*cad_done) (bool channel_activity_detected);
|
||||
mbed::Callback<void(bool channel_busy)> cad_done;
|
||||
} radio_events_t;
|
||||
|
||||
/**
|
||||
|
|
|
@ -64,6 +64,39 @@ public:
|
|||
*/
|
||||
virtual lora_mac_status_t disconnect() = 0;
|
||||
|
||||
/** Validate the connectivity with the network.
|
||||
*
|
||||
* Application may use this API to submit a request to the stack for
|
||||
* validation of its connectivity to a Network Server. Under the hood, this
|
||||
* API schedules a Link Check Request command (LinkCheckReq) for the network
|
||||
* server and once the response, i.e., LinkCheckAns MAC command is received
|
||||
* from the Network Server, user provided method is called.
|
||||
*
|
||||
* This API is usable only when the link check response is callback set by
|
||||
* the application. See add_lora_app_callbacks API. If the above mentioned
|
||||
* callback is not set, a LORA_MAC_STATUS_PARAMETER_INVALID error is thrown.
|
||||
*
|
||||
* First parameter to callback function is the demodulation margin and
|
||||
* the second parameter is the number of gateways that successfully received
|
||||
* the last request.
|
||||
*
|
||||
* A 'Link Check Request' MAC command remains set for every subsequent
|
||||
* transmission, until/unless application explicitly turns it off using
|
||||
* remove_link_check_request() API.
|
||||
*
|
||||
* @param cb A callback function to receive link check response
|
||||
* @return LORA_MAC_STATUS_OK on successfully queuing a request, or
|
||||
* a negative error code on failure.
|
||||
*
|
||||
*/
|
||||
virtual lora_mac_status_t add_link_check_request() = 0;
|
||||
|
||||
/** Detaches Link Request MAC command.
|
||||
*
|
||||
* Removes sticky MAC command for link check request.
|
||||
*/
|
||||
virtual void remove_link_check_request() = 0;
|
||||
|
||||
/** Sets up a particular data rate of choice
|
||||
*
|
||||
* @param data_rate Intended data rate e.g., DR_0, DR_1 etc.
|
||||
|
|
Loading…
Reference in New Issue