Merge pull request #6059 from hasnainvirk/pr_branch

Enabling LoRaWAN technology in Mbed-OS 5.8
pull/6087/head
Cruz Monrreal 2018-02-13 14:15:03 -06:00 committed by GitHub
commit 213d2b649e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
48 changed files with 9475 additions and 18549 deletions

View File

@ -18,6 +18,9 @@
#ifndef LORARADIO_H_ #ifndef LORARADIO_H_
#define LORARADIO_H_ #define LORARADIO_H_
#include "platform/Callback.h"
#include "PinNames.h"
/** /**
* Structure to hold RF controls for LoRa Radio. * Structure to hold RF controls for LoRa Radio.
* SX1276 have an extra control for the crystal (used in DOSCO-L072CZ) * SX1276 have an extra control for the crystal (used in DOSCO-L072CZ)
@ -131,17 +134,18 @@ typedef struct radio_settings {
* *
*/ */
typedef struct radio_events { 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 payload Received buffer pointer.
* @param size Received buffer size. * @param size Received buffer size.
@ -150,29 +154,31 @@ typedef struct radio_events {
* FSK : N/A (set to 0) * FSK : N/A (set to 0)
* LoRa: SNR value in dB * 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. *
*/ * @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; } radio_events_t;
/** /**

View File

@ -31,20 +31,20 @@ public:
* *
* @param queue A pointer to EventQueue provided by the application. * @param queue A pointer to EventQueue provided by the application.
* *
* @return LORA_MAC_STATUS_OK on success, a negative error code on * @return LORAWAN_STATUS_OK on success, a negative error code on
* failure. * failure.
*/ */
virtual lora_mac_status_t initialize(events::EventQueue *queue) = 0; virtual lorawan_status_t initialize(events::EventQueue *queue) = 0;
/** Connect OTAA or ABP by setup. /** Connect OTAA or ABP by setup.
* *
* Connect by Over The Air Activation or Activation By Personalization. * Connect by Over The Air Activation or Activation By Personalization.
* The connection type is selected at the setup. * The connection type is selected at the setup.
* *
* @return LORA_MAC_STATUS_OK on success, a negative error code on * @return LORAWAN_STATUS_OK on success, a negative error code on
* failure. * failure.
*/ */
virtual lora_mac_status_t connect() = 0; virtual lorawan_status_t connect() = 0;
/** Connect OTAA or ABP by parameters /** Connect OTAA or ABP by parameters
* *
@ -53,46 +53,78 @@ public:
* You need to define the parameters in the main application. * You need to define the parameters in the main application.
* *
* @param connect Options how end-device will connect to gateway * @param connect Options how end-device will connect to gateway
* @return LORA_MAC_STATUS_OK on success, negative error code * @return LORAWAN_STATUS_OK on success, negative error code
* on failure * on failure
*/ */
virtual lora_mac_status_t connect(const lorawan_connect_t &connect) = 0; virtual lorawan_status_t connect(const lorawan_connect_t &connect) = 0;
/** Disconnects the current session. /** Disconnects the current session.
* *
* @return LORA_MAC_STATUS_OK on success, a negative error code on failure. * @return LORAWAN_STATUS_OK on success, a negative error code on failure.
*/ */
virtual lora_mac_status_t disconnect() = 0; virtual lorawan_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 LORAWAN_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 LORAWAN_STATUS_OK on successfully queuing a request, or
* a negative error code on failure.
*
*/
virtual lorawan_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 /** Sets up a particular data rate of choice
* *
* @param data_rate Intended data rate e.g., DR_0, DR_1 etc. * @param data_rate Intended data rate e.g., DR_0, DR_1 etc.
* Caution is advised as the macro DR_* can mean different * Caution is advised as the macro DR_* can mean different
* things while being in a different region. * things while being in a different region.
* @return LORA_MAC_STATUS_OK if everything goes well, otherwise * @return LORAWAN_STATUS_OK if everything goes well, otherwise
* a negative error code. * a negative error code.
*/ */
virtual lora_mac_status_t set_datarate(uint8_t data_rate) = 0; virtual lorawan_status_t set_datarate(uint8_t data_rate) = 0;
/** Enables adaptive data rate (ADR) /** Enables adaptive data rate (ADR)
* *
* Underlying LoRaPHY and LoRaMac layers handle the data rate automatically * Underlying LoRaPHY and LoRaMac layers handle the data rate automatically
* for the user based upon radio conditions (network congestion). * for the user based upon radio conditions (network congestion).
* *
* @return LORA_MAC_STATUS_OK on success, negative error code * @return LORAWAN_STATUS_OK on success, negative error code
* on failure. * on failure.
*/ */
virtual lora_mac_status_t enable_adaptive_datarate() = 0; virtual lorawan_status_t enable_adaptive_datarate() = 0;
/** Disables adaptive data rate /** Disables adaptive data rate
* *
* When adaptive data rate (ADR) is disabled, user can either set a certain * When adaptive data rate (ADR) is disabled, user can either set a certain
* data rate or the Mac layer will choose a default value. * data rate or the Mac layer will choose a default value.
* *
* @return LORA_MAC_STATUS_OK on success, negative error code * @return LORAWAN_STATUS_OK on success, negative error code
* on failure. * on failure.
*/ */
virtual lora_mac_status_t disable_adaptive_datarate() = 0; virtual lorawan_status_t disable_adaptive_datarate() = 0;
/** Sets up retry counter for confirmed messages /** Sets up retry counter for confirmed messages
* *
@ -108,25 +140,25 @@ public:
* *
* @param count number of retries for confirmed messages * @param count number of retries for confirmed messages
* *
* @return LORA_MAC_STATUS_OK or a negative error code * @return LORAWAN_STATUS_OK or a negative error code
*/ */
virtual lora_mac_status_t set_confirmed_msg_retries(uint8_t count) = 0; virtual lorawan_status_t set_confirmed_msg_retries(uint8_t count) = 0;
/** Sets channel plan /** Sets channel plan
* *
* @param channel_plan The defined channel plans to be set. * @param channel_plan The defined channel plans to be set.
* @return 0 on success, a negative error code on failure. * @return 0 on success, a negative error code on failure.
*/ */
virtual lora_mac_status_t set_channel_plan(const lora_channelplan_t &channel_plan) = 0; virtual lorawan_status_t set_channel_plan(const lorawan_channelplan_t &channel_plan) = 0;
/** Gets the current channel plan. /** Gets the current channel plan.
* *
* @param channel_plan The current channel information. * @param channel_plan The current channel information.
* *
* @return LORA_MAC_STATUS_OK on success, a negative error * @return LORAWAN_STATUS_OK on success, a negative error
* code on failure. * code on failure.
*/ */
virtual lora_mac_status_t get_channel_plan(lora_channelplan_t &channel_plan) = 0; virtual lorawan_status_t get_channel_plan(lorawan_channelplan_t &channel_plan) = 0;
/** Removes currently active channel plan /** Removes currently active channel plan
* *
@ -134,10 +166,10 @@ public:
* allowed to be removed. So when a plan is abolished, only non-default * allowed to be removed. So when a plan is abolished, only non-default
* channels are removed. * channels are removed.
* *
* @return LORA_MAC_STATUS_OK on success, negative error * @return LORAWAN_STATUS_OK on success, negative error
* code on failure * code on failure
*/ */
virtual lora_mac_status_t remove_channel_plan() = 0; virtual lorawan_status_t remove_channel_plan() = 0;
/** Removes a given single channel /** Removes a given single channel
* *
@ -146,10 +178,10 @@ public:
* *
* @param index The channel index * @param index The channel index
* *
* @return LORA_MAC_STATUS_OK on success, negative error * @return LORAWAN_STATUS_OK on success, negative error
* code on failure * code on failure
*/ */
virtual lora_mac_status_t remove_channel(uint8_t index) = 0; virtual lorawan_status_t remove_channel(uint8_t index) = 0;
/** Send message to gateway /** Send message to gateway
* *
@ -182,7 +214,7 @@ public:
* *
* *
* @return The number of bytes sent, or * @return The number of bytes sent, or
* LORA_MAC_STATUS_WOULD_BLOCK if another TX is * LORAWAN_STATUS_WOULD_BLOCK if another TX is
* ongoing, or a negative error code on failure. * ongoing, or a negative error code on failure.
*/ */
virtual int16_t send(uint8_t port, const uint8_t* data, virtual int16_t send(uint8_t port, const uint8_t* data,
@ -223,7 +255,7 @@ public:
* @return It could be one of these: * @return It could be one of these:
* i) 0 if there is nothing else to read. * i) 0 if there is nothing else to read.
* ii) Number of bytes written to user buffer. * ii) Number of bytes written to user buffer.
* iii) LORA_MAC_STATUS_WOULD_BLOCK if there is * iii) LORAWAN_STATUS_WOULD_BLOCK if there is
* nothing available to read at the moment. * nothing available to read at the moment.
* iv) A negative error code on failure. * iv) A negative error code on failure.
*/ */
@ -298,7 +330,7 @@ public:
* @param callbacks A pointer to the structure containing application * @param callbacks A pointer to the structure containing application
* callbacks. * callbacks.
*/ */
virtual lora_mac_status_t add_app_callbacks(lorawan_app_callbacks_t *callbacks) = 0; virtual lorawan_status_t add_app_callbacks(lorawan_app_callbacks_t *callbacks) = 0;
}; };
#endif /* LORAWAN_BASE_H_ */ #endif /* LORAWAN_BASE_H_ */

View File

@ -28,7 +28,7 @@ inline LoRaWANStack& stk_obj()
return LoRaWANStack::get_lorawan_stack(); 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 // Pass mac_handlers to radio to the radio driver after
// binding radio driver to PHY layer // binding radio driver to PHY layer
@ -42,16 +42,16 @@ LoRaWANInterface::~LoRaWANInterface()
{ {
} }
lora_mac_status_t LoRaWANInterface::initialize(EventQueue *queue) lorawan_status_t LoRaWANInterface::initialize(EventQueue *queue)
{ {
if(!queue) { if(!queue) {
return LORA_MAC_STATUS_PARAMETER_INVALID; return LORAWAN_STATUS_PARAMETER_INVALID;
} }
return stk_obj().initialize_mac_layer(queue); return stk_obj().initialize_mac_layer(queue);
} }
lora_mac_status_t LoRaWANInterface::connect() lorawan_status_t LoRaWANInterface::connect()
{ {
// connection attempt without parameters. // connection attempt without parameters.
// System tries to look for configuration in mbed_lib.json that can be // System tries to look for configuration in mbed_lib.json that can be
@ -61,10 +61,10 @@ lora_mac_status_t LoRaWANInterface::connect()
lorawan_connect_t connection_params; lorawan_connect_t connection_params;
if (OVER_THE_AIR_ACTIVATION != 0) { if (MBED_CONF_LORA_OVER_THE_AIR_ACTIVATION) {
static uint8_t dev_eui[] = LORAWAN_DEVICE_EUI; static uint8_t dev_eui[] = MBED_CONF_LORA_DEVICE_EUI;
static uint8_t app_eui[] = LORAWAN_APPLICATION_EUI; static uint8_t app_eui[] = MBED_CONF_LORA_APPLICATION_EUI;
static uint8_t app_key[] = LORAWAN_APPLICATION_KEY; static uint8_t app_key[] = MBED_CONF_LORA_APPLICATION_KEY;
/** /**
* *
* OTAA join * OTAA join
@ -73,14 +73,14 @@ lora_mac_status_t LoRaWANInterface::connect()
connection_params.connection_u.otaa.app_eui = app_eui; connection_params.connection_u.otaa.app_eui = app_eui;
connection_params.connection_u.otaa.dev_eui = dev_eui; connection_params.connection_u.otaa.dev_eui = dev_eui;
connection_params.connection_u.otaa.app_key = app_key; connection_params.connection_u.otaa.app_key = app_key;
connection_params.connection_u.otaa.nb_trials = LORAWAN_NB_TRIALS; connection_params.connection_u.otaa.nb_trials = MBED_CONF_LORA_NB_TRIALS;
return connect(connection_params); return connect(connection_params);
} else { } else {
static uint8_t nwk_skey[] = LORAWAN_NWKSKEY; static uint8_t nwk_skey[] = MBED_CONF_LORA_NWKSKEY;
static uint8_t app_skey[] = LORAWAN_APPSKEY; static uint8_t app_skey[] = MBED_CONF_LORA_APPSKEY;
static uint32_t dev_addr = LORAWAN_DEVICE_ADDRESS; static uint32_t dev_addr = MBED_CONF_LORA_DEVICE_ADDRESS;
static uint32_t nwk_id = (LORAWAN_DEVICE_ADDRESS & LORAWAN_NETWORK_ID_MASK); static uint32_t nwk_id = (MBED_CONF_LORA_DEVICE_ADDRESS & LORAWAN_NETWORK_ID_MASK);
/** /**
* *
@ -96,63 +96,73 @@ lora_mac_status_t LoRaWANInterface::connect()
} }
} }
lora_mac_status_t LoRaWANInterface::connect(const lorawan_connect_t &connect) lorawan_status_t LoRaWANInterface::connect(const lorawan_connect_t &connect)
{ {
lora_mac_status_t mac_status; lorawan_status_t mac_status;
if (connect.connect_type == LORAWAN_CONNECTION_OTAA) { if (connect.connect_type == LORAWAN_CONNECTION_OTAA) {
mac_status = stk_obj().join_request_by_otaa(connect); mac_status = stk_obj().join_request_by_otaa(connect);
} else if (connect.connect_type == LORAWAN_CONNECTION_ABP) { } else if (connect.connect_type == LORAWAN_CONNECTION_ABP) {
mac_status = stk_obj().activation_by_personalization(connect); mac_status = stk_obj().activation_by_personalization(connect);
} else { } else {
return LORA_MAC_STATUS_PARAMETER_INVALID; return LORAWAN_STATUS_PARAMETER_INVALID;
} }
return mac_status; return mac_status;
} }
lora_mac_status_t LoRaWANInterface::disconnect() lorawan_status_t LoRaWANInterface::disconnect()
{ {
stk_obj().shutdown(); return stk_obj().shutdown();
return LORA_MAC_STATUS_OK;
} }
lora_mac_status_t LoRaWANInterface::set_datarate(uint8_t data_rate) lorawan_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;
}
lorawan_status_t LoRaWANInterface::set_datarate(uint8_t data_rate)
{ {
return stk_obj().set_channel_data_rate(data_rate); return stk_obj().set_channel_data_rate(data_rate);
} }
lora_mac_status_t LoRaWANInterface::set_confirmed_msg_retries(uint8_t count) lorawan_status_t LoRaWANInterface::set_confirmed_msg_retries(uint8_t count)
{ {
return stk_obj().set_confirmed_msg_retry(count); return stk_obj().set_confirmed_msg_retry(count);
} }
lora_mac_status_t LoRaWANInterface::enable_adaptive_datarate() lorawan_status_t LoRaWANInterface::enable_adaptive_datarate()
{ {
return stk_obj().enable_adaptive_datarate(true); return stk_obj().enable_adaptive_datarate(true);
} }
lora_mac_status_t LoRaWANInterface::disable_adaptive_datarate() lorawan_status_t LoRaWANInterface::disable_adaptive_datarate()
{ {
return stk_obj().enable_adaptive_datarate(false); return stk_obj().enable_adaptive_datarate(false);
} }
lora_mac_status_t LoRaWANInterface::set_channel_plan(const lora_channelplan_t &channel_plan) lorawan_status_t LoRaWANInterface::set_channel_plan(const lorawan_channelplan_t &channel_plan)
{ {
return stk_obj().add_channels(channel_plan); return stk_obj().add_channels(channel_plan);
} }
lora_mac_status_t LoRaWANInterface::get_channel_plan(lora_channelplan_t &channel_plan) lorawan_status_t LoRaWANInterface::get_channel_plan(lorawan_channelplan_t &channel_plan)
{ {
return stk_obj().get_enabled_channels(channel_plan); return stk_obj().get_enabled_channels(channel_plan);
} }
lora_mac_status_t LoRaWANInterface::remove_channel(uint8_t id) lorawan_status_t LoRaWANInterface::remove_channel(uint8_t id)
{ {
return stk_obj().remove_a_channel(id); return stk_obj().remove_a_channel(id);
} }
lora_mac_status_t LoRaWANInterface::remove_channel_plan() lorawan_status_t LoRaWANInterface::remove_channel_plan()
{ {
return stk_obj().drop_channel_list(); return stk_obj().drop_channel_list();
} }
@ -160,10 +170,16 @@ lora_mac_status_t LoRaWANInterface::remove_channel_plan()
int16_t LoRaWANInterface::send(uint8_t port, const uint8_t* data, int16_t LoRaWANInterface::send(uint8_t port, const uint8_t* data,
uint16_t length, int flags) 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) { if (data) {
return stk_obj().handle_tx(port, data, length, flags); return stk_obj().handle_tx(port, data, length, flags);
} else { } else {
return LORA_MAC_STATUS_PARAMETER_INVALID; return LORAWAN_STATUS_PARAMETER_INVALID;
} }
} }
@ -173,19 +189,18 @@ int16_t LoRaWANInterface::receive(uint8_t port, uint8_t* data, uint16_t length,
if (data && length > 0) { if (data && length > 0) {
return stk_obj().handle_rx(port, data, length, flags); return stk_obj().handle_rx(port, data, length, flags);
} else { } else {
return LORA_MAC_STATUS_PARAMETER_INVALID; return LORAWAN_STATUS_PARAMETER_INVALID;
} }
} }
lora_mac_status_t LoRaWANInterface::add_app_callbacks(lorawan_app_callbacks_t *callbacks) lorawan_status_t LoRaWANInterface::add_app_callbacks(lorawan_app_callbacks_t *callbacks)
{ {
if (!callbacks || !callbacks->events) { if (!callbacks || !callbacks->events) {
// Event Callback is mandatory // Event Callback is mandatory
return LORA_MAC_STATUS_PARAMETER_INVALID; return LORAWAN_STATUS_PARAMETER_INVALID;
} }
stk_obj().set_lora_callbacks(callbacks); stk_obj().set_lora_callbacks(callbacks);
return LORAWAN_STATUS_OK;
return LORA_MAC_STATUS_OK;
} }

View File

@ -19,9 +19,9 @@
#define LORAWANINTERFACE_H_ #define LORAWANINTERFACE_H_
#include "platform/Callback.h" #include "platform/Callback.h"
#include "netsocket/LoRaWANBase.h"
#include "lorawan/LoRaWANStack.h" #include "lorawan/LoRaWANStack.h"
#include "netsocket/LoRaRadio.h" #include "lorawan/LoRaRadio.h"
#include "lorawan/LoRaWANBase.h"
class LoRaWANInterface: public LoRaWANBase { class LoRaWANInterface: public LoRaWANBase {
@ -44,7 +44,7 @@ public:
* *
* @return 0 on success, a negative error code on failure. * @return 0 on success, a negative error code on failure.
*/ */
virtual lora_mac_status_t initialize(events::EventQueue *ev_queue) ; virtual lorawan_status_t initialize(events::EventQueue *ev_queue) ;
/** Connect OTAA or ABP using Mbed-OS config system /** Connect OTAA or ABP using Mbed-OS config system
* *
@ -52,7 +52,7 @@ public:
* You need to configure the connection properly via the Mbed OS configuration * You need to configure the connection properly via the Mbed OS configuration
* system. * system.
* *
* When connecting via OTAA, the return code for success (LORA_MAC_STATUS_CONNECT_IN_PROGRESS) is negative. * When connecting via OTAA, the return code for success (LORAWAN_STATUS_CONNECT_IN_PROGRESS) is negative.
* However, this is not a real error. It tells you that the connection is in progress and you will * However, this is not a real error. It tells you that the connection is in progress and you will
* be notified of the completion via an event. By default, after the Join Accept message * be notified of the completion via an event. By default, after the Join Accept message
* is received, base stations may provide the node with a CF-List that replaces * is received, base stations may provide the node with a CF-List that replaces
@ -78,17 +78,17 @@ public:
* is important, at least for ABP. That's why we try to restore frame counters from * is important, at least for ABP. That's why we try to restore frame counters from
* session information after a disconnection. * session information after a disconnection.
* *
* @return LORA_MAC_STATUS_OK or LORA_MAC_STATUS_CONNECT_IN_PROGRESS * @return LORAWAN_STATUS_OK or LORAWAN_STATUS_CONNECT_IN_PROGRESS
* on success, or a negative error code on failure. * on success, or a negative error code on failure.
*/ */
virtual lora_mac_status_t connect(); virtual lorawan_status_t connect();
/** Connect OTAA or ABP with parameters /** Connect OTAA or ABP with parameters
* *
* All connection parameters are chosen by the user and provided in the * All connection parameters are chosen by the user and provided in the
* data structure passed down. * data structure passed down.
* *
* When connecting via OTAA, the return code for success (LORA_MAC_STATUS_CONNECT_IN_PROGRESS) is negative. * When connecting via OTAA, the return code for success (LORAWAN_STATUS_CONNECT_IN_PROGRESS) is negative.
* However, this is not a real error. It tells you that connection is in progress and you will * However, this is not a real error. It tells you that connection is in progress and you will
* be notified of completion via an event. By default, after Join Accept message * be notified of completion via an event. By default, after Join Accept message
* is received, base stations may provide the node with a CF-List which replaces * is received, base stations may provide the node with a CF-List which replaces
@ -118,17 +118,54 @@ public:
* *
* @param connect Options for an end device connection to the gateway. * @param connect Options for an end device connection to the gateway.
* *
* @return LORA_MAC_STATUS_OK or LORA_MAC_STATUS_CONNECT_IN_PROGRESS, * @return LORAWAN_STATUS_OK or LORAWAN_STATUS_CONNECT_IN_PROGRESS,
* a negative error code on failure. * a negative error code on failure.
*/ */
virtual lora_mac_status_t connect(const lorawan_connect_t &connect); virtual lorawan_status_t connect(const lorawan_connect_t &connect);
/** Disconnect the current session. /** Disconnect the current session.
* *
* @return LORA_MAC_STATUS_OK on success, a negative error code on * @return LORAWAN_STATUS_DEVICE_OFF on successfully shutdown.
* failure.
*/ */
virtual lora_mac_status_t disconnect(); virtual lorawan_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 LORAWAN_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 LORAWAN_STATUS_OK on successfully queuing a request, or
* a negative error code on failure.
*
*/
virtual lorawan_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 /** Sets up a particular data rate
* *
@ -138,28 +175,28 @@ public:
* @param data_rate The intended data rate, for example DR_0 or DR_1. * @param data_rate The intended data rate, for example DR_0 or DR_1.
* Please note, that the macro DR_* can mean different * Please note, that the macro DR_* can mean different
* things in different regions. * things in different regions.
* @return LORA_MAC_STATUS_OK if everything goes well, otherwise * @return LORAWAN_STATUS_OK if everything goes well, otherwise
* a negative error code. * a negative error code.
*/ */
virtual lora_mac_status_t set_datarate(uint8_t data_rate); virtual lorawan_status_t set_datarate(uint8_t data_rate);
/** Enables adaptive data rate (ADR). /** Enables adaptive data rate (ADR).
* *
* The underlying LoRaPHY and LoRaMac layers handle the data rate automatically * The underlying LoRaPHY and LoRaMac layers handle the data rate automatically
* for the user, based upon the radio conditions (network congestion). * for the user, based upon the radio conditions (network congestion).
* *
* @return LORA_MAC_STATUS_OK or negative error code otherwise. * @return LORAWAN_STATUS_OK or negative error code otherwise.
*/ */
virtual lora_mac_status_t enable_adaptive_datarate(); virtual lorawan_status_t enable_adaptive_datarate();
/** Disables adaptive data rate. /** Disables adaptive data rate.
* *
* When adaptive data rate (ADR) is disabled, you can either set a certain * When adaptive data rate (ADR) is disabled, you can either set a certain
* data rate or the MAC layer selects a default value. * data rate or the MAC layer selects a default value.
* *
* @return LORA_MAC_STATUS_OK or negative error code otherwise. * @return LORAWAN_STATUS_OK or negative error code otherwise.
*/ */
virtual lora_mac_status_t disable_adaptive_datarate(); virtual lorawan_status_t disable_adaptive_datarate();
/** Sets up the retry counter for confirmed messages. /** Sets up the retry counter for confirmed messages.
* *
@ -174,9 +211,9 @@ public:
* *
* @param count The number of retries for confirmed messages. * @param count The number of retries for confirmed messages.
* *
* @return LORA_MAC_STATUS_OK or a negative error code. * @return LORAWAN_STATUS_OK or a negative error code.
*/ */
virtual lora_mac_status_t set_confirmed_msg_retries(uint8_t count); virtual lorawan_status_t set_confirmed_msg_retries(uint8_t count);
/** Sets the channel plan. /** Sets the channel plan.
* *
@ -188,6 +225,9 @@ public:
* is already active, the request is silently ignored. A negative error * is already active, the request is silently ignored. A negative error
* code is returned if there is any problem with parameters. * code is returned if there is any problem with parameters.
* *
* Please note that this API can also be used to add a single channel to the
* existing channel plan.
*
* There is no reverse mechanism in the 1.0.2 specification for a node to request * There is no reverse mechanism in the 1.0.2 specification for a node to request
* a particular channel. Only the network server can initiate such a request. * a particular channel. Only the network server can initiate such a request.
* You need to ensure that the corresponding base station supports the channel or channels being added. * You need to ensure that the corresponding base station supports the channel or channels being added.
@ -199,10 +239,10 @@ public:
* *
* @param channel_plan The channel plan to set. * @param channel_plan The channel plan to set.
* *
* @return LORA_MAC_STATUS_OK on success, a negative error * @return LORAWAN_STATUS_OK on success, a negative error
* code on failure. * code on failure.
*/ */
virtual lora_mac_status_t set_channel_plan(const lora_channelplan_t &channel_plan); virtual lorawan_status_t set_channel_plan(const lorawan_channelplan_t &channel_plan);
/** Gets the channel plans from the LoRa stack. /** Gets the channel plans from the LoRa stack.
* *
@ -213,20 +253,20 @@ public:
* *
* @param channel_plan The current channel plan information. * @param channel_plan The current channel plan information.
* *
* @return LORA_MAC_STATUS_OK on success, a negative error * @return LORAWAN_STATUS_OK on success, a negative error
* code on failure. * code on failure.
*/ */
virtual lora_mac_status_t get_channel_plan(lora_channelplan_t &channel_plan); virtual lorawan_status_t get_channel_plan(lorawan_channelplan_t &channel_plan);
/** Removes an active channel plan. /** Removes an active channel plan.
* *
* You cannot remove default channels (the channels the base stations are listening to). * You cannot remove default channels (the channels the base stations are listening to).
* When a plan is abolished, only the non-default channels are removed. * When a plan is abolished, only the non-default channels are removed.
* *
* @return LORA_MAC_STATUS_OK on success, a negative error * @return LORAWAN_STATUS_OK on success, a negative error
* code on failure. * code on failure.
*/ */
virtual lora_mac_status_t remove_channel_plan(); virtual lorawan_status_t remove_channel_plan();
/** Removes a single channel. /** Removes a single channel.
* *
@ -234,10 +274,10 @@ public:
* *
* @param index The channel index. * @param index The channel index.
* *
* @return LORA_MAC_STATUS_OK on success, a negative error * @return LORAWAN_STATUS_OK on success, a negative error
* code on failure. * code on failure.
*/ */
virtual lora_mac_status_t remove_channel(uint8_t index); virtual lorawan_status_t remove_channel(uint8_t index);
/** Send message to gateway /** Send message to gateway
* *
@ -270,7 +310,7 @@ public:
* *
* *
* @return The number of bytes sent, or * @return The number of bytes sent, or
* LORA_MAC_STATUS_WOULD_BLOCK if another TX is * LORAWAN_STATUS_WOULD_BLOCK if another TX is
* ongoing, or a negative error code on failure. * ongoing, or a negative error code on failure.
*/ */
virtual int16_t send(uint8_t port, const uint8_t* data, uint16_t length, virtual int16_t send(uint8_t port, const uint8_t* data, uint16_t length,
@ -311,7 +351,7 @@ public:
* @return It could be one of these: * @return It could be one of these:
* i) 0 if there is nothing else to read. * i) 0 if there is nothing else to read.
* ii) Number of bytes written to user buffer. * ii) Number of bytes written to user buffer.
* iii) LORA_MAC_STATUS_WOULD_BLOCK if there is * iii) LORAWAN_STATUS_WOULD_BLOCK if there is
* nothing available to read at the moment. * nothing available to read at the moment.
* iv) A negative error code on failure. * iv) A negative error code on failure.
*/ */
@ -361,7 +401,7 @@ public:
* int main() * int main()
* { * {
* lorawan.initialize(&queue); * lorawan.initialize(&queue);
* cbs.lorawan_events = mbed::callback(my_event_handler); * cbs.events = mbed::callback(my_event_handler);
* lorawan.add_app_callbacks(&cbs); * lorawan.add_app_callbacks(&cbs);
* lorawan.connect(); * lorawan.connect();
* } * }
@ -386,7 +426,10 @@ public:
* @param callbacks A pointer to the structure containing application * @param callbacks A pointer to the structure containing application
* callbacks. * callbacks.
*/ */
virtual lora_mac_status_t add_app_callbacks(lorawan_app_callbacks_t *callbacks); virtual lorawan_status_t add_app_callbacks(lorawan_app_callbacks_t *callbacks);
private:
bool _link_check_requested;
}; };
#endif /* LORAWANINTERFACE_H_ */ #endif /* LORAWANINTERFACE_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -35,6 +35,42 @@ SPDX-License-Identifier: BSD-3-Clause
#include "lorawan/system/lorawan_data_structures.h" #include "lorawan/system/lorawan_data_structures.h"
#include "LoRaRadio.h" #include "LoRaRadio.h"
#ifdef MBED_CONF_LORA_PHY
#if MBED_CONF_LORA_PHY == 0
#include "lorawan/lorastack/phy/LoRaPHYEU868.h"
#define LoRaPHY_region LoRaPHYEU868
#elif MBED_CONF_LORA_PHY == 1
#include "lorawan/lorastack/phy/LoRaPHYAS923.h"
#define LoRaPHY_region LoRaPHYAS923
#elif MBED_CONF_LORA_PHY == 2
#include "lorawan/lorastack/phy/LoRaPHYAU915.h"
#define LoRaPHY_region LoRaPHYAU915;
#elif MBED_CONF_LORA_PHY == 3
#include "lorawan/lorastack/phy/LoRaPHYCN470.h"
#define LoRaPHY_region LoRaPHYCN470
#elif MBED_CONF_LORA_PHY == 4
#include "lorawan/lorastack/phy/LoRaPHYCN779.h"
#define LoRaPHY_region LoRaPHYCN779
#elif MBED_CONF_LORA_PHY == 5
#include "lorawan/lorastack/phy/LoRaPHYEU433.h"
#define LoRaPHY_region LoRaPHYEU433
#elif MBED_CONF_LORA_PHY == 6
#include "lorawan/lorastack/phy/LoRaPHYIN865.h"
#define LoRaPHY_region LoRaPHYIN865
#elif MBED_CONF_LORA_PHY == 7
#include "lorawan/lorastack/phy/LoRaPHYKR920.h"
#define LoRaPHY_region LoRaPHYKR920
#elif MBED_CONF_LORA_PHY == 8
#include "lorawan/lorastack/phy/LoRaPHYUS915.h"
#define LoRaPHY_region LoRaPHYUS915
#elif MBED_CONF_LORA_PHY == 9
#include "lorawan/lorastack/phy/LoRaPHYUS915Hybrid.h"
#define LoRaPHY_region LoRaPHYUS915Hybrid
#endif //MBED_CONF_LORA_PHY == VALUE
#else
#error "Must set LoRa PHY layer parameters."
#endif //MBED_CONF_LORA_PHY
/** /**
* A mask for the network ID. * A mask for the network ID.
*/ */
@ -61,13 +97,13 @@ public:
/** End device initialization. /** End device initialization.
* @param queue A pointer to an EventQueue passed from the application. * @param queue A pointer to an EventQueue passed from the application.
* @return LORA_MAC_STATUS_OK on success, a negative error code on failure. * @return LORAWAN_STATUS_OK on success, a negative error code on failure.
*/ */
lora_mac_status_t initialize_mac_layer(events::EventQueue *queue); lorawan_status_t initialize_mac_layer(events::EventQueue *queue);
/** Sets all callbacks for the application. /** 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); void set_lora_callbacks(lorawan_app_callbacks_t *callbacks);
@ -90,35 +126,35 @@ public:
* *
* @param channel_plan A list of channels or a single channel. * @param channel_plan A list of channels or a single channel.
* *
* @return LORA_MAC_STATUS_OK on success, a negative error * @return LORAWAN_STATUS_OK on success, a negative error
* code on failure. * code on failure.
*/ */
lora_mac_status_t add_channels(const lora_channelplan_t &channel_plan); lorawan_status_t add_channels(const lorawan_channelplan_t &channel_plan);
/** Removes a channel from the list. /** Removes a channel from the list.
* *
* @param channel_id Index of the channel being removed * @param channel_id Index of the channel being removed
* *
* @return LORA_MAC_STATUS_OK on success, a negative error * @return LORAWAN_STATUS_OK on success, a negative error
* code on failure. * code on failure.
*/ */
lora_mac_status_t remove_a_channel(uint8_t channel_id); lorawan_status_t remove_a_channel(uint8_t channel_id);
/** Removes a previously set channel plan. /** Removes a previously set channel plan.
* *
* @return LORA_MAC_STATUS_OK on success, a negative error * @return LORAWAN_STATUS_OK on success, a negative error
* code on failure. * code on failure.
*/ */
lora_mac_status_t drop_channel_list(); lorawan_status_t drop_channel_list();
/** Gets a list of currently enabled channels . /** Gets a list of currently enabled channels .
* *
* @param channel_plan The channel plan structure to store final result. * @param channel_plan The channel plan structure to store final result.
* *
* @return LORA_MAC_STATUS_OK on success, a negative error * @return LORAWAN_STATUS_OK on success, a negative error
* code on failure. * code on failure.
*/ */
lora_mac_status_t get_enabled_channels(lora_channelplan_t &channel_plan); lorawan_status_t get_enabled_channels(lorawan_channelplan_t &channel_plan);
/** Sets up a retry counter for confirmed messages. /** Sets up a retry counter for confirmed messages.
* *
@ -128,9 +164,9 @@ public:
* *
* @param count The number of retries for confirmed messages. * @param count The number of retries for confirmed messages.
* *
* @return LORA_MAC_STATUS_OK or a negative error code. * @return LORAWAN_STATUS_OK or a negative error code.
*/ */
lora_mac_status_t set_confirmed_msg_retry(uint8_t count); lorawan_status_t set_confirmed_msg_retry(uint8_t count);
/** Sets up the data rate. /** Sets up the data rate.
* *
@ -141,26 +177,26 @@ public:
* Note that the macro DR_* can mean different * Note that the macro DR_* can mean different
* things in different regions. * things in different regions.
* *
* @return LORA_MAC_STATUS_OK if everything goes well, otherwise * @return LORAWAN_STATUS_OK if everything goes well, otherwise
* a negative error code. * a negative error code.
*/ */
lora_mac_status_t set_channel_data_rate(uint8_t data_rate); lorawan_status_t set_channel_data_rate(uint8_t data_rate);
/** Enables ADR. /** Enables ADR.
* *
* @param adr_enabled 0 ADR disabled, 1 ADR enabled. * @param adr_enabled 0 ADR disabled, 1 ADR enabled.
* *
* @return LORA_MAC_STATUS_OK on success, a negative error * @return LORAWAN_STATUS_OK on success, a negative error
* code on failure. * code on failure.
*/ */
lora_mac_status_t enable_adaptive_datarate(bool adr_enabled); lorawan_status_t enable_adaptive_datarate(bool adr_enabled);
/** Commissions a LoRa device. /** Commissions a LoRa device.
* *
* @param commission_data A structure representing all the commission * @param commission_data A structure representing all the commission
* information. * information.
*/ */
void commission_device(const lora_dev_commission_t &commission_data); void commission_device(const lorawan_dev_commission_t &commission_data);
/** End device OTAA join. /** End device OTAA join.
* *
@ -169,11 +205,11 @@ public:
* *
* @param params The `lorawan_connect_t` type structure. * @param params The `lorawan_connect_t` type structure.
* *
* @return LORA_MAC_STATUS_OK or * @return LORAWAN_STATUS_OK or
* LORA_MAC_STATUS_CONNECT_IN_PROGRESS on success, * LORAWAN_STATUS_CONNECT_IN_PROGRESS on success,
* or a negative error code on failure. * or a negative error code on failure.
*/ */
lora_mac_status_t join_request_by_otaa(const lorawan_connect_t &params); lorawan_status_t join_request_by_otaa(const lorawan_connect_t &params);
/** End device ABP join. /** End device ABP join.
* *
@ -182,11 +218,11 @@ public:
* *
* @param params The `lorawan_connect_t` type structure. * @param params The `lorawan_connect_t` type structure.
* *
* @return LORA_MAC_STATUS_OK or * @return LORAWAN_STATUS_OK or
* LORA_MAC_STATUS_CONNECT_IN_PROGRESS on success, * LORAWAN_STATUS_CONNECT_IN_PROGRESS on success,
* or a negative error code on failure. * or a negative error code on failure.
*/ */
lora_mac_status_t activation_by_personalization(const lorawan_connect_t &params); lorawan_status_t activation_by_personalization(const lorawan_connect_t &params);
/** Send message to gateway /** Send message to gateway
* *
@ -219,7 +255,7 @@ public:
* *
* *
* @return The number of bytes sent, or * @return The number of bytes sent, or
* LORA_MAC_STATUS_WOULD_BLOCK if another TX is * LORAWAN_STATUS_WOULD_BLOCK if another TX is
* ongoing, or a negative error code on failure. * ongoing, or a negative error code on failure.
*/ */
int16_t handle_tx(uint8_t port, const uint8_t* data, int16_t handle_tx(uint8_t port, const uint8_t* data,
@ -260,18 +296,36 @@ public:
* @return It could be one of these: * @return It could be one of these:
* i) 0 if there is nothing else to read. * i) 0 if there is nothing else to read.
* ii) Number of bytes written to user buffer. * ii) Number of bytes written to user buffer.
* iii) LORA_MAC_STATUS_WOULD_BLOCK if there is * iii) LORAWAN_STATUS_WOULD_BLOCK if there is
* nothing available to read at the moment. * nothing available to read at the moment.
* iv) A negative error code on failure. * iv) A negative error code on failure.
*/ */
int16_t handle_rx(const uint8_t port, uint8_t* data, int16_t handle_rx(const uint8_t port, uint8_t* data,
uint16_t length, uint8_t flags); 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 LORAWAN_STATUS_PARAMETER_INVALID error is thrown.
*
* @return LORAWAN_STATUS_OK on successfully queuing a request, or
* a negative error code on failure.
*
*/
lorawan_status_t set_link_check_request();
/** Shuts down the LoRaWAN protocol. /** Shuts down the LoRaWAN protocol.
* *
* In response to the user call for disconnection, the stack shuts down itself. * In response to the user call for disconnection, the stack shuts down itself.
*
* @return LORAWAN_STATUS_DEVICE_OFF on successfully shutdown.
*/ */
void shutdown(); lorawan_status_t shutdown();
private: private:
LoRaWANStack(); LoRaWANStack();
@ -286,7 +340,7 @@ private:
* State machine for stack controller layer. * State machine for stack controller layer.
* Needs to be wriggled for every state change * Needs to be wriggled for every state change
*/ */
lora_mac_status_t lora_state_machine(); lorawan_status_t lora_state_machine();
/** /**
* Sets the current state of the device. * Sets the current state of the device.
@ -296,57 +350,38 @@ private:
*/ */
void set_device_state(device_states_t new_state); 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. * Hands over the packet to Mac layer by posting an MCPS request.
*/ */
lora_mac_status_t send_frame_to_mac(); lorawan_status_t send_frame_to_mac();
/** /**
* Callback function for MCPS confirm. Mac layer calls this function once * Callback function for MLME indication. Mac layer calls this function once
* an MCPS confirmation is received. This method translates Mac layer data * an MLME indication is received. This method translates Mac layer data
* structure into stack layer data structure. * structure into stack layer data structure.
*/ */
void mcps_confirm(McpsConfirm_t *mcps_confirm); void mlme_indication_handler(loramac_mlme_indication_t *mlmeIndication);
/**
* Callback function for MCPS indication. Mac layer calls this function once
* an MCPS indication is received. This method translates Mac layer data
* structure into stack layer data structure.
*/
void mcps_indication(McpsIndication_t *mcps_indication);
/**
* Callback function for MLME confirm. Mac layer calls this function once
* an MLME confirmation is received. This method translates Mac layer data
* structure into stack layer data structure.
*/
void mlme_confirm(MlmeConfirm_t *mlme_confirm);
/** /**
* Handles an MLME request coming from the upper layers and delegates * 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 * it to the Mac layer, for example, a Join request goes as an MLME request
* to the Mac layer. * to the Mac layer.
*/ */
lora_mac_status_t mlme_request_handler(lora_mac_mlme_req_t *mlme_request); lorawan_status_t mlme_request_handler(loramac_mlme_req_t *mlme_request);
/** /**
* Handles an MLME confirmation coming from the Mac layer and uses it to * Handles an MLME confirmation coming from the Mac layer and uses it to
* update the state for example, a Join Accept triggers an MLME confirmation, * update the state for example, a Join Accept triggers an MLME confirmation,
* that eventually comes here and we take necessary steps accordingly. * that eventually comes here and we take necessary steps accordingly.
*/ */
void mlme_confirm_handler(lora_mac_mlme_confirm_t *mlme_confirm); void mlme_confirm_handler(loramac_mlme_confirm_t *mlme_confirm);
/** /**
* Handles an MCPS request while attempting to hand over a packet from * Handles an MCPS request while attempting to hand over a packet from
* upper layers to Mac layer. For example in response to send_frame_to_mac(), * upper layers to Mac layer. For example in response to send_frame_to_mac(),
* an MCPS request is generated. * an MCPS request is generated.
*/ */
lora_mac_status_t mcps_request_handler(lora_mac_mcps_req_t *mcps_request); lorawan_status_t mcps_request_handler(loramac_mcps_req_t *mcps_request);
/** /**
* Handles an MCPS confirmation coming from the Mac layer in response to an * Handles an MCPS confirmation coming from the Mac layer in response to an
@ -354,7 +389,7 @@ private:
* e.g., letting the application know that ack was not received in case of * e.g., letting the application know that ack was not received in case of
* a CONFIRMED message or scheduling error etc. * a CONFIRMED message or scheduling error etc.
*/ */
void mcps_confirm_handler(lora_mac_mcps_confirm_t *mcps_confirm); void mcps_confirm_handler(loramac_mcps_confirm_t *mcps_confirm);
/** /**
* Handles an MCPS indication coming from the Mac layer, e.g., once we * Handles an MCPS indication coming from the Mac layer, e.g., once we
@ -362,22 +397,22 @@ private:
* and consequently this handler posts an event to the application that * and consequently this handler posts an event to the application that
* there is something available to read. * there is something available to read.
*/ */
void mcps_indication_handler(lora_mac_mcps_indication_t *mcps_indication); void mcps_indication_handler(loramac_mcps_indication_t *mcps_indication);
/** /**
* Sets a MIB request, i.e., update a particular parameter etc. * Sets a MIB request, i.e., update a particular parameter etc.
*/ */
lora_mac_status_t mib_set_request(lora_mac_mib_request_confirm_t *mib_set_params); lorawan_status_t mib_set_request(loramac_mib_req_confirm_t *mib_set_params);
/** /**
* Requests the MIB to inquire about a particular parameter. * Requests the MIB to inquire about a particular parameter.
*/ */
lora_mac_status_t mib_get_request(lora_mac_mib_request_confirm_t *mib_get_params); lorawan_status_t mib_get_request(loramac_mib_req_confirm_t *mib_get_params);
/** /**
* Sets up user application port * Sets up user application port
*/ */
lora_mac_status_t set_application_port(uint8_t port); lorawan_status_t set_application_port(uint8_t port);
/** /**
* Helper function to figure out if the user defined data size is possible * Helper function to figure out if the user defined data size is possible
@ -389,22 +424,30 @@ private:
*/ */
uint16_t check_possible_tx_size(uint16_t size); uint16_t check_possible_tx_size(uint16_t size);
#if defined(LORAWAN_COMPLIANCE_TEST)
/** /**
* Used only for compliance testing * This function is used only for compliance testing
*/ */
void compliance_test_handler(lora_mac_mcps_indication_t *mcps_indication); void prepare_special_tx_frame(uint8_t port);
/** /**
* Used only for compliance testing * Used only for compliance testing
*/ */
lora_mac_status_t send_compliance_test_frame_to_mac(); void compliance_test_handler(loramac_mcps_indication_t *mcps_indication);
/** /**
* converts error codes from Mac layer to controller layer * Used only for compliance testing
*/ */
lora_mac_status_t error_type_converter(LoRaMacStatus_t type); lorawan_status_t send_compliance_test_frame_to_mac();
#endif
LoRaWANTimeHandler _lora_time;
LoRaMac _loramac;
LoRaPHY_region _lora_phy;
loramac_primitives_t LoRaMacPrimitives;
#if defined(LORAWAN_COMPLIANCE_TEST) #if defined(LORAWAN_COMPLIANCE_TEST)
uint8_t compliance_test_buffer[MBED_CONF_LORA_TX_MAX_SIZE];
compliance_test_t _compliance_test; compliance_test_t _compliance_test;
#endif #endif
@ -412,8 +455,8 @@ private:
lorawan_app_callbacks_t _callbacks; lorawan_app_callbacks_t _callbacks;
radio_events_t *_mac_handlers; radio_events_t *_mac_handlers;
lorawan_session_t _lw_session; lorawan_session_t _lw_session;
lora_mac_tx_message_t _tx_msg; loramac_tx_message_t _tx_msg;
lora_mac_rx_message_t _rx_msg; loramac_rx_message_t _rx_msg;
uint8_t _app_port; uint8_t _app_port;
uint8_t _num_retry; uint8_t _num_retry;
events::EventQueue *_queue; events::EventQueue *_queue;

File diff suppressed because it is too large Load Diff

View File

@ -37,324 +37,642 @@
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
* *
*/ */
#ifndef __LORAMAC_H__ #ifndef MBED_LORAWAN_MAC_H__
#define __LORAMAC_H__ #define MBED_LORAWAN_MAC_H__
#include "lorawan/system/LoRaWANTimer.h" #include "lorawan/system/LoRaWANTimer.h"
#include "netsocket/LoRaRadio.h"
#include "lorastack/phy/LoRaPHY.h" #include "lorastack/phy/LoRaPHY.h"
#include "lorawan/system/lorawan_data_structures.h" #include "lorawan/system/lorawan_data_structures.h"
#include "lorastack/mac/LoRaMacCommand.h"
#include "events/EventQueue.h"
#include "lorastack/mac/LoRaMacMlme.h"
#include "lorastack/mac/LoRaMacMcps.h"
#include "lorastack/mac/LoRaMacMib.h"
#include "lorastack/mac/LoRaMacChannelPlan.h"
/*! class LoRaMac {
* Check the MAC layer state every MAC_STATE_CHECK_TIMEOUT in ms.
*/
#define MAC_STATE_CHECK_TIMEOUT 1000
/*! public:
* The maximum number of times the MAC layer tries to get an acknowledge.
*/
#define MAX_ACK_RETRIES 8
/*! /**
* The frame direction definition for uplink communications. * Constructor
*/ */
#define UP_LINK 0 LoRaMac(LoRaWANTimeHandler &lora_time);
/*! /**
* The frame direction definition for downlink communications. * Destructor
*/ */
#define DOWN_LINK 1 ~LoRaMac();
/**
* @brief LoRaMAC layer initialization
*
* @details In addition to the initialization of the LoRaMAC layer, this
* function initializes the callback primitives of the MCPS and
* MLME services. Every data field of \ref loramac_primitives_t must be
* set to a valid callback function.
*
* @param primitives [in] A pointer to the structure defining the LoRaMAC
* event functions. Refer to \ref loramac_primitives_t.
*
* @param phy [in] A pointer to the selected PHY layer.
*
* @param queue [in] A pointer to the application provided EventQueue.
*
* @return `lorawan_status_t` The status of the operation. The possible values are:
* \ref LORAWAN_STATUS_OK
* \ref LORAWAN_STATUS_PARAMETER_INVALID
*/
lorawan_status_t initialize(loramac_primitives_t *primitives, LoRaPHY *phy,
events::EventQueue *queue);
/*! /**
* LoRaMAC max EIRP (dBm) table. * @brief Disconnect LoRaMac layer
*/ *
static const uint8_t LoRaMacMaxEirpTable[] = { 8, 10, 12, 13, 14, 16, 18, 20, 21, 24, 26, 27, 29, 30, 33, 36 }; * @details Cancels all outstanding requests and sets LoRaMac's
* internal state to idle.
*/
void disconnect(void);
/**
* @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.
*
* @param size [in] The size of the applicable payload to be sent next.
* @param tx_info [out] The structure \ref loramac_tx_info_t contains
* information on the actual maximum payload possible
* (according to the configured datarate or the next
* datarate according to ADR), and the maximum frame
* size, taking the scheduled MAC commands into account.
*
* @return `lorawan_status_t` The status of the operation. When the parameters are
* not valid, the function returns \ref LORAWAN_STATUS_PARAMETER_INVALID.
* In case of a length error caused by the applicable payload in combination
* with the MAC commands, the function returns \ref LORAWAN_STATUS_LENGTH_ERROR.
* Please note that if the size of the MAC commands in the queue do
* not fit into the payload size on the related datarate, the LoRaMAC will
* omit the MAC commands.
* If the query is valid, and the LoRaMAC is able to send the frame,
* the function returns \ref LORAWAN_STATUS_OK.
*/
lorawan_status_t query_tx_possible(uint8_t size, loramac_tx_info_t* tx_info);
/*! /**
* \brief LoRaMAC layer initialization * @brief Adds a channel plan to the system.
* *
* \details In addition to the initialization of the LoRaMAC layer, this * @details Adds a whole channel plan or a single new channel if the plan
* function initializes the callback primitives of the MCPS and * contains only one channel and 'plan.nb_channels' is set to 1.
* MLME services. Every data field of \ref LoRaMacPrimitives_t must be * Please note that this functionality is not available in all regions.
* set to a valid callback function. * Information on the allowed ranges is available at the
* * LoRaWAN Regional Parameters V1.0.2rB.
* \param primitives [in] - A pointer to the structure defining the LoRaMAC *
* event functions. Refer to \ref LoRaMacPrimitives_t. * @param plan [in] A reference to application provided channel plan.
* *
* \param callbacks [in] - A pointer to the structure defining the LoRaMAC * @return `lorawan_status_t` The status of the operation. The possible values are:
* callback functions. Refer to \ref LoRaMacCallback_t. * \ref LORAWAN_STATUS_OK
* * \ref LORAWAN_STATUS_BUSY
* \param phy [in]- A pointer to the selected PHY layer. * \ref LORAWAN_STATUS_PARAMETER_INVALID
* */
* \param queue [in]- A pointer to the application provided EventQueue. lorawan_status_t add_channel_plan(const lorawan_channelplan_t& plan);
*
* \retval `LoRaMacStatus_t` The status of the operation. The possible values are:
* \ref LORAMAC_STATUS_OK
* \ref LORAMAC_STATUS_PARAMETER_INVALID
* \ref LORAMAC_STATUS_REGION_NOT_SUPPORTED.
*/
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 * @brief Removes a channel plan from the system.
* a given payload size. The LoRaMAC takes the scheduled MAC commands into *
* account and reports when the frame can be sent. * @details Removes the whole active channel plan except the 'Default Channels'.
* * Please note that this functionality is not available in all regions.
* \param size [in]- The size of the applicable payload to be sent next. * Information on the allowed ranges is available at the
* \param txInfo [out] - The structure \ref LoRaMacTxInfo_t contains * LoRaWAN Regional Parameters V1.0.2rB.
* information on the actual maximum payload possible *
* (according to the configured datarate or the next * @return `lorawan_status_t` The status of the operation. The possible values are:
* datarate according to ADR), and the maximum frame * \ref LORAWAN_STATUS_OK
* size, taking the scheduled MAC commands into account. * \ref LORAWAN_STATUS_BUSY
* * \ref LORAWAN_STATUS_PARAMETER_INVALID
* \retval `LoRaMacStatus_t` The status of the operation. When the parameters are */
* not valid, the function returns \ref LORAMAC_STATUS_PARAMETER_INVALID. lorawan_status_t remove_channel_plan();
* In case of a length error caused by the applicable payload in combination
* with the MAC commands, the function returns \ref LORAMAC_STATUS_LENGTH_ERROR.
* Please note that if the size of the MAC commands in the queue do
* not fit into the payload size on the related datarate, the LoRaMAC will
* omit the MAC commands.
* 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 );
/*! /**
* \brief LoRaMAC channel add service. * @brief Access active channel plan.
* *
* \details Adds a new channel to the channel list and activates the ID in * @details Provides access to the current active channel plan.
* the channel mask. Please note that this functionality is not available *
* in all regions. Information on the allowed ranges is available at the LoRaWAN Regional Parameters V1.0.2rB. * @param plan [out] A reference to application provided channel plan data
* * structure which will be filled in with active channel
* \param id [in] - The ID of the channel. * plan.
* *
* \param params [in] - The channel parameters to set. * @return `lorawan_status_t` The status of the operation. The possible values are:
* * \ref LORAWAN_STATUS_OK
* \retval `LoRaMacStatus_t` The status of the operation. The possible values are: * \ref LORAWAN_STATUS_BUSY
* \ref LORAMAC_STATUS_OK * \ref LORAWAN_STATUS_PARAMETER_INVALID
* \ref LORAMAC_STATUS_BUSY */
* \ref LORAMAC_STATUS_PARAMETER_INVALID lorawan_status_t get_channel_plan(lorawan_channelplan_t& plan);
*/
LoRaMacStatus_t LoRaMacChannelAdd( uint8_t id, ChannelParams_t params );
/*! /**
* \brief LoRaMAC channel remove service. * @brief Remove a given channel from the active plan.
* *
* \details Deactivates the ID in the channel mask. * @details Deactivates the given channel.
* *
* \param id - Id of the channel. * @param id Id of the channel.
* *
* \retval `LoRaMacStatus_t` The status of the operation. The possible values are: * @return `lorawan_status_t` The status of the operation. The possible values are:
* \ref LORAMAC_STATUS_OK * \ref LORAWAN_STATUS_OK
* \ref LORAMAC_STATUS_BUSY * \ref LORAWAN_STATUS_BUSY
* \ref LORAMAC_STATUS_PARAMETER_INVALID * \ref LORAWAN_STATUS_PARAMETER_INVALID
*/ */
LoRaMacStatus_t LoRaMacChannelRemove( uint8_t id ); lorawan_status_t remove_single_channel(uint8_t id);
/*! /**
* \brief LoRaMAC multicast channel link service. * @brief LoRaMAC multicast channel link service.
* *
* \details Links a multicast channel into the linked list. * @details Links a multicast channel into the linked list.
* *
* \param [in] channelParam - The multicast channel parameters to link. * @param [in] channel_param The multicast channel parameters to link.
* *
* \retval `LoRaMacStatus_t` The status of the operation. The possible values are: * @return `lorawan_status_t` The status of the operation. The possible values are:
* \ref LORAMAC_STATUS_OK * \ref LORAWAN_STATUS_OK
* \ref LORAMAC_STATUS_BUSY * \ref LORAWAN_STATUS_BUSY
* \ref LORAMAC_STATUS_PARAMETER_INVALID * \ref LORAWAN_STATUS_PARAMETER_INVALID
*/ */
LoRaMacStatus_t LoRaMacMulticastChannelLink( MulticastParams_t *channelParam ); lorawan_status_t multicast_channel_link(multicast_params_t *channel_param);
/*! /**
* \brief LoRaMAC multicast channel unlink service. * @brief LoRaMAC multicast channel unlink service.
* *
* \details Unlinks a multicast channel from the linked list. * @details Unlinks a multicast channel from the linked list.
* *
* \param [in] channelParam - The multicast channel parameters to unlink. * @param [in] channel_param The multicast channel parameters to unlink.
* *
* \retval `LoRaMacStatus_t` The status of the operation. The possible values are: * @return `lorawan_status_t` The status of the operation. The possible values are:
* \ref LORAMAC_STATUS_OK * \ref LORAWAN_STATUS_OK
* \ref LORAMAC_STATUS_BUSY * \ref LORAWAN_STATUS_BUSY
* \ref LORAMAC_STATUS_PARAMETER_INVALID * \ref LORAWAN_STATUS_PARAMETER_INVALID
*/ */
LoRaMacStatus_t LoRaMacMulticastChannelUnlink( MulticastParams_t *channelParam ); lorawan_status_t multicast_channel_unlink(multicast_params_t *channel_param);
/*! /**
* \brief LoRaMAC MIB-GET. * @brief Get parameter values from MIB service.
* *
* \details The MAC information base service to get the attributes of the LoRaMac layer. * @details The MAC information base service to get the attributes of the LoRaMac layer.
* *
* The following code-snippet shows how to use the API to get the * The following code-snippet shows how to use the API to get the
* parameter `AdrEnable`, defined by the enumeration type * parameter `AdrEnable`, defined by the enumeration type
* \ref MIB_ADR. * \ref MIB_ADR.
* \code *
* MibRequestConfirm_t mibReq; * @code
* mibReq.Type = MIB_ADR; *
* * loramac_mib_req_confirm_t mib_get;
* if( LoRaMacMibGetRequestConfirm( &mibReq ) == LORAMAC_STATUS_OK ) * mib_get.type = MIB_ADR;
* { *
* // LoRaMAC updated the parameter mibParam.AdrEnable * if (mib_get_request_confirm(&mib_get) == LORAWAN_STATUS_OK) {
* } * // LoRaMAC updated the parameter mibParam.AdrEnable
* \endcode * }
* *
* \param [in] mibGet - The MIB-GET request to perform. Refer to \ref MibRequestConfirm_t. * @endcode
* *
* \retval `LoRaMacStatus_t` The status of the operation. The possible values are: * @param [in] mib_get The MIB-GET request to perform. Refer to
* \ref LORAMAC_STATUS_OK * \ref loramac_mib_req_confirm_t.
* \ref LORAMAC_STATUS_SERVICE_UNKNOWN *
* \ref LORAMAC_STATUS_PARAMETER_INVALID * @return `lorawan_status_t` The status of the operation.
*/ * The possible values are:
LoRaMacStatus_t LoRaMacMibGetRequestConfirm( MibRequestConfirm_t *mibGet ); * \ref LORAWAN_STATUS_OK
* \ref LORAWAN_STATUS_SERVICE_UNKNOWN
* \ref LORAWAN_STATUS_PARAMETER_INVALID
*/
lorawan_status_t mib_get_request_confirm(loramac_mib_req_confirm_t *mib_get);
/*! /**
* \brief LoRaMAC MIB-SET. * @brief Set attributes for MAC layer using MIB service.
* *
* \details The MAC information base service to set the attributes of the LoRaMac layer. * @details The MAC information base service to set the attributes of the LoRaMac layer.
* *
* The following code-snippet shows how to use the API to set the * The following code-snippet shows how to use the API to set the
* parameter `AdrEnable`, defined by the enumeration type * parameter `adr_enable`, defined by the enumeration type
* \ref MIB_ADR. * \ref MIB_ADR.
* *
* \code * @code
* MibRequestConfirm_t mibReq; *
* mibReq.Type = MIB_ADR; * loramac_mib_req_confirm_t mib_set;
* mibReq.Param.AdrEnable = true; * mib_set.Type = MIB_ADR;
* * mib_set.param.adr_enable = true;
* if( LoRaMacMibGetRequestConfirm( &mibReq ) == LORAMAC_STATUS_OK ) *
* { * if (mib_set_request_confirm(&mib_set) == LORAWAN_STATUS_OK) {
* // LoRaMAC updated the parameter * // LoRaMAC updated the parameter
* } * }
* \endcode *
* * @endcode
* \param [in] mibSet - The MIB-SET request to perform. Refer to \ref MibRequestConfirm_t. *
* * @param [in] mib_set The MIB-SET request to perform. Refer to
* \retval `LoRaMacStatus_t` The status of the operation. The possible values are: * \ref loramac_mib_req_confirm_t.
* \ref LORAMAC_STATUS_OK *
* \ref LORAMAC_STATUS_BUSY * @return `lorawan_status_t` The status of the operation. The possible values are:
* \ref LORAMAC_STATUS_SERVICE_UNKNOWN * \ref LORAWAN_STATUS_OK
* \ref LORAMAC_STATUS_PARAMETER_INVALID * \ref LORAWAN_STATUS_BUSY
*/ * \ref LORAWAN_STATUS_SERVICE_UNKNOWN
LoRaMacStatus_t LoRaMacMibSetRequestConfirm( MibRequestConfirm_t *mibSet ); * \ref LORAWAN_STATUS_PARAMETER_INVALID
*/
lorawan_status_t mib_set_request_confirm(loramac_mib_req_confirm_t *mib_set);
/*! /**
* \brief LoRaMAC MLME request * @brief Set forth an MLME request.
* *
* \details The MAC layer management entity handles the management services. The * @details The MAC layer management entity handles the management services. The
* following code-snippet shows how to use the API to perform a * following code-snippet shows how to use the API to perform a
* network join request. * network join request.
* *
* \code * @code
* static uint8_t DevEui[] = *
* { * static uint8_t dev_eui[] =
* 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 * {
* }; * 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
* static uint8_t AppEui[] = * };
* { * static uint8_t app_eui[] =
* 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 * {
* }; * 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
* static uint8_t AppKey[] = * };
* { * static uint8_t app_key[] =
* 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, * {
* 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C * 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
* }; * 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C
* * };
* MlmeReq_t mlmeReq; *
* mlmeReq.Type = MLME_JOIN; * loramac_mlme_req_t mlme_req;
* mlmeReq.Req.Join.DevEui = DevEui; * mlme_req.Type = MLME_JOIN;
* mlmeReq.Req.Join.AppEui = AppEui; * mlme_req.req.join.dev_eui = dev_eui;
* mlmeReq.Req.Join.AppKey = AppKey; * mlme_req.req.join.app_eui = app_eui;
* * mlme_req.req.join.app_key = app_key;
* if( LoRaMacMlmeRequest( &mlmeReq ) == LORAMAC_STATUS_OK ) *
* { * if (LoRaMacMlmeRequest(&mlme_req) == LORAWAN_STATUS_OK) {
* // Service started successfully. Waiting for the Mlme-Confirm event * // Service started successfully. Waiting for the Mlme-Confirm event
* } * }
* \endcode *
* * @endcode
* \param [in] mlmeRequest - The MLME request to perform. Refer to \ref MlmeReq_t. *
* * @param [in] request The MLME request to perform.
* \retval `LoRaMacStatus_t` The status of the operation. The possible values are: * Refer to \ref loramac_mlme_req_t.
* \ref LORAMAC_STATUS_OK *
* \ref LORAMAC_STATUS_BUSY * @return `lorawan_status_t` The status of the operation. The possible values are:
* \ref LORAMAC_STATUS_SERVICE_UNKNOWN * \ref LORAWAN_STATUS_OK
* \ref LORAMAC_STATUS_PARAMETER_INVALID * \ref LORAWAN_STATUS_BUSY
* \ref LORAMAC_STATUS_NO_NETWORK_JOINED * \ref LORAWAN_STATUS_SERVICE_UNKNOWN
* \ref LORAMAC_STATUS_LENGTH_ERROR * \ref LORAWAN_STATUS_PARAMETER_INVALID
* \ref LORAMAC_STATUS_DEVICE_OFF * \ref LORAWAN_STATUS_NO_NETWORK_JOINED
*/ * \ref LORAWAN_STATUS_LENGTH_ERROR
LoRaMacStatus_t LoRaMacMlmeRequest( MlmeReq_t *mlmeRequest ); * \ref LORAWAN_STATUS_DEVICE_OFF
*/
lorawan_status_t mlme_request(loramac_mlme_req_t *request);
/*! /**
* \brief LoRaMAC MCPS request * @brief Set forth an MCPS request.
* *
* \details The MAC Common Part Sublayer handles the data services. The following * @details The MAC Common Part Sublayer handles the data services. The following
* code-snippet shows how to use the API to send an unconfirmed * code-snippet shows how to use the API to send an unconfirmed
* LoRaMAC frame. * LoRaMAC frame.
* *
* \code * @code
* uint8_t myBuffer[] = { 1, 2, 3 }; *
* * uint8_t buffer[] = {1, 2, 3};
* McpsReq_t mcpsReq; *
* mcpsReq.Type = MCPS_UNCONFIRMED; * loramac_mcps_req_t request;
* mcpsReq.Req.Unconfirmed.fPort = 1; * request.type = MCPS_UNCONFIRMED;
* mcpsReq.Req.Unconfirmed.fBuffer = myBuffer; * request.req.unconfirmed.fport = 1;
* mcpsReq.Req.Unconfirmed.fBufferSize = sizeof( myBuffer ); * request.req.unconfirmed.f_buffer = buffer;
* * request.req.unconfirmed.f_buffer_size = sizeof(buffer);
* if( LoRaMacMcpsRequest( &mcpsReq ) == LORAMAC_STATUS_OK ) *
* { * if (mcps_request(&request) == LORAWAN_STATUS_OK) {
* // Service started successfully. Waiting for the MCPS-Confirm event * // Service started successfully. Waiting for the MCPS-Confirm event
* } * }
* \endcode *
* * @endcode
* \param [in] mcpsRequest - The MCPS request to perform. Refer to \ref McpsReq_t. *
* * @param [in] request The MCPS request to perform.
* \retval `LoRaMacStatus_t` The status of the operation. The possible values are: * Refer to \ref loramac_mcps_req_t.
* \ref LORAMAC_STATUS_OK *
* \ref LORAMAC_STATUS_BUSY * @return `lorawan_status_t` The status of the operation. The possible values are:
* \ref LORAMAC_STATUS_SERVICE_UNKNOWN * \ref LORAWAN_STATUS_OK
* \ref LORAMAC_STATUS_PARAMETER_INVALID * \ref LORAWAN_STATUS_BUSY
* \ref LORAMAC_STATUS_NO_NETWORK_JOINED * \ref LORAWAN_STATUS_SERVICE_UNKNOWN
* \ref LORAMAC_STATUS_LENGTH_ERROR * \ref LORAWAN_STATUS_PARAMETER_INVALID
* \ref LORAMAC_STATUS_DEVICE_OFF * \ref LORAWAN_STATUS_NO_NETWORK_JOINED
*/ * \ref LORAWAN_STATUS_LENGTH_ERROR
LoRaMacStatus_t LoRaMacMcpsRequest( McpsReq_t *mcpsRequest ); * \ref LORAWAN_STATUS_DEVICE_OFF
*/
lorawan_status_t mcps_request(loramac_mcps_req_t *request);
/** /**
* \brief LoRaMAC layer provides its callback functions for * @brief LoRaMAC layer provides its callback functions for
* PHY layer * PHY layer.
* *
* \return Pointer to callback functions for radio events * @return Pointer to callback functions for radio events
*/ */
radio_events_t *GetPhyEventHandlers(); radio_events_t *get_phy_event_handlers();
/**
* @brief Configures the events to trigger an MLME-Indication with
* a MLME type of MLME_SCHEDULE_UPLINK.
*/
void set_mlme_schedule_ul_indication(void);
/**
* @brief Schedules the frame for sending.
*
* @details Prepares a full MAC frame and schedules it for physical
* transmission.
*
* @param [in] mac_hdr MAC frame header field
* @param [in] fport Payload port
* @param [in] fbuffer MAC frame data buffer to be sent
* @param [in] fbuffer_size MAC frame data buffer size
*
* @return status Status of the operation. LORAWAN_STATUS_OK in case
* of success and a negative error code in case of
* failure.
*/
lorawan_status_t send(loramac_mhdr_t *mac_hdr, uint8_t fport, void *fbuffer,
uint16_t fbuffer_size);
/**
* @brief Puts the system 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
*
* @return status Status of the operation. LORAWAN_STATUS_OK in case
* of success and a negative error code in case of
* failure.
*/
lorawan_status_t set_tx_continuous_wave(uint16_t timeout);
/**
* @brief Puts the system in continuous transmission mode
*
* @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.
*
* @return status Status of the operation. LORAWAN_STATUS_OK in case
* of success and a negative error code in case of
* failure.
*/
lorawan_status_t set_tx_continuous_wave1(uint16_t timeout, uint32_t frequency, uint8_t power);
/**
* @brief Resets MAC specific parameters to default
*/
void reset_mac_parameters(void);
/**
* @brief Opens up a continuous RX 2 window. This is used for
* class c devices.
*/
void open_continuous_rx2_window(void);
#if defined(LORAWAN_COMPLIANCE_TEST) #if defined(LORAWAN_COMPLIANCE_TEST)
/** public: // Test interface
* \brief LoRaMAC set tx timer.
*
* \details Sets up a timer for next transmission (application specific timers).
*
* \param [in] NextTxTime - Periodic time for next uplink.
* \retval `LoRaMacStatus_t` The status of the operation. The possible values are: /**
* \ref LORAMAC_STATUS_OK * \brief LoRaMAC set tx timer.
* \ref LORAMAC_STATUS_PARAMETER_INVALID *
*/ * \details Sets up a timer for next transmission (application specific timers).
LoRaMacStatus_t LoRaMacSetTxTimer( uint32_t NextTxTime ); *
* \param [in] NextTxTime - Periodic time for next uplink.
/** * \retval `lorawan_status_t` The status of the operation. The possible values are:
* \brief LoRaMAC stop tx timer. * \ref LORAWAN_STATUS_OK
* * \ref LORAWAN_STATUS_PARAMETER_INVALID
* \details Stops the next tx timer. */
* lorawan_status_t LoRaMacSetTxTimer( uint32_t NextTxTime );
* \retval `LoRaMacStatus_t` The status of the operation. The possible values are:
* \ref LORAMAC_STATUS_OK /**
* \ref LORAMAC_STATUS_PARAMETER_INVALID * \brief LoRaMAC stop tx timer.
*/ *
LoRaMacStatus_t LoRaMacStopTxTimer( ); * \details Stops the next tx timer.
*
* \retval `lorawan_status_t` The status of the operation. The possible values are:
* \ref LORAWAN_STATUS_OK
* \ref LORAWAN_STATUS_PARAMETER_INVALID
*/
lorawan_status_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
*/
timer_event_t tx_next_packet_timer;
#endif #endif
#endif // __LORAMAC_H__ private:
/**
* Function to be executed on Radio Tx Done event
*/
void on_radio_tx_done(void);
/**
* This function prepares the MAC to abort the execution of function
* on_radio_rx_done() in case of a reception error.
*/
void prepare_rx_done_abort(void);
/**
* Function to be executed on Radio Rx Done event
*/
void on_radio_rx_done(uint8_t *payload, uint16_t size, int16_t rssi,
int8_t snr);
/**
* Function executed on Radio Tx Timeout event
*/
void on_radio_tx_timeout(void);
/**
* Function executed on Radio Rx error event
*/
void on_radio_rx_error(void);
/**
* Function executed on Radio Rx Timeout event
*/
void on_radio_rx_timeout(void);
/**
*Function executed on Resend Frame timer event.
*/
void on_mac_state_check_timer_event(void);
/**
* Function executed on duty cycle delayed Tx timer event
*/
void on_tx_delayed_timer_event(void);
/**
* Function executed on first Rx window timer event
*/
void on_rx_window1_timer_event(void);
/**
* Function executed on second Rx window timer event
*/
void on_rx_window2_timer_event(void);
/**
* Function executed on AckTimeout timer event
*/
void on_ack_timeout_timer_event(void);
/**
* Initializes and opens the reception window
*/
void rx_window_setup(bool rx_continuous, uint32_t max_rx_window_time);
/**
* Validates if the payload fits into the frame, taking the datarate
* into account.
*
* Please Refer to chapter 4.3.2 of the LoRaWAN specification, v1.0.2
*/
bool validate_payload_length(uint8_t length, int8_t datarate, uint8_t fopts_len);
/**
* Prepares MAC frame on the behest of send() API.
*/
lorawan_status_t prepare_frame(loramac_mhdr_t *mac_hdr,
loramac_frame_ctrl_t *fctrl, uint8_t fport,
void *fbuffer, uint16_t fbuffer_size);
/**
* Schedules a transmission on the behest of send() API.
*/
lorawan_status_t schedule_tx(void);
/**
* Calculates the back-off time for the band of a channel.
* Takes in the last used channel id as a parameter.
*/
void calculate_backOff(uint8_t channel_id);
/**
* Hands over the MAC frame to PHY layer.
*/
lorawan_status_t send_frame_on_channel(uint8_t channel);
/**
* Checks for Port validity.
*/
bool is_fPort_allowed(uint8_t fPort);
/**
* Prototypes for ISR handlers
*/
void handle_cad_done(bool cad);
void handle_tx_done(void);
void handle_rx_done(uint8_t *payload, uint16_t size, int16_t rssi,
int8_t snr);
void handle_rx_error(void);
void handle_rx_timeout(void);
void handle_tx_timeout(void);
void handle_fhss_change_channel(uint8_t cur_channel);
void handle_rx1_timer_event(void);
void handle_rx2_timer_event(void);
void handle_ack_timeout(void);
void handle_delayed_tx_timer_event(void);
void handle_mac_state_check_timer_event(void);
void handle_next_tx_timer_event(void);
private:
/**
* LoRa PHY layer object storage
*/
LoRaPHY *lora_phy;
/**
* MAC command handle
*/
LoRaMacCommand mac_commands;
/**
* MLME subsystem handle
*/
LoRaMacMlme mlme;
/**
* MCPS subsystem handle
*/
LoRaMacMcps mcps;
/**
* MCPS subsystem handle
*/
LoRaMacMib mib;
/**
* Channel planning subsystem
*/
LoRaMacChannelPlan channel_plan;
/**
* Timer subsystem handle
*/
LoRaWANTimeHandler &_lora_time;
/**
* Central MAC layer data storage
*/
loramac_protocol_params _params;
/**
* Radio event callback handlers for MAC
*/
radio_events_t radio_events;
/**
* LoRaMac upper layer event functions
*/
loramac_primitives_t *mac_primitives;
/**
* EventQueue object storage
*/
events::EventQueue *ev_queue;
};
#endif // MBED_LORAWAN_MAC_H__

View File

@ -0,0 +1,243 @@
/**
/ _____) _ | |
( (____ _____ ____ _| |_ _____ ____| |__
\____ \| ___ | (_ _) ___ |/ ___) _ \
_____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
(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;
}

View File

@ -0,0 +1,117 @@
/**
\code
/ _____) _ | |
( (____ _____ ____ _| |_ _____ ____| |__
\____ \| ___ | (_ _) ___ |/ ___) _ \
_____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
(C)2013 Semtech
___ _____ _ ___ _ _____ ___ ___ ___ ___
/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
embedded.connectivity.solutions===============
\endcode
Description: LoRaWAN stack layer that controls both MAC and PHY underneath
License: Revised BSD License, see LICENSE.TXT file include in the project
Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )
Copyright (c) 2017, Arm Limited and affiliates.
SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef MBED_LORAWAN_LORAMACCHANNELPLAN_H_
#define MBED_LORAWAN_LORAMACCHANNELPLAN_H_
#include "lorawan/system/lorawan_data_structures.h"
#include "lorastack/phy/LoRaPHY.h"
#include "lorastack/mac/LoRaMacMib.h"
class LoRaMacChannelPlan {
public:
/** Constructor
*
* Sets local handles to NULL. These handles will be set when the subsystem
* is activated by the MAC layer.
*/
LoRaMacChannelPlan();
/** Destructor
*
* Does nothing
*/
~LoRaMacChannelPlan();
/** Activates Channel Planning subsystem
*
* Stores pointers to PHY layer MIB subsystem
*
* @param phy pointer to PHY layer
* @param mib pointer to MIB subsystem
*/
void activate_channelplan_subsystem(LoRaPHY *phy,LoRaMacMib *mib);
/** Set a given channel plan
*
* Used to set application provided channel plan. This API can be used to
* set a single channel as well to the existing channel plan.
*
* @param plan a reference to application channel plan. PHY layer takes a
* copy of the channel parameters provided within.
*
* @return LORAWAN_STATUS_OK if everything goes well otherwise
* a negative error code is returned.
*/
lorawan_status_t set_plan(const lorawan_channelplan_t& plan);
/** Access the active channel plan
*
* Used to get active channel plan.
*
* @param plan a reference to application provided channel plan structure
* which gets filled in with active channel plan data.
*
* @param params pointer to active MAC layer parameters.
*
* @return LORAWAN_STATUS_OK if everything goes well otherwise
* a negative error code is returned.
*/
lorawan_status_t get_plan(lorawan_channelplan_t& plan, loramac_protocol_params *params);
/** Remove the active channel plan
*
* Drops the whole channel list except the 'Default Channels' ofcourse.
*
* @return LORAWAN_STATUS_OK if everything goes well otherwise
* a negative error code is returned.
*/
lorawan_status_t remove_plan();
/** Remove a single channel from the plan
*
* @param id the channel id which needs to be removed
*
* @return LORAWAN_STATUS_OK if everything goes well otherwise
* a negative error code is returned.
*/
lorawan_status_t remove_single_channel(uint8_t id);
private:
/**
* Local handles
*/
LoRaPHY *_lora_phy;
LoRaMacMib * _mib;
};
#endif /* MBED_LORAWAN_LORAMACCHANNELPLAN_H_ */

View File

@ -0,0 +1,424 @@
/**
/ _____) _ | |
( (____ _____ ____ _| |_ _____ ____| |__
\____ \| ___ | (_ _) ___ |/ ___) _ \
_____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
(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 max_eirp_table[] = { 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)
{
mac_cmd_in_next_tx = false;
mac_cmd_buf_idx = 0;
mac_cmd_buf_idx_to_repeat = 0;
memset(mac_cmd_buffer, 0, sizeof(mac_cmd_buffer));
memset(mac_cmd_buffer_to_repeat, 0, sizeof(mac_cmd_buffer_to_repeat));
}
LoRaMacCommand::~LoRaMacCommand()
{
}
lorawan_status_t LoRaMacCommand::add_mac_command(uint8_t cmd, uint8_t p1,
uint8_t p2)
{
lorawan_status_t status = LORAWAN_STATUS_BUSY;
// The maximum buffer length must take MAC commands to re-send into account.
const uint8_t bufLen = LORA_MAC_COMMAND_MAX_LENGTH
- mac_cmd_buf_idx_to_repeat;
switch (cmd) {
case MOTE_MAC_LINK_CHECK_REQ:
if (mac_cmd_buf_idx < bufLen) {
mac_cmd_buffer[mac_cmd_buf_idx++] = cmd;
// No payload for this command
status = LORAWAN_STATUS_OK;
}
break;
case MOTE_MAC_LINK_ADR_ANS:
if (mac_cmd_buf_idx < (bufLen - 1)) {
mac_cmd_buffer[mac_cmd_buf_idx++] = cmd;
// Margin
mac_cmd_buffer[mac_cmd_buf_idx++] = p1;
status = LORAWAN_STATUS_OK;
}
break;
case MOTE_MAC_DUTY_CYCLE_ANS:
if (mac_cmd_buf_idx < bufLen) {
mac_cmd_buffer[mac_cmd_buf_idx++] = cmd;
// No payload for this answer
status = LORAWAN_STATUS_OK;
}
break;
case MOTE_MAC_RX_PARAM_SETUP_ANS:
if (mac_cmd_buf_idx < (bufLen - 1)) {
mac_cmd_buffer[mac_cmd_buf_idx++] = cmd;
// Status: Datarate ACK, Channel ACK
mac_cmd_buffer[mac_cmd_buf_idx++] = p1;
// This is a sticky MAC command answer. Setup indication
_lora_mac.set_mlme_schedule_ul_indication();
status = LORAWAN_STATUS_OK;
}
break;
case MOTE_MAC_DEV_STATUS_ANS:
if (mac_cmd_buf_idx < (bufLen - 2)) {
mac_cmd_buffer[mac_cmd_buf_idx++] = cmd;
// 1st byte Battery
// 2nd byte Margin
mac_cmd_buffer[mac_cmd_buf_idx++] = p1;
mac_cmd_buffer[mac_cmd_buf_idx++] = p2;
status = LORAWAN_STATUS_OK;
}
break;
case MOTE_MAC_NEW_CHANNEL_ANS:
if (mac_cmd_buf_idx < (bufLen - 1)) {
mac_cmd_buffer[mac_cmd_buf_idx++] = cmd;
// Status: Datarate range OK, Channel frequency OK
mac_cmd_buffer[mac_cmd_buf_idx++] = p1;
status = LORAWAN_STATUS_OK;
}
break;
case MOTE_MAC_RX_TIMING_SETUP_ANS:
if (mac_cmd_buf_idx < bufLen) {
mac_cmd_buffer[mac_cmd_buf_idx++] = cmd;
// No payload for this answer
// This is a sticky MAC command answer. Setup indication
_lora_mac.set_mlme_schedule_ul_indication();
status = LORAWAN_STATUS_OK;
}
break;
case MOTE_MAC_TX_PARAM_SETUP_ANS:
if (mac_cmd_buf_idx < bufLen) {
mac_cmd_buffer[mac_cmd_buf_idx++] = cmd;
// No payload for this answer
status = LORAWAN_STATUS_OK;
}
break;
case MOTE_MAC_DL_CHANNEL_ANS:
if (mac_cmd_buf_idx < bufLen) {
mac_cmd_buffer[mac_cmd_buf_idx++] = cmd;
// Status: Uplink frequency exists, Channel frequency OK
mac_cmd_buffer[mac_cmd_buf_idx++] = p1;
// This is a sticky MAC command answer. Setup indication
_lora_mac.set_mlme_schedule_ul_indication();
status = LORAWAN_STATUS_OK;
}
break;
default:
return LORAWAN_STATUS_SERVICE_UNKNOWN;
}
if (status == LORAWAN_STATUS_OK) {
mac_cmd_in_next_tx = true;
}
return status;
}
void LoRaMacCommand::clear_command_buffer()
{
mac_cmd_buf_idx = 0;
}
uint8_t LoRaMacCommand::get_mac_cmd_length() const
{
return mac_cmd_buf_idx;
}
uint8_t *LoRaMacCommand::get_mac_commands_buffer()
{
return mac_cmd_buffer;
}
void LoRaMacCommand::parse_mac_commands_to_repeat()
{
uint8_t i = 0;
uint8_t cmd_cnt = 0;
for (i = 0; i < mac_cmd_buf_idx; i++) {
switch (mac_cmd_buffer[i]) {
// STICKY
case MOTE_MAC_DL_CHANNEL_ANS:
case MOTE_MAC_RX_PARAM_SETUP_ANS: { // 1 byte payload
mac_cmd_buffer_to_repeat[cmd_cnt++] = mac_cmd_buffer[i++];
mac_cmd_buffer_to_repeat[cmd_cnt++] = mac_cmd_buffer[i];
break;
}
case MOTE_MAC_RX_TIMING_SETUP_ANS: { // 0 byte payload
mac_cmd_buffer_to_repeat[cmd_cnt++] = mac_cmd_buffer[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 (cmd_cnt > 0) {
mac_cmd_in_next_tx = true;
} else {
mac_cmd_in_next_tx = false;
}
}
void LoRaMacCommand::clear_repeat_buffer()
{
mac_cmd_buf_idx_to_repeat = 0;
}
void LoRaMacCommand::copy_repeat_commands_to_buffer()
{
// Copy the MAC commands which must be re-send into the MAC command buffer
memcpy(&mac_cmd_buffer[mac_cmd_buf_idx], mac_cmd_buffer_to_repeat, mac_cmd_buf_idx_to_repeat);
mac_cmd_buf_idx += mac_cmd_buf_idx_to_repeat;
}
uint8_t LoRaMacCommand::get_repeat_commands_length() const
{
return mac_cmd_buf_idx_to_repeat;
}
void LoRaMacCommand::clear_mac_commands_in_next_tx()
{
mac_cmd_in_next_tx = false;
}
bool LoRaMacCommand::is_mac_command_in_next_tx() const
{
return mac_cmd_in_next_tx;
}
lorawan_status_t LoRaMacCommand::process_mac_commands(uint8_t *payload,
uint8_t mac_index,
uint8_t commands_size,
uint8_t snr,
loramac_mlme_confirm_t& mlme_conf,
lora_mac_system_params_t &mac_sys_params,
LoRaPHY &lora_phy)
{
uint8_t status = 0;
lorawan_status_t ret_value = LORAWAN_STATUS_OK;
while (mac_index < commands_size) {
// Decode Frame MAC commands
switch (payload[mac_index++]) {
case SRV_MAC_LINK_CHECK_ANS:
mlme_conf.status = LORAMAC_EVENT_INFO_STATUS_OK;
mlme_conf.demod_margin = payload[mac_index++];
mlme_conf.nb_gateways = payload[mac_index++];
break;
case SRV_MAC_LINK_ADR_REQ: {
adr_req_params_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[mac_index - 1];
linkAdrReq.payload_size = commands_size - (mac_index - 1);
linkAdrReq.adr_enabled = mac_sys_params.adr_on;
linkAdrReq.ul_dwell_time = mac_sys_params.uplink_dwell_time;
linkAdrReq.current_datarate = mac_sys_params.channel_data_rate;
linkAdrReq.current_tx_power = mac_sys_params.channel_tx_power;
linkAdrReq.current_nb_rep = mac_sys_params.retry_num;
// Process the ADR requests
status = lora_phy.link_ADR_request(&linkAdrReq,
&linkAdrDatarate,
&linkAdrTxPower,
&linkAdrNbRep,
&linkAdrNbBytesParsed);
if ((status & 0x07) == 0x07) {
mac_sys_params.channel_data_rate = linkAdrDatarate;
mac_sys_params.channel_tx_power = linkAdrTxPower;
mac_sys_params.retry_num = linkAdrNbRep;
}
// Add the answers to the buffer
for (uint8_t i = 0; i < (linkAdrNbBytesParsed / 5); i++) {
ret_value = add_mac_command(MOTE_MAC_LINK_ADR_ANS, status, 0);
}
// Update MAC index
mac_index += linkAdrNbBytesParsed - 1;
}
break;
case SRV_MAC_DUTY_CYCLE_REQ:
mac_sys_params.max_duty_cycle = payload[mac_index++];
mac_sys_params.aggregated_duty_cycle = 1 << mac_sys_params.max_duty_cycle;
ret_value = add_mac_command(MOTE_MAC_DUTY_CYCLE_ANS, 0, 0);
break;
case SRV_MAC_RX_PARAM_SETUP_REQ: {
rx_param_setup_req_t rxParamSetupReq;
rxParamSetupReq.dr_offset = (payload[mac_index] >> 4) & 0x07;
rxParamSetupReq.datarate = payload[mac_index] & 0x0F;
mac_index++;
rxParamSetupReq.frequency = (uint32_t) payload[mac_index++];
rxParamSetupReq.frequency |= (uint32_t) payload[mac_index++]
<< 8;
rxParamSetupReq.frequency |= (uint32_t) payload[mac_index++]
<< 16;
rxParamSetupReq.frequency *= 100;
// Perform request on region
status = lora_phy.accept_rx_param_setup_req(&rxParamSetupReq);
if ((status & 0x07) == 0x07) {
mac_sys_params.rx2_channel.datarate =
rxParamSetupReq.datarate;
mac_sys_params.rx2_channel.frequency =
rxParamSetupReq.frequency;
mac_sys_params.rx1_dr_offset = rxParamSetupReq.dr_offset;
}
ret_value = add_mac_command(MOTE_MAC_RX_PARAM_SETUP_ANS, status,
0);
}
break;
case SRV_MAC_DEV_STATUS_REQ: {
uint8_t batteryLevel = BAT_LEVEL_NO_MEASURE;
// we don't have a mechanism at the moment to measure
// battery levels
ret_value = add_mac_command(MOTE_MAC_DEV_STATUS_ANS,
batteryLevel, snr);
break;
}
case SRV_MAC_NEW_CHANNEL_REQ: {
new_channel_req_params_t newChannelReq;
channel_params_t chParam;
newChannelReq.channel_id = payload[mac_index++];
newChannelReq.new_channel = &chParam;
chParam.frequency = (uint32_t) payload[mac_index++];
chParam.frequency |= (uint32_t) payload[mac_index++] << 8;
chParam.frequency |= (uint32_t) payload[mac_index++] << 16;
chParam.frequency *= 100;
chParam.rx1_frequency = 0;
chParam.dr_range.value = payload[mac_index++];
status = lora_phy.request_new_channel(&newChannelReq);
ret_value = add_mac_command(MOTE_MAC_NEW_CHANNEL_ANS, status, 0);
}
break;
case SRV_MAC_RX_TIMING_SETUP_REQ: {
uint8_t delay = payload[mac_index++] & 0x0F;
if (delay == 0) {
delay++;
}
mac_sys_params.recv_delay1 = delay * 1000;
mac_sys_params.recv_delay2 = mac_sys_params.recv_delay1 + 1000;
ret_value = add_mac_command(MOTE_MAC_RX_TIMING_SETUP_ANS, 0, 0);
}
break;
case SRV_MAC_TX_PARAM_SETUP_REQ: {
tx_param_setup_req_t txParamSetupReq;
uint8_t eirpDwellTime = payload[mac_index++];
txParamSetupReq.ul_dwell_time = 0;
txParamSetupReq.dl_dwell_time = 0;
if ((eirpDwellTime & 0x20) == 0x20) {
txParamSetupReq.dl_dwell_time = 1;
}
if ((eirpDwellTime & 0x10) == 0x10) {
txParamSetupReq.ul_dwell_time = 1;
}
txParamSetupReq.max_eirp = eirpDwellTime & 0x0F;
// Check the status for correctness
if (lora_phy.accept_tx_param_setup_req(&txParamSetupReq)) {
// Accept command
mac_sys_params.uplink_dwell_time =
txParamSetupReq.ul_dwell_time;
mac_sys_params.downlink_dwell_time =
txParamSetupReq.dl_dwell_time;
mac_sys_params.max_eirp =
max_eirp_table[txParamSetupReq.max_eirp];
// Add command response
ret_value = add_mac_command(MOTE_MAC_TX_PARAM_SETUP_ANS, 0, 0);
}
}
break;
case SRV_MAC_DL_CHANNEL_REQ: {
dl_channel_req_params_t dlChannelReq;
dlChannelReq.channel_id = payload[mac_index++];
dlChannelReq.rx1_frequency = (uint32_t) payload[mac_index++];
dlChannelReq.rx1_frequency |= (uint32_t) payload[mac_index++] << 8;
dlChannelReq.rx1_frequency |= (uint32_t) payload[mac_index++] << 16;
dlChannelReq.rx1_frequency *= 100;
status = lora_phy.dl_channel_request(&dlChannelReq);
ret_value = add_mac_command(MOTE_MAC_DL_CHANNEL_ANS, status, 0);
}
break;
default:
// Unknown command. ABORT MAC commands processing
ret_value = LORAWAN_STATUS_UNSUPPORTED;
}
}
return ret_value;
}
bool LoRaMacCommand::is_sticky_mac_command_pending()
{
if (mac_cmd_buf_idx_to_repeat > 0) {
// Sticky MAC commands pending
return true;
}
return false;
}

View File

@ -0,0 +1,180 @@
/**
* \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)
*
* @return status Function status [0: OK, 1: Unknown command, 2: Buffer full]
*/
lorawan_status_t add_mac_command(uint8_t cmd, uint8_t p1, uint8_t p2);
/**
* @brief Clear MAC command buffer.
*/
void clear_command_buffer(void);
/**
* @brief Get the length of MAC commands
*
* @return status Length of used MAC buffer (bytes)
*/
uint8_t get_mac_cmd_length() const;
/**
* @brief Get MAC command buffer
*
* @return Pointer to MAC command buffer
*/
uint8_t *get_mac_commands_buffer();
/**
* @brief Parses the MAC commands which must be resent.
*/
void parse_mac_commands_to_repeat();
/**
* @brief Clear MAC command repeat buffer.
*/
void clear_repeat_buffer();
/**
* @brief Copy MAC commands from repeat buffer to actual MAC command buffer.
*/
void copy_repeat_commands_to_buffer();
/**
* @brief Get the length of MAC commands in repeat buffer
*
* @return status Length of used MAC Repeat buffer (bytes)
*/
uint8_t get_repeat_commands_length() const;
/**
* @brief Clear MAC commands in next TX.
*/
void clear_mac_commands_in_next_tx();
/**
* @brief Check if MAC command buffer has commands to be sent in next TX
*
* @return status True: buffer has MAC commands to be sent, false: no commands in buffer]
*/
bool is_mac_command_in_next_tx() const;
/**
* @brief Decodes MAC commands in the fOpts field and in the payload
*
* @return status Function status. LORAWAN_STATUS_OK if command successful.
*/
lorawan_status_t process_mac_commands(uint8_t *payload, uint8_t mac_index,
uint8_t commands_size, uint8_t snr,
loramac_mlme_confirm_t& mlme_conf,
lora_mac_system_params_t& mac_params,
LoRaPHY& lora_phy);
/**
* @brief Verifies if sticky MAC commands are pending.
*
* @return [true: sticky MAC commands pending, false: No MAC commands pending]
*/
bool is_sticky_mac_command_pending();
private:
LoRaMac& _lora_mac;
/**
* Indicates if the MAC layer wants to send MAC commands
*/
bool mac_cmd_in_next_tx;
/**
* Contains the current Mac command buffer index in 'mac_cmd_buffer'
*/
uint8_t mac_cmd_buf_idx;
/**
* Contains the current Mac command buffer index for MAC commands to repeat in
* 'mac_cmd_buffer_to_repeat'
*/
uint8_t mac_cmd_buf_idx_to_repeat;
/**
* Buffer containing the MAC layer commands
*/
uint8_t mac_cmd_buffer[LORA_MAC_COMMAND_MAX_LENGTH];
/**
* Buffer containing the MAC layer commands which must be repeated
*/
uint8_t mac_cmd_buffer_to_repeat[LORA_MAC_COMMAND_MAX_LENGTH];
};
#endif //__LORAMACCOMMAND_H__

View File

@ -41,251 +41,253 @@
/** /**
* MIC field computation initial data * MIC field computation initial data
*/ */
static uint8_t MicBlockB0[] = { 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, static uint8_t mic_block_b0[] = {0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
};
/** /**
* Contains the computed MIC field. * Contains the computed MIC field.
* *
* \remark Only the 4 first bytes are used * \remark Only the 4 first bytes are used
*/ */
static uint8_t Mic[16]; static uint8_t computed_mic[16];
/** /**
* Encryption aBlock and sBlock * Encryption aBlock and sBlock
*/ */
static uint8_t aBlock[] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, static uint8_t a_block[] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
};
static uint8_t sBlock[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, static uint8_t s_block[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
};
/** /**
* AES computation context variable * AES computation context variable
*/ */
static mbedtls_aes_context AesContext; static mbedtls_aes_context aes_ctx;
/** /**
* CMAC computation context variable * CMAC computation context variable
*/ */
static mbedtls_cipher_context_t AesCmacCtx[1]; static mbedtls_cipher_context_t aes_cmac_ctx[1];
#define AES_CMAC_KEY_LENGTH 16 #define AES_CMAC_KEY_LENGTH 16
/** int compute_mic(const uint8_t *buffer, uint16_t size, const uint8_t *key,
* \brief Computes the LoRaMAC frame MIC field uint32_t address, uint8_t dir, uint32_t seq_counter,
* uint32_t *mic)
* \param [in] buffer Data buffer
* \param [in] size Data buffer size
* \param [in] key AES key to be used
* \param [in] address Frame address
* \param [in] dir Frame direction [0: uplink, 1: downlink]
* \param [in] sequenceCounter Frame sequence counter
* \param [out] mic Computed MIC field
*/
int LoRaMacComputeMic( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t address, uint8_t dir, uint32_t sequenceCounter, uint32_t *mic )
{ {
int ret = 0; int ret = 0;
MicBlockB0[5] = dir; mic_block_b0[5] = dir;
MicBlockB0[6] = ( address ) & 0xFF; mic_block_b0[6] = (address) & 0xFF;
MicBlockB0[7] = ( address >> 8 ) & 0xFF; mic_block_b0[7] = (address >> 8) & 0xFF;
MicBlockB0[8] = ( address >> 16 ) & 0xFF; mic_block_b0[8] = (address >> 16) & 0xFF;
MicBlockB0[9] = ( address >> 24 ) & 0xFF; mic_block_b0[9] = (address >> 24) & 0xFF;
MicBlockB0[10] = ( sequenceCounter ) & 0xFF; mic_block_b0[10] = (seq_counter) & 0xFF;
MicBlockB0[11] = ( sequenceCounter >> 8 ) & 0xFF; mic_block_b0[11] = (seq_counter >> 8) & 0xFF;
MicBlockB0[12] = ( sequenceCounter >> 16 ) & 0xFF; mic_block_b0[12] = (seq_counter >> 16) & 0xFF;
MicBlockB0[13] = ( sequenceCounter >> 24 ) & 0xFF; mic_block_b0[13] = (seq_counter >> 24) & 0xFF;
MicBlockB0[15] = size & 0xFF; mic_block_b0[15] = size & 0xFF;
mbedtls_cipher_init(aes_cmac_ctx);
mbedtls_cipher_init(AesCmacCtx);
const mbedtls_cipher_info_t* cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_ECB); const mbedtls_cipher_info_t* cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_ECB);
if (NULL != cipher_info) { if (NULL != cipher_info) {
ret = mbedtls_cipher_setup(AesCmacCtx, cipher_info); ret = mbedtls_cipher_setup(aes_cmac_ctx, cipher_info);
if (0 != ret) if (0 != ret)
goto exit; goto exit;
ret = mbedtls_cipher_cmac_starts(AesCmacCtx, key, AES_CMAC_KEY_LENGTH*8); ret = mbedtls_cipher_cmac_starts(aes_cmac_ctx, key,
AES_CMAC_KEY_LENGTH * 8);
if (0 != ret) if (0 != ret)
goto exit; goto exit;
ret = mbedtls_cipher_cmac_update(AesCmacCtx, MicBlockB0, LORAMAC_MIC_BLOCK_B0_SIZE); ret = mbedtls_cipher_cmac_update(aes_cmac_ctx, mic_block_b0,
LORAMAC_MIC_BLOCK_B0_SIZE);
if (0 != ret) if (0 != ret)
goto exit; goto exit;
ret = mbedtls_cipher_cmac_update(AesCmacCtx, buffer, size & 0xFF); ret = mbedtls_cipher_cmac_update(aes_cmac_ctx, buffer, size & 0xFF);
if (0 != ret) if (0 != ret)
goto exit; goto exit;
ret = mbedtls_cipher_cmac_finish(AesCmacCtx, Mic); ret = mbedtls_cipher_cmac_finish(aes_cmac_ctx, computed_mic);
if (0 != ret) if (0 != ret)
goto exit; goto exit;
*mic = ( uint32_t )( ( uint32_t )Mic[3] << 24 | ( uint32_t )Mic[2] << 16 | ( uint32_t )Mic[1] << 8 | ( uint32_t )Mic[0] ); *mic = (uint32_t) ((uint32_t) computed_mic[3] << 24
| (uint32_t) computed_mic[2] << 16
| (uint32_t) computed_mic[1] << 8 | (uint32_t) computed_mic[0]);
} else { } else {
ret = MBEDTLS_ERR_CIPHER_ALLOC_FAILED; ret = MBEDTLS_ERR_CIPHER_ALLOC_FAILED;
} }
exit: exit: mbedtls_cipher_free(aes_cmac_ctx);
mbedtls_cipher_free( AesCmacCtx );
return ret; return ret;
} }
int LoRaMacPayloadEncrypt( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t address, uint8_t dir, uint32_t sequenceCounter, uint8_t *encBuffer ) int encrypt_payload(const uint8_t *buffer, uint16_t size, const uint8_t *key,
uint32_t address, uint8_t dir, uint32_t seq_counter,
uint8_t *enc_buffer)
{ {
uint16_t i; uint16_t i;
uint8_t bufferIndex = 0; uint8_t bufferIndex = 0;
uint16_t ctr = 1; uint16_t ctr = 1;
int ret = 0; int ret = 0;
mbedtls_aes_init(&AesContext); mbedtls_aes_init(&aes_ctx);
ret = mbedtls_aes_setkey_enc(&AesContext, key, 16*8); ret = mbedtls_aes_setkey_enc(&aes_ctx, key, 16 * 8);
if (0 != ret) if (0 != ret)
goto exit; goto exit;
aBlock[5] = dir; a_block[5] = dir;
aBlock[6] = ( address ) & 0xFF; a_block[6] = (address) & 0xFF;
aBlock[7] = ( address >> 8 ) & 0xFF; a_block[7] = (address >> 8) & 0xFF;
aBlock[8] = ( address >> 16 ) & 0xFF; a_block[8] = (address >> 16) & 0xFF;
aBlock[9] = ( address >> 24 ) & 0xFF; a_block[9] = (address >> 24) & 0xFF;
aBlock[10] = ( sequenceCounter ) & 0xFF; a_block[10] = (seq_counter) & 0xFF;
aBlock[11] = ( sequenceCounter >> 8 ) & 0xFF; a_block[11] = (seq_counter >> 8) & 0xFF;
aBlock[12] = ( sequenceCounter >> 16 ) & 0xFF; a_block[12] = (seq_counter >> 16) & 0xFF;
aBlock[13] = ( sequenceCounter >> 24 ) & 0xFF; a_block[13] = (seq_counter >> 24) & 0xFF;
while( size >= 16 ) while (size >= 16) {
{ a_block[15] = ((ctr) & 0xFF);
aBlock[15] = ( ( ctr ) & 0xFF );
ctr++; ctr++;
ret = mbedtls_aes_crypt_ecb(&AesContext, MBEDTLS_AES_ENCRYPT, aBlock, sBlock); ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT, a_block,
s_block);
if (0 != ret) if (0 != ret)
goto exit; goto exit;
for( i = 0; i < 16; i++ ) for (i = 0; i < 16; i++) {
{ enc_buffer[bufferIndex + i] = buffer[bufferIndex + i] ^ s_block[i];
encBuffer[bufferIndex + i] = buffer[bufferIndex + i] ^ sBlock[i];
} }
size -= 16; size -= 16;
bufferIndex += 16; bufferIndex += 16;
} }
if( size > 0 ) if (size > 0) {
{ a_block[15] = ((ctr) & 0xFF);
aBlock[15] = ( ( ctr ) & 0xFF ); ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT, a_block,
ret = mbedtls_aes_crypt_ecb(&AesContext, MBEDTLS_AES_ENCRYPT, aBlock, sBlock); s_block);
if (0 != ret) if (0 != ret)
goto exit; goto exit;
for( i = 0; i < size; i++ ) for (i = 0; i < size; i++) {
{ enc_buffer[bufferIndex + i] = buffer[bufferIndex + i] ^ s_block[i];
encBuffer[bufferIndex + i] = buffer[bufferIndex + i] ^ sBlock[i];
} }
} }
exit: exit: mbedtls_aes_free(&aes_ctx);
mbedtls_aes_free(&AesContext);
return ret; return ret;
} }
int LoRaMacPayloadDecrypt( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t address, uint8_t dir, uint32_t sequenceCounter, uint8_t *decBuffer ) int decrypt_payload(const uint8_t *buffer, uint16_t size, const uint8_t *key,
uint32_t address, uint8_t dir, uint32_t seq_counter,
uint8_t *dec_buffer)
{ {
return LoRaMacPayloadEncrypt( buffer, size, key, address, dir, sequenceCounter, decBuffer ); return encrypt_payload(buffer, size, key, address, dir, seq_counter,
dec_buffer);
} }
int LoRaMacJoinComputeMic( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t *mic ) int compute_join_frame_mic(const uint8_t *buffer, uint16_t size,
const uint8_t *key, uint32_t *mic)
{ {
int ret = 0; int ret = 0;
mbedtls_cipher_init(AesCmacCtx); mbedtls_cipher_init(aes_cmac_ctx);
const mbedtls_cipher_info_t* cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_ECB); const mbedtls_cipher_info_t* cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_ECB);
if (NULL != cipher_info) { if (NULL != cipher_info) {
ret = mbedtls_cipher_setup(AesCmacCtx, cipher_info); ret = mbedtls_cipher_setup(aes_cmac_ctx, cipher_info);
if (0 != ret) if (0 != ret)
goto exit; goto exit;
ret = mbedtls_cipher_cmac_starts(AesCmacCtx, key, AES_CMAC_KEY_LENGTH*8); ret = mbedtls_cipher_cmac_starts(aes_cmac_ctx, key,
AES_CMAC_KEY_LENGTH * 8);
if (0 != ret) if (0 != ret)
goto exit; goto exit;
ret = mbedtls_cipher_cmac_update(AesCmacCtx, buffer, size & 0xFF); ret = mbedtls_cipher_cmac_update(aes_cmac_ctx, buffer, size & 0xFF);
if (0 != ret) if (0 != ret)
goto exit; goto exit;
ret = mbedtls_cipher_cmac_finish(AesCmacCtx, Mic); ret = mbedtls_cipher_cmac_finish(aes_cmac_ctx, computed_mic);
if (0 != ret) if (0 != ret)
goto exit; goto exit;
*mic = ( uint32_t )( ( uint32_t )Mic[3] << 24 | ( uint32_t )Mic[2] << 16 | ( uint32_t )Mic[1] << 8 | ( uint32_t )Mic[0] ); *mic = (uint32_t) ((uint32_t) computed_mic[3] << 24
| (uint32_t) computed_mic[2] << 16
| (uint32_t) computed_mic[1] << 8 | (uint32_t) computed_mic[0]);
} else { } else {
ret = MBEDTLS_ERR_CIPHER_ALLOC_FAILED; ret = MBEDTLS_ERR_CIPHER_ALLOC_FAILED;
} }
exit: exit: mbedtls_cipher_free(aes_cmac_ctx);
mbedtls_cipher_free(AesCmacCtx);
return ret; return ret;
} }
int LoRaMacJoinDecrypt( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint8_t *decBuffer ) int decrypt_join_frame(const uint8_t *buffer, uint16_t size, const uint8_t *key,
uint8_t *dec_buffer)
{ {
int ret = 0; int ret = 0;
mbedtls_aes_init(&AesContext); mbedtls_aes_init(&aes_ctx);
ret = mbedtls_aes_setkey_enc(&AesContext, key, 16*8); ret = mbedtls_aes_setkey_enc(&aes_ctx, key, 16 * 8);
if (0 != ret) if (0 != ret)
goto exit; goto exit;
ret = mbedtls_aes_crypt_ecb(&AesContext, MBEDTLS_AES_ENCRYPT, buffer, decBuffer); ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT, buffer,
dec_buffer);
if (0 != ret) if (0 != ret)
goto exit; goto exit;
// Check if optional CFList is included // Check if optional CFList is included
if( size >= 16 ) if (size >= 16) {
{ ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT, buffer + 16,
ret = mbedtls_aes_crypt_ecb(&AesContext, MBEDTLS_AES_ENCRYPT, buffer + 16, decBuffer + 16); dec_buffer + 16);
} }
exit: exit: mbedtls_aes_free(&aes_ctx);
mbedtls_aes_free(&AesContext);
return ret; return ret;
} }
int LoRaMacJoinComputeSKeys( const uint8_t *key, const uint8_t *appNonce, uint16_t devNonce, uint8_t *nwkSKey, uint8_t *appSKey ) int compute_skeys_for_join_frame(const uint8_t *key, const uint8_t *app_nonce,
uint16_t dev_nonce, uint8_t *nwk_skey,
uint8_t *app_skey)
{ {
uint8_t nonce[16]; uint8_t nonce[16];
uint8_t *pDevNonce = ( uint8_t * )&devNonce; uint8_t *p_dev_nonce = (uint8_t *) &dev_nonce;
int ret = 0; int ret = 0;
mbedtls_aes_init(&AesContext); mbedtls_aes_init(&aes_ctx);
ret = mbedtls_aes_setkey_enc(&AesContext, key, 16*8); ret = mbedtls_aes_setkey_enc(&aes_ctx, key, 16 * 8);
if (0 != ret) if (0 != ret)
goto exit; goto exit;
memset( nonce, 0, sizeof( nonce ) ); memset(nonce, 0, sizeof(nonce));
nonce[0] = 0x01; nonce[0] = 0x01;
memcpy( nonce + 1, appNonce, 6 ); memcpy(nonce + 1, app_nonce, 6);
memcpy( nonce + 7, pDevNonce, 2 ); memcpy(nonce + 7, p_dev_nonce, 2);
ret = mbedtls_aes_crypt_ecb(&AesContext, MBEDTLS_AES_ENCRYPT, nonce, nwkSKey); ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT, nonce, nwk_skey);
if (0 != ret) if (0 != ret)
goto exit; goto exit;
memset( nonce, 0, sizeof( nonce ) ); memset(nonce, 0, sizeof(nonce));
nonce[0] = 0x02; nonce[0] = 0x02;
memcpy( nonce + 1, appNonce, 6 ); memcpy(nonce + 1, app_nonce, 6);
memcpy( nonce + 7, pDevNonce, 2 ); memcpy(nonce + 7, p_dev_nonce, 2);
ret = mbedtls_aes_crypt_ecb(&AesContext, MBEDTLS_AES_ENCRYPT, nonce, appSKey); ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT, nonce, app_skey);
exit: exit: mbedtls_aes_free(&aes_ctx);
mbedtls_aes_free(&AesContext);
return ret; return ret;
} }
#else #else
@ -294,54 +296,56 @@ exit:
// user knows what is wrong and in addition to that these ensure that // user knows what is wrong and in addition to that these ensure that
// Mbed-OS compiles properly under normal conditions where LoRaWAN in conjunction // Mbed-OS compiles properly under normal conditions where LoRaWAN in conjunction
// with mbedTLS is not being used. // with mbedTLS is not being used.
int LoRaMacComputeMic( const uint8_t *, uint16_t , const uint8_t *, uint32_t, int compute_mic(const uint8_t *, uint16_t , const uint8_t *, uint32_t,
uint8_t dir, uint32_t, uint32_t * ) uint8_t dir, uint32_t, uint32_t *)
{ {
MBED_ASSERT("[LoRaCrypto] Must enable AES, CMAC & CIPHER from mbedTLS"); MBED_ASSERT("[LoRaCrypto] Must enable AES, CMAC & CIPHER from mbedTLS");
// Never actually reaches here // Never actually reaches here
return LORA_MAC_STATUS_CRYPTO_FAIL; return LORAWAN_STATUS_CRYPTO_FAIL;
} }
int LoRaMacPayloadEncrypt( const uint8_t *, uint16_t , const uint8_t *, uint32_t, int encrypt_payload(const uint8_t *, uint16_t , const uint8_t *, uint32_t,
uint8_t , uint32_t , uint8_t * ) uint8_t , uint32_t , uint8_t *)
{ {
MBED_ASSERT("[LoRaCrypto] Must enable AES, CMAC & CIPHER from mbedTLS"); MBED_ASSERT("[LoRaCrypto] Must enable AES, CMAC & CIPHER from mbedTLS");
// Never actually reaches here // Never actually reaches here
return LORA_MAC_STATUS_CRYPTO_FAIL; return LORAWAN_STATUS_CRYPTO_FAIL;
} }
int LoRaMacPayloadDecrypt( const uint8_t *, uint16_t , const uint8_t *, uint32_t, int decrypt_payload(const uint8_t *, uint16_t , const uint8_t *, uint32_t,
uint8_t , uint32_t , uint8_t * ) uint8_t , uint32_t , uint8_t *)
{ {
MBED_ASSERT("[LoRaCrypto] Must enable AES, CMAC & CIPHER from mbedTLS"); MBED_ASSERT("[LoRaCrypto] Must enable AES, CMAC & CIPHER from mbedTLS");
// Never actually reaches here // Never actually reaches here
return LORA_MAC_STATUS_CRYPTO_FAIL; return LORAWAN_STATUS_CRYPTO_FAIL;
}
int LoRaMacJoinComputeMic( const uint8_t *, uint16_t , const uint8_t *, uint32_t * )
{
MBED_ASSERT("[LoRaCrypto] Must enable AES, CMAC & CIPHER from mbedTLS");
// Never actually reaches here
return LORA_MAC_STATUS_CRYPTO_FAIL;
} }
int LoRaMacJoinDecrypt( const uint8_t *, uint16_t , const uint8_t *, uint8_t * ) int compute_join_frame_mic(const uint8_t *, uint16_t , const uint8_t *, uint32_t *)
{ {
MBED_ASSERT("[LoRaCrypto] Must enable AES, CMAC & CIPHER from mbedTLS"); MBED_ASSERT("[LoRaCrypto] Must enable AES, CMAC & CIPHER from mbedTLS");
// Never actually reaches here // Never actually reaches here
return LORA_MAC_STATUS_CRYPTO_FAIL; return LORAWAN_STATUS_CRYPTO_FAIL;
} }
int LoRaMacJoinComputeSKeys( const uint8_t *, const uint8_t *, uint16_t , uint8_t *, uint8_t * ) int decrypt_join_frame(const uint8_t *, uint16_t , const uint8_t *, uint8_t *)
{ {
MBED_ASSERT("[LoRaCrypto] Must enable AES, CMAC & CIPHER from mbedTLS"); MBED_ASSERT("[LoRaCrypto] Must enable AES, CMAC & CIPHER from mbedTLS");
// Never actually reaches here // Never actually reaches here
return LORA_MAC_STATUS_CRYPTO_FAIL; return LORAWAN_STATUS_CRYPTO_FAIL;
}
int compute_skeys_for_join_frame(const uint8_t *, const uint8_t *, uint16_t ,
uint8_t *, uint8_t *)
{
MBED_ASSERT("[LoRaCrypto] Must enable AES, CMAC & CIPHER from mbedTLS");
// Never actually reaches here
return LORAWAN_STATUS_CRYPTO_FAIL;
} }
#endif #endif

View File

@ -29,84 +29,94 @@ SPDX-License-Identifier: BSD-3-Clause
/** /**
* Computes the LoRaMAC frame MIC field * Computes the LoRaMAC frame MIC field
* *
* \param [in] buffer - Data buffer * @param [in] buffer - Data buffer
* \param [in] size - Data buffer size * @param [in] size - Data buffer size
* \param [in] key - AES key to be used * @param [in] key - AES key to be used
* \param [in] address - Frame address * @param [in] address - Frame address
* \param [in] dir - Frame direction [0: uplink, 1: downlink] * @param [in] dir - Frame direction [0: uplink, 1: downlink]
* \param [in] sequenceCounter - Frame sequence counter * @param [in] seq_counter - Frame sequence counter
* \param [out] mic - Computed MIC field * @param [out] mic - Computed MIC field
* *
* \return 0 if successful, or a cipher specific error code * @return 0 if successful, or a cipher specific error code
*/ */
int LoRaMacComputeMic( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t address, uint8_t dir, uint32_t sequenceCounter, uint32_t *mic ); int compute_mic(const uint8_t *buffer, uint16_t size, const uint8_t *key,
uint32_t address, uint8_t dir, uint32_t seq_counter,
uint32_t *mic);
/** /**
* Computes the LoRaMAC payload encryption * Performs payload encryption
* *
* \param [in] buffer - Data buffer * @param [in] buffer - Data buffer
* \param [in] size - Data buffer size * @param [in] size - Data buffer size
* \param [in] key - AES key to be used * @param [in] key - AES key to be used
* \param [in] address - Frame address * @param [in] address - Frame address
* \param [in] dir - Frame direction [0: uplink, 1: downlink] * @param [in] dir - Frame direction [0: uplink, 1: downlink]
* \param [in] sequenceCounter - Frame sequence counter * @param [in] seq_counter - Frame sequence counter
* \param [out] encBuffer - Encrypted buffer * @param [out] enc_buffer - Encrypted buffer
* *
* \return 0 if successful, or a cipher specific error code * @return 0 if successful, or a cipher specific error code
*/ */
int LoRaMacPayloadEncrypt( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t address, uint8_t dir, uint32_t sequenceCounter, uint8_t *encBuffer ); int encrypt_payload(const uint8_t *buffer, uint16_t size, const uint8_t *key,
uint32_t address, uint8_t dir, uint32_t seq_counter,
uint8_t *enc_buffer);
/** /**
* Computes the LoRaMAC payload decryption * Performs payload decryption
* *
* \param [in] buffer - Data buffer * @param [in] buffer - Data buffer
* \param [in] size - Data buffer size * @param [in] size - Data buffer size
* \param [in] key - AES key to be used * @param [in] key - AES key to be used
* \param [in] address - Frame address * @param [in] address - Frame address
* \param [in] dir - Frame direction [0: uplink, 1: downlink] * @param [in] dir - Frame direction [0: uplink, 1: downlink]
* \param [in] sequenceCounter - Frame sequence counter * @param [in] seq_counter - Frame sequence counter
* \param [out] decBuffer - Decrypted buffer * @param [out] dec_buffer - Decrypted buffer
* *
* \return 0 if successful, or a cipher specific error code * @return 0 if successful, or a cipher specific error code
*/ */
int LoRaMacPayloadDecrypt( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t address, uint8_t dir, uint32_t sequenceCounter, uint8_t *decBuffer ); int decrypt_payload(const uint8_t *buffer, uint16_t size, const uint8_t *key,
uint32_t address, uint8_t dir, uint32_t seq_counter,
uint8_t *dec_buffer);
/** /**
* Computes the LoRaMAC Join Request frame MIC field * Computes the LoRaMAC Join Request frame MIC field
* *
* \param [in] buffer - Data buffer * @param [in] buffer - Data buffer
* \param [in] size - Data buffer size * @param [in] size - Data buffer size
* \param [in] key - AES key to be used * @param [in] key - AES key to be used
* \param [out] mic - Computed MIC field * @param [out] mic - Computed MIC field
* *
* \return 0 if successful, or a cipher specific error code * @return 0 if successful, or a cipher specific error code
* *
*/ */
int LoRaMacJoinComputeMic( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t *mic ); int compute_join_frame_mic(const uint8_t *buffer, uint16_t size,
const uint8_t *key, uint32_t *mic);
/** /**
* Computes the LoRaMAC join frame decryption * Computes the LoRaMAC join frame decryption
* *
* \param [in] buffer - Data buffer * @param [in] buffer - Data buffer
* \param [in] size - Data buffer size * @param [in] size - Data buffer size
* \param [in] key - AES key to be used * @param [in] key - AES key to be used
* \param [out] decBuffer - Decrypted buffer * @param [out] dec_buffer - Decrypted buffer
* *
* \return 0 if successful, or a cipher specific error code * @return 0 if successful, or a cipher specific error code
*/ */
int LoRaMacJoinDecrypt( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint8_t *decBuffer ); int decrypt_join_frame(const uint8_t *buffer, uint16_t size,
const uint8_t *key, uint8_t *dec_buffer);
/** /**
* Computes the LoRaMAC join frame decryption * Computes the LoRaMAC join frame decryption
* *
* \param [in] key - AES key to be used * @param [in] key - AES key to be used
* \param [in] appNonce - Application nonce * @param [in] app_nonce - Application nonce
* \param [in] devNonce - Device nonce * @param [in] dev_nonce - Device nonce
* \param [out] nwkSKey - Network session key * @param [out] nwk_skey - Network session key
* \param [out] appSKey - Application session key * @param [out] app_skey - Application session key
* *
* \return 0 if successful, or a cipher specific error code * @return 0 if successful, or a cipher specific error code
*/ */
int LoRaMacJoinComputeSKeys( const uint8_t *key, const uint8_t *appNonce, uint16_t devNonce, uint8_t *nwkSKey, uint8_t *appSKey ); int compute_skeys_for_join_frame(const uint8_t *key, const uint8_t *app_nonce,
uint16_t dev_nonce, uint8_t *nwk_skey,
uint8_t *app_skey );
#endif // MBED_LORAWAN_MAC_LORAMAC_CRYPTO_H__ #endif // MBED_LORAWAN_MAC_LORAMAC_CRYPTO_H__

View File

@ -0,0 +1,146 @@
/**
/ _____) _ | |
( (____ _____ ____ _| |_ _____ ____| |__
\____ \| ___ | (_ _) ___ |/ ___) _ \
_____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
(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;
}

View File

@ -0,0 +1,113 @@
/**
/ _____) _ | |
( (____ _____ ____ _| |_ _____ ____| |__
\____ \| ___ | (_ _) ___ |/ ___) _ \
_____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
(C)2013 Semtech
___ _____ _ ___ _ _____ ___ ___ ___ ___
/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
embedded.connectivity.solutions===============
Description: LoRaWAN stack layer that controls both MAC and PHY underneath
License: Revised BSD License, see LICENSE.TXT file include in the project
Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )
Copyright (c) 2017, Arm Limited and affiliates.
SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef MBED_OS_LORAWAN_MAC_MCPS_H_
#define MBED_OS_LORAWAN_MAC_MCPS_H_
#include "lorawan/system/lorawan_data_structures.h"
#include "lorastack/phy/LoRaPHY.h"
// forward declaration
class LoRaMac;
class LoRaMacMcps {
public:
/** Constructor
*
* Sets local handles to NULL. These handles will be set when the subsystem
* is activated by the MAC layer.
*/
LoRaMacMcps();
/** Destructor
*
* Does nothing
*/
~LoRaMacMcps();
/** Activating MCPS subsystem
*
* Stores pointers to MAC and PHY layer handles
*
* @param mac pointer to MAC layer
* @param phy pointer to PHY layer
*/
void activate_mcps_subsystem(LoRaMac *mac, LoRaPHY *phy);
/** Sets up an MCPS Request
*
* Sets up an MCPS request and sends it through to the central MAC control.
* It also modifies or uses protocol information provided in the MAC
* protocol data structure.
*
* @param mcpsRequest pointer to MCPS request structure
* @param params pointer to MAC protocol parameters
*
* @return LORAWAN_STATUS_OK if everything goes well otherwise
* a negative error code is returned.
*/
lorawan_status_t set_request(loramac_mcps_req_t *mcpsRequest, loramac_protocol_params *params);
/** Grants access to MCPS confirmation data
*
* @return a reference to MCPS confirm data structure
*/
inline loramac_mcps_confirm_t& get_confirmation()
{
return confirmation;
}
/** Grants access to MCPS indication data
*
* @return a reference to MCPS indication data structure
*/
inline loramac_mcps_indication_t& get_indication()
{
return indication;
}
private:
/**
* Pointers to MAC and PHY handles
*/
LoRaMac *_lora_mac;
LoRaPHY *_lora_phy;
/**
* Structure to hold MCPS indication data.
*/
loramac_mcps_indication_t indication;
/**
* Structure to hold MCPS confirm data.
*/
loramac_mcps_confirm_t confirmation;
};
#endif /* MBED_OS_LORAWAN_MAC_MCPS_H_ */

View File

@ -0,0 +1,462 @@
/**
/ _____) _ | |
( (____ _____ ____ _| |_ _____ ____| |__
\____ \| ___ | (_ _) ___ |/ ___) _ \
_____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
(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/LoRaMac.h"
#include "lorastack/mac/LoRaMacMib.h"
LoRaMacMib::LoRaMacMib()
: _lora_mac(NULL), _lora_phy(NULL)
{
}
LoRaMacMib::~LoRaMacMib()
{
}
void LoRaMacMib::activate_mib_subsystem(LoRaMac *mac, LoRaPHY *phy)
{
_lora_mac = mac;
_lora_phy = phy;
}
lorawan_status_t LoRaMacMib::set_request(loramac_mib_req_confirm_t *mibSet,
loramac_protocol_params *params)
{
if (mibSet == NULL || _lora_phy == NULL || _lora_mac == NULL) {
return LORAWAN_STATUS_PARAMETER_INVALID;
}
lorawan_status_t status = LORAWAN_STATUS_OK;
verification_params_t verify;
switch (mibSet->type) {
case MIB_DEVICE_CLASS: {
params->dev_class = mibSet->param.dev_class;
switch (params->dev_class) {
case CLASS_A: {
// Set the radio into sleep to setup a defined state
_lora_phy->put_radio_to_sleep();
break;
}
case CLASS_B: {
break;
}
case CLASS_C: {
// Set the is_node_ack_requested indicator to default
params->is_node_ack_requested = false;
// Set the radio into sleep mode in case we are still in RX mode
_lora_phy->put_radio_to_sleep();
// Compute Rx2 windows parameters in case the RX2 datarate has changed
_lora_phy->compute_rx_win_params(
params->sys_params.rx2_channel.datarate,
params->sys_params.min_rx_symb,
params->sys_params.max_sys_rx_error,
&params->rx_window2_config);
_lora_mac->open_continuous_rx2_window();
break;
}
}
break;
}
case MIB_NETWORK_JOINED: {
params->is_nwk_joined = mibSet->param.is_nwk_joined;
break;
}
case MIB_ADR: {
params->sys_params.adr_on = mibSet->param.is_adr_enable;
break;
}
case MIB_NET_ID: {
params->net_id = mibSet->param.net_id;
break;
}
case MIB_DEV_ADDR: {
params->dev_addr = mibSet->param.dev_addr;
break;
}
case MIB_NWK_SKEY: {
if (mibSet->param.nwk_skey != NULL) {
memcpy(params->keys.nwk_skey, mibSet->param.nwk_skey,
sizeof(params->keys.nwk_skey));
} else {
status = LORAWAN_STATUS_PARAMETER_INVALID;
}
break;
}
case MIB_APP_SKEY: {
if (mibSet->param.app_skey != NULL) {
memcpy(params->keys.app_skey, mibSet->param.app_skey,
sizeof(params->keys.app_skey));
} else {
status = LORAWAN_STATUS_PARAMETER_INVALID;
}
break;
}
case MIB_PUBLIC_NETWORK: {
params->is_nwk_public = mibSet->param.enable_public_nwk;
_lora_phy->setup_public_network_mode(params->is_nwk_public);
break;
}
case MIB_REPEATER_SUPPORT: {
params->is_repeater_supported = mibSet->param.enable_repeater_support;
break;
}
case MIB_RX2_CHANNEL: {
verify.datarate = mibSet->param.rx2_channel.datarate;
if (_lora_phy->verify(&verify, PHY_RX_DR) == true) {
params->sys_params.rx2_channel = mibSet->param.rx2_channel;
if ((params->dev_class == CLASS_C)
&& (params->is_nwk_joined == true)) {
// We can only compute the RX window parameters directly, if we are already
// in class c mode and joined. We cannot setup an RX window in case of any other
// class type.
// Set the radio into sleep mode in case we are still in RX mode
_lora_phy->put_radio_to_sleep();
// Compute Rx2 windows parameters
_lora_phy->compute_rx_win_params(
params->sys_params.rx2_channel.datarate,
params->sys_params.min_rx_symb,
params->sys_params.max_sys_rx_error,
&params->rx_window2_config);
_lora_mac->open_continuous_rx2_window();
}
} else {
status = LORAWAN_STATUS_PARAMETER_INVALID;
}
break;
}
case MIB_RX2_DEFAULT_CHANNEL: {
verify.datarate = mibSet->param.rx2_channel.datarate;
if (_lora_phy->verify(&verify, PHY_RX_DR) == true) {
params->sys_params.rx2_channel = mibSet->param.default_rx2_channel;
} else {
status = LORAWAN_STATUS_PARAMETER_INVALID;
}
break;
}
case MIB_CHANNELS_DEFAULT_MASK:
case MIB_CHANNELS_MASK: {
// channel masks must not be tempered with.
// They should be manipulated only on request with certain
// APIs like add_channel() and remove_channel()
// You should be able to get these MIB parameters, not set
status = LORAWAN_STATUS_SERVICE_UNKNOWN;
break;
}
case MIB_CHANNELS_NB_REP: {
if ((mibSet->param.channel_nb_rep >= 1)
&& (mibSet->param.channel_nb_rep <= 15)) {
params->sys_params.retry_num = mibSet->param.channel_nb_rep;
} else {
status = LORAWAN_STATUS_PARAMETER_INVALID;
}
break;
}
case MIB_MAX_RX_WINDOW_DURATION: {
params->sys_params.max_rx_win_time = mibSet->param.max_rx_window;
break;
}
case MIB_RECEIVE_DELAY_1: {
params->sys_params.recv_delay1 = mibSet->param.recv_delay1;
break;
}
case MIB_RECEIVE_DELAY_2: {
params->sys_params.recv_delay2 = mibSet->param.recv_delay2;
break;
}
case MIB_JOIN_ACCEPT_DELAY_1: {
params->sys_params.join_accept_delay1 = mibSet->param.join_accept_delay1;
break;
}
case MIB_JOIN_ACCEPT_DELAY_2: {
params->sys_params.join_accept_delay2 = mibSet->param.join_accept_delay2;
break;
}
case MIB_CHANNELS_DEFAULT_DATARATE: {
verify.datarate = mibSet->param.default_channel_data_rate;
if (_lora_phy->verify(&verify, PHY_DEF_TX_DR) == true) {
params->sys_params.channel_data_rate = verify.datarate;
} else {
status = LORAWAN_STATUS_PARAMETER_INVALID;
}
break;
}
case MIB_CHANNELS_DATARATE: {
verify.datarate = mibSet->param.channel_data_rate;
if (_lora_phy->verify(&verify, PHY_TX_DR) == true) {
params->sys_params.channel_data_rate = verify.datarate;
} else {
status = LORAWAN_STATUS_PARAMETER_INVALID;
}
break;
}
case MIB_CHANNELS_DEFAULT_TX_POWER: {
verify.tx_power = mibSet->param.default_channel_tx_pwr;
if (_lora_phy->verify(&verify, PHY_DEF_TX_POWER) == true) {
params->sys_params.channel_tx_power = verify.tx_power;
} else {
status = LORAWAN_STATUS_PARAMETER_INVALID;
}
break;
}
case MIB_CHANNELS_TX_POWER: {
verify.tx_power = mibSet->param.channel_tx_pwr;
if (_lora_phy->verify(&verify, PHY_TX_POWER) == true) {
params->sys_params.channel_tx_power = verify.tx_power;
} else {
status = LORAWAN_STATUS_PARAMETER_INVALID;
}
break;
}
case MIB_UPLINK_COUNTER: {
params->ul_frame_counter = mibSet->param.ul_frame_counter;
break;
}
case MIB_DOWNLINK_COUNTER: {
params->dl_frame_counter = mibSet->param.dl_frame_counter;
break;
}
case MIB_SYSTEM_MAX_RX_ERROR: {
params->sys_params.max_sys_rx_error = mibSet->param.max_rx_sys_error;
break;
}
case MIB_MIN_RX_SYMBOLS: {
params->sys_params.min_rx_symb = mibSet->param.min_rx_symb;
break;
}
case MIB_ANTENNA_GAIN: {
params->sys_params.antenna_gain = mibSet->param.antenna_gain;
break;
}
default:
status = LORAWAN_STATUS_SERVICE_UNKNOWN;
break;
}
return status;
}
lorawan_status_t LoRaMacMib::get_request(loramac_mib_req_confirm_t *mibGet,
loramac_protocol_params *params)
{
lorawan_status_t status = LORAWAN_STATUS_OK;
get_phy_params_t get_phy;
phy_param_t phy_param;
rx2_channel_params rx2_channel;
if( mibGet == NULL )
{
return LORAWAN_STATUS_PARAMETER_INVALID;
}
switch( mibGet->type )
{
case MIB_DEVICE_CLASS:
{
mibGet->param.dev_class = params->dev_class;
break;
}
case MIB_NETWORK_JOINED:
{
mibGet->param.is_nwk_joined = params->is_nwk_joined;
break;
}
case MIB_ADR:
{
mibGet->param.is_adr_enable = params->sys_params.adr_on;
break;
}
case MIB_NET_ID:
{
mibGet->param.net_id = params->net_id;
break;
}
case MIB_DEV_ADDR:
{
mibGet->param.dev_addr = params->dev_addr;
break;
}
case MIB_NWK_SKEY:
{
mibGet->param.nwk_skey =params->keys.nwk_skey;
break;
}
case MIB_APP_SKEY:
{
mibGet->param.app_skey = params->keys.app_skey;
break;
}
case MIB_PUBLIC_NETWORK:
{
mibGet->param.enable_public_nwk = params->is_nwk_public;
break;
}
case MIB_REPEATER_SUPPORT:
{
mibGet->param.enable_repeater_support = params->is_repeater_supported;
break;
}
case MIB_CHANNELS:
{
get_phy.attribute = PHY_CHANNELS;
phy_param = _lora_phy->get_phy_params( &get_phy );
mibGet->param.channel_list = phy_param.channel_params;
break;
}
case MIB_RX2_CHANNEL:
{
mibGet->param.rx2_channel = params->sys_params.rx2_channel;
break;
}
case MIB_RX2_DEFAULT_CHANNEL:
{
get_phy.attribute = PHY_DEF_RX2_DR;
phy_param = _lora_phy->get_phy_params( &get_phy );
rx2_channel.datarate = phy_param.value;
get_phy.attribute = PHY_DEF_RX2_FREQUENCY;
phy_param = _lora_phy->get_phy_params( &get_phy );
rx2_channel.frequency = phy_param.value;
mibGet->param.rx2_channel = rx2_channel;
break;
}
case MIB_CHANNELS_DEFAULT_MASK:
{
get_phy.attribute = PHY_DEFAULT_CHANNEL_MASK;
phy_param = _lora_phy->get_phy_params( &get_phy );
mibGet->param.default_channel_mask = phy_param.channel_mask;
break;
}
case MIB_CHANNELS_MASK:
{
get_phy.attribute = PHY_CHANNEL_MASK;
phy_param = _lora_phy->get_phy_params( &get_phy );
mibGet->param.channel_mask = phy_param.channel_mask;
break;
}
case MIB_CHANNELS_NB_REP:
{
mibGet->param.channel_nb_rep = params->sys_params.retry_num;
break;
}
case MIB_MAX_RX_WINDOW_DURATION:
{
mibGet->param.max_rx_window = params->sys_params.max_rx_win_time;
break;
}
case MIB_RECEIVE_DELAY_1:
{
mibGet->param.recv_delay1 = params->sys_params.recv_delay1;
break;
}
case MIB_RECEIVE_DELAY_2:
{
mibGet->param.recv_delay2 = params->sys_params.recv_delay2;
break;
}
case MIB_JOIN_ACCEPT_DELAY_1:
{
mibGet->param.join_accept_delay1 = params->sys_params.join_accept_delay1;
break;
}
case MIB_JOIN_ACCEPT_DELAY_2:
{
mibGet->param.join_accept_delay2 = params->sys_params.join_accept_delay2;
break;
}
case MIB_CHANNELS_DEFAULT_DATARATE:
{
get_phy.attribute = PHY_DEF_TX_DR;
phy_param = _lora_phy->get_phy_params( &get_phy );
mibGet->param.default_channel_data_rate = phy_param.value;
break;
}
case MIB_CHANNELS_DATARATE:
{
mibGet->param.channel_data_rate = params->sys_params.channel_data_rate;
break;
}
case MIB_CHANNELS_DEFAULT_TX_POWER:
{
get_phy.attribute = PHY_DEF_TX_POWER;
phy_param = _lora_phy->get_phy_params( &get_phy );
mibGet->param.default_channel_tx_pwr = phy_param.value;
break;
}
case MIB_CHANNELS_TX_POWER:
{
mibGet->param.channel_tx_pwr = params->sys_params.channel_tx_power;
break;
}
case MIB_UPLINK_COUNTER:
{
mibGet->param.ul_frame_counter = params->ul_frame_counter;
break;
}
case MIB_DOWNLINK_COUNTER:
{
mibGet->param.dl_frame_counter = params->dl_frame_counter;
break;
}
case MIB_MULTICAST_CHANNEL:
{
mibGet->param.multicast_list = params->multicast_channels;
break;
}
case MIB_SYSTEM_MAX_RX_ERROR:
{
mibGet->param.max_rx_sys_error = params->sys_params.max_sys_rx_error;
break;
}
case MIB_MIN_RX_SYMBOLS:
{
mibGet->param.min_rx_symb = params->sys_params.min_rx_symb;
break;
}
case MIB_ANTENNA_GAIN:
{
mibGet->param.antenna_gain = params->sys_params.antenna_gain;
break;
}
default:
status = LORAWAN_STATUS_SERVICE_UNKNOWN;
break;
}
return status;
}

View File

@ -0,0 +1,102 @@
/**
/ _____) _ | |
( (____ _____ ____ _| |_ _____ ____| |__
\____ \| ___ | (_ _) ___ |/ ___) _ \
_____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
(C)2013 Semtech
___ _____ _ ___ _ _____ ___ ___ ___ ___
/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
embedded.connectivity.solutions===============
Description: LoRaWAN stack layer that controls both MAC and PHY underneath
License: Revised BSD License, see LICENSE.TXT file include in the project
Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )
Copyright (c) 2017, Arm Limited and affiliates.
SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef MBED_OS_LORAWAN_MAC_MIB_H_
#define MBED_OS_LORAWAN_MAC_MIB_H_
#include "lorawan/system/lorawan_data_structures.h"
#include "lorastack/phy/LoRaPHY.h"
// forward declaration
class LoRaMac;
class LoRaMacMib {
public:
/** Constructor
*
* Sets local handles to NULL. These handles will be set when the subsystem
* is activated by the MAC layer.
*/
LoRaMacMib();
/** Destructor
*
* Does nothing
*/
~LoRaMacMib();
/** Activating MLME subsystem
*
* Stores pointers to MAC and PHY layer handles
*
* @param mac pointer to MAC layer
* @param phy pointer to PHY layer
*/
void activate_mib_subsystem(LoRaMac *mac, LoRaPHY *phy);
/** Sets up a MIB Request
*
* Used to configure MAC protocol parameters using appropriate
* key/value pair in the MIB request structure. Use this API to set
* any system wide configurable parameter exposed by MIB service.
*
* @param mibSet [in] pointer to MIB request structure
* @param params pointer to MAC protocol parameters which will be modified
*
* @return LORAWAN_STATUS_OK if everything goes well otherwise
* a negative error code is returned.
*/
lorawan_status_t set_request(loramac_mib_req_confirm_t *mibSet,
loramac_protocol_params *params);
/** Provides access to the given MIB parameter
*
* Used to extract information about system wide MAC protocol parameters
* which are exposed by MIB service.
*
* @param mibGet [out] pointer to MIB request structure which will be filled in
* @param params pointer to MAC protocol parameters
*
* @return LORAWAN_STATUS_OK if everything goes well otherwise
* a negative error code is returned.
*/
lorawan_status_t get_request(loramac_mib_req_confirm_t *mibGet,
loramac_protocol_params *params);
private:
/**
* Pointers to MAC and PHY handles
*/
LoRaMac *_lora_mac;
LoRaPHY *_lora_phy;
};
#endif /* MBED_OS_LORAWAN_MAC_MIB_H_ */

View File

@ -0,0 +1,151 @@
/**
/ _____) _ | |
( (____ _____ ____ _| |_ _____ ____| |__
\____ \| ___ | (_ _) ___ |/ ___) _ \
_____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
(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/LoRaMacMlme.h"
LoRaMacMlme::LoRaMacMlme()
: _lora_mac(NULL), _lora_phy(NULL), _mac_cmd(NULL)
{
}
LoRaMacMlme::~LoRaMacMlme()
{
}
void LoRaMacMlme::activate_mlme_subsystem(LoRaMac *mac, LoRaPHY *phy,
LoRaMacCommand *cmd)
{
_lora_mac = mac;
_lora_phy = phy;
_mac_cmd = cmd;
}
lorawan_status_t LoRaMacMlme::set_request(loramac_mlme_req_t *request,
loramac_protocol_params *params)
{
if (request && params && _lora_mac && _lora_phy && _mac_cmd) {
lorawan_status_t status = LORAWAN_STATUS_SERVICE_UNKNOWN;
loramac_mhdr_t machdr;
verification_params_t verify;
get_phy_params_t get_phy;
phy_param_t phy_param;
if (params->mac_state != LORAMAC_IDLE) {
return LORAWAN_STATUS_BUSY;
}
// Before setting a new MLME request, clear the MLME confirmation
// structure
memset((uint8_t*) &confirmation, 0, sizeof(confirmation));
confirmation.status = LORAMAC_EVENT_INFO_STATUS_ERROR;
switch (request->type) {
case MLME_JOIN: {
if ((params->mac_state & LORAMAC_TX_DELAYED)
== LORAMAC_TX_DELAYED) {
return LORAWAN_STATUS_BUSY;
}
if ((request->req.join.dev_eui == NULL)
|| (request->req.join.app_eui == NULL)
|| (request->req.join.app_key == NULL)
|| (request->req.join.nb_trials == 0)) {
return LORAWAN_STATUS_PARAMETER_INVALID;
}
// Verify the parameter NbTrials for the join procedure
verify.nb_join_trials = request->req.join.nb_trials;
if (_lora_phy->verify(&verify, PHY_NB_JOIN_TRIALS) == false) {
// Value not supported, get default
get_phy.attribute = PHY_DEF_NB_JOIN_TRIALS;
phy_param = _lora_phy->get_phy_params(&get_phy);
request->req.join.nb_trials = (uint8_t) phy_param.value;
}
params->flags.bits.mlme_req = 1;
confirmation.req_type = request->type;
params->keys.dev_eui = request->req.join.dev_eui;
params->keys.app_eui = request->req.join.app_eui;
params->keys.app_key = request->req.join.app_key;
params->max_join_request_trials = request->req.join.nb_trials;
// Reset variable JoinRequestTrials
params->join_request_trial_counter = 0;
// Setup header information
machdr.value = 0;
machdr.bits.mtype = FRAME_TYPE_JOIN_REQ;
_lora_mac->reset_mac_parameters();
params->sys_params.channel_data_rate =
_lora_phy->get_alternate_DR(params->join_request_trial_counter + 1);
status = _lora_mac->send(&machdr, 0, NULL, 0);
break;
}
case MLME_LINK_CHECK: {
params->flags.bits.mlme_req = 1;
// LoRaMac will send this command piggy-backed
confirmation.req_type = request->type;
status = _mac_cmd->add_mac_command(MOTE_MAC_LINK_CHECK_REQ, 0, 0);
break;
}
case MLME_TXCW: {
confirmation.req_type = request->type;
params->flags.bits.mlme_req = 1;
status = _lora_mac->set_tx_continuous_wave(request->req.cw_tx_mode.timeout);
break;
}
case MLME_TXCW_1: {
confirmation.req_type = request->type;
params->flags.bits.mlme_req = 1;
status = _lora_mac->set_tx_continuous_wave1(request->req.cw_tx_mode.timeout,
request->req.cw_tx_mode.frequency,
request->req.cw_tx_mode.power);
break;
}
default:
break;
}
if (status != LORAWAN_STATUS_OK) {
params->is_node_ack_requested = false;
params->flags.bits.mlme_req = 0;
}
return status;
}
return LORAWAN_STATUS_PARAMETER_INVALID;
}

View File

@ -0,0 +1,115 @@
/**
/ _____) _ | |
( (____ _____ ____ _| |_ _____ ____| |__
\____ \| ___ | (_ _) ___ |/ ___) _ \
_____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
(C)2013 Semtech
___ _____ _ ___ _ _____ ___ ___ ___ ___
/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
embedded.connectivity.solutions===============
Description: LoRaWAN stack layer that controls both MAC and PHY underneath
License: Revised BSD License, see LICENSE.TXT file include in the project
Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )
Copyright (c) 2017, Arm Limited and affiliates.
SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef MBED_OS_LORAWAN_MAC_MLME_H_
#define MBED_OS_LORAWAN_MAC_MLME_H_
#include "lorawan/system/lorawan_data_structures.h"
#include "lorastack/phy/LoRaPHY.h"
#include "lorastack/mac/LoRaMacCommand.h"
// forward declaration
class LoRaMac;
class LoRaMacMlme {
public:
/** Constructor
*
* Sets local handles to NULL. These handles will be set when the subsystem
* is activated by the MAC layer.
*/
LoRaMacMlme();
/** Destructor
*
* Does nothing
*/
~LoRaMacMlme();
/** Activating MLME subsystem
*
* Stores pointers to MAC and PHY layer handles
*
* @param mac pointer to MAC layer
* @param phy pointer to PHY layer
* @param cmd pointer to MAC commands
*/
void activate_mlme_subsystem(LoRaMac *mac, LoRaPHY *phy, LoRaMacCommand *cmd);
/** Sets up an MLME Request
*
* Sets up an MLME request, e.g., a Join Request and sends it through
* to the central MAC control. It also modifies or uses protocol information
* provided in the MAC protocol data structure.
*
* @param request pointer to MLME request structure
* @param params pointer to MAC protocol parameters
*
* @return LORAWAN_STATUS_OK if everything goes well otherwise
* a negative error code is returned.
*/
lorawan_status_t set_request(loramac_mlme_req_t *request, loramac_protocol_params *params);
/** Grants access to MLME confirmation data
*
* @return a reference to MLME confirm data structure
*/
inline loramac_mlme_confirm_t& get_confirmation()
{
return confirmation;
}
/** Grants access to MLME indication data
*
* @return a reference to MLME indication data structure
*/
inline loramac_mlme_indication_t& get_indication()
{
return indication;
}
private:
/**
* Pointers to MAC and PHY handles
*/
LoRaMac *_lora_mac;
LoRaPHY *_lora_phy;
LoRaMacCommand *_mac_cmd;
/**
* Structure to hold MLME indication data.
*/
loramac_mlme_indication_t indication;
/**
* Structure to hold MLME confirm data.
*/
loramac_mlme_confirm_t confirmation;
};
#endif /* MBED_OS_LORAWAN_MAC_MLME_H_ */

View File

@ -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__

File diff suppressed because it is too large Load Diff

View File

@ -34,112 +34,192 @@
#ifndef MBED_OS_LORAPHY_BASE_ #ifndef MBED_OS_LORAPHY_BASE_
#define MBED_OS_LORAPHY_BASE_ #define MBED_OS_LORAPHY_BASE_
#include "lorawan/LoRaRadio.h"
#include "lorawan/system/LoRaWANTimer.h" #include "lorawan/system/LoRaWANTimer.h"
#include "lorawan/lorastack/phy/lora_phy_ds.h" #include "lorawan/lorastack/phy/lora_phy_ds.h"
#include "netsocket/LoRaRadio.h" #include "platform/NonCopyable.h"
class LoRaPHY { class LoRaPHY : private mbed::NonCopyable<LoRaPHY> {
public: public:
LoRaPHY();
virtual ~LoRaPHY(); virtual ~LoRaPHY();
/** Stores a reference to Radio object.
*
* Application is responsible for constructing a 'LoRaRadio' object
* which is passed down to the PHY layer.
*
* @param radio a reference to radio driver object
*/
void set_radio_instance(LoRaRadio& radio); void set_radio_instance(LoRaRadio& radio);
/** Puts radio in sleep mode.
*
* Requests the radio driver to enter sleep mode.
*/
void put_radio_to_sleep(void); void put_radio_to_sleep(void);
/** Puts radio in standby mode.
*
* Requests the radio driver to enter standby mode.
*/
void put_radio_to_standby(void); void put_radio_to_standby(void);
/** Puts radio in receive mode.
*
* Requests the radio driver to enter receive mode for a given time or to
* enter continuous reception mode.
*
* @param is_rx_continuous if true, sets the radio to enter continuous
* reception mode.
*
* @param max_rx_window duration of receive window
*/
void setup_rx_window(bool is_rx_continuous, uint32_t max_rx_window); void setup_rx_window(bool is_rx_continuous, uint32_t max_rx_window);
void setup_tx_cont_wave_mode(uint16_t timeout, uint32_t frequency, /** Delegates MAC layer request to transmit packet.
uint8_t power); *
* @param buf a pointer to the data which needs to be transmitted
*
* @param size size of the data in bytes
*/
void handle_send(uint8_t *buf, uint8_t size); void handle_send(uint8_t *buf, uint8_t size);
/** Enables/Disables public network mode.
*
* Public and private LoRaWAN network constitute different preambles and
* Net IDs. This API isused to tell the radio which network mode is in use.
*
* @param set true or false
*/
void setup_public_network_mode(bool set); void setup_public_network_mode(bool set);
/** Provides a random number from radio.
*
* Returns a 32-bit random unsigned integer value based upon RSSI
* measurements.
*
* @return a 32-bit long random number
*
*/
uint32_t get_radio_rng(); uint32_t get_radio_rng();
/*! /** Calculates and applies duty cycle back-off time.
* \brief The function gets a value of a specific PHY attribute.
* *
* \param [in] getPhy A pointer to the function parameters. * Explicitly updates the band time-off.
* *
* \retval A structure containing the PHY parameter. * @param [in] backoff_params A pointer to backoff parameters.
*/ */
virtual PhyParam_t get_phy_params(GetPhyParams_t* getPhy ) = 0; void calculate_backoff(backoff_params_t* backoff_params);
/*! /**
* \brief Updates the last TX done parameters of the current channel. * Tests if a channel is on or off in the channel mask
*/
inline bool mask_bit_test(const uint16_t *mask, unsigned bit) {
return mask[bit/16] & (1U << (bit % 16));
}
/**
* Tests if a channel is on or off in the channel mask
*/
inline void mask_bit_set(uint16_t *mask, unsigned bit) {
mask[bit/16] |= (1U << (bit % 16));
}
/**
* Tests if a channel is on or off in the channel mask
*/
inline void mask_bit_clear(uint16_t *mask, unsigned bit) {
mask[bit/16] &= ~(1U << (bit % 16));
}
/** Entertain a new channel request MAC command.
* *
* \param [in] txDone A pointer to the function parameters. * MAC command subsystem processes the new channel request coming form
* the network server and then MAC layer asks the PHY layer to entertain
* the request.
*
* @param [in] new_channel_req A pointer to the new_channel_req_params_t.
*
* @return bit mask, according to the LoRaWAN spec 1.0.2.
*/ */
virtual void set_band_tx_done(SetBandTxDoneParams_t* txDone ) = 0; virtual uint8_t request_new_channel(new_channel_req_params_t* new_channel_req);
/*! /** Grants access to PHY layer parameters.
* \brief Initializes the channels masks and the channels.
* *
* \param [in] type Sets the initialization type. * This is essentially a PHY layer parameter retrieval system.
* A request is made for a certain parameter by setting an appropriate
* attribute.
*
* @param [in] get_phy A pointer to get_phy_params_t
*
* @return A structure containing the requested PHY parameter value.
*/ */
virtual void load_defaults(InitType_t type ) = 0; virtual phy_param_t get_phy_params(get_phy_params_t* get_phy);
/*! /** Process PHY layer state after a successful transmission.
* \brief Verifies a parameter.
* *
* \param [in] verify A pointer to the function parameters. * Updates times of the last transmission for the particular channel and
* band upon which last transmission took place.
* *
* \param [in] phyAttribute The attribute for which the verification is needed. * @param [in] tx_done A pointer to set_band_txdone_params_t
*
* \retval True, if the parameter is valid.
*/ */
virtual bool verify(VerifyParams_t* verify, PhyAttribute_t phyAttribute ) = 0; virtual void set_last_tx_done(set_band_txdone_params_t* tx_done);
/*! /** Enables default channels only.
* \brief The function parses the input buffer and sets up the channels of the CF list.
* *
* \param [in] applyCFList A pointer to the function parameters. * Falls back to a channel mask where only default channels are enabled, all
* other channels are disabled.
*/ */
virtual void apply_cf_list(ApplyCFListParams_t* applyCFList ) = 0; virtual void restore_default_channels();
/*! /** Verify if a parameter is eligible.
* \brief Sets a channels mask.
* *
* \param [in] chanMaskSet A pointer to the function parameters. * @param verify A pointer to the verification_params_t that contains
* parameters which we need to check for validity.
* *
* \retval True, if the channels mask could be set. * @param phy_attr The attribute for which the verification is needed.
*
* @return True, if the parameter is valid.
*/ */
virtual bool set_channel_mask(ChanMaskSetParams_t* chanMaskSet ) = 0; virtual bool verify(verification_params_t* verify, phy_attributes_t phy_attr);
/*! /** Processes the incoming CF-list.
* \brief Calculates the next datarate to set, when ADR is on or off.
* *
* \param [in] adrNext A pointer to the function parameters. * Handles the payload containing CF-list and enables channels defined
* therein.
* *
* \param [out] drOut The calculated datarate for the next TX. * @param cflist_params A pointer to cflist_params_t.
*
* \param [out] txPowOut The TX power for the next TX.
*
* \param [out] adrAckCounter The calculated ADR acknowledgement counter.
*
* \retval True, if an ADR request should be performed.
*/ */
virtual bool get_next_ADR(AdrNextParams_t* adrNext, int8_t* drOut, virtual void apply_cf_list(cflist_params_t* cflist_params);
int8_t* txPowOut, uint32_t* adrAckCounter ) = 0;
/*! /** Calculates the next datarate to set, when ADR is on or off.
* \brief Configuration of the RX windows.
* *
* \param [in] rxConfig A pointer to the function parameters. * @param restore_channel_mask A boolean set restore channel mask in case
* of failure.
* *
* \param [out] datarate The datarate index set. * @param dr_out The calculated datarate for the next TX.
* *
* \retval True, if the configuration was applied successfully. * @param tx_power_out The TX power for the next TX.
*
* @param adr_ack_counter The calculated ADR acknowledgement counter.
*
* @return True, if an ADR request should be performed.
*/ */
virtual bool rx_config(RxConfigParams_t* rxConfig, int8_t* datarate ) = 0; bool get_next_ADR(bool restore_channel_mask, int8_t& dr_out,
int8_t& tx_power_out, uint32_t& adr_ack_counter);
/* /** Configure radio reception.
* RX window precise timing *
* @param [in] config A pointer to the RX configuration.
*
* @param [out] datarate The datarate index set.
*
* @return True, if the configuration was applied successfully.
*/
virtual bool rx_config(rx_config_params_t* config, int8_t* datarate);
/** Computing Receive Windows
* *
* For more details please consult the following document, chapter 3.1.2. * For more details please consult the following document, chapter 3.1.2.
* http://www.semtech.com/images/datasheet/SX1272_settings_for_LoRaWAN_v2.0.pdf * http://www.semtech.com/images/datasheet/SX1272_settings_for_LoRaWAN_v2.0.pdf
@ -179,499 +259,258 @@ public:
/*! /*!
* Computes the RX window timeout and offset. * Computes the RX window timeout and offset.
* *
* \param [in] datarate The RX window datarate index to be used. * @param [in] datarate The RX window datarate index to be used.
* *
* \param [in] minRxSymbols The minimum number of symbols required to detect an RX frame. * @param [in] min_rx_symbols The minimum number of symbols required to
* detect an RX frame.
* *
* \param [in] rxError The maximum timing error of the receiver in milliseconds. * @param [in] rx_error The maximum timing error of the receiver
* The receiver will turn on in a [-rxError : +rxError] ms * in milliseconds. The receiver will turn on
* interval around RxOffset. * in a [-rxError : +rxError] ms interval around
* RxOffset.
* *
* \param [out] rxConfigParams Returns the updated WindowTimeout and WindowOffset fields. * @param [out] rx_conf_params Pointer to the structure that needs to be
* filled with receive window parameters.
* *
*/ */
virtual void compute_rx_win_params(int8_t datarate, virtual void compute_rx_win_params(int8_t datarate, uint8_t min_rx_symbols,
uint8_t minRxSymbols, uint32_t rx_error,
uint32_t rxError, rx_config_params_t *rx_conf_params);
RxConfigParams_t *rxConfigParams) = 0;
/*!
* \brief TX configuration.
*
* \param [in] txConfig A pointer to the function parameters.
*
* \param [out] txPower The TX power index set.
*
* \param [out] txTimeOnAir The time-on-air of the frame.
*
* \retval True, if the configuration was applied successfully.
*/
virtual bool tx_config(TxConfigParams_t* txConfig, int8_t* txPower,
TimerTime_t* txTimeOnAir ) = 0;
/*! /** Configure radio transmission.
* \brief The function processes a Link ADR Request.
* *
* \param [in] linkAdrReq A pointer to the function parameters. * @param [in] tx_config Structure containing tx parameters.
* *
* \param [out] drOut The datarate applied. * @param [out] tx_power The TX power which will be set.
* *
* \param [out] txPowOut The TX power applied. * @param [out] tx_toa The time-on-air of the frame.
* *
* \param [out] nbRepOut The number of repetitions to apply. * @return True, if the configuration was applied successfully.
*
* \param [out] nbBytesParsed The number of bytes parsed.
*
* \retval The status of the operation, according to the LoRaMAC specification.
*/ */
virtual uint8_t link_ADR_request(LinkAdrReqParams_t* linkAdrReq, virtual bool tx_config(tx_config_params_t* tx_config, int8_t* tx_power,
int8_t* drOut, int8_t* txPowOut, lorawan_time_t* tx_toa);
uint8_t* nbRepOut,
uint8_t* nbBytesParsed ) = 0;
/*! /** Processes a Link ADR Request.
* \brief The function processes a RX Parameter Setup Request.
* *
* \param [in] rxParamSetupReq A pointer to the function parameters. * @param [in] params A pointer ADR request parameters.
* *
* \retval The status of the operation, according to the LoRaMAC specification. * @param [out] dr_out The datarate applied.
*
* @param [out] tx_power_out The TX power applied.
*
* @param [out] nb_rep_out The number of repetitions to apply.
*
* @param [out] nb_bytes_parsed The number of bytes parsed.
*
* @return The status of the operation, according to the LoRaMAC specification.
*/ */
virtual uint8_t setup_rx_params(RxParamSetupReqParams_t* rxParamSetupReq ) = 0; virtual uint8_t link_ADR_request(adr_req_params_t* params,
int8_t* dr_out, int8_t* tx_power_out,
uint8_t* nb_rep_out,
uint8_t* nb_bytes_parsed);
/*! /** Accept or rejects RxParamSetupReq MAC command
* \brief The function processes a New Channel Request.
* *
* \param [in] newChannelReq A pointer to the function parameters. * The function processes a RX parameter setup request in response to
* server MAC command for RX setup.
* *
* \retval The status of the operation, according to the LoRaMAC specification. * @param [in] params A pointer to rx parameter setup request.
*
* @return The status of the operation, according to the LoRaWAN specification.
*/ */
virtual uint8_t request_new_channel(NewChannelReqParams_t* newChannelReq ) = 0; virtual uint8_t accept_rx_param_setup_req(rx_param_setup_req_t* params);
/*! /** Makes decision whether to accept or reject TxParamSetupReq MAC command
* \brief The function processes a TX ParamSetup Request.
* *
* \param [in] txParamSetupReq A pointer to the function parameters. * @param [in] params A pointer to tx parameter setup request.
* *
* \retval The status of the operation, according to the LoRaMAC specification. * @return True to let the MAC know that the request is
* Returns -1, if the functionality is not implemented. In this case, the end node * accepted and MAC can apply TX parameters received
* shall ignore the command. * form Network Server. Otherwise false is returned.
*/ */
virtual int8_t setup_tx_params(TxParamSetupReqParams_t* txParamSetupReq ) = 0; virtual bool accept_tx_param_setup_req(tx_param_setup_req_t* params);
/*! /** Processes a DlChannelReq MAC command.
* \brief The function processes a DlChannel Request.
* *
* \param [in] dlChannelReq A pointer to the function parameters. * @param [in] params A pointer to downlink channel request.
* *
* \retval The status of the operation, according to the LoRaMAC specification. * @return The status of the operation, according to the LoRaWAN specification.
*/ */
virtual uint8_t dl_channel_request(DlChannelReqParams_t* dlChannelReq ) = 0; virtual uint8_t dl_channel_request(dl_channel_req_params_t* params);
/*! /** Alternates the datarate of the channel for the join request.
* \brief Alternates the datarate of the channel for the join request.
* *
* \param [in] alternateDr A pointer to the function parameters. * @param nb_trials Number of trials to be made on one given data rate.
* *
* \retval The datarate to apply. * @return The datarate to apply .
*/ */
virtual int8_t get_alternate_DR(AlternateDrParams_t* alternateDr ) = 0; virtual int8_t get_alternate_DR(uint8_t nb_trials);
/*! /** Searches and sets the next available channel.
* \brief Calculates the back-off time.
* *
* \param [in] calcBackOff A pointer to the function parameters. * If there are multiple channels found available, one of them is selected
* randomly.
*
* @param [in] nextChanParams Parameters for the next channel.
*
* @param [out] channel The next channel to use for TX.
*
* @param [out] time The time to wait for the next transmission according to the duty cycle.
*
* @param [out] aggregatedTimeOff Updates the aggregated time off.
*
* @return Function status [1: OK, 0: Unable to find a channel on the current datarate].
*/ */
virtual void calculate_backoff(CalcBackOffParams_t* calcBackOff ) = 0; virtual bool set_next_channel(channel_selection_params_t* nextChanParams,
uint8_t* channel, lorawan_time_t* time,
lorawan_time_t* aggregatedTimeOff);
/*! /** Adds a channel to the channel list.
* \brief Searches and sets the next random available channel.
* *
* \param [in] nextChanParams Parameters for the next channel. * Verifies the channel parameters and if everything is found legitimate,
* adds that particular channel to the channel list and updates the channel
* mask.
* *
* \param [out] channel The next channel to use for TX. * @param [in] new_channel A pointer to the parameters for the new channel.
* @param [in] id Channel ID
* *
* \param [out] time The time to wait for the next transmission according to the duty cycle. * @return LORAWAN_STATUS_OK if everything goes fine, negative error code
* * otherwise.
* \param [out] aggregatedTimeOff Updates the aggregated time off.
*
* \retval Function status [1: OK, 0: Unable to find a channel on the current datarate].
*/ */
virtual bool set_next_channel(NextChanParams_t* nextChanParams, virtual lorawan_status_t add_channel(channel_params_t* new_channel, uint8_t id);
uint8_t* channel, TimerTime_t* time,
TimerTime_t* aggregatedTimeOff ) = 0;
/*! /** Removes a channel from the channel list.
* \brief Adds a channel.
* *
* \param [in] channelAdd A pointer to the function parameters. * @param [in] channel_id Index of the channel to be removed
* *
* \retval The status of the operation. * @return True, if the channel was removed successfully.
*/ */
virtual LoRaMacStatus_t add_channel(ChannelAddParams_t* channelAdd ) = 0; virtual bool remove_channel(uint8_t channel_id);
/*! /** Puts the radio into continuous wave mode.
* \brief Removes a channel.
* *
* \param [in] channelRemove A pointer to the function parameters. * @param [in] continuous_wave A pointer to the function parameters.
* *
* \retval True, if the channel was removed successfully. * @param [in] frequency Frequency to transmit at
*/ */
virtual bool remove_channel(ChannelRemoveParams_t* channelRemove ) = 0; virtual void set_tx_cont_mode(cw_mode_params_t* continuous_wave,
uint32_t frequency = 0);
/*! /** Computes new data rate according to the given offset
* \brief Sets the radio into continuous wave mode.
* *
* \param [in] continuousWave A pointer to the function parameters. * @param [in] dr The current datarate.
*
* @param [in] dr_offset The offset to be applied.
*
* @return The computed datarate.
*/ */
virtual void set_tx_cont_mode(ContinuousWaveParams_t* continuousWave ) = 0; virtual uint8_t apply_DR_offset(int8_t dr, int8_t dr_offset);
/*!
* \brief Computes new datarate according to the given offset
*
* \param [in] downlinkDwellTime The downlink dwell time configuration. 0: No limit, 1: 400ms
*
* \param [in] dr The current datarate.
*
* \param [in] drOffset The offset to be applied.
*
* \retval newDr The computed datarate.
*/
virtual uint8_t apply_DR_offset(uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset ) = 0;
protected: protected:
LoRaRadio *_radio; LoRaRadio *_radio;
LoRaWANTimeHandler &_lora_time;
loraphy_params_t phy_params;
typedef struct sRegionCommonLinkAdrParams LoRaPHY(LoRaWANTimeHandler &lora_time);
{
/*!
* The number of repetitions.
*/
uint8_t NbRep;
/*!
* Datarate.
*/
int8_t Datarate;
/*!
* TX power.
*/
int8_t TxPower;
/*!
* Channels mask control field.
*/
uint8_t ChMaskCtrl;
/*!
* Channels mask field.
*/
uint16_t ChMask;
}RegionCommonLinkAdrParams_t;
typedef struct sRegionCommonLinkAdrReqVerifyParams /**
{ * Verifies the given frequency.
/*!
* The current status of the AdrLinkRequest.
*/
uint8_t Status;
/*!
* Set to true, if ADR is enabled.
*/
bool AdrEnabled;
/*!
* The datarate the AdrLinkRequest wants to set.
*/
int8_t Datarate;
/*!
* The TX power the AdrLinkRequest wants to set.
*/
int8_t TxPower;
/*!
* The number of repetitions the AdrLinkRequest wants to set.
*/
uint8_t NbRep;
/*!
* The current datarate the node is using.
*/
int8_t CurrentDatarate;
/*!
* The current TX power the node is using.
*/
int8_t CurrentTxPower;
/*!
* The current number of repetitions the node is using.
*/
int8_t CurrentNbRep;
/*!
* The number of channels.
*/
uint8_t NbChannels;
/*!
* A pointer to the first element of the channels mask.
*/
uint16_t* ChannelsMask;
/*!
* The minimum possible datarate.
*/
int8_t MinDatarate;
/*!
* The maximum possible datarate.
*/
int8_t MaxDatarate;
/*!
* A pointer to the channels.
*/
ChannelParams_t* Channels;
/*!
* The minimum possible TX power.
*/
int8_t MinTxPower;
/*!
* The maximum possible TX power.
*/
int8_t MaxTxPower;
}RegionCommonLinkAdrReqVerifyParams_t;
typedef struct sRegionCommonCalcBackOffParams
{
/*!
* A pointer to region specific channels.
*/
ChannelParams_t* Channels;
/*!
* A pointer to region specific bands.
*/
Band_t* Bands;
/*!
* Set to true, if the last uplink was a join request.
*/
bool LastTxIsJoinRequest;
/*!
* Set to true, if the node is joined.
*/
bool Joined;
/*!
* Set to true, if the duty cycle is enabled.
*/
bool DutyCycleEnabled;
/*!
* The current channel.
*/
uint8_t Channel;
/*!
* The elapsed time since initialization.
*/
TimerTime_t ElapsedTime;
/*!
* The time on air of the last TX frame.
*/
TimerTime_t TxTimeOnAir;
}RegionCommonCalcBackOffParams_t;
/*!
* \brief Calculates the join duty cycle.
* This is a generic function and valid for all regions.
*
* \param [in] elapsedTime The time elapsed since starting the device.
*
* \retval Duty cycle restriction.
*/ */
uint16_t get_join_DC( TimerTime_t elapsedTime ); virtual bool verify_frequency(uint32_t freq);
/*!
* \brief Verifies, if a value is in a given range. /**
* This is a generic function and valid for all regions. * Verifies, if a value is in a given range.
*
* \param [in] value The value to verify, if it is in range.
*
* \param [in] min The minimum possible value.
*
* \param [in] max The maximum possible value.
*
* \retval 1 if the value is in range, otherwise 0.
*/ */
uint8_t val_in_range( int8_t value, int8_t min, int8_t max ); uint8_t val_in_range(int8_t value, int8_t min, int8_t max);
/*! /**
* \brief Verifies, if a datarate is available on an active channel. * Verifies, if a datarate is available on an active channel.
* This is a generic function and valid for all regions.
*
* \param [in] nbChannels The number of channels.
*
* \param [in] channelsMask The channels mask of the region.
*
* \param [in] dr The datarate to verify.
*
* \param [in] minDr The minimum datarate.
*
* \param [in] maxDr The maximum datarate.
*
* \param [in] channels The channels of the region.
*
* \retval True if the datarate is supported, false if not.
*/ */
bool verify_channel_DR( uint8_t nbChannels, uint16_t* channelsMask, int8_t dr, bool verify_channel_DR(uint8_t nbChannels, uint16_t* channelsMask, int8_t dr,
int8_t minDr, int8_t maxDr, ChannelParams_t* channels ); int8_t minDr, int8_t maxDr, channel_params_t* channels);
/*! /**
* \brief Disables a channel in a given channels mask. * Disables a channel in a given channels mask.
* This is a generic function and valid for all regions.
*
* \param [in] channelsMask The channels mask of the region.
*
* \param [in] id The ID of the channels mask to disable.
*
* \param [in] maxChannels The maximum number of channels.
*
* \retval True if the channel could be disabled, false if not.
*/ */
bool disable_channel( uint16_t* channelsMask, uint8_t id, uint8_t maxChannels ); bool disable_channel(uint16_t* channel_mask, uint8_t id, uint8_t max_channels);
/*! /**
* \brief Counts the number of active channels in a given channels mask. * Counts number of bits on in a given mask
* This is a generic function and valid for all regions.
*
* \param [in] channelsMask The channels mask of the region.
*
* \param [in] startIdx The start index.
*
* \param [in] stopIdx The stop index (the channels of this index will not be counted).
*
* \retval The number of active channels.
*/ */
uint8_t num_active_channels( uint16_t* channelsMask, uint8_t startIdx, uint8_t stopIdx ); uint8_t count_bits(uint16_t mask, uint8_t nb_bits);
/*! /**
* \brief Copy a channels mask. * Counts the number of active channels in a given channels mask.
* This is a generic function and valid for all regions.
*
* \param [in] channelsMaskDest The destination channels mask.
*
* \param [in] channelsMaskSrc The source channels mask.
*
* \param [in] len The index length to copy.
*/ */
void copy_channel_mask( uint16_t* channelsMaskDest, uint16_t* channelsMaskSrc, uint8_t len ); uint8_t num_active_channels(uint16_t* channel_mask, uint8_t start_idx,
uint8_t stop_idx);
/*! /**
* \brief Sets the last TX done property. * Copy channel masks.
* This is a generic function and valid for all regions.
*
* \param [in] joined Set to true, if the node has joined the network
*
* \param [in] band The band to be updated.
*
* \param [in] lastTxDone The time of the last TX done.
*/ */
void set_last_tx_done( bool joined, Band_t* band, TimerTime_t lastTxDone ); void copy_channel_mask(uint16_t* dest_mask, uint16_t* src_mask, uint8_t len);
/*! /**
* \brief Updates the time-offs of the bands. * Updates the time-offs of the bands.
* This is a generic function and valid for all regions.
*
* \param [in] joined Set to true, if the node has joined the network
*
* \param [in] dutyCycle Set to true, if the duty cycle is enabled.
*
* \param [in] bands A pointer to the bands.
*
* \param [in] nbBands The number of bands available.
*
* \retval The time which must be waited to perform the next uplink.
*/ */
TimerTime_t update_band_timeoff( bool joined, bool dutyCycle, Band_t* bands, uint8_t nbBands ); lorawan_time_t update_band_timeoff(bool joined, bool dutyCycle, band_t* bands,
uint8_t nb_bands);
/*! /**
* \brief Parses the parameter of an LinkAdrRequest. * Parses the parameter of an LinkAdrRequest.
* This is a generic function and valid for all regions.
*
* \param [in] payload A pointer to the payload containing the MAC commands. The payload
* must contain the CMD identifier, followed by the parameters.
*
* \param [out] parseLinkAdr The function fills the structure with the ADR parameters.
*
* \retval The length of the ADR request, if a request was found. Otherwise, the
* function returns 0.
*/ */
uint8_t parse_link_ADR_req( uint8_t* payload, RegionCommonLinkAdrParams_t* parseLinkAdr ); uint8_t parse_link_ADR_req(uint8_t* payload, link_adr_params_t* adr_params);
/*! /**
* \brief Verifies and updates the datarate, the TX power and the number of repetitions * Verifies and updates the datarate, the TX power and the number of repetitions
* of a LinkAdrRequest. This also depends on the ADR configuration. * of a LinkAdrRequest.
*
* \param [in] verifyParams A pointer to a structure containing the input parameters.
*
* \param [out] dr The updated datarate.
*
* \param [out] txPow The updated TX power.
*
* \param [out] nbRep The updated number of repetitions.
*
* \retval The status according to the LinkAdrRequest definition.
*/ */
uint8_t verify_link_ADR_req( RegionCommonLinkAdrReqVerifyParams_t* verifyParams, int8_t* dr, int8_t* txPow, uint8_t* nbRep ); uint8_t verify_link_ADR_req(verify_adr_params_t* verify_params, int8_t* dr,
int8_t* tx_pow, uint8_t* nb_rep);
/*! /**
* \brief Computes the symbol time for LoRa modulation. * Computes the symbol time for LoRa modulation.
*
* \param [in] phyDr The physical datarate to use.
*
* \param [in] bandwidth The bandwidth to use.
*
* \retval The symbol time.
*/ */
double compute_symb_timeout_lora( uint8_t phyDr, uint32_t bandwidth ); double compute_symb_timeout_lora(uint8_t phy_dr, uint32_t bandwidth );
/*! /**
* \brief Computes the symbol time for FSK modulation. * Computes the symbol time for FSK modulation.
*
* \param [in] phyDr The physical datarate to use.
*
* \retval The symbol time.
*/ */
double compute_symb_timeout_fsk( uint8_t phyDr ); double compute_symb_timeout_fsk(uint8_t phy_dr);
/*! /**
* \brief Computes the RX window timeout and the RX window offset. * Computes the RX window timeout and the RX window offset.
*
* \param [in] tSymbol The symbol timeout.
*
* \param [in] minRxSymbols The minimum required number of symbols to detect an RX frame.
*
* \param [in] rxError The system maximum timing error of the receiver in milliseconds
* The receiver will turn on in a [-rxError : +rxError] ms interval around RxOffset.
*
* \param [in] wakeUpTime The wakeup time of the system.
*
* \param [out] windowTimeout The RX window timeout.
*
* \param [out] windowOffset The RX window time offset to be applied to the RX delay.
*/ */
void get_rx_window_params( double tSymbol, uint8_t minRxSymbols, uint32_t rxError, uint32_t wakeUpTime, uint32_t* windowTimeout, int32_t* windowOffset ); void get_rx_window_params(double t_symbol, uint8_t min_rx_symbols,
uint32_t rx_error, uint32_t wakeup_time,
uint32_t* window_timeout, int32_t* window_offset);
/*! /**
* \brief Computes the txPower, based on the max EIRP and the antenna gain. * Computes the txPower, based on the max EIRP and the antenna gain.
*
* \param [in] txPowerIndex The TX power index.
*
* \param [in] maxEirp The maximum EIRP.
*
* \param [in] antennaGain The antenna gain.
*
* \retval The physical TX power.
*/ */
int8_t compute_tx_power( int8_t txPowerIndex, float maxEirp, float antennaGain ); int8_t compute_tx_power(int8_t txPowerIndex, float maxEirp, float antennaGain);
/*! /**
* \brief Provides a random number in the range provided. * Provides a random number in the range provided.
*
* \param [in] min lower boundary
* \param [in] max upper boundary
*/ */
int32_t get_random(int32_t min, int32_t max); int32_t get_random(int32_t min, int32_t max);
/*! /**
* \brief Calculates the duty cycle for the current band. * Get next lower data rate
*
* \param [in] calcBackOffParams A pointer to the input parameters.
*/ */
void get_DC_backoff( RegionCommonCalcBackOffParams_t* calcBackOffParams ); int8_t get_next_lower_dr(int8_t dr, int8_t min_dr);
/**
* Get channel bandwidth depending upon data rate table index
*/
uint8_t get_bandwidth(uint8_t dr_index);
uint8_t enabled_channel_count(bool joined, uint8_t datarate,
const uint16_t *mask, uint8_t* enabledChannels,
uint8_t* delayTx);
}; };
#endif /* MBED_OS_LORAPHY_BASE_ */ #endif /* MBED_OS_LORAPHY_BASE_ */

File diff suppressed because it is too large Load Diff

View File

@ -33,7 +33,6 @@
#define MBED_OS_LORAPHY_AS923_H_ #define MBED_OS_LORAPHY_AS923_H_
#include "LoRaPHY.h" #include "LoRaPHY.h"
#include "netsocket/LoRaRadio.h"
/*! /*!
* LoRaMac maximum number of channels * LoRaMac maximum number of channels
@ -45,319 +44,28 @@
*/ */
#define AS923_MAX_NB_BANDS 1 #define AS923_MAX_NB_BANDS 1
#define AS923_CHANNELS_MASK_SIZE 1 #define AS923_CHANNEL_MASK_SIZE 1
class LoRaPHYAS923 : public LoRaPHY { class LoRaPHYAS923 : public LoRaPHY {
public: public:
LoRaPHYAS923(LoRaWANTimeHandler &lora_time);
LoRaPHYAS923();
virtual ~LoRaPHYAS923(); virtual ~LoRaPHYAS923();
/*! virtual int8_t get_alternate_DR(uint8_t nb_trials);
* \brief The function gets a value of a specific PHY attribute.
*
* \param [in] getPhy A pointer to the function parameters.
*
* \retval A structure containing the PHY parameter.
*/
virtual PhyParam_t get_phy_params(GetPhyParams_t* getPhy );
/*! virtual bool set_next_channel(channel_selection_params_t* nextChanParams,
* \brief Updates the last TX done parameters of the current channel. uint8_t* channel, lorawan_time_t* time,
* lorawan_time_t* aggregatedTimeOff );
* \param [in] txDone A pointer to the function parameters.
*/
virtual void set_band_tx_done(SetBandTxDoneParams_t* txDone );
/*! virtual uint8_t apply_DR_offset(int8_t dr, int8_t drOffset );
* \brief Initializes the channels masks and the channels.
*
* \param [in] type Sets the initialization type.
*/
virtual void load_defaults(InitType_t type );
/*!
* \brief Verifies a parameter.
*
* \param [in] verify A pointer to the function parameters.
*
* \param [in] phyAttribute The attribute to be verified.
*
* \retval True, if the parameter is valid.
*/
virtual bool verify(VerifyParams_t* verify, PhyAttribute_t phyAttribute );
/*!
* \brief The function parses the input buffer and sets up the channels of the
* CF list.
*
* \param [in] applyCFList A pointer to the function parameters.
*/
virtual void apply_cf_list(ApplyCFListParams_t* applyCFList );
/*!
* \brief Sets a channels mask.
*
* \param [in] chanMaskSet A pointer to the function parameters.
*
* \retval True, if the channels mask could be set.
*/
virtual bool set_channel_mask(ChanMaskSetParams_t* chanMaskSet );
/*!
* \brief Calculates the next datarate to set, when ADR is on or off.
*
* \param [in] adrNext A pointer to the function parameters.
*
* \param [out] drOut The calculated datarate for the next TX.
*
* \param [out] txPowOut The TX power for the next TX.
*
* \param [out] adrAckCounter The calculated ADR acknowledgement counter.
*
* \retval True, if an ADR request should be performed.
*/
virtual bool get_next_ADR(AdrNextParams_t* adrNext, int8_t* drOut,
int8_t* txPowOut, uint32_t* adrAckCounter );
/*!
* \brief Configuration of the RX windows.
*
* \param [in] rxConfig A pointer to the function parameters.
*
* \param [out] datarate The datarate index set.
*
* \retval True, if the configuration was applied successfully.
*/
virtual bool rx_config(RxConfigParams_t* rxConfig, int8_t* datarate );
/*
* RX window precise timing.
*
* For more details please consult the following document, chapter 3.1.2.
* http://www.semtech.com/images/datasheet/SX1272_settings_for_LoRaWAN_v2.0.pdf
* or
* http://www.semtech.com/images/datasheet/SX1276_settings_for_LoRaWAN_v2.0.pdf
*
* Downlink start: T = Tx + 1s (+/- 20 us)
* |
* TRxEarly | TRxLate
* | | |
* | | +---+---+---+---+---+---+---+---+
* | | | Latest Rx window |
* | | +---+---+---+---+---+---+---+---+
* | | |
* +---+---+---+---+---+---+---+---+
* | Earliest Rx window |
* +---+---+---+---+---+---+---+---+
* |
* +---+---+---+---+---+---+---+---+
*Downlink preamble 8 symbols | | | | | | | | |
* +---+---+---+---+---+---+---+---+
*
* Worst case Rx window timings
*
* TRxLate = DEFAULT_MIN_RX_SYMBOLS * tSymbol - RADIO_WAKEUP_TIME
* TRxEarly = 8 - DEFAULT_MIN_RX_SYMBOLS * tSymbol - RxWindowTimeout - RADIO_WAKEUP_TIME
*
* TRxLate - TRxEarly = 2 * DEFAULT_SYSTEM_MAX_RX_ERROR
*
* RxOffset = ( TRxLate + TRxEarly ) / 2
*
* RxWindowTimeout = ( 2 * DEFAULT_MIN_RX_SYMBOLS - 8 ) * tSymbol + 2 * DEFAULT_SYSTEM_MAX_RX_ERROR
* RxOffset = 4 * tSymbol - RxWindowTimeout / 2 - RADIO_WAKE_UP_TIME
*
* The minimum value of RxWindowTimeout must be 5 symbols which implies that the system always tolerates at least an error of 1.5 * tSymbol
*/
/*!
* Computes the RX window timeout and offset.
*
* \param [in] datarate The RX window datarate index to be used.
*
* \param [in] minRxSymbols The minimum required number of symbols to detect an RX frame.
*
* \param [in] rxError The system maximum timing error of the receiver in milliseconds.
* The receiver will turn on in a [-rxError : +rxError] ms
* interval around RxOffset.
*
* \param [out] rxConfigParams The updated WindowTimeout and WindowOffset fields.
*/
virtual void compute_rx_win_params(int8_t datarate,
uint8_t minRxSymbols,
uint32_t rxError,
RxConfigParams_t *rxConfigParams);
/*!
* \brief TX configuration.
*
* \param [in] txConfig A pointer to the function parameters.
*
* \param [out] txPower The TX power index set.
*
* \param [out] txTimeOnAir The time-on-air of the frame.
*
* \retval True, if the configuration was applied successfully.
*/
virtual bool tx_config(TxConfigParams_t* txConfig, int8_t* txPower,
TimerTime_t* txTimeOnAir );
/*!
* \brief The function processes a Link ADR Request.
*
* \param [in] linkAdrReq A pointer to the function parameters.
*
* \param [out] drOut The datarate applied.
*
* \param [out] txPowOut The TX power applied.
*
* \param [out] nbRepOut The number of repetitions to apply.
*
* \param [out] nbBytesParsed The number of bytes parsed.
*
* \retval The status of the operation, according to the LoRaMAC specification.
*/
virtual uint8_t link_ADR_request(LinkAdrReqParams_t* linkAdrReq,
int8_t* drOut, int8_t* txPowOut,
uint8_t* nbRepOut,
uint8_t* nbBytesParsed );
/*!
* \brief The function processes a RX parameter setup request.
*
* \param [in] rxParamSetupReq A pointer to the function parameters.
*
* \retval The status of the operation, according to the LoRaMAC specification.
*/
virtual uint8_t setup_rx_params(RxParamSetupReqParams_t* rxParamSetupReq );
/*!
* \brief The function processes a new channel request.
*
* \param [in] newChannelReq A pointer to the function parameters.
*
* \retval The status of the operation, according to the LoRaMAC specification.
*/
virtual uint8_t request_new_channel(NewChannelReqParams_t* newChannelReq );
/*!
* \brief The function processes a TX ParamSetup request.
*
* \param [in] txParamSetupReq A pointer to the function parameters.
*
* \retval The status of the operation, according to the LoRaMAC specification.
* Returns -1, if the functionality is not implemented. In this case, the end node
* shall ignore the command.
*/
virtual int8_t setup_tx_params(TxParamSetupReqParams_t* txParamSetupReq );
/*!
* \brief The function processes a DlChannel request.
*
* \param [in] dlChannelReq A pointer to the function parameters.
*
* \retval The status of the operation, according to the LoRaMAC specification.
*/
virtual uint8_t dl_channel_request(DlChannelReqParams_t* dlChannelReq );
/*!
* \brief Alternates the datarate of the channel for the join request.
*
* \param [in] alternateDr A pointer to the function parameters.
*
* \retval The datarate to apply.
*/
virtual int8_t get_alternate_DR(AlternateDrParams_t* alternateDr );
/*!
* \brief Calculates the back-off time.
*
* \param [in] calcBackOff A pointer to the function parameters.
*/
virtual void calculate_backoff(CalcBackOffParams_t* calcBackOff );
/*!
* \brief Searches and sets the next random available channel.
*
* \param [in] nextChanParams The parameters for the next channel
*
* \param [out] channel The next channel to use for TX.
*
* \param [out] time The time to wait for the next transmission according to the duty cycle.
*
* \param [out] aggregatedTimeOff Updates the aggregated time off.
*
* \retval Function status [1: OK, 0: Unable to find a channel on the current datarate].
*/
virtual bool set_next_channel(NextChanParams_t* nextChanParams,
uint8_t* channel, TimerTime_t* time,
TimerTime_t* aggregatedTimeOff );
/*!
* \brief Adds a channel.
*
* \param [in] channelAdd A pointer to the function parameters.
*
* \retval The status of the operation.
*/
virtual LoRaMacStatus_t add_channel(ChannelAddParams_t* channelAdd );
/*!
* \brief Removes a channel.
*
* \param [in] channelRemove A pointer to the function parameters.
*
* \retval True, if the channel was removed successfully.
*/
virtual bool remove_channel(ChannelRemoveParams_t* channelRemove );
/*!
* \brief Sets the radio into continuous wave mode.
*
* \param [in] continuousWave A pointer to the function parameters.
*/
virtual void set_tx_cont_mode(ContinuousWaveParams_t* continuousWave );
/*!
* \brief Computes a new datarate according to the given offset.
*
* \param [in] downlinkDwellTime The downlink dwell time configuration. 0: No limit, 1: 400ms
*
* \param [in] dr The current datarate.
*
* \param [in] drOffset The offset to be applied.
*
* \retval newDr The computed datarate.
*/
virtual uint8_t apply_DR_offset(uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
private: private:
uint8_t CountNbOfEnabledChannels(bool joined, uint8_t datarate, channel_params_t channels[AS923_MAX_NB_CHANNELS];
uint16_t* channelsMask, band_t bands[AS923_MAX_NB_BANDS];
ChannelParams_t* channels, Band_t* bands, uint16_t channel_mask[AS923_CHANNEL_MASK_SIZE];
uint8_t* enabledChannels, uint8_t* delayTx); uint16_t default_channel_mask[AS923_CHANNEL_MASK_SIZE];
// Global attributes
/*!
* LoRaMAC channels
*/
ChannelParams_t Channels[AS923_MAX_NB_CHANNELS];
/*!
* LoRaMac bands
*/
Band_t Bands[AS923_MAX_NB_BANDS];
/*!
* LoRaMac channels mask
*/
uint16_t ChannelsMask[AS923_CHANNELS_MASK_SIZE];
/*!
* LoRaMac channels default mask
*/
uint16_t ChannelsDefaultMask[AS923_CHANNELS_MASK_SIZE];
}; };
#endif /* MBED_OS_LORAPHY_AS923_H_ */ #endif /* MBED_OS_LORAPHY_AS923_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -34,7 +34,6 @@
#define MBED_OS_LORAPHY_AU915_H_ #define MBED_OS_LORAPHY_AU915_H_
#include "LoRaPHY.h" #include "LoRaPHY.h"
#include "netsocket/LoRaRadio.h"
// Definitions // Definitions
/*! /*!
@ -47,327 +46,62 @@
*/ */
#define AU915_MAX_NB_BANDS 1 #define AU915_MAX_NB_BANDS 1
#define AU915_CHANNELS_MASK_SIZE 6 #define AU915_CHANNEL_MASK_SIZE 5
class LoRaPHYAU915 : public LoRaPHY{ class LoRaPHYAU915 : public LoRaPHY{
public: public:
LoRaPHYAU915(); LoRaPHYAU915(LoRaWANTimeHandler &lora_time);
virtual ~LoRaPHYAU915(); virtual ~LoRaPHYAU915();
/*! virtual bool rx_config(rx_config_params_t* config, int8_t* datarate);
* \brief The function gets a value of a specific PHY attribute.
*
* \param [in] getPhy A pointer to the function parameters.
*
* \retval A structure containing the PHY parameter.
*/
virtual PhyParam_t get_phy_params(GetPhyParams_t* getPhy );
/*! virtual bool tx_config(tx_config_params_t* config, int8_t* txPower,
* \brief Updates the last TX done parameters of the current channel. lorawan_time_t* txTimeOnAir);
*
* \param [in] txDone A pointer to the function parameters.
*/
virtual void set_band_tx_done(SetBandTxDoneParams_t* txDone );
/*! virtual uint8_t link_ADR_request(adr_req_params_t* params,
* \brief Initializes the channels masks and the channels.
*
* \param [in] type Sets the initialization type.
*/
virtual void load_defaults(InitType_t type );
/*!
* \brief Verifies a parameter.
*
* \param [in] verify A pointer to the function parameters.
*
* \param [in] phyAttribute The attribute to be verified.
*
* \retval True, if the parameter is valid.
*/
virtual bool verify(VerifyParams_t* verify, PhyAttribute_t phyAttribute );
/*!
* \brief The function parses the input buffer and sets up the channels of the
* CF list.
*
* \param [in] applyCFList A pointer to the function parameters.
*/
virtual void apply_cf_list(ApplyCFListParams_t* applyCFList );
/*!
* \brief Sets a channels mask.
*
* \param [in] chanMaskSet A pointer to the function parameters.
*
* \retval True, if the channels mask could be set.
*/
virtual bool set_channel_mask(ChanMaskSetParams_t* chanMaskSet );
/*!
* \brief Calculates the next datarate to set, when ADR is on or off.
*
* \param [in] adrNext A pointer to the function parameters.
*
* \param [out] drOut The calculated datarate for the next TX.
*
* \param [out] txPowOut The TX power for the next TX.
*
* \param [out] adrAckCounter The calculated ADR acknowledgement counter.
*
* \retval True, if an ADR request should be performed.
*/
virtual bool get_next_ADR(AdrNextParams_t* adrNext, int8_t* drOut,
int8_t* txPowOut, uint32_t* adrAckCounter );
/*!
* \brief Configuration of the RX windows.
*
* \param [in] rxConfig A pointer to the function parameters.
*
* \param [out] datarate The datarate index set.
*
* \retval True, if the configuration was applied successfully.
*/
virtual bool rx_config(RxConfigParams_t* rxConfig, int8_t* datarate );
/*
* RX window precise timing
*
* For more details please consult the following document, chapter 3.1.2.
* http://www.semtech.com/images/datasheet/SX1272_settings_for_LoRaWAN_v2.0.pdf
* or
* http://www.semtech.com/images/datasheet/SX1276_settings_for_LoRaWAN_v2.0.pdf
*
* Downlink start: T = Tx + 1s (+/- 20 us)
* |
* TRxEarly | TRxLate
* | | |
* | | +---+---+---+---+---+---+---+---+
* | | | Latest Rx window |
* | | +---+---+---+---+---+---+---+---+
* | | |
* +---+---+---+---+---+---+---+---+
* | Earliest Rx window |
* +---+---+---+---+---+---+---+---+
* |
* +---+---+---+---+---+---+---+---+
*Downlink preamble 8 symbols | | | | | | | | |
* +---+---+---+---+---+---+---+---+
*
* Worst case Rx window timings
*
* TRxLate = DEFAULT_MIN_RX_SYMBOLS * tSymbol - RADIO_WAKEUP_TIME
* TRxEarly = 8 - DEFAULT_MIN_RX_SYMBOLS * tSymbol - RxWindowTimeout - RADIO_WAKEUP_TIME
*
* TRxLate - TRxEarly = 2 * DEFAULT_SYSTEM_MAX_RX_ERROR
*
* RxOffset = ( TRxLate + TRxEarly ) / 2
*
* RxWindowTimeout = ( 2 * DEFAULT_MIN_RX_SYMBOLS - 8 ) * tSymbol + 2 * DEFAULT_SYSTEM_MAX_RX_ERROR
* RxOffset = 4 * tSymbol - RxWindowTimeout / 2 - RADIO_WAKE_UP_TIME
*
* The minimum value of RxWindowTimeout must be 5 symbols which implies that the system always tolerates at least an error of 1.5 * tSymbol
*/
/*!
* Computes the Rx window timeout and offset.
*
* \param [in] datarate The RX window datarate index to be used.
*
* \param [in] minRxSymbols The minimum number of symbols required to detect an RX frame.
*
* \param [in] rxError The system maximum timing error of the receiver in milliseconds.
* The receiver will turn on in a [-rxError : +rxError] ms
* interval around RxOffset.
*
* \param [out] rxConfigParams The updated WindowTimeout and WindowOffset fields.
*/
virtual void compute_rx_win_params(int8_t datarate,
uint8_t minRxSymbols,
uint32_t rxError,
RxConfigParams_t *rxConfigParams);
/*!
* \brief TX configuration.
*
* \param [in] txConfig A pointer to the function parameters.
*
* \param [out] txPower The TX power index set.
*
* \param [out] txTimeOnAir The time-on-air of the frame.
*
* \retval True, if the configuration was applied successfully.
*/
virtual bool tx_config(TxConfigParams_t* txConfig, int8_t* txPower,
TimerTime_t* txTimeOnAir );
/*!
* \brief The function processes a Link ADR Request.
*
* \param [in] linkAdrReq A pointer to the function parameters.
*
* \param [out] drOut The datarate applied.
*
* \param [out] txPowOut The TX power applied.
*
* \param [out] nbRepOut The number of repetitions to apply.
*
* \param [out] nbBytesParsed The number bytes parsed.
*
* \retval The status of the operation, according to the LoRaMAC specification.
*/
virtual uint8_t link_ADR_request(LinkAdrReqParams_t* linkAdrReq,
int8_t* drOut, int8_t* txPowOut, int8_t* drOut, int8_t* txPowOut,
uint8_t* nbRepOut, uint8_t* nbRepOut,
uint8_t* nbBytesParsed ); uint8_t* nbBytesParsed);
/*! virtual uint8_t accept_rx_param_setup_req(rx_param_setup_req_t* params);
* \brief The function processes a RX parameter setup request.
*
* \param [in] rxParamSetupReq A pointer to the function parameters.
*
* \retval The status of the operation, according to the LoRaMAC specification.
*/
virtual uint8_t setup_rx_params(RxParamSetupReqParams_t* rxParamSetupReq );
/*! virtual int8_t get_alternate_DR(uint8_t nb_trials);
* \brief The function processes a new channel request.
*
* \param [in] newChannelReq A pointer to the function parameters.
*
* \retval The status of the operation, according to the LoRaMAC specification.
*/
virtual uint8_t request_new_channel(NewChannelReqParams_t* newChannelReq );
/*! virtual bool set_next_channel(channel_selection_params_t* next_chan_params,
* \brief The function processes a TX ParamSetup request. uint8_t* channel, lorawan_time_t* time,
* lorawan_time_t* aggregate_timeoff);
* \param [in] txParamSetupReq A pointer to the function parameters.
*
* \retval The status of the operation, according to the LoRaMAC specification.
* Returns -1, if the functionality is not implemented. In this case, the end node
* shall ignore the command.
*/
virtual int8_t setup_tx_params(TxParamSetupReqParams_t* txParamSetupReq );
/*! virtual uint8_t apply_DR_offset(int8_t dr, int8_t dr_offset);
* \brief The function processes a DlChannel request.
*
* \param [in] dlChannelReq A pointer to the function parameters.
*
* \retval The status of the operation, according to the LoRaMAC specification.
*/
virtual uint8_t dl_channel_request(DlChannelReqParams_t* dlChannelReq );
/*!
* \brief Alternates the datarate of the channel for the join request.
*
* \param [in] alternateDr A pointer to the function parameters.
*
* \retval The datarate to apply.
*/
virtual int8_t get_alternate_DR(AlternateDrParams_t* alternateDr );
/*!
* \brief Calculates the back-off time.
*
* \param [in] calcBackOff A pointer to the function parameters.
*/
virtual void calculate_backoff(CalcBackOffParams_t* calcBackOff );
/*!
* \brief Searches and sets the next random available channel.
*
* \param [in] nextChanParams The parameters for the next channel.
*
* \param [out] channel The next channel to use for TX.
*
* \param [out] time The time to wait for the next transmission according to the duty
* cycle.
*
* \param [out] aggregatedTimeOff Updates the aggregated time off.
*
* \retval The function status [1: OK, 0: Unable to find a channel on the current datarate].
*/
virtual bool set_next_channel(NextChanParams_t* nextChanParams,
uint8_t* channel, TimerTime_t* time,
TimerTime_t* aggregatedTimeOff );
/*!
* \brief Adds a channel.
*
* \param [in] channelAdd A pointer to the function parameters.
*
* \retval The status of the operation.
*/
virtual LoRaMacStatus_t add_channel(ChannelAddParams_t* channelAdd );
/*!
* \brief Removes a channel.
*
* \param [in] channelRemove A pointer to the function parameters.
*
* \retval True, if the channel was removed successfully.
*/
virtual bool remove_channel(ChannelRemoveParams_t* channelRemove );
/*!
* \brief Sets the radio into continuous wave mode.
*
* \param [in] continuousWave A pointer to the function parameters.
*/
virtual void set_tx_cont_mode(ContinuousWaveParams_t* continuousWave );
/*!
* \brief Computes a new datarate according to the given offset.
*
* \param [in] downlinkDwellTime The downlink dwell time configuration. 0: No limit, 1: 400ms
*
* \param [in] dr The current datarate.
*
* \param [in] drOffset The offset to be applied.
*
* \retval newDr The computed datarate.
*/
virtual uint8_t apply_DR_offset(uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
private: private:
uint8_t CountNbOfEnabledChannels(uint8_t datarate,
uint16_t* channelsMask,
ChannelParams_t* channels,
Band_t* bands, uint8_t* enabledChannels,
uint8_t* delayTx);
// Global attributes
/*! /*!
* LoRaMAC channels * LoRaMAC channels
*/ */
ChannelParams_t Channels[AU915_MAX_NB_CHANNELS]; channel_params_t channels[AU915_MAX_NB_CHANNELS];
/*! /*!
* LoRaMac bands * LoRaMac bands
*/ */
Band_t Bands[AU915_MAX_NB_BANDS]; band_t bands[AU915_MAX_NB_BANDS];
/*! /*!
* LoRaMac channels mask * LoRaMac channel mask
*/ */
uint16_t ChannelsMask[AU915_CHANNELS_MASK_SIZE]; uint16_t channel_mask[AU915_CHANNEL_MASK_SIZE];
/*! /*!
* LoRaMac channels remaining * Previously used channel mask
*/ */
uint16_t ChannelsMaskRemaining[AU915_CHANNELS_MASK_SIZE]; uint16_t current_channel_mask[AU915_CHANNEL_MASK_SIZE];
/*! /*!
* LoRaMac channels default mask * LoRaMac channels default mask
*/ */
uint16_t ChannelsDefaultMask[AU915_CHANNELS_MASK_SIZE]; uint16_t default_channel_mask[AU915_CHANNEL_MASK_SIZE];
}; };
#endif /* MBED_OS_LORAPHY_AU915_H_ */ #endif /* MBED_OS_LORAPHY_AU915_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -33,7 +33,6 @@
#define MBED_OS_LORAPHY_CN470_H_ #define MBED_OS_LORAPHY_CN470_H_
#include "LoRaPHY.h" #include "LoRaPHY.h"
#include "netsocket/LoRaRadio.h"
// Definitions // Definitions
/*! /*!
@ -47,319 +46,48 @@
#define CN470_MAX_NB_BANDS 1 #define CN470_MAX_NB_BANDS 1
#define CN470_CHANNELS_MASK_SIZE 6 #define CN470_CHANNEL_MASK_SIZE 6
class LoRaPHYCN470 : public LoRaPHY { class LoRaPHYCN470 : public LoRaPHY {
public: public:
LoRaPHYCN470(); LoRaPHYCN470(LoRaWANTimeHandler &lora_time);
virtual ~LoRaPHYCN470(); virtual ~LoRaPHYCN470();
/*! virtual bool rx_config(rx_config_params_t* config, int8_t* datarate );
* \brief The function gets a value of a specific PHY attribute.
*
* \param [in] getPhy A pointer to the function parameters.
*
* \retval A structure containing the PHY parameter.
*/
virtual PhyParam_t get_phy_params(GetPhyParams_t* getPhy );
/*! virtual bool tx_config(tx_config_params_t* config, int8_t* tx_power,
* \brief Updates the last TX done parameters of the current channel. lorawan_time_t* tx_toa);
*
* \param [in] txDone A pointer to the function parameters.
*/
virtual void set_band_tx_done(SetBandTxDoneParams_t* txDone );
/*! virtual uint8_t link_ADR_request(adr_req_params_t* params, int8_t* dr_out,
* \brief Initializes the channels masks and the channels. int8_t* tx_power_out, uint8_t* nb_rep_out,
* uint8_t* nb_bytes_parsed);
* \param [in] type Sets the initialization type.
*/
virtual void load_defaults(InitType_t type );
/*! virtual uint8_t accept_rx_param_setup_req(rx_param_setup_req_t* params);
* \brief Verifies a parameter.
*
* \param [in] verify A pointer to the function parameters.
*
* \param [in] phyAttribute The attribute to be verified.
*
* \retval True, if the parameter is valid.
*/
virtual bool verify(VerifyParams_t* verify, PhyAttribute_t phyAttribute );
/*!
* \brief The function parses the input buffer and sets up the channels of the
* CF list.
*
* \param [in] applyCFList A pointer to the function parameters.
*/
virtual void apply_cf_list(ApplyCFListParams_t* applyCFList );
/*!
* \brief Sets a channels mask.
*
* \param [in] chanMaskSet A pointer to the function parameters.
*
* \retval True, if the channels mask could be set.
*/
virtual bool set_channel_mask(ChanMaskSetParams_t* chanMaskSet );
/*!
* \brief Calculates the next datarate to set, when ADR is on or off.
*
* \param [in] adrNext A pointer to the function parameters.
*
* \param [out] drOut The calculated datarate for the next TX.
*
* \param [out] txPowOut The TX power for the next TX.
*
* \param [out] adrAckCounter The calculated ADR acknowledgement counter.
*
* \retval True, if an ADR request should be performed.
*/
virtual bool get_next_ADR(AdrNextParams_t* adrNext, int8_t* drOut,
int8_t* txPowOut, uint32_t* adrAckCounter );
/*!
* \brief Configuration of the RX windows.
*
* \param [in] rxConfig A pointer to the function parameters.
*
* \param [out] datarate The datarate index set.
*
* \retval True, if the configuration was applied successfully.
*/
virtual bool rx_config(RxConfigParams_t* rxConfig, int8_t* datarate );
/*
* RX window precise timing
*
* For more details please consult the following document, chapter 3.1.2.
* http://www.semtech.com/images/datasheet/SX1272_settings_for_LoRaWAN_v2.0.pdf
* or
* http://www.semtech.com/images/datasheet/SX1276_settings_for_LoRaWAN_v2.0.pdf
*
* Downlink start: T = Tx + 1s (+/- 20 us)
* |
* TRxEarly | TRxLate
* | | |
* | | +---+---+---+---+---+---+---+---+
* | | | Latest Rx window |
* | | +---+---+---+---+---+---+---+---+
* | | |
* +---+---+---+---+---+---+---+---+
* | Earliest Rx window |
* +---+---+---+---+---+---+---+---+
* |
* +---+---+---+---+---+---+---+---+
*Downlink preamble 8 symbols | | | | | | | | |
* +---+---+---+---+---+---+---+---+
*
* Worst case Rx window timings
*
* TRxLate = DEFAULT_MIN_RX_SYMBOLS * tSymbol - RADIO_WAKEUP_TIME
* TRxEarly = 8 - DEFAULT_MIN_RX_SYMBOLS * tSymbol - RxWindowTimeout - RADIO_WAKEUP_TIME
*
* TRxLate - TRxEarly = 2 * DEFAULT_SYSTEM_MAX_RX_ERROR
*
* RxOffset = ( TRxLate + TRxEarly ) / 2
*
* RxWindowTimeout = ( 2 * DEFAULT_MIN_RX_SYMBOLS - 8 ) * tSymbol + 2 * DEFAULT_SYSTEM_MAX_RX_ERROR
* RxOffset = 4 * tSymbol - RxWindowTimeout / 2 - RADIO_WAKE_UP_TIME
*
* The minimum value of RxWindowTimeout must be 5 symbols which implies that the system always tolerates at least an error of 1.5 * tSymbol
*/
/*!
* Computes the RX window timeout and offset.
*
* \param [in] datarate The RX window datarate index to be used.
*
* \param [in] minRxSymbols The minimum number of symbols required to detect an RX frame.
*
* \param [in] rxError The system maximum timing error of the receiver in milliseconds.
* The receiver will turn on in a [-rxError : +rxError] ms
* interval around RxOffset.
*
* \param [out] rxConfigParams The updated WindowTimeout and WindowOffset fields.
*/
virtual void compute_rx_win_params(int8_t datarate,
uint8_t minRxSymbols,
uint32_t rxError,
RxConfigParams_t *rxConfigParams);
/*!
* \brief TX configuration.
*
* \param [in] txConfig A pointer to the function parameters.
*
* \param [out] txPower The TX power index set.
*
* \param [out] txTimeOnAir The time-on-air of the frame.
*
* \retval True, if the configuration was applied successfully.
*/
virtual bool tx_config(TxConfigParams_t* txConfig, int8_t* txPower,
TimerTime_t* txTimeOnAir );
/*!
* \brief The function processes a Link ADR request.
*
* \param [in] linkAdrReq A pointer to the function parameters.
*
* \param [out] drOut The datarate applied.
*
* \param [out] txPowOut The TX power applied.
*
* \param [out] nbRepOut The number of repetitions to apply.
*
* \param [out] nbBytesParsed The number of bytes parsed.
*
* \retval The status of the operation, according to the LoRaMAC specification.
*/
virtual uint8_t link_ADR_request(LinkAdrReqParams_t* linkAdrReq,
int8_t* drOut, int8_t* txPowOut,
uint8_t* nbRepOut,
uint8_t* nbBytesParsed );
/*!
* \brief The function processes a RX parameter setup request.
*
* \param [in] rxParamSetupReq A pointer to the function parameters.
*
* \retval The status of the operation, according to the LoRaMAC specification.
*/
virtual uint8_t setup_rx_params(RxParamSetupReqParams_t* rxParamSetupReq );
/*!
* \brief The function processes a new channel request.
*
* \param [in] newChannelReq A pointer to the function parameters.
*
* \retval The status of the operation, according to the LoRaMAC specification.
*/
virtual uint8_t request_new_channel(NewChannelReqParams_t* newChannelReq );
/*!
* \brief The function processes a TX ParamSetup request.
*
* \param [in] txParamSetupReq A pointer to the function parameters.
*
* \retval The status of the operation, according to the LoRaMAC specification.
* Returns -1, if the functionality is not implemented. In this case, the end node
* shall ignore the command.
*/
virtual int8_t setup_tx_params(TxParamSetupReqParams_t* txParamSetupReq );
/*!
* \brief The function processes a DlChannel request.
*
* \param [in] dlChannelReq A pointer to the function parameters.
*
* \retval The status of the operation, according to the LoRaMAC specification.
*/
virtual uint8_t dl_channel_request(DlChannelReqParams_t* dlChannelReq );
/*!
* \brief Alternates the datarate of the channel for the join request.
*
* \param [in] alternateDr A pointer to the function parameters.
*
* \retval The datarate to apply.
*/
virtual int8_t get_alternate_DR(AlternateDrParams_t* alternateDr );
/*!
* \brief Calculates the back-off time.
*
* \param [in] calcBackOff A pointer to the function parameters.
*/
virtual void calculate_backoff(CalcBackOffParams_t* calcBackOff );
/*!
* \brief Searches and sets the next random available channel.
*
* \param [in] nextChanParams The parameters for the next channel
*
* \param [out] channel The next channel to use for TX.
*
* \param [out] time The time to wait for the next transmission according to the duty
* cycle.
*
* \param [out] aggregatedTimeOff Updates the aggregated time off.
*
* \retval Function status [1: OK, 0: Unable to find a channel on the current datarate].
*/
virtual bool set_next_channel(NextChanParams_t* nextChanParams,
uint8_t* channel, TimerTime_t* time,
TimerTime_t* aggregatedTimeOff );
/*!
* \brief Adds a channel.
*
* \param [in] channelAdd A pointer to the function parameters.
*
* \retval The status of the operation.
*/
virtual LoRaMacStatus_t add_channel(ChannelAddParams_t* channelAdd );
/*!
* \brief Removes a channel.
*
* \param [in] channelRemove A pointer to the function parameters.
*
* \retval True, if the channel was removed successfully.
*/
virtual bool remove_channel(ChannelRemoveParams_t* channelRemove );
/*!
* \brief Sets the radio into continuous wave mode.
*
* \param [in] continuousWave A pointer to the function parameters.
*/
virtual void set_tx_cont_mode(ContinuousWaveParams_t* continuousWave );
/*!
* \brief Computes a new datarate according to the given offset.
*
* \param [in] downlinkDwellTime The downlink dwell time configuration. 0: No limit, 1: 400ms
*
* \param [in] dr The current datarate.
*
* \param [in] drOffset The offset to be applied.
*
* \retval newDr The computed datarate.
*/
virtual uint8_t apply_DR_offset(uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
private: private:
uint8_t CountNbOfEnabledChannels( uint8_t datarate, uint16_t* channelsMask, ChannelParams_t* channels, Band_t* bands, uint8_t* enabledChannels, uint8_t* delayTx );
bool RegionCN470ChanMaskSet( ChanMaskSetParams_t* chanMaskSet );
// Global attributes
/*! /*!
* LoRaMAC channels * LoRaMAC channels
*/ */
ChannelParams_t Channels[CN470_MAX_NB_CHANNELS]; channel_params_t channels[CN470_MAX_NB_CHANNELS];
/*! /*!
* LoRaMac bands * LoRaMac bands
*/ */
Band_t Bands[CN470_MAX_NB_BANDS]; band_t bands[CN470_MAX_NB_BANDS];
/*! /*!
* LoRaMac channels mask * LoRaMac channel mask
*/ */
uint16_t ChannelsMask[CN470_CHANNELS_MASK_SIZE]; uint16_t channel_mask[CN470_CHANNEL_MASK_SIZE];
/*! /*!
* LoRaMac channels default mask * LoRaMac default channel mask
*/ */
uint16_t ChannelsDefaultMask[CN470_CHANNELS_MASK_SIZE]; uint16_t default_channel_mask[CN470_CHANNEL_MASK_SIZE];
}; };
#endif /* MBED_OS_LORAPHY_CN470_H_ */ #endif /* MBED_OS_LORAPHY_CN470_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -33,322 +33,41 @@
#define MBED_OS_LORAPHY_CN779_H_ #define MBED_OS_LORAPHY_CN779_H_
#include "LoRaPHY.h" #include "LoRaPHY.h"
#include "netsocket/LoRaRadio.h"
#define CN779_MAX_NB_CHANNELS 16 #define CN779_MAX_NB_CHANNELS 16
#define CN779_MAX_NB_BANDS 1 #define CN779_MAX_NB_BANDS 1
#define CN779_CHANNELS_MASK_SIZE 1 #define CN779_CHANNEL_MASK_SIZE 1
class LoRaPHYCN779 : public LoRaPHY { class LoRaPHYCN779 : public LoRaPHY {
public: public:
LoRaPHYCN779(); LoRaPHYCN779(LoRaWANTimeHandler &lora_time);
virtual ~LoRaPHYCN779(); virtual ~LoRaPHYCN779();
/*!
* \brief The function gets a value of a specific PHY attribute.
*
* \param [in] getPhy A pointer to the function parameters.
*
* \retval The structure containing the PHY parameter.
*/
virtual PhyParam_t get_phy_params(GetPhyParams_t* getPhy );
/*!
* \brief Updates the last TX done parameters of the current channel.
*
* \param [in] txDone A pointer to the function parameters.
*/
virtual void set_band_tx_done(SetBandTxDoneParams_t* txDone );
/*!
* \brief Initializes the channels masks and the channels.
*
* \param [in] type Sets the initialization type.
*/
virtual void load_defaults(InitType_t type );
/*!
* \brief Verifies a parameter.
*
* \param [in] verify A pointer to the function parameters.
*
* \param [in] phyAttribute The attribute to verify.
*
* \retval True, if the parameter is valid.
*/
virtual bool verify(VerifyParams_t* verify, PhyAttribute_t phyAttribute );
/*!
* \brief The function parses the input buffer and sets up the channels of the CF list.
*
* \param [in] applyCFList A pointer to the function parameters.
*/
virtual void apply_cf_list(ApplyCFListParams_t* applyCFList );
/*!
* \brief Sets a channels mask.
*
* \param [in] chanMaskSet A pointer to the function parameters.
*
* \retval True, if the channels mask could be set.
*/
virtual bool set_channel_mask(ChanMaskSetParams_t* chanMaskSet );
/*!
* \brief Calculates the next datarate to set, when ADR is on or off.
*
* \param [in] adrNext A pointer to the function parameters.
*
* \param [out] drOut The calculated datarate for the next TX.
*
* \param [out] txPowOut The TX power for the next TX.
*
* \param [out] adrAckCounter The calculated ADR acknowledgement counter.
*
* \retval True, if an ADR request should be performed.
*/
virtual bool get_next_ADR(AdrNextParams_t* adrNext, int8_t* drOut,
int8_t* txPowOut, uint32_t* adrAckCounter );
/*!
* \brief Configuration of the RX windows.
*
* \param [in] rxConfig A pointer to the function parameters.
*
* \param [out] datarate The datarate index set.
*
* \retval True, if the configuration was applied successfully.
*/
virtual bool rx_config(RxConfigParams_t* rxConfig, int8_t* datarate );
/*
* RX window precise timing
*
* For more details please consult the following document, chapter 3.1.2.
* http://www.semtech.com/images/datasheet/SX1272_settings_for_LoRaWAN_v2.0.pdf
* or
* http://www.semtech.com/images/datasheet/SX1276_settings_for_LoRaWAN_v2.0.pdf
*
* Downlink start: T = Tx + 1s (+/- 20 us)
* |
* TRxEarly | TRxLate
* | | |
* | | +---+---+---+---+---+---+---+---+
* | | | Latest Rx window |
* | | +---+---+---+---+---+---+---+---+
* | | |
* +---+---+---+---+---+---+---+---+
* | Earliest Rx window |
* +---+---+---+---+---+---+---+---+
* |
* +---+---+---+---+---+---+---+---+
*Downlink preamble 8 symbols | | | | | | | | |
* +---+---+---+---+---+---+---+---+
*
* Worst case Rx window timings
*
* TRxLate = DEFAULT_MIN_RX_SYMBOLS * tSymbol - RADIO_WAKEUP_TIME
* TRxEarly = 8 - DEFAULT_MIN_RX_SYMBOLS * tSymbol - RxWindowTimeout - RADIO_WAKEUP_TIME
*
* TRxLate - TRxEarly = 2 * DEFAULT_SYSTEM_MAX_RX_ERROR
*
* RxOffset = ( TRxLate + TRxEarly ) / 2
*
* RxWindowTimeout = ( 2 * DEFAULT_MIN_RX_SYMBOLS - 8 ) * tSymbol + 2 * DEFAULT_SYSTEM_MAX_RX_ERROR
* RxOffset = 4 * tSymbol - RxWindowTimeout / 2 - RADIO_WAKE_UP_TIME
*
* The minimum value of RxWindowTimeout must be 5 symbols which implies that the system always tolerates at least an error of 1.5 * tSymbol
*/
/*!
* Computes the RX window timeout and offset.
*
* \param [in] datarate The RX window datarate index to be used.
*
* \param [in] minRxSymbols The minimum required number of symbols to detect an RX frame.
*
* \param [in] rxError The system maximum timing error of the receiver in milliseconds.
* The receiver will turn on in a [-rxError : +rxError] ms
* interval around RxOffset.
*
* \param [out] rxConfigParams Returns the updated WindowTimeout and WindowOffset fields.
*/
virtual void compute_rx_win_params(int8_t datarate,
uint8_t minRxSymbols,
uint32_t rxError,
RxConfigParams_t *rxConfigParams);
/*!
* \brief TX configuration.
*
* \param [in] txConfig A pointer to the function parameters.
*
* \param [out] txPower The TX power index set.
*
* \param [out] txTimeOnAir The time-on-air of the frame.
*
* \retval True, if the configuration was applied successfully.
*/
virtual bool tx_config(TxConfigParams_t* txConfig, int8_t* txPower,
TimerTime_t* txTimeOnAir );
/*!
* \brief The function processes a Link ADR request.
*
* \param [in] linkAdrReq A pointer to the function parameters.
*
* \param [out] drOut The datarate applied.
*
* \param [out] txPowOut The TX power applied.
*
* \param [out] nbRepOut The number of repetitions to apply.
*
* \param [out] nbBytesParsed The number of bytes parsed.
*
* \retval The status of the operation, according to the LoRaMAC specification.
*/
virtual uint8_t link_ADR_request(LinkAdrReqParams_t* linkAdrReq,
int8_t* drOut, int8_t* txPowOut,
uint8_t* nbRepOut,
uint8_t* nbBytesParsed );
/*!
* \brief The function processes a RX parameter setup request.
*
* \param [in] rxParamSetupReq A pointer to the function parameters.
*
* \retval The status of the operation, according to the LoRaMAC specification.
*/
virtual uint8_t setup_rx_params(RxParamSetupReqParams_t* rxParamSetupReq );
/*!
* \brief The function processes a new channel request.
*
* \param [in] newChannelReq A pointer to the function parameters.
*
* \retval The status of the operation, according to the LoRaMAC specification.
*/
virtual uint8_t request_new_channel(NewChannelReqParams_t* newChannelReq );
/*!
* \brief The function processes a TX ParamSetup request.
*
* \param [in] txParamSetupReq A pointer to the function parameters.
*
* \retval The status of the operation, according to the LoRaMAC specification.
* Returns -1, if the functionality is not implemented. In this case, the end node
* shall ignore the command.
*/
virtual int8_t setup_tx_params(TxParamSetupReqParams_t* txParamSetupReq );
/*!
* \brief The function processes a DlChannel request.
*
* \param [in] dlChannelReq A pointer to the function parameters.
*
* \retval The status of the operation, according to the LoRaMAC specification.
*/
virtual uint8_t dl_channel_request(DlChannelReqParams_t* dlChannelReq );
/*!
* \brief Alternates the datarate of the channel for the join request.
*
* \param [in] alternateDr A pointer to the function parameters.
*
* \retval The datarate to apply.
*/
virtual int8_t get_alternate_DR(AlternateDrParams_t* alternateDr );
/*!
* \brief Calculates the back-off time.
*
* \param [in] calcBackOff A pointer to the function parameters.
*/
virtual void calculate_backoff(CalcBackOffParams_t* calcBackOff );
/*!
* \brief Searches and sets the next random available channel.
*
* \param [in] nextChanParams The parameters for the next channel.
*
* \param [out] channel The next channel to use for TX.
*
* \param [out] time The time to wait for the next transmission according to the duty
* cycle.
*
* \param [out] aggregatedTimeOff Updates the aggregated time off.
*
* \retval Function status [1: OK, 0: Unable to find a channel on the current datarate].
*/
virtual bool set_next_channel(NextChanParams_t* nextChanParams,
uint8_t* channel, TimerTime_t* time,
TimerTime_t* aggregatedTimeOff );
/*!
* \brief Adds a channel.
*
* \param [in] channelAdd A pointer to the function parameters.
*
* \retval The status of the operation.
*/
virtual LoRaMacStatus_t add_channel(ChannelAddParams_t* channelAdd );
/*!
* \brief Removes a channel.
*
* \param [in] channelRemove A pointer to the function parameters.
*
* \retval True, if the channel was removed successfully.
*/
virtual bool remove_channel(ChannelRemoveParams_t* channelRemove );
/*!
* \brief Sets the radio into continuous wave mode.
*
* \param [in] continuousWave A pointer to the function parameters.
*/
virtual void set_tx_cont_mode(ContinuousWaveParams_t* continuousWave );
/*!
* \brief Computes a new datarate according to the given offset.
*
* \param [in] downlinkDwellTime The downlink dwell time configuration. 0: No limit, 1: 400ms
*
* \param [in] dr The current datarate.
*
* \param [in] drOffset The offset to be applied.
*
* \retval newDr The computed datarate.
*/
virtual uint8_t apply_DR_offset(uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
private: private:
uint8_t CountNbOfEnabledChannels( bool joined, uint8_t datarate, uint16_t* channelsMask, ChannelParams_t* channels, Band_t* bands, uint8_t* enabledChannels, uint8_t* delayTx );
// Global attributes
/*! /*!
* LoRaMAC channels * LoRaMAC channels
*/ */
ChannelParams_t Channels[CN779_MAX_NB_CHANNELS]; channel_params_t channels[CN779_MAX_NB_CHANNELS];
/*! /*!
* LoRaMac bands * LoRaMac bands
*/ */
Band_t Bands[CN779_MAX_NB_BANDS]; band_t bands[CN779_MAX_NB_BANDS];
/*! /*!
* LoRaMac channels mask * LoRaMac channel mask
*/ */
uint16_t ChannelsMask[CN779_CHANNELS_MASK_SIZE]; uint16_t channel_mask[CN779_CHANNEL_MASK_SIZE];
/*! /*!
* LoRaMac channels default mask * LoRaMac default channel mask
*/ */
uint16_t ChannelsDefaultMask[CN779_CHANNELS_MASK_SIZE]; uint16_t default_channel_mask[CN779_CHANNEL_MASK_SIZE];
}; };
#endif /* MBED_OS_LORAPHY_CN779_H_ */ #endif /* MBED_OS_LORAPHY_CN779_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -33,7 +33,6 @@
#define MBED_OS_LORAPHY_EU433_H_ #define MBED_OS_LORAPHY_EU433_H_
#include "LoRaPHY.h" #include "LoRaPHY.h"
#include "netsocket/LoRaRadio.h"
/*! /*!
* LoRaMac maximum number of channels * LoRaMac maximum number of channels
@ -45,316 +44,36 @@
*/ */
#define EU433_MAX_NB_BANDS 1 #define EU433_MAX_NB_BANDS 1
#define EU433_CHANNELS_MASK_SIZE 1 #define EU433_CHANNEL_MASK_SIZE 1
class LoRaPHYEU433 : public LoRaPHY { class LoRaPHYEU433 : public LoRaPHY {
public: public:
LoRaPHYEU433(); LoRaPHYEU433(LoRaWANTimeHandler &lora_time);
virtual ~LoRaPHYEU433(); virtual ~LoRaPHYEU433();
/*!
* \brief The function gets a value of a specific PHY attribute.
*
* \param [in] getPhy A pointer to the function parameters.
*
* \retval The structure containing the PHY parameter.
*/
virtual PhyParam_t get_phy_params(GetPhyParams_t* getPhy );
/*!
* \brief Updates the last TX done parameters of the current channel.
*
* \param [in] txDone A pointer to the function parameters.
*/
virtual void set_band_tx_done(SetBandTxDoneParams_t* txDone );
/*!
* \brief Initializes the channels masks and the channels.
*
* \param [in] type Sets the initialization type.
*/
virtual void load_defaults(InitType_t type );
/*!
* \brief Verifies a parameter.
*
* \param [in] verify A pointer to the function parameters.
*
* \param [in] phyAttribute The attribute to verify.
*
* \retval True, if the parameter is valid.
*/
virtual bool verify(VerifyParams_t* verify, PhyAttribute_t phyAttribute );
/*!
* \brief The function parses the input buffer and sets up the channels of the CF list.
*
* \param [in] applyCFList A pointer to the function parameters.
*/
virtual void apply_cf_list(ApplyCFListParams_t* applyCFList );
/*!
* \brief Sets a channels mask.
*
* \param [in] chanMaskSet A pointer to the function parameters.
*
* \retval True, if the channels mask could be set.
*/
virtual bool set_channel_mask(ChanMaskSetParams_t* chanMaskSet );
/*!
* \brief Calculates the next datarate to set, when ADR is on or off.
*
* \param [in] adrNext A pointer to the function parameters.
*
* \param [out] drOut The calculated datarate for the next TX.
*
* \param [out] txPowOut The TX power for the next TX.
*
* \param [out] adrAckCounter The calculated ADR acknowledgement counter.
*
* \retval True, if an ADR request should be performed.
*/
virtual bool get_next_ADR(AdrNextParams_t* adrNext, int8_t* drOut,
int8_t* txPowOut, uint32_t* adrAckCounter );
/*!
* \brief Configuration of the RX windows.
*
* \param [in] rxConfig A pointer to the function parameters.
*
* \param [out] datarate The datarate index set.
*
* \retval True, if the configuration was applied successfully.
*/
virtual bool rx_config(RxConfigParams_t* rxConfig, int8_t* datarate );
/*
* RX window precise timing
*
* For more details please consult the following document, chapter 3.1.2.
* http://www.semtech.com/images/datasheet/SX1272_settings_for_LoRaWAN_v2.0.pdf
* or
* http://www.semtech.com/images/datasheet/SX1276_settings_for_LoRaWAN_v2.0.pdf
*
* Downlink start: T = Tx + 1s (+/- 20 us)
* |
* TRxEarly | TRxLate
* | | |
* | | +---+---+---+---+---+---+---+---+
* | | | Latest Rx window |
* | | +---+---+---+---+---+---+---+---+
* | | |
* +---+---+---+---+---+---+---+---+
* | Earliest Rx window |
* +---+---+---+---+---+---+---+---+
* |
* +---+---+---+---+---+---+---+---+
*Downlink preamble 8 symbols | | | | | | | | |
* +---+---+---+---+---+---+---+---+
*
* Worst case Rx window timings
*
* TRxLate = DEFAULT_MIN_RX_SYMBOLS * tSymbol - RADIO_WAKEUP_TIME
* TRxEarly = 8 - DEFAULT_MIN_RX_SYMBOLS * tSymbol - RxWindowTimeout - RADIO_WAKEUP_TIME
*
* TRxLate - TRxEarly = 2 * DEFAULT_SYSTEM_MAX_RX_ERROR
*
* RxOffset = ( TRxLate + TRxEarly ) / 2
*
* RxWindowTimeout = ( 2 * DEFAULT_MIN_RX_SYMBOLS - 8 ) * tSymbol + 2 * DEFAULT_SYSTEM_MAX_RX_ERROR
* RxOffset = 4 * tSymbol - RxWindowTimeout / 2 - RADIO_WAKE_UP_TIME
*
* The minimum value of RxWindowTimeout must be 5 symbols which implies that the system always tolerates at least an error of 1.5 * tSymbol
*/
/*!
* Computes the RX window timeout and offset.
*
* \param [in] datarate The RX window datarate index to be used.
*
* \param [in] minRxSymbols The minimum number of symbols required to detect an RX frame.
*
* \param [in] rxError The system maximum timing error of the receiver in milliseconds.
* The receiver will turn on in a [-rxError : +rxError] ms
* interval around RxOffset.
*
* \param [out] rxConfigParams Returns the updated WindowTimeout and WindowOffset fields.
*/
virtual void compute_rx_win_params(int8_t datarate,
uint8_t minRxSymbols,
uint32_t rxError,
RxConfigParams_t *rxConfigParams);
/*!
* \brief TX configuration.
*
* \param [in] txConfig A pointer to the function parameters.
*
* \param [out] txPower The TX power index set.
*
* \param [out] txTimeOnAir The time-on-air of the frame.
*
* \retval True, if the configuration was applied successfully.
*/
virtual bool tx_config(TxConfigParams_t* txConfig, int8_t* txPower,
TimerTime_t* txTimeOnAir );
/*!
* \brief The function processes a Link ADR request.
*
* \param [in] linkAdrReq A pointer to the function parameters.
*
* \param [out] drOut The datarate applied.
*
* \param [out] txPowOut The TX power applied.
*
* \param [out] nbRepOut The number of repetitions to apply.
*
* \param [out] nbBytesParsed The number of bytes parsed.
*
* \retval The status of the operation, according to the LoRaMAC specification.
*/
virtual uint8_t link_ADR_request(LinkAdrReqParams_t* linkAdrReq,
int8_t* drOut, int8_t* txPowOut,
uint8_t* nbRepOut,
uint8_t* nbBytesParsed );
/*!
* \brief The function processes a RX parameter setup request.
*
* \param [in] rxParamSetupReq A pointer to the function parameters.
*
* \retval The status of the operation, according to the LoRaMAC specification.
*/
virtual uint8_t setup_rx_params(RxParamSetupReqParams_t* rxParamSetupReq );
/*!
* \brief The function processes a new channel request.
*
* \param [in] newChannelReq A pointer to the function parameters.
*
* \retval The status of the operation, according to the LoRaMAC specification.
*/
virtual uint8_t request_new_channel(NewChannelReqParams_t* newChannelReq );
/*!
* \brief The function processes a TX ParamSetup request.
*
* \param [in] txParamSetupReq A pointer to the function parameters.
*
* \retval The status of the operation, according to the LoRaMAC specification.
* Returns -1, if the functionality is not implemented. In this case, the end node
* shall ignore the command.
*/
virtual int8_t setup_tx_params(TxParamSetupReqParams_t* txParamSetupReq );
/*!
* \brief The function processes a DlChannel request.
*
* \param [in] dlChannelReq A pointer to the function parameters.
*
* \retval The status of the operation, according to the LoRaMAC specification.
*/
virtual uint8_t dl_channel_request(DlChannelReqParams_t* dlChannelReq );
/*!
* \brief Alternates the datarate of the channel for the join request.
*
* \param [in] alternateDr A pointer to the function parameters.
*
* \retval The datarate to apply.
*/
virtual int8_t get_alternate_DR(AlternateDrParams_t* alternateDr );
/*!
* \brief Calculates the back-off time.
*
* \param [in] calcBackOff A pointer to the function parameters.
*/
virtual void calculate_backoff(CalcBackOffParams_t* calcBackOff );
/*!
* \brief Searches and sets the next random available channel.
*
* \param [in] nextChanParams The parameters for the next channel
*
* \param [out] channel The next channel to use for TX.
*
* \param [out] time The time to wait for the next transmission according to the duty
* cycle.
*
* \param [out] aggregatedTimeOff Updates the aggregated time off.
*
* \retval Function status [1: OK, 0: Unable to find a channel on the current datarate].
*/
virtual bool set_next_channel(NextChanParams_t* nextChanParams,
uint8_t* channel, TimerTime_t* time,
TimerTime_t* aggregatedTimeOff );
/*!
* \brief Adds a channel.
*
* \param [in] channelAdd A pointer to the function parameters.
*
* \retval The status of the operation.
*/
virtual LoRaMacStatus_t add_channel(ChannelAddParams_t* channelAdd );
/*!
* \brief Removes a channel.
*
* \param [in] channelRemove A pointer to the function parameters.
*
* \retval True, if the channel was removed successfully.
*/
virtual bool remove_channel(ChannelRemoveParams_t* channelRemove );
/*!
* \brief Sets the radio into continuous wave mode.
*
* \param [in] continuousWave A pointer to the function parameters.
*/
virtual void set_tx_cont_mode(ContinuousWaveParams_t* continuousWave );
/*!
* \brief Computes new datarate according to the given offset.
*
* \param [in] downlinkDwellTime The downlink dwell time configuration. 0: No limit, 1: 400ms
*
* \param [in] dr The current datarate.
*
* \param [in] drOffset The offset to be applied.
*
* \retval newDr The computed datarate.
*/
virtual uint8_t apply_DR_offset(uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
private: private:
uint8_t CountNbOfEnabledChannels( bool joined, uint8_t datarate, uint16_t* channelsMask, ChannelParams_t* channels, Band_t* bands, uint8_t* enabledChannels, uint8_t* delayTx );
// Global attributes
/*! /*!
* LoRaMAC channels * LoRaMAC channels
*/ */
ChannelParams_t Channels[EU433_MAX_NB_CHANNELS]; channel_params_t channels[EU433_MAX_NB_CHANNELS];
/*! /*!
* LoRaMac bands * LoRaMac bands
*/ */
Band_t Bands[EU433_MAX_NB_BANDS]; band_t bands[EU433_MAX_NB_BANDS];
/*! /*!
* LoRaMac channels mask * LoRaMac channel mask
*/ */
uint16_t ChannelsMask[EU433_CHANNELS_MASK_SIZE]; uint16_t channel_mask[EU433_CHANNEL_MASK_SIZE];
/*! /*!
* LoRaMac channels default mask * LoRaMac default channel mask
*/ */
uint16_t ChannelsDefaultMask[EU433_CHANNELS_MASK_SIZE]; uint16_t default_channel_mask[EU433_CHANNEL_MASK_SIZE];
}; };

File diff suppressed because it is too large Load Diff

View File

@ -33,7 +33,6 @@
#define MBED_OS_LORAPHY_EU868_H_ #define MBED_OS_LORAPHY_EU868_H_
#include "LoRaPHY.h" #include "LoRaPHY.h"
#include "netsocket/LoRaRadio.h"
/*! /*!
* LoRaMac maximum number of channels * LoRaMac maximum number of channels
@ -42,317 +41,42 @@
/*! /*!
* Maximum number of bands * Maximum number of bands
*
* We have broken down EU-868 MHz BAND 2 into two parts. That's why
* total number of sub-bands is 6.
* from 863 MHz to 865 MHz region is part of BAND 2, however
* we call it Band-5 here. Duty cycle limit is 0.1 % in this sub band.
*/ */
#define EU868_MAX_NB_BANDS 5 #define EU868_MAX_NB_BANDS 6
#define EU868_CHANNELS_MASK_SIZE 1
#define EU868_CHANNEL_MASK_SIZE 1
class LoRaPHYEU868 : public LoRaPHY { class LoRaPHYEU868 : public LoRaPHY {
public: public:
LoRaPHYEU868(); LoRaPHYEU868(LoRaWANTimeHandler &lora_time);
virtual ~LoRaPHYEU868(); virtual ~LoRaPHYEU868();
/*!
* \brief The function gets a value of a specific PHY attribute.
*
* \param [in] getPhy A pointer to the function parameters.
*
* \retval The structure containing the PHY parameter.
*/
virtual PhyParam_t get_phy_params(GetPhyParams_t* getPhy );
/*!
* \brief Updates the last TX done parameters of the current channel.
*
* \param [in] txDone A pointer to the function parameters.
*/
virtual void set_band_tx_done(SetBandTxDoneParams_t* txDone );
/*!
* \brief Initializes the channels masks and the channels.
*
* \param [in] type Sets the initialization type.
*/
virtual void load_defaults(InitType_t type );
/*!
* \brief Verifies a parameter.
*
* \param [in] verify A pointer to the function parameters.
*
* \param [in] phyAttribute The attribute to verify.
*
* \retval True, if the parameter is valid.
*/
virtual bool verify(VerifyParams_t* verify, PhyAttribute_t phyAttribute );
/*!
* \brief The function parses the input buffer and sets up the channels of the CF list.
*
* \param [in] applyCFList A pointer to the function parameters.
*/
virtual void apply_cf_list(ApplyCFListParams_t* applyCFList );
/*!
* \brief Sets a channels mask.
*
* \param [in] chanMaskSet A pointer to the function parameters.
*
* \retval True, if the channels mask could be set.
*/
virtual bool set_channel_mask(ChanMaskSetParams_t* chanMaskSet );
/*!
* \brief Calculates the next datarate to set, when ADR is on or off.
*
* \param [in] adrNext A pointer to the function parameters.
*
* \param [out] drOut The calculated datarate for the next TX.
*
* \param [out] txPowOut The TX power for the next TX.
*
* \param [out] adrAckCounter The calculated ADR acknowledgement counter.
*
* \retval True, if an ADR request should be performed.
*/
virtual bool get_next_ADR(AdrNextParams_t* adrNext, int8_t* drOut,
int8_t* txPowOut, uint32_t* adrAckCounter );
/*!
* \brief Configuration of the RX windows.
*
* \param [in] rxConfig A pointer to the function parameters.
*
* \param [out] datarate The datarate index set.
*
* \retval True, if the configuration was applied successfully.
*/
virtual bool rx_config(RxConfigParams_t* rxConfig, int8_t* datarate );
/*
* RX window precise timing
*
* For more details please consult the following document, chapter 3.1.2.
* http://www.semtech.com/images/datasheet/SX1272_settings_for_LoRaWAN_v2.0.pdf
* or
* http://www.semtech.com/images/datasheet/SX1276_settings_for_LoRaWAN_v2.0.pdf
*
* Downlink start: T = Tx + 1s (+/- 20 us)
* |
* TRxEarly | TRxLate
* | | |
* | | +---+---+---+---+---+---+---+---+
* | | | Latest Rx window |
* | | +---+---+---+---+---+---+---+---+
* | | |
* +---+---+---+---+---+---+---+---+
* | Earliest Rx window |
* +---+---+---+---+---+---+---+---+
* |
* +---+---+---+---+---+---+---+---+
*Downlink preamble 8 symbols | | | | | | | | |
* +---+---+---+---+---+---+---+---+
*
* Worst case Rx window timings
*
* TRxLate = DEFAULT_MIN_RX_SYMBOLS * tSymbol - RADIO_WAKEUP_TIME
* TRxEarly = 8 - DEFAULT_MIN_RX_SYMBOLS * tSymbol - RxWindowTimeout - RADIO_WAKEUP_TIME
*
* TRxLate - TRxEarly = 2 * DEFAULT_SYSTEM_MAX_RX_ERROR
*
* RxOffset = ( TRxLate + TRxEarly ) / 2
*
* RxWindowTimeout = ( 2 * DEFAULT_MIN_RX_SYMBOLS - 8 ) * tSymbol + 2 * DEFAULT_SYSTEM_MAX_RX_ERROR
* RxOffset = 4 * tSymbol - RxWindowTimeout / 2 - RADIO_WAKE_UP_TIME
*
* The minimum value of RxWindowTimeout must be 5 symbols which implies that the system always tolerates at least an error of 1.5 * tSymbol
*/
/*!
* Computes the RX window timeout and offset.
*
* \param [in] datarate The RX window datarate index to be used.
*
* \param [in] minRxSymbols The minimum number of symbols required to detect an RX frame.
*
* \param [in] rxError The system maximum timing error of the receiver in milliseconds.
* The receiver will turn on in a [-rxError : +rxError] ms
* interval around RxOffset.
*
* \param [out] rxConfigParams Returns the updated WindowTimeout and WindowOffset fields.
*/
virtual void compute_rx_win_params(int8_t datarate,
uint8_t minRxSymbols,
uint32_t rxError,
RxConfigParams_t *rxConfigParams);
/*!
* \brief TX configuration.
*
* \param [in] txConfig A pointer to the function parameters.
*
* \param [out] txPower The TX power index set.
*
* \param [out] txTimeOnAir The time-on-air of the frame.
*
* \retval True, if the configuration was applied successfully.
*/
virtual bool tx_config(TxConfigParams_t* txConfig, int8_t* txPower,
TimerTime_t* txTimeOnAir );
/*!
* \brief The function processes a Link ADR request.
*
* \param [in] linkAdrReq A pointer to the function parameters.
*
* \param [out] drOut The datarate applied.
*
* \param [out] txPowOut The TX power applied.
*
* \param [out] nbRepOut The number of repetitions to apply.
*
* \param [out] nbBytesParsed The number of bytes parsed.
*
* \retval The status of the operation, according to the LoRaMAC specification.
*/
virtual uint8_t link_ADR_request(LinkAdrReqParams_t* linkAdrReq,
int8_t* drOut, int8_t* txPowOut,
uint8_t* nbRepOut,
uint8_t* nbBytesParsed );
/*!
* \brief The function processes a RX parameter setup request.
*
* \param [in] rxParamSetupReq A pointer to the function parameters.
*
* \retval The status of the operation, according to the LoRaMAC specification.
*/
virtual uint8_t setup_rx_params(RxParamSetupReqParams_t* rxParamSetupReq );
/*!
* \brief The function processes a new channel request.
*
* \param [in] newChannelReq A pointer to the function parameters.
*
* \retval The status of the operation, according to the LoRaMAC specification.
*/
virtual uint8_t request_new_channel(NewChannelReqParams_t* newChannelReq );
/*!
* \brief The function processes a TX ParamSetup request.
*
* \param [in] txParamSetupReq A pointer to the function parameters.
*
* \retval The status of the operation, according to the LoRaMAC specification.
* Returns -1, if the functionality is not implemented. In this case, the end node
* shall ignore the command.
*/
virtual int8_t setup_tx_params(TxParamSetupReqParams_t* txParamSetupReq );
/*!
* \brief The function processes a DlChannel request.
*
* \param [in] dlChannelReq A pointer to the function parameters.
*
* \retval The status of the operation, according to the LoRaMAC specification.
*/
virtual uint8_t dl_channel_request(DlChannelReqParams_t* dlChannelReq );
/*!
* \brief Alternates the datarate of the channel for the join request.
*
* \param [in] alternateDr A pointer to the function parameters.
*
* \retval The datarate to apply.
*/
virtual int8_t get_alternate_DR(AlternateDrParams_t* alternateDr );
/*!
* \brief Calculates the back-off time.
*
* \param [in] calcBackOff A pointer to the function parameters.
*/
virtual void calculate_backoff(CalcBackOffParams_t* calcBackOff );
/*!
* \brief Searches and sets the next random available channel.
*
* \param [in] nextChanParams The parameters for the next channel.
*
* \param [out] channel The next channel to use for TX.
*
* \param [out] time The time to wait for the next transmission according to the duty cycle.
*
* \param [out] aggregatedTimeOff Updates the aggregated time off.
*
* \retval The function status [1: OK, 0: Unable to find a channel on the current datarate].
*/
virtual bool set_next_channel(NextChanParams_t* nextChanParams,
uint8_t* channel, TimerTime_t* time,
TimerTime_t* aggregatedTimeOff );
/*!
* \brief Adds a channel.
*
* \param [in] channelAdd A pointer to the function parameters.
*
* \retval The status of the operation.
*/
virtual LoRaMacStatus_t add_channel(ChannelAddParams_t* channelAdd );
/*!
* \brief Removes a channel.
*
* \param [in] channelRemove A pointer to the function parameters.
*
* \retval True, if the channel was removed successfully.
*/
virtual bool remove_channel(ChannelRemoveParams_t* channelRemove );
/*!
* \brief Sets the radio into continuous wave mode.
*
* \param [in] continuousWave A pointer to the function parameters.
*/
virtual void set_tx_cont_mode(ContinuousWaveParams_t* continuousWave );
/*!
* \brief Computes a new datarate according to the given offset.
*
* \param [in] downlinkDwellTime The downlink dwell time configuration. 0: No limit, 1: 400ms
*
* \param [in] dr The current datarate.
*
* \param [in] drOffset The offset to be applied.
*
* \retval newDr The computed datarate.
*/
virtual uint8_t apply_DR_offset(uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
private: private:
uint8_t CountNbOfEnabledChannels( bool joined, uint8_t datarate, uint16_t* channelsMask, ChannelParams_t* channels, Band_t* bands, uint8_t* enabledChannels, uint8_t* delayTx );
// Global attributes
/*! /*!
* LoRaMAC channels * LoRaMAC channels
*/ */
ChannelParams_t Channels[EU868_MAX_NB_CHANNELS]; channel_params_t channels[EU868_MAX_NB_CHANNELS];
/*! /*!
* LoRaMac bands * LoRaMac bands
*/ */
Band_t Bands[EU868_MAX_NB_BANDS]; band_t bands[EU868_MAX_NB_BANDS];
/*! /*!
* LoRaMac channels mask * LoRaMac channels mask
*/ */
uint16_t ChannelsMask[EU868_CHANNELS_MASK_SIZE]; uint16_t channel_mask[EU868_CHANNEL_MASK_SIZE];
/*! /*!
* LoRaMac channels default mask * LoRaMac default channel mask
*/ */
uint16_t ChannelsDefaultMask[EU868_CHANNELS_MASK_SIZE]; uint16_t default_channel_mask[EU868_CHANNEL_MASK_SIZE];
}; };
#endif /* MBED_OS_LORAPHY_EU868_H_ */ #endif /* MBED_OS_LORAPHY_EU868_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -33,7 +33,6 @@
#define MBED_OS_LORAPHY_IN865_H_ #define MBED_OS_LORAPHY_IN865_H_
#include "LoRaPHY.h" #include "LoRaPHY.h"
#include "netsocket/LoRaRadio.h"
/*! /*!
@ -46,316 +45,38 @@
*/ */
#define IN865_MAX_NB_BANDS 1 #define IN865_MAX_NB_BANDS 1
#define IN865_CHANNEL_MASK_SIZE 1
#define IN865_CHANNELS_MASK_SIZE 1
class LoRaPHYIN865 : public LoRaPHY { class LoRaPHYIN865 : public LoRaPHY {
public: public:
LoRaPHYIN865(); LoRaPHYIN865(LoRaWANTimeHandler &lora_time);
virtual ~LoRaPHYIN865(); virtual ~LoRaPHYIN865();
/*! virtual uint8_t apply_DR_offset(int8_t dr, int8_t dr_offset );
* \brief The function gets a value of a specific PHY attribute.
*
* \param [in] getPhy A pointer to the function parameters.
*
* \retval The structure containing the PHY parameter.
*/
virtual PhyParam_t get_phy_params(GetPhyParams_t* getPhy );
/*!
* \brief Updates the last TX done parameters of the current channel.
*
* \param [in] txDone A pointer to the function parameters.
*/
virtual void set_band_tx_done(SetBandTxDoneParams_t* txDone );
/*!
* \brief Initializes the channels masks and the channels.
*
* \param [in] type Sets the initialization type.
*/
virtual void load_defaults(InitType_t type );
/*!
* \brief Verifies a parameter.
*
* \param [in] verify A pointer to the function parameters.
*
* \param [in] phyAttribute The attribute to verify.
*
* \retval True, if the parameter is valid.
*/
virtual bool verify(VerifyParams_t* verify, PhyAttribute_t phyAttribute );
/*!
* \brief The function parses the input buffer and sets up the channels of the CF list.
*
* \param [in] applyCFList A pointer to the function parameters.
*/
virtual void apply_cf_list(ApplyCFListParams_t* applyCFList );
/*!
* \brief Sets a channels mask.
*
* \param [in] chanMaskSet A pointer to the function parameters.
*
* \retval True, if the channels mask could be set.
*/
virtual bool set_channel_mask(ChanMaskSetParams_t* chanMaskSet );
/*!
* \brief Calculates the next datarate to set, when ADR is on or off.
*
* \param [in] adrNext A pointer to the function parameters.
*
* \param [out] drOut The calculated datarate for the next TX.
*
* \param [out] txPowOut The TX power for the next TX.
*
* \param [out] adrAckCounter The calculated ADR acknowledgement counter.
*
* \retval True, if an ADR request should be performed.
*/
virtual bool get_next_ADR(AdrNextParams_t* adrNext, int8_t* drOut,
int8_t* txPowOut, uint32_t* adrAckCounter );
/*!
* \brief Configuration of the RX windows.
*
* \param [in] rxConfig A pointer to the function parameters.
*
* \param [out] datarate The datarate index set.
*
* \retval True, if the configuration was applied successfully.
*/
virtual bool rx_config(RxConfigParams_t* rxConfig, int8_t* datarate );
/*
* RX window precise timing
*
* For more details, please consult the following document, chapter 3.1.2.
* http://www.semtech.com/images/datasheet/SX1272_settings_for_LoRaWAN_v2.0.pdf
* or
* http://www.semtech.com/images/datasheet/SX1276_settings_for_LoRaWAN_v2.0.pdf
*
* Downlink start: T = Tx + 1s (+/- 20 us)
* |
* TRxEarly | TRxLate
* | | |
* | | +---+---+---+---+---+---+---+---+
* | | | Latest Rx window |
* | | +---+---+---+---+---+---+---+---+
* | | |
* +---+---+---+---+---+---+---+---+
* | Earliest Rx window |
* +---+---+---+---+---+---+---+---+
* |
* +---+---+---+---+---+---+---+---+
*Downlink preamble 8 symbols | | | | | | | | |
* +---+---+---+---+---+---+---+---+
*
* Worst case Rx window timings
*
* TRxLate = DEFAULT_MIN_RX_SYMBOLS * tSymbol - RADIO_WAKEUP_TIME
* TRxEarly = 8 - DEFAULT_MIN_RX_SYMBOLS * tSymbol - RxWindowTimeout - RADIO_WAKEUP_TIME
*
* TRxLate - TRxEarly = 2 * DEFAULT_SYSTEM_MAX_RX_ERROR
*
* RxOffset = ( TRxLate + TRxEarly ) / 2
*
* RxWindowTimeout = ( 2 * DEFAULT_MIN_RX_SYMBOLS - 8 ) * tSymbol + 2 * DEFAULT_SYSTEM_MAX_RX_ERROR
* RxOffset = 4 * tSymbol - RxWindowTimeout / 2 - RADIO_WAKE_UP_TIME
*
* The minimum value of RxWindowTimeout must be 5 symbols which implies that the system always tolerates at least an error of 1.5 * tSymbol
*/
/*!
* Computes the RX window timeout and offset.
*
* \param [in] datarate The RX window datarate index to be used.
*
* \param [in] minRxSymbols The minimum number of symbols required to detect an RX frame.
*
* \param [in] rxError The system maximum timing error of the receiver in milliseconds.
* The receiver will turn on in a [-rxError : +rxError] ms
* interval around RxOffset.
*
* \param [out] rxConfigParams Returns the updated WindowTimeout and WindowOffset fields.
*/
virtual void compute_rx_win_params(int8_t datarate,
uint8_t minRxSymbols,
uint32_t rxError,
RxConfigParams_t *rxConfigParams);
/*!
* \brief TX configuration.
*
* \param [in] txConfig A pointer to the function parameters.
*
* \param [out] txPower The TX power index set.
*
* \param [out] txTimeOnAir The time-on-air of the frame.
*
* \retval True, if the configuration was applied successfully.
*/
virtual bool tx_config(TxConfigParams_t* txConfig, int8_t* txPower,
TimerTime_t* txTimeOnAir );
/*!
* \brief The function processes a Link ADR request.
*
* \param [in] linkAdrReq A pointer to the function parameters.
*
* \param [out] drOut The datarate applied.
*
* \param [out] txPowOut The TX power applied.
*
* \param [out] nbRepOut The number of repetitions to apply.
*
* \param [out] nbBytesParsed The number of bytes parsed.
*
* \retval The status of the operation, according to the LoRaMAC specification.
*/
virtual uint8_t link_ADR_request(LinkAdrReqParams_t* linkAdrReq,
int8_t* drOut, int8_t* txPowOut,
uint8_t* nbRepOut,
uint8_t* nbBytesParsed );
/*!
* \brief The function processes a RX parameter setup request.
*
* \param [in] rxParamSetupReq A pointer to the function parameters.
*
* \retval The status of the operation, according to the LoRaMAC specification.
*/
virtual uint8_t setup_rx_params(RxParamSetupReqParams_t* rxParamSetupReq );
/*!
* \brief The function processes a new channel request.
*
* \param [in] newChannelReq A pointer to the function parameters.
*
* \retval The status of the operation, according to the LoRaMAC specification.
*/
virtual uint8_t request_new_channel(NewChannelReqParams_t* newChannelReq );
/*!
* \brief The function processes a TX ParamSetup request.
*
* \param [in] txParamSetupReq A pointer to the function parameters.
*
* \retval The status of the operation, according to the LoRaMAC specification.
* Returns -1, if the functionality is not implemented. In this case, the end node
* shall ignore the command.
*/
virtual int8_t setup_tx_params(TxParamSetupReqParams_t* txParamSetupReq );
/*!
* \brief The function processes a DlChannel request.
*
* \param [in] dlChannelReq A pointer to the function parameters.
*
* \retval The status of the operation, according to the LoRaMAC specification.
*/
virtual uint8_t dl_channel_request(DlChannelReqParams_t* dlChannelReq );
/*!
* \brief Alternates the datarate of the channel for the join request.
*
* \param [in] alternateDr A pointer to the function parameters.
*
* \retval The datarate to apply.
*/
virtual int8_t get_alternate_DR(AlternateDrParams_t* alternateDr );
/*!
* \brief Calculates the back-off time.
*
* \param [in] calcBackOff A pointer to the function parameters.
*/
virtual void calculate_backoff(CalcBackOffParams_t* calcBackOff );
/*!
* \brief Searches and sets the next random available channel.
*
* \param [in] nextChanParams The parameters for the next channel.
*
* \param [out] channel The next channel to use for TX.
*
* \param [out] time The time to wait for the next transmission according to the duty cycle.
*
* \param [out] aggregatedTimeOff Updates the aggregated time off.
*
* \retval The function status [1: OK, 0: Unable to find a channel on the current datarate].
*/
virtual bool set_next_channel(NextChanParams_t* nextChanParams,
uint8_t* channel, TimerTime_t* time,
TimerTime_t* aggregatedTimeOff );
/*!
* \brief Adds a channel.
*
* \param [in] channelAdd A pPointer to the function parameters.
*
* \retval The status of the operation.
*/
virtual LoRaMacStatus_t add_channel(ChannelAddParams_t* channelAdd );
/*!
* \brief Removes a channel.
*
* \param [in] channelRemove A pointer to the function parameters.
*
* \retval True, if the channel was removed successfully.
*/
virtual bool remove_channel(ChannelRemoveParams_t* channelRemove );
/*!
* \brief Sets the radio into continuous wave mode.
*
* \param [in] continuousWave A pointer to the function parameters.
*/
virtual void set_tx_cont_mode(ContinuousWaveParams_t* continuousWave );
/*!
* \brief Computes a new datarate according to the given offset.
*
* \param [in] downlinkDwellTime The downlink dwell time configuration. 0: No limit, 1: 400ms
*
* \param [in] dr The current datarate.
*
* \param [in] drOffset The offset to be applied.
*
* \retval newDr The computed datarate.
*/
virtual uint8_t apply_DR_offset(uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
private: private:
uint8_t CountNbOfEnabledChannels( bool joined, uint8_t datarate, uint16_t* channelsMask, ChannelParams_t* channels, Band_t* bands, uint8_t* enabledChannels, uint8_t* delayTx );
// Global attributes
/*! /*!
* LoRaMAC channels * LoRaMAC channels
*/ */
ChannelParams_t Channels[IN865_MAX_NB_CHANNELS]; channel_params_t channels[IN865_MAX_NB_CHANNELS];
/*! /*!
* LoRaMac bands * LoRaMac bands
*/ */
Band_t Bands[IN865_MAX_NB_BANDS]; band_t bands[IN865_MAX_NB_BANDS];
/*! /*!
* LoRaMac channels mask * LoRaMac channel mask
*/ */
uint16_t ChannelsMask[IN865_CHANNELS_MASK_SIZE]; uint16_t channel_mask[IN865_CHANNEL_MASK_SIZE];
/*! /*!
* LoRaMac channels default mask * LoRaMac default channel mask
*/ */
uint16_t ChannelsDefaultMask[IN865_CHANNELS_MASK_SIZE]; uint16_t default_channel_mask[IN865_CHANNEL_MASK_SIZE];
}; };
#endif /* MBED_OS_LORAPHY_IN865_H_ */ #endif /* MBED_OS_LORAPHY_IN865_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -33,7 +33,6 @@
#define MBED_OS_LORAPHY_KR920_H_ #define MBED_OS_LORAPHY_KR920_H_
#include "LoRaPHY.h" #include "LoRaPHY.h"
#include "netsocket/LoRaRadio.h"
/*! /*!
* LoRaMac maximum number of channels * LoRaMac maximum number of channels
@ -45,314 +44,52 @@
*/ */
#define KR920_MAX_NB_BANDS 1 #define KR920_MAX_NB_BANDS 1
#define KR920_CHANNELS_MASK_SIZE 1 #define KR920_CHANNEL_MASK_SIZE 1
class LoRaPHYKR920 : public LoRaPHY { class LoRaPHYKR920 : public LoRaPHY {
public: public:
LoRaPHYKR920(); LoRaPHYKR920(LoRaWANTimeHandler &lora_time);
virtual ~LoRaPHYKR920(); virtual ~LoRaPHYKR920();
/*! virtual bool verify_frequency(uint32_t freq);
* \brief The function gets a value of a specific PHY attribute.
*
* \param [in] getPhy A pointer to the function parameters.
*
* \retval The structure containing the PHY parameter.
*/
virtual PhyParam_t get_phy_params(GetPhyParams_t* getPhy );
/*! virtual bool tx_config(tx_config_params_t* config, int8_t* tx_power,
* \brief Updates the last TX done parameters of the current channel. lorawan_time_t* tx_toa);
*
* \param [in] txDone A pointer to the function parameters.
*/
virtual void set_band_tx_done(SetBandTxDoneParams_t* txDone );
/*! virtual bool set_next_channel(channel_selection_params_t* params, uint8_t* channel,
* \brief Initializes the channels masks and the channels. lorawan_time_t* time,
* lorawan_time_t* aggregate_timeOff);
* \param [in] type Sets the initialization type.
*/
virtual void load_defaults(InitType_t type );
/*! virtual void set_tx_cont_mode(cw_mode_params_t* continuousWave,
* \brief Verifies a parameter. uint32_t frequency = 0);
*
* \param [in] verify A pointer to the function parameters.
*
* \param [in] phyAttribute The attribute to verify.
*
* \retval True, if the parameter is valid.
*/
virtual bool verify(VerifyParams_t* verify, PhyAttribute_t phyAttribute );
/*!
* \brief The function parses the input buffer and sets up the channels of the CF list.
*
* \param [in] applyCFList A pointer to the function parameters.
*/
virtual void apply_cf_list(ApplyCFListParams_t* applyCFList );
/*! private:
* \brief Sets a channels mask.
*
* \param [in] chanMaskSet A pointer to the function parameters.
*
* \retval True, if the channels mask could be set.
*/
virtual bool set_channel_mask(ChanMaskSetParams_t* chanMaskSet );
/*! int8_t get_max_eirp(uint32_t freq);
* \brief Calculates the next datarate to set, when ADR is on or off.
*
* \param [in] adrNext A pointer to the function parameters.
*
* \param [out] drOut The calculated datarate for the next TX.
*
* \param [out] txPowOut The TX power for the next TX.
*
* \param [out] adrAckCounter The calculated ADR acknowledgement counter.
*
* \retval True, if an ADR request should be performed.
*/
virtual bool get_next_ADR(AdrNextParams_t* adrNext, int8_t* drOut,
int8_t* txPowOut, uint32_t* adrAckCounter );
/*! /**
* \brief Configuration of the RX windows.
*
* \param [in] rxConfig A pointer to the function parameters.
*
* \param [out] datarate The datarate index set.
*
* \retval True, if the configuration was applied successfully.
*/
virtual bool rx_config(RxConfigParams_t* rxConfig, int8_t* datarate );
/*
* RX window precise timing
*
* For more details, please consult the following document, chapter 3.1.2.
* http://www.semtech.com/images/datasheet/SX1272_settings_for_LoRaWAN_v2.0.pdf
* or
* http://www.semtech.com/images/datasheet/SX1276_settings_for_LoRaWAN_v2.0.pdf
*
* Downlink start: T = Tx + 1s (+/- 20 us)
* |
* TRxEarly | TRxLate
* | | |
* | | +---+---+---+---+---+---+---+---+
* | | | Latest Rx window |
* | | +---+---+---+---+---+---+---+---+
* | | |
* +---+---+---+---+---+---+---+---+
* | Earliest Rx window |
* +---+---+---+---+---+---+---+---+
* |
* +---+---+---+---+---+---+---+---+
*Downlink preamble 8 symbols | | | | | | | | |
* +---+---+---+---+---+---+---+---+
*
* Worst case Rx window timings
*
* TRxLate = DEFAULT_MIN_RX_SYMBOLS * tSymbol - RADIO_WAKEUP_TIME
* TRxEarly = 8 - DEFAULT_MIN_RX_SYMBOLS * tSymbol - RxWindowTimeout - RADIO_WAKEUP_TIME
*
* TRxLate - TRxEarly = 2 * DEFAULT_SYSTEM_MAX_RX_ERROR
*
* RxOffset = ( TRxLate + TRxEarly ) / 2
*
* RxWindowTimeout = ( 2 * DEFAULT_MIN_RX_SYMBOLS - 8 ) * tSymbol + 2 * DEFAULT_SYSTEM_MAX_RX_ERROR
* RxOffset = 4 * tSymbol - RxWindowTimeout / 2 - RADIO_WAKE_UP_TIME
*
* The minimum value of RxWindowTimeout must be 5 symbols which implies that the system always tolerates at least an error of 1.5 * tSymbol
*/
/*!
* Computes the RX window timeout and offset.
*
* \param [in] datarate The RX window datarate index to be used.
*
* \param [in] minRxSymbols The minimum number of symbols required to detect an RX frame.
*
* \param [in] rxError The system maximum timing error of the receiver in milliseconds.
* The receiver will turn on in a [-rxError : +rxError] ms
* interval around RxOffset.
*
* \param [out] rxConfigParams Returns the updated WindowTimeout and WindowOffset fields.
*/
virtual void compute_rx_win_params(int8_t datarate,
uint8_t minRxSymbols,
uint32_t rxError,
RxConfigParams_t *rxConfigParams);
/*!
* \brief TX configuration.
*
* \param [in] txConfig A pointer to the function parameters.
*
* \param [out] txPower The TX power index set.
*
* \param [out] txTimeOnAir The time-on-air of the frame.
*
* \retval True, if the configuration was applied successfully.
*/
virtual bool tx_config(TxConfigParams_t* txConfig, int8_t* txPower,
TimerTime_t* txTimeOnAir );
/*!
* \brief The function processes a Link ADR request.
*
* \param [in] linkAdrReq A pointer to the function parameters.
*
* \param [out] drOut The datarate applied.
*
* \param [out] txPowOut The TX power applied.
*
* \param [out] nbRepOut The number of repetitions to apply.
*
* \param [out] nbBytesParsed The number of bytes parsed.
*
* \retval The status of the operation, according to the LoRaMAC specification.
*/
virtual uint8_t link_ADR_request(LinkAdrReqParams_t* linkAdrReq,
int8_t* drOut, int8_t* txPowOut,
uint8_t* nbRepOut,
uint8_t* nbBytesParsed );
/*!
* \brief The function processes a RX parameter setup request.
*
* \param [in] rxParamSetupReq A pointer to the function parameters.
*
* \retval The status of the operation, according to the LoRaMAC specification.
*/
virtual uint8_t setup_rx_params(RxParamSetupReqParams_t* rxParamSetupReq );
/*!
* \brief The function processes a new channel request.
*
* \param [in] newChannelReq A pointer to the function parameters.
*
* \retval The status of the operation, according to the LoRaMAC specification.
*/
virtual uint8_t request_new_channel(NewChannelReqParams_t* newChannelReq );
/*!
* \brief The function processes a TX ParamSetup request.
*
* \param [in] txParamSetupReq A pointer to the function parameters.
*
* \retval The status of the operation, according to the LoRaMAC specification.
* Returns -1, if the functionality is not implemented. In this case, the end node
* shall ignore the command.
*/
virtual int8_t setup_tx_params(TxParamSetupReqParams_t* txParamSetupReq );
/*!
* \brief The function processes a DlChannel request.
*
* \param [in] dlChannelReq A pointer to the function parameters.
*
* \retval The status of the operation, according to the LoRaMAC specification.
*/
virtual uint8_t dl_channel_request(DlChannelReqParams_t* dlChannelReq );
/*!
* \brief Alternates the datarate of the channel for the join request.
*
* \param [in] alternateDr A pointer to the function parameters.
*
* \retval The datarate to apply.
*/
virtual int8_t get_alternate_DR(AlternateDrParams_t* alternateDr );
/*!
* \brief Calculates the back-off time.
*
* \param [in] calcBackOff A pointer to the function parameters.
*/
virtual void calculate_backoff(CalcBackOffParams_t* calcBackOff );
/*!
* \brief Searches and sets the next random available channel.
*
* \param [in] nextChanParams The parameters for the next channel.
*
* \param [out] channel The next channel to use for TX.
*
* \param [out] time The time to wait for the next transmission according to the duty cycle.
*
* \param [out] aggregatedTimeOff Updates the aggregated time off.
*
* \retval The function status [1: OK, 0: Unable to find a channel on the current datarate].
*/
virtual bool set_next_channel(NextChanParams_t* nextChanParams,
uint8_t* channel, TimerTime_t* time,
TimerTime_t* aggregatedTimeOff );
/*!
* \brief Adds a channel.
*
* \param [in] channelAdd A pointer to the function parameters.
*
* \retval The status of the operation.
*/
virtual LoRaMacStatus_t add_channel(ChannelAddParams_t* channelAdd );
/*!
* \brief Removes a channel.
*
* \param [in] channelRemove A pointer to the function parameters.
*
* \retval True, if the channel was removed successfully.
*/
virtual bool remove_channel(ChannelRemoveParams_t* channelRemove );
/*!
* \brief Sets the radio into continuous wave mode.
*
* \param [in] continuousWave A pointer to the function parameters.
*/
virtual void set_tx_cont_mode(ContinuousWaveParams_t* continuousWave );
/*!
* \brief Computes new datarate according to the given offset.
*
* \param [in] downlinkDwellTime The downlink dwell time configuration. 0: No limit, 1: 400ms
*
* \param [in] dr The current datarate.
*
* \param [in] drOffset The offset to be applied.
*
* \retval newDr The computed datarate.
*/
virtual uint8_t apply_DR_offset(uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
uint8_t CountNbOfEnabledChannels( bool joined, uint8_t datarate, uint16_t* channelsMask, ChannelParams_t* channels, Band_t* bands, uint8_t* enabledChannels, uint8_t* delayTx );
// Global attributes
/*!
* LoRaMAC channels * LoRaMAC channels
*/ */
ChannelParams_t Channels[KR920_MAX_NB_CHANNELS]; channel_params_t channels[KR920_MAX_NB_CHANNELS];
/*! /**
* LoRaMac bands * LoRaMac bands
*/ */
Band_t Bands[KR920_MAX_NB_BANDS]; band_t bands[KR920_MAX_NB_BANDS];
/*! /**
* LoRaMac channels mask * LoRaMac channel mask
*/ */
uint16_t ChannelsMask[KR920_CHANNELS_MASK_SIZE]; uint16_t channel_mask[KR920_CHANNEL_MASK_SIZE];
/*! /**
* LoRaMac channels default mask * LoRaMac default channel mask
*/ */
uint16_t ChannelsDefaultMask[KR920_CHANNELS_MASK_SIZE]; uint16_t default_channel_mask[KR920_CHANNEL_MASK_SIZE];
}; };
#endif // MBED_OS_LORAPHY_KR920_H_ #endif // MBED_OS_LORAPHY_KR920_H_

File diff suppressed because it is too large Load Diff

View File

@ -33,7 +33,6 @@
#define MBED_OS_LORAPHYUS_915_H_ #define MBED_OS_LORAPHYUS_915_H_
#include "LoRaPHY.h" #include "LoRaPHY.h"
#include "netsocket/LoRaRadio.h"
/*! /*!
* LoRaMac maximum number of channels * LoRaMac maximum number of channels
@ -45,321 +44,69 @@
*/ */
#define US915_MAX_NB_BANDS 1 #define US915_MAX_NB_BANDS 1
#define US915_CHANNELS_MASK_SIZE 6 #define US915_CHANNEL_MASK_SIZE 5
class LoRaPHYUS915 : public LoRaPHY { class LoRaPHYUS915 : public LoRaPHY {
public: public:
LoRaPHYUS915(); LoRaPHYUS915(LoRaWANTimeHandler &lora_time);
virtual ~LoRaPHYUS915(); virtual ~LoRaPHYUS915();
/*! virtual void restore_default_channels();
* \brief The function gets a value of a specific PHY attribute.
*
* \param [in] getPhy A pointer to the function parameters.
*
* \retval The structure containing the PHY parameter.
*/
virtual PhyParam_t get_phy_params(GetPhyParams_t* getPhy );
/*! virtual bool rx_config(rx_config_params_t* config, int8_t* datarate);
* \brief Updates the last TX done parameters of the current channel.
*
* \param [in] txDone A pointer to the function parameters.
*/
virtual void set_band_tx_done(SetBandTxDoneParams_t* txDone );
/*! virtual bool tx_config(tx_config_params_t* config, int8_t* tx_power,
* \brief Initializes the channels masks and the channels. lorawan_time_t* tx_toa);
*
* \param [in] type Sets the initialization type.
*/
virtual void load_defaults(InitType_t type );
/*! virtual uint8_t link_ADR_request(adr_req_params_t* params,
* \brief Verifies a parameter. int8_t* dr_out, int8_t* tx_power_out,
* uint8_t* nb_rep_out,
* \param [in] verify A pointer to the function parameters. uint8_t* nb_bytes_parsed);
*
* \param [in] phyAttribute The attribute to verify.
*
* \retval True, if the parameter is valid.
*/
virtual bool verify(VerifyParams_t* verify, PhyAttribute_t phyAttribute );
/*! virtual uint8_t accept_rx_param_setup_req(rx_param_setup_req_t* params);
* \brief The function parses the input buffer and sets up the channels of the CF list.
*
* \param [in] applyCFList A pointer to the function parameters.
*/
virtual void apply_cf_list(ApplyCFListParams_t* applyCFList );
/*! virtual int8_t get_alternate_DR(uint8_t nb_trials);
* \brief Sets a channels mask.
*
* \param [in] chanMaskSet A pointer to the function parameters.
*
* \retval True, if the channels mask could be set.
*/
virtual bool set_channel_mask(ChanMaskSetParams_t* chanMaskSet );
/*! virtual bool set_next_channel(channel_selection_params_t* params, uint8_t* channel,
* \brief Calculates the next datarate to set, when ADR is on or off. lorawan_time_t* time, lorawan_time_t* aggregate_timeOff);
*
* \param [in] adrNext A pointer to the function parameters.
*
* \param [out] drOut The calculated datarate for the next TX.
*
* \param [out] txPowOut The TX power for the next TX.
*
* \param [out] adrAckCounter The calculated ADR acknowledgement counter.
*
* \retval True, if an ADR request should be performed.
*/
virtual bool get_next_ADR(AdrNextParams_t* adrNext, int8_t* drOut,
int8_t* txPowOut, uint32_t* adrAckCounter );
/*! virtual void set_tx_cont_mode(cw_mode_params_t* continuousWave,
* \brief Configuration of the RX windows. uint32_t frequency = 0);
*
* \param [in] rxConfig A pointer to the function parameters.
*
* \param [out] datarate The datarate index set.
*
* \retval True, if the configuration was applied successfully.
*/
virtual bool rx_config(RxConfigParams_t* rxConfig, int8_t* datarate );
/* virtual uint8_t apply_DR_offset(int8_t dr, int8_t dr_offset);
* RX window precise timing
*
* For more details, please consult the following document, chapter 3.1.2.
* http://www.semtech.com/images/datasheet/SX1272_settings_for_LoRaWAN_v2.0.pdf
* or
* http://www.semtech.com/images/datasheet/SX1276_settings_for_LoRaWAN_v2.0.pdf
*
* Downlink start: T = Tx + 1s (+/- 20 us)
* |
* TRxEarly | TRxLate
* | | |
* | | +---+---+---+---+---+---+---+---+
* | | | Latest Rx window |
* | | +---+---+---+---+---+---+---+---+
* | | |
* +---+---+---+---+---+---+---+---+
* | Earliest Rx window |
* +---+---+---+---+---+---+---+---+
* |
* +---+---+---+---+---+---+---+---+
*Downlink preamble 8 symbols | | | | | | | | |
* +---+---+---+---+---+---+---+---+
*
* Worst case Rx window timings
*
* TRxLate = DEFAULT_MIN_RX_SYMBOLS * tSymbol - RADIO_WAKEUP_TIME
* TRxEarly = 8 - DEFAULT_MIN_RX_SYMBOLS * tSymbol - RxWindowTimeout - RADIO_WAKEUP_TIME
*
* TRxLate - TRxEarly = 2 * DEFAULT_SYSTEM_MAX_RX_ERROR
*
* RxOffset = ( TRxLate + TRxEarly ) / 2
*
* RxWindowTimeout = ( 2 * DEFAULT_MIN_RX_SYMBOLS - 8 ) * tSymbol + 2 * DEFAULT_SYSTEM_MAX_RX_ERROR
* RxOffset = 4 * tSymbol - RxWindowTimeout / 2 - RADIO_WAKE_UP_TIME
*
* The minimum value of RxWindowTimeout must be 5 symbols which implies that the system always tolerates at least an error of 1.5 * tSymbol
*/
/*!
* Computes the RX window timeout and offset.
*
* \param [in] datarate The RX window datarate index to be used.
*
* \param [in] minRxSymbols The minimum number of symbols required to detect an RX frame.
*
* \param [in] rxError The system maximum timing error of the receiver in milliseconds.
* The receiver will turn on in a [-rxError : +rxError] ms
* interval around RxOffset.
*
* \param [out] rxConfigParams Returns the updated WindowTimeout and WindowOffset fields.
*/
virtual void compute_rx_win_params(int8_t datarate,
uint8_t minRxSymbols,
uint32_t rxError,
RxConfigParams_t *rxConfigParams);
/*!
* \brief TX configuration.
*
* \param [in] txConfig A pointer to the function parameters.
*
* \param [out] txPower The TX power index set.
*
* \param [out] txTimeOnAir The time-on-air of the frame.
*
* \retval True, if the configuration was applied successfully.
*/
virtual bool tx_config(TxConfigParams_t* txConfig, int8_t* txPower,
TimerTime_t* txTimeOnAir );
/*!
* \brief The function processes a Link ADR request.
*
* \param [in] linkAdrReq A pointer to the function parameters.
*
* \param [out] drOut The datarate applied.
*
* \param [out] txPowOut The TX power applied.
*
* \param [out] nbRepOut The number of repetitions to apply.
*
* \param [out] nbBytesParsed The number of bytes parsed.
*
* \retval The status of the operation, according to the LoRaMAC specification.
*/
virtual uint8_t link_ADR_request(LinkAdrReqParams_t* linkAdrReq,
int8_t* drOut, int8_t* txPowOut,
uint8_t* nbRepOut,
uint8_t* nbBytesParsed );
/*!
* \brief The function processes a RX parameter setup request.
*
* \param [in] rxParamSetupReq A pointer to the function parameters.
*
* \retval The status of the operation, according to the LoRaMAC specification.
*/
virtual uint8_t setup_rx_params(RxParamSetupReqParams_t* rxParamSetupReq );
/*!
* \brief The function processes a new channel request.
*
* \param [in] newChannelReq A pointer to the function parameters.
*
* \retval The status of the operation, according to the LoRaMAC specification.
*/
virtual uint8_t request_new_channel(NewChannelReqParams_t* newChannelReq );
/*!
* \brief The function processes a TX ParamSetup request.
*
* \param [in] txParamSetupReq A pointer to the function parameters.
*
* \retval The status of the operation, according to the LoRaMAC specification.
* Returns -1, if the functionality is not implemented. In this case, the end node
* shall ignore the command.
*/
virtual int8_t setup_tx_params(TxParamSetupReqParams_t* txParamSetupReq );
/*!
* \brief The function processes a DlChannel request.
*
* \param [in] dlChannelReq A pointer to the function parameters.
*
* \retval The status of the operation, according to the LoRaMAC specification.
*/
virtual uint8_t dl_channel_request(DlChannelReqParams_t* dlChannelReq );
/*!
* \brief Alternates the datarate of the channel for the join request.
*
* \param [in] alternateDr A pointer to the function parameters.
*
* \retval The datarate to apply.
*/
virtual int8_t get_alternate_DR(AlternateDrParams_t* alternateDr );
/*!
* \brief Calculates the back-off time.
*
* \param [in] calcBackOff A pointer to the function parameters.
*/
virtual void calculate_backoff(CalcBackOffParams_t* calcBackOff );
/*!
* \brief Searches and sets the next random available channel.
*
* \param [in] nextChanParams The parameters for the next channel.
*
* \param [out] channel The next channel to use for TX.
*
* \param [out] time The time to wait for the next transmission according to the duty cycle.
*
* \param [out] aggregatedTimeOff Updates the aggregated time off.
*
* \retval The function status [1: OK, 0: Unable to find a channel on the current datarate].
*/
virtual bool set_next_channel(NextChanParams_t* nextChanParams,
uint8_t* channel, TimerTime_t* time,
TimerTime_t* aggregatedTimeOff );
/*!
* \brief Adds a channel.
*
* \param [in] channelAdd A pointer to the function parameters.
*
* \retval The status of the operation.
*/
virtual LoRaMacStatus_t add_channel(ChannelAddParams_t* channelAdd );
/*!
* \brief Removes a channel.
*
* \param [in] channelRemove A pointer to the function parameters.
*
* \retval True, if the channel was removed successfully.
*/
virtual bool remove_channel(ChannelRemoveParams_t* channelRemove );
/*!
* \brief Sets the radio into continuous wave mode.
*
* \param [in] continuousWave A pointer to the function parameters.
*/
virtual void set_tx_cont_mode(ContinuousWaveParams_t* continuousWave );
/*!
* \brief Computes a new datarate according to the given offset
*
* \param [in] downlinkDwellTime The downlink dwell time configuration. 0: No limit, 1: 400ms
*
* \param [in] dr The current datarate.
*
* \param [in] drOffset The offset to be applied.
*
* \retval newDr The computed datarate.
*/
virtual uint8_t apply_DR_offset(uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
private: private:
int8_t LimitTxPower( int8_t txPower, int8_t maxBandTxPower, int8_t datarate, uint16_t* channelsMask );
uint8_t CountNbOfEnabledChannels( uint8_t datarate, uint16_t* channelsMask, ChannelParams_t* channels, Band_t* bands, uint8_t* enabledChannels, uint8_t* delayTx );
// Global attributes int8_t limit_tx_power(int8_t tx_power, int8_t max_band_tx_power,
int8_t datarate);
/*! /*!
* LoRaMAC channels * LoRaMAC channels
*/ */
ChannelParams_t Channels[US915_MAX_NB_CHANNELS]; channel_params_t channels[US915_MAX_NB_CHANNELS];
/*! /*!
* LoRaMac bands * LoRaMac bands
*/ */
Band_t Bands[US915_MAX_NB_BANDS]; band_t bands[US915_MAX_NB_BANDS];
/*! /*!
* LoRaMac channels mask * LoRaMac channel mask
*/ */
uint16_t ChannelsMask[US915_CHANNELS_MASK_SIZE]; uint16_t channel_mask[US915_CHANNEL_MASK_SIZE];
/*! /*!
* LoRaMac channels remaining * Previously used channel mask
*/ */
uint16_t ChannelsMaskRemaining[US915_CHANNELS_MASK_SIZE]; uint16_t current_channel_mask[US915_CHANNEL_MASK_SIZE];
/*! /*!
* LoRaMac channels default mask * LoRaMac default channel mask
*/ */
uint16_t ChannelsDefaultMask[US915_CHANNELS_MASK_SIZE]; uint16_t default_channel_mask[US915_CHANNEL_MASK_SIZE];
}; };
#endif /* MBED_OS_LORAPHY_US915_H_ */ #endif /* MBED_OS_LORAPHY_US915_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -29,11 +29,10 @@
* *
*/ */
#ifndef MBED_OS_LORAPHY_US915HYBRID_H_ #ifndef MBED_OS_LORAPHY_US915_HYBRID_H_
#define MBED_OS_LORAPHY_US915_HYBRID_H_ #define MBED_OS_LORAPHY_US915_HYBRID_H_
#include "LoRaPHY.h" #include "LoRaPHY.h"
#include "netsocket/LoRaRadio.h"
/*! /*!
@ -46,321 +45,73 @@
*/ */
#define US915_HYBRID_MAX_NB_BANDS 1 #define US915_HYBRID_MAX_NB_BANDS 1
#define US915_HYBRID_CHANNELS_MASK_SIZE 6 #define US915_HYBRID_CHANNEL_MASK_SIZE 5
class LoRaPHYUS915Hybrid : public LoRaPHY { class LoRaPHYUS915Hybrid : public LoRaPHY {
public: public:
LoRaPHYUS915Hybrid(); LoRaPHYUS915Hybrid(LoRaWANTimeHandler &lora_time);
virtual ~LoRaPHYUS915Hybrid(); virtual ~LoRaPHYUS915Hybrid();
/*! virtual void restore_default_channels();
* \brief The function gets a value of a specific PHY attribute.
*
* \param [in] getPhy A pointer to the function parameters.
*
* \retval The structure containing the PHY parameter.
*/
virtual PhyParam_t get_phy_params(GetPhyParams_t* getPhy );
/*! virtual bool get_next_ADR(bool restore_channel_mask, int8_t& dr_out,
* \brief Updates the last TX done parameters of the current channel. int8_t& tx_power_out, uint32_t& adr_ack_cnt);
*
* \param [in] txDone A pointer to the function parameters.
*/
virtual void set_band_tx_done(SetBandTxDoneParams_t* txDone );
/*! virtual bool rx_config(rx_config_params_t* rxConfig, int8_t* datarate);
* \brief Initializes the channels masks and the channels.
*
* \param [in] type Sets the initialization type.
*/
virtual void load_defaults(InitType_t type );
/*! virtual bool tx_config(tx_config_params_t* tx_config, int8_t* tx_power,
* \brief Verifies a parameter. lorawan_time_t* tx_toa);
*
* \param [in] verify A pointer to the function parameters.
*
* \param [in] phyAttribute The attribute to verify.
*
* \retval True, if the parameter is valid.
*/
virtual bool verify(VerifyParams_t* verify, PhyAttribute_t phyAttribute );
/*! virtual uint8_t link_ADR_request(adr_req_params_t* params,
* \brief The function parses the input buffer and sets up the channels of the CF list. int8_t* dr_out, int8_t* tx_power_out,
* uint8_t* nb_rep_out,
* \param [in] applyCFList A pointer to the function parameters. uint8_t* nb_bytes_parsed);
*/
virtual void apply_cf_list(ApplyCFListParams_t* applyCFList );
/*! virtual uint8_t accept_rx_param_setup_req(rx_param_setup_req_t* params);
* \brief Sets a channels mask.
*
* \param [in] chanMaskSet A pointer to the function parameters.
*
* \retval True, if the channels mask could be set.
*/
virtual bool set_channel_mask(ChanMaskSetParams_t* chanMaskSet );
/*! virtual int8_t get_alternate_DR(uint8_t nb_trials);
* \brief Calculates the next datarate to set, when ADR is on or off.
*
* \param [in] adrNext A pointer to the function parameters.
*
* \param [out] drOut The calculated datarate for the next TX.
*
* \param [out] txPowOut The TX power for the next TX.
*
* \param [out] adrAckCounter The calculated ADR acknowledgement counter.
*
* \retval True, if an ADR request should be performed.
*/
virtual bool get_next_ADR(AdrNextParams_t* adrNext, int8_t* drOut,
int8_t* txPowOut, uint32_t* adrAckCounter );
/*! virtual bool set_next_channel(channel_selection_params_t* params,
* \brief Configuration of the RX windows. uint8_t* channel, lorawan_time_t* time,
* lorawan_time_t* aggregate_timeoff);
* \param [in] rxConfig A pointer to the function parameters.
*
* \param [out] datarate The datarate index set.
*
* \retval True, if the configuration was applied successfully.
*/
virtual bool rx_config(RxConfigParams_t* rxConfig, int8_t* datarate );
/* virtual void set_tx_cont_mode(cw_mode_params_t* continuousWave,
* RX window precise timing uint32_t frequency = 0);
*
* For more details, please consult the following document, chapter 3.1.2.
* http://www.semtech.com/images/datasheet/SX1272_settings_for_LoRaWAN_v2.0.pdf
* or
* http://www.semtech.com/images/datasheet/SX1276_settings_for_LoRaWAN_v2.0.pdf
*
* Downlink start: T = Tx + 1s (+/- 20 us)
* |
* TRxEarly | TRxLate
* | | |
* | | +---+---+---+---+---+---+---+---+
* | | | Latest Rx window |
* | | +---+---+---+---+---+---+---+---+
* | | |
* +---+---+---+---+---+---+---+---+
* | Earliest Rx window |
* +---+---+---+---+---+---+---+---+
* |
* +---+---+---+---+---+---+---+---+
*Downlink preamble 8 symbols | | | | | | | | |
* +---+---+---+---+---+---+---+---+
*
* Worst case Rx window timings
*
* TRxLate = DEFAULT_MIN_RX_SYMBOLS * tSymbol - RADIO_WAKEUP_TIME
* TRxEarly = 8 - DEFAULT_MIN_RX_SYMBOLS * tSymbol - RxWindowTimeout - RADIO_WAKEUP_TIME
*
* TRxLate - TRxEarly = 2 * DEFAULT_SYSTEM_MAX_RX_ERROR
*
* RxOffset = ( TRxLate + TRxEarly ) / 2
*
* RxWindowTimeout = ( 2 * DEFAULT_MIN_RX_SYMBOLS - 8 ) * tSymbol + 2 * DEFAULT_SYSTEM_MAX_RX_ERROR
* RxOffset = 4 * tSymbol - RxWindowTimeout / 2 - RADIO_WAKE_UP_TIME
*
* The minimum value of RxWindowTimeout must be 5 symbols which implies that the system always tolerates at least an error of 1.5 * tSymbol
*/
/*!
* Computes the RX window timeout and offset.
*
* \param [in] datarate The RX window datarate index to be used.
*
* \param [in] minRxSymbols The minimum number of symbols required to detect an RX frame.
*
* \param [in] rxError The system maximum timing error of the receiver in milliseconds.
* The receiver will turn on in a [-rxError : +rxError] ms
* interval around RxOffset.
*
* \param [out] rxConfigParams Returns the updated WindowTimeout and WindowOffset fields.
*/
virtual void compute_rx_win_params(int8_t datarate,
uint8_t minRxSymbols,
uint32_t rxError,
RxConfigParams_t *rxConfigParams);
/*! virtual uint8_t apply_DR_offset(int8_t dr, int8_t dr_offset);
* \brief TX configuration.
*
* \param [in] txConfig A pointer to the function parameters.
*
* \param [out] txPower The TX power index set.
*
* \param [out] txTimeOnAir The time-on-air of the frame.
*
* \retval True, if the configuration was applied successfully.
*/
virtual bool tx_config(TxConfigParams_t* txConfig, int8_t* txPower,
TimerTime_t* txTimeOnAir );
/*!
* \brief The function processes a Link ADR request.
*
* \param [in] linkAdrReq A pointer to the function parameters.
*
* \param [out] drOut The datarate applied.
*
* \param [out] txPowOut The TX power applied.
*
* \param [out] nbRepOut The number of repetitions to apply.
*
* \param [out] nbBytesParsed The number of bytes parsed.
*
* \retval The status of the operation, according to the LoRaMAC specification.
*/
virtual uint8_t link_ADR_request(LinkAdrReqParams_t* linkAdrReq,
int8_t* drOut, int8_t* txPowOut,
uint8_t* nbRepOut,
uint8_t* nbBytesParsed );
/*!
* \brief The function processes a RX parameter setup request.
*
* \param [in] rxParamSetupReq A pointer to the function parameters.
*
* \retval The status of the operation, according to the LoRaMAC specification.
*/
virtual uint8_t setup_rx_params(RxParamSetupReqParams_t* rxParamSetupReq );
/*!
* \brief The function processes a new channel request.
*
* \param [in] newChannelReq A pointer to the function parameters.
*
* \retval The status of the operation, according to the LoRaMAC specification.
*/
virtual uint8_t request_new_channel(NewChannelReqParams_t* newChannelReq );
/*!
* \brief The function processes a TX ParamSetup request.
*
* \param [in] txParamSetupReq A pointer to the function parameters.
*
* \retval The status of the operation, according to the LoRaMAC specification.
* Returns -1, if the functionality is not implemented. In this case, the end node
* shall ignore the command.
*/
virtual int8_t setup_tx_params(TxParamSetupReqParams_t* txParamSetupReq );
/*!
* \brief The function processes a DlChannel request.
*
* \param [in] dlChannelReq A pointer to the function parameters.
*
* \retval The status of the operation, according to the LoRaMAC specification.
*/
virtual uint8_t dl_channel_request(DlChannelReqParams_t* dlChannelReq );
/*!
* \brief Alternates the datarate of the channel for the join request.
*
* \param [in] alternateDr A pointer to the function parameters.
*
* \retval The datarate to apply.
*/
virtual int8_t get_alternate_DR(AlternateDrParams_t* alternateDr );
/*!
* \brief Calculates the back-off time.
*
* \param [in] calcBackOff A pointer to the function parameters.
*/
virtual void calculate_backoff(CalcBackOffParams_t* calcBackOff );
/*!
* \brief Searches and sets the next random available channel.
*
* \param [in] nextChanParams The parameters for the next channel.
*
* \param [out] channel The next channel to use for TX.
*
* \param [out] time The time to wait for the next transmission according to the duty cycle.
*
* \param [out] aggregatedTimeOff Updates the aggregated time off.
*
* \retval The function status [1: OK, 0: Unable to find a channel on the current datarate].
*/
virtual bool set_next_channel(NextChanParams_t* nextChanParams,
uint8_t* channel, TimerTime_t* time,
TimerTime_t* aggregatedTimeOff );
/*!
* \brief Adds a channel.
*
* \param [in] channelAdd A pointer to the function parameters.
*
* \retval The status of the operation.
*/
virtual LoRaMacStatus_t add_channel(ChannelAddParams_t* channelAdd );
/*!
* \brief Removes a channel.
*
* \param [in] channelRemove A pointer to the function parameters.
*
* \retval True, if the channel was removed successfully.
*/
virtual bool remove_channel(ChannelRemoveParams_t* channelRemove );
/*!
* \brief Sets the radio into continuous wave mode.
*
* \param [in] continuousWave A pointer to the function parameters.
*/
virtual void set_tx_cont_mode(ContinuousWaveParams_t* continuousWave );
/*!
* \brief Computes a new datarate according to the given offset.
*
* \param [in] downlinkDwellTime The downlink dwell time configuration. 0: No limit, 1: 400ms
*
* \param [in] dr The current datarate.
*
* \param [in] drOffset The offset to be applied.
*
* \retval newDr The computed datarate.
*/
virtual uint8_t apply_DR_offset(uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
private: private:
int8_t LimitTxPower( int8_t txPower, int8_t maxBandTxPower, int8_t datarate, uint16_t* channelsMask ); int8_t limit_tx_power(int8_t tx_power, int8_t max_band_tx_power, int8_t datarate);
uint8_t CountNbOfEnabledChannels( uint8_t datarate, uint16_t* channelsMask, ChannelParams_t* channels, Band_t* bands, uint8_t* enabledChannels, uint8_t* delayTx ); bool validate_channel_mask(uint16_t* channel_mask);
void reenable_500khz_channels(uint16_t mask, uint16_t* channel_mask);
// Global attributes
/*! /*!
* LoRaMAC channels * LoRaMAC channels
*/ */
ChannelParams_t Channels[US915_HYBRID_MAX_NB_CHANNELS]; channel_params_t channels[US915_HYBRID_MAX_NB_CHANNELS];
/*! /*!
* LoRaMac bands * LoRaMac bands
*/ */
Band_t Bands[US915_HYBRID_MAX_NB_BANDS]; band_t bands[US915_HYBRID_MAX_NB_BANDS];
/*! /*!
* LoRaMac channels mask * LoRaMac channels mask
*/ */
uint16_t ChannelsMask[US915_HYBRID_CHANNELS_MASK_SIZE]; uint16_t channel_mask[US915_HYBRID_CHANNEL_MASK_SIZE];
/*! /*!
* LoRaMac channels remaining * Previously used channel mask
*/ */
uint16_t ChannelsMaskRemaining[US915_HYBRID_CHANNELS_MASK_SIZE]; uint16_t current_channel_mask[US915_HYBRID_CHANNEL_MASK_SIZE];
/*! /*!
* LoRaMac channels default mask * LoRaMac default channel mask
*/ */
uint16_t ChannelsDefaultMask[US915_HYBRID_CHANNELS_MASK_SIZE]; uint16_t default_channel_mask[US915_HYBRID_CHANNEL_MASK_SIZE];
}; };
#endif /* MBED_OS_LORAPHY_US915HYBRID_H_ */ #endif /* MBED_OS_LORAPHY_US915HYBRID_H_ */

View File

@ -527,7 +527,7 @@
/*! /*!
* Enumeration of PHY attributes. * Enumeration of PHY attributes.
*/ */
typedef enum ePhyAttribute typedef enum phy_attributes__e
{ {
/*! /*!
* The minimum RX datarate. * The minimum RX datarate.
@ -620,11 +620,11 @@ typedef enum ePhyAttribute
/*! /*!
* The channels mask. * The channels mask.
*/ */
PHY_CHANNELS_MASK, PHY_CHANNEL_MASK,
/*! /*!
* The channels default mask. * The default channel mask.
*/ */
PHY_CHANNELS_DEFAULT_MASK, PHY_DEFAULT_CHANNEL_MASK,
/*! /*!
* The maximum number of supported channels. * The maximum number of supported channels.
*/ */
@ -633,6 +633,13 @@ typedef enum ePhyAttribute
* The channels. * The channels.
*/ */
PHY_CHANNELS, PHY_CHANNELS,
/*!
* The PHYs that support dynamic channel plan (non-custom)
* support do not let the user add/remove to the channel plan.
* The network guides the device for the plan. So only
* EU like regions support custom channel planning.
*/
PHY_CUSTOM_CHANNEL_PLAN_SUPPORT,
/*! /*!
* The default value of the uplink dwell time. * The default value of the uplink dwell time.
*/ */
@ -661,517 +668,481 @@ typedef enum ePhyAttribute
* The next lower datarate. * The next lower datarate.
*/ */
PHY_NEXT_LOWER_TX_DR PHY_NEXT_LOWER_TX_DR
}PhyAttribute_t; } phy_attributes_t;
/*! /*!
* Enumeration of initialization types. * Keeps value in response to a call to
* get_phy_params() API.
*/ */
typedef enum eInitType typedef union phy_param_u
{
/*!
* Performs an initialization and overwrites all existing data.
*/
INIT_TYPE_INIT,
/*!
* Restores default channels only.
*/
INIT_TYPE_RESTORE
}InitType_t;
/*!
* Selects a given or a default channel mask.
*/
typedef enum eChannelsMask
{
/*!
* The channels mask.
*/
CHANNELS_MASK,
/*!
* The channels default mask.
*/
CHANNELS_DEFAULT_MASK
}ChannelsMask_t;
/*!
* The union for the structure uGetPhyParams.
*/
typedef union uPhyParam
{ {
/*! /*!
* A parameter value. * A parameter value.
*/ */
uint32_t Value; uint32_t value;
/*! /*!
* A floating point value. * A floating point value.
*/ */
float fValue; float f_value;
/*! /*!
* A pointer to the channels mask. * A pointer to the channels mask.
*/ */
uint16_t* ChannelsMask; uint16_t* channel_mask;
/*! /*!
* A pointer to the channels. * A pointer to the channels.
*/ */
ChannelParams_t* Channels; channel_params_t* channel_params;
}PhyParam_t; } phy_param_t;
/*! /**
* The parameter structure for the function RegionGetPhyParam. * The parameter structure for the function RegionGetPhyParam.
*/ */
typedef struct sGetPhyParams typedef struct
{ {
/*! /**
* Set up the parameter to get. * Set up the parameter to get.
*/ */
PhyAttribute_t Attribute; phy_attributes_t attribute;
/*!
* Datarate. /**
* The parameter is needed for the following queries: * The parameter is needed for the following queries:
* PHY_MAX_PAYLOAD, PHY_MAX_PAYLOAD_REPEATER, PHY_NEXT_LOWER_TX_DR. * PHY_MAX_PAYLOAD, PHY_MAX_PAYLOAD_REPEATER, PHY_NEXT_LOWER_TX_DR.
*/ */
int8_t Datarate; int8_t datarate;
/*!
* Uplink dwell time.
* The parameter is needed for the following queries:
* PHY_MIN_TX_DR, PHY_MAX_PAYLOAD, PHY_MAX_PAYLOAD_REPEATER, PHY_NEXT_LOWER_TX_DR.
*/
uint8_t UplinkDwellTime;
/*!
* Downlink dwell time.
* The parameter is needed for the following queries:
* PHY_MIN_RX_DR, PHY_MAX_PAYLOAD, PHY_MAX_PAYLOAD_REPEATER.
*/
uint8_t DownlinkDwellTime;
}GetPhyParams_t;
/*! } get_phy_params_t;
/**
* The parameter structure for the function RegionSetBandTxDone. * The parameter structure for the function RegionSetBandTxDone.
*/ */
typedef struct sSetBandTxDoneParams typedef struct
{ {
/*! /**
* The channel to update. * The channel to update.
*/ */
uint8_t Channel; uint8_t channel;
/*! /**
* Joined set to true, if the node has joined the network. * Joined set to true, if the node has joined the network.
*/ */
bool Joined; bool joined;
/*! /**
* The last TX done time. * The last TX done time.
*/ */
TimerTime_t LastTxDoneTime; lorawan_time_t last_tx_done_time;
}SetBandTxDoneParams_t; } set_band_txdone_params_t;
/*! /**
* The parameter structure for the function RegionVerify. * The parameter verification structure.
*/ */
typedef union uVerifyParams typedef union
{ {
/*! /**
* The TX power to verify. * The TX power to verify.
*/ */
int8_t TxPower; int8_t tx_power;
/*! /**
* Set to true, if the duty cycle is enabled, otherwise false. * Set to true, if the duty cycle is enabled, otherwise false.
*/ */
bool DutyCycle; bool duty_cycle;
/*! /**
* The number of join trials. * The number of join trials.
*/ */
uint8_t NbJoinTrials; uint8_t nb_join_trials;
/*! /**
* The datarate to verify. * The datarate to verify.
*/ */
struct sDatarateParams int8_t datarate;
{
/*!
* The datarate to verify.
*/
int8_t Datarate;
/*!
* The downlink dwell time.
*/
uint8_t DownlinkDwellTime;
/*!
* The uplink dwell time.
*/
uint8_t UplinkDwellTime;
}DatarateParams;
}VerifyParams_t;
/*! } verification_params_t;
/**
* The parameter structure for the function RegionApplyCFList. * The parameter structure for the function RegionApplyCFList.
*/ */
typedef struct sApplyCFListParams typedef struct
{ {
/*! /**
* The payload containing the CF list. * The payload containing the CF list.
*/ */
uint8_t* Payload; uint8_t* payload;
/*! /**
* The size of the payload. * The size of the payload.
*/ */
uint8_t Size; uint8_t size;
}ApplyCFListParams_t; } cflist_params_t;
/*! /**
* The parameter structure for the function RegionChanMaskSet. * TX configuration parameters.
*/ */
typedef struct sChanMaskSetParams typedef struct
{ {
/*! /**
* A pointer to the channels mask which should be set.
*/
uint16_t* ChannelsMaskIn;
/*!
* A pointer to the channels mask which should be set.
*/
ChannelsMask_t ChannelsMaskType;
}ChanMaskSetParams_t;
/*!
* The parameter structure for the function RegionAdrNext.
*/
typedef struct sAdrNextParams
{
/*!
* Set to true, if the function should update the channels mask.
*/
bool UpdateChanMask;
/*!
* Set to true, if ADR is enabled.
*/
bool AdrEnabled;
/*!
* The ADR ack counter.
*/
uint32_t AdrAckCounter;
/*!
* The datarate used currently.
*/
int8_t Datarate;
/*!
* The TX power used currently.
*/
int8_t TxPower;
/*!
* UplinkDwellTime
*/
uint8_t UplinkDwellTime;
}AdrNextParams_t;
/*!
* The parameter structure for the function RegionRxConfig.
*/
typedef struct sRxConfigParams
{
/*!
* The RX channel.
*/
uint8_t Channel;
/*!
* The RX datarate.
*/
int8_t Datarate;
/*!
* The RX bandwidth.
*/
uint8_t Bandwidth;
/*!
* The RX datarate offset.
*/
int8_t DrOffset;
/*!
* The RX frequency.
*/
uint32_t Frequency;
/*!
* The RX window timeout
*/
uint32_t WindowTimeout;
/*!
* The RX window offset
*/
int32_t WindowOffset;
/*!
* The downlink dwell time.
*/
uint8_t DownlinkDwellTime;
/*!
* Set to true, if a repeater is supported.
*/
bool RepeaterSupport;
/*!
* Set to true, if RX should be continuous.
*/
bool RxContinuous;
/*!
* Sets the RX window. 0: RX window 1, 1: RX window 2.
*/
bool Window;
}RxConfigParams_t;
/*!
* The parameter structure for the function RegionTxConfig.
*/
typedef struct sTxConfigParams
{
/*!
* The TX channel. * The TX channel.
*/ */
uint8_t Channel; uint8_t channel;
/*! /**
* The TX datarate. * The TX datarate.
*/ */
int8_t Datarate; int8_t datarate;
/*! /**
* The TX power. * The TX power.
*/ */
int8_t TxPower; int8_t tx_power;
/*! /**
* The Max EIRP, if applicable. * The Max EIRP, if applicable.
*/ */
float MaxEirp; float max_eirp;
/*! /**
* The antenna gain, if applicable. * The antenna gain, if applicable.
*/ */
float AntennaGain; float antenna_gain;
/*! /**
* The frame length to set up. * The frame length to set up.
*/ */
uint16_t PktLen; uint16_t pkt_len;
}TxConfigParams_t; } tx_config_params_t;
/*! /**
* The parameter structure for the function RegionLinkAdrReq. * This structure contains parameters for ADR request coming from
* network server.
*/ */
typedef struct sLinkAdrReqParams typedef struct
{ {
/*! /*!
* A pointer to the payload containing the MAC commands. * A pointer to the payload containing the MAC commands.
*/ */
uint8_t* Payload; uint8_t* payload;
/*! /*!
* The size of the payload. * The size of the payload.
*/ */
uint8_t PayloadSize; uint8_t payload_size;
/*! /*!
* The uplink dwell time. * The uplink dwell time.
*/ */
uint8_t UplinkDwellTime; uint8_t ul_dwell_time;
/*! /*!
* Set to true, if ADR is enabled. * Set to true, if ADR is enabled.
*/ */
bool AdrEnabled; bool adr_enabled;
/*! /*!
* The current datarate. * The current datarate.
*/ */
int8_t CurrentDatarate; int8_t current_datarate;
/*! /*!
* The current TX power. * The current TX power.
*/ */
int8_t CurrentTxPower; int8_t current_tx_power;
/*! /*!
* The current number of repetitions. * The current number of repetitions.
*/ */
uint8_t CurrentNbRep; uint8_t current_nb_rep;
}LinkAdrReqParams_t; } adr_req_params_t;
/*! /**
* The parameter structure for the function RegionRxParamSetupReq. * Structure containing data for local ADR settings
*/ */
typedef struct sRxParamSetupReqParams typedef struct link_adr_params_s
{
/**
* The number of repetitions.
*/
uint8_t nb_rep;
/**
* Datarate.
*/
int8_t datarate;
/**
* TX power.
*/
int8_t tx_power;
/**
* Channels mask control field.
*/
uint8_t ch_mask_ctrl;
/**
* Channels mask field.
*/
uint16_t channel_mask;
} link_adr_params_t;
/**
* Structure used to store ADR values received from network
* for verification (legality) purposes.
*/
typedef struct verify_adr_params_s
{ {
/*! /*!
* The current status of the AdrLinkRequest.
*/
uint8_t status;
/*!
* Set to true, if ADR is enabled.
*/
bool adr_enabled;
/*!
* The datarate the AdrLinkRequest wants to set.
*/
int8_t datarate;
/*!
* The TX power the AdrLinkRequest wants to set.
*/
int8_t tx_power;
/*!
* The number of repetitions the AdrLinkRequest wants to set.
*/
uint8_t nb_rep;
/*!
* The current datarate the node is using.
*/
int8_t current_datarate;
/*!
* The current TX power the node is using.
*/
int8_t current_tx_power;
/*!
* The current number of repetitions the node is using.
*/
int8_t current_nb_rep;
/*!
* A pointer to the first element of the channels mask.
*/
uint16_t* channel_mask;
} verify_adr_params_t;
/**
* Contains rx parameter setup request coming from
* network server.
*/
typedef struct rx_param_setup_req_s
{
/**
* The datarate to set up. * The datarate to set up.
*/ */
int8_t Datarate; int8_t datarate;
/*! /**
* The datarate offset. * The datarate offset.
*/ */
int8_t DrOffset; int8_t dr_offset;
/*! /**
* The frequency to set up. * The frequency to set up.
*/ */
uint32_t Frequency; uint32_t frequency;
}RxParamSetupReqParams_t; } rx_param_setup_req_t;
/*! /**
* The parameter structure for the function RegionNewChannelReq. * Contains tx parameter setup request coming from
* network server.
*/ */
typedef struct sNewChannelReqParams typedef struct tx_param_setup_req_s
{ {
/*! /**
* A pointer to the new channels.
*/
ChannelParams_t* NewChannel;
/*!
* The channel ID.
*/
int8_t ChannelId;
}NewChannelReqParams_t;
/*!
* The parameter structure for the function RegionTxParamSetupReq.
*/
typedef struct sTxParamSetupReqParams
{
/*!
* The uplink dwell time. * The uplink dwell time.
*/ */
uint8_t UplinkDwellTime; uint8_t ul_dwell_time;
/*! /**
* The downlink dwell time. * The downlink dwell time.
*/ */
uint8_t DownlinkDwellTime; uint8_t dl_dwell_time;
/*! /**
* The max EIRP. * The max EIRP.
*/ */
uint8_t MaxEirp; uint8_t max_eirp;
}TxParamSetupReqParams_t; } tx_param_setup_req_t;
/*! /**
* A structure that holds new channel parameters coming
* from the network server.
*/
typedef struct new_channel_req_params_s
{
/**
* A pointer to the new channel's parameters.
*/
channel_params_t* new_channel;
/**
* The channel ID.
*/
int8_t channel_id;
} new_channel_req_params_t;
/**
* The parameter structure for the function RegionDlChannelReq. * The parameter structure for the function RegionDlChannelReq.
*/ */
typedef struct sDlChannelReqParams typedef struct dl_channel_req_params_s
{ {
/*! /**
* The channel ID to add the frequency. * The channel ID to add the frequency.
*/ */
uint8_t ChannelId; uint8_t channel_id;
/*! /**
* The alternative frequency for the Rx1 window. * The alternative frequency for the Rx1 window.
*/ */
uint32_t Rx1Frequency; uint32_t rx1_frequency;
}DlChannelReqParams_t; } dl_channel_req_params_t;
/*!
* The parameter structure for the function RegionAlternateDr.
*/
typedef struct sAlternateDrParams
{
/*!
* The number of trials.
*/
uint16_t NbTrials;
}AlternateDrParams_t;
/*! /*!
* The parameter structure for the function RegionCalcBackOff. * The parameter structure for the function RegionCalcBackOff.
*/ */
typedef struct sCalcBackOffParams typedef struct backoff_params_s
{ {
/*! /**
* Set to true, if the node has already joined a network, otherwise false. * Set to true, if the node has already joined a network, otherwise false.
*/ */
bool Joined; bool joined;
/*! /**
* Joined set to true, if the last uplink was a join request. * set to true, if the last uplink was a join request.
*/ */
bool LastTxIsJoinRequest; bool last_tx_was_join_req;
/*! /**
* Set to true, if the duty cycle is enabled, otherwise false. * Set to true, if the duty cycle is enabled, otherwise false.
*/ */
bool DutyCycleEnabled; bool dc_enabled;
/*! /**
* The current channel index. * The current channel index.
*/ */
uint8_t Channel; uint8_t channel;
/*! /**
* Elapsed time since the start of the node. * Elapsed time since the start of the node.
*/ */
TimerTime_t ElapsedTime; lorawan_time_t elapsed_time;
/*! /**
* Time-on-air of the last transmission. * Time-on-air of the last transmission.
*/ */
TimerTime_t TxTimeOnAir; lorawan_time_t tx_toa;
}CalcBackOffParams_t;
/*! } backoff_params_t;
/**
* The parameter structure for the function RegionNextChannel. * The parameter structure for the function RegionNextChannel.
*/ */
typedef struct sNextChanParams typedef struct channel_selection_params_s
{ {
/*! /**
* The aggregated time-off time. * The aggregated time-off time.
*/ */
TimerTime_t AggrTimeOff; lorawan_time_t aggregate_timeoff;
/*! /**
* The time of the last aggregated TX. * The time of the last aggregated TX.
*/ */
TimerTime_t LastAggrTx; lorawan_time_t last_aggregate_tx_time;
/*! /**
* The current datarate. * The current datarate.
*/ */
int8_t Datarate; int8_t current_datarate;
/*! /**
* Set to true, if the node has already joined a network, otherwise false. * Set to true, if the node has already joined a network, otherwise false.
*/ */
bool Joined; bool joined;
/*! /**
* Set to true, if the duty cycle is enabled, otherwise false. * Set to true, if the duty cycle is enabled, otherwise false.
*/ */
bool DutyCycleEnabled; bool dc_enabled;
}NextChanParams_t; } channel_selection_params_t;
/*!
* The parameter structure for the function RegionChannelsAdd.
*/
typedef struct sChannelAddParams
{
/*!
* A pointer to the new channel to add.
*/
ChannelParams_t* NewChannel;
/*!
* The channel ID to add.
*/
uint8_t ChannelId;
}ChannelAddParams_t;
/*!
* The parameter structure for the function RegionChannelsRemove.
*/
typedef struct sChannelRemoveParams
{
/*!
* The channel ID to remove.
*/
uint8_t ChannelId;
}ChannelRemoveParams_t;
/*! /*!
* The parameter structure for the function RegionContinuousWave. * The parameter structure for the function RegionContinuousWave.
*/ */
typedef struct sContinuousWaveParams typedef struct continuous_wave_mode_params_s
{ {
/*! /*!
* The current channel index. * The current channel index.
*/ */
uint8_t Channel; uint8_t channel;
/*! /*!
* The datarate. Used to limit the TX power. * The datarate. Used to limit the TX power.
*/ */
int8_t Datarate; int8_t datarate;
/*! /*!
* The TX power to set up. * The TX power to set up.
*/ */
int8_t TxPower; int8_t tx_power;
/*! /*!
* The max EIRP, if applicable. * The max EIRP, if applicable.
*/ */
float MaxEirp; float max_eirp;
/*! /*!
* The antenna gain, if applicable. * The antenna gain, if applicable.
*/ */
float AntennaGain; float antenna_gain;
/*! /*!
* Specifies the time the radio will stay in CW mode. * Specifies the time the radio will stay in CW mode.
*/ */
uint16_t Timeout; uint16_t timeout;
}ContinuousWaveParams_t; } cw_mode_params_t;
typedef struct {
void *table;
uint8_t size;
} loraphy_table_t;
typedef struct {
channel_params_t *channel_list;
uint8_t channel_list_size;
uint16_t *mask;
uint16_t *default_mask;
uint8_t mask_size;
} loraphy_channels_t;
typedef struct {
bool duty_cycle_enabled;
bool accept_tx_param_setup_req;
bool fsk_supported;
bool cflist_supported;
bool custom_channelplans_supported;
bool dl_channel_req_supported;
uint8_t default_channel_cnt;
uint8_t cflist_channel_cnt;
uint8_t max_channel_cnt;
uint8_t min_tx_power;
uint8_t max_tx_power;
uint8_t default_tx_power;
uint8_t adr_ack_limit;
uint8_t adr_ack_delay;
uint8_t min_tx_datarate;
uint8_t max_tx_datarate;
uint8_t min_rx_datarate;
uint8_t max_rx_datarate;
uint8_t default_datarate;
uint8_t default_max_datarate;
uint8_t min_rx1_dr_offset;
uint8_t max_rx1_dr_offset;
uint8_t default_rx1_dr_offset;
uint8_t dwell_limit_datarate;
uint16_t max_rx_window;
uint16_t recv_delay1;
uint16_t recv_delay2;
uint16_t join_accept_delay1;
uint16_t join_accept_delay2;
uint16_t join_channel_mask;
uint16_t max_fcnt_gap;
uint16_t ack_timeout;
uint16_t ack_timeout_rnd;
float default_max_eirp;
float default_antenna_gain;
uint8_t rx_window2_datarate;
uint32_t rx_window2_frequency;
loraphy_table_t bands;
loraphy_table_t bandwidths;
loraphy_table_t datarates;
loraphy_table_t payloads;
loraphy_table_t payloads_with_repeater;
loraphy_channels_t channels;
unsigned ul_dwell_time_setting : 1;
unsigned dl_dwell_time_setting : 1;
} loraphy_params_t;
#endif /* MBED_OS_LORA_PHY_DATASTRUCTURES_ */ #endif /* MBED_OS_LORA_PHY_DATASTRUCTURES_ */

View File

@ -2,16 +2,7 @@
"name": "lora", "name": "lora",
"config": { "config": {
"phy": { "phy": {
"help": ["Select LoRa PHY layer. See README.md for more information. Default: 0 = LORA_PHY_EU868", "help": "LoRa PHY region. 0 = EU868 (default), 1 = AS923, 2 = AU915, 3 = CN470, 4 = CN779, 5 = EU433, 6 = IN865, 7 = KR920, 8 = US915, 9 = US915_HYBRID",
" 1 = LORA_PHY_AS923",
" 2 = LORA_PHY_AU915",
" 3 = LORA_PHY_CN470",
" 4 = LORA_PHY_CN779",
" 5 = LORA_PHY_EU433",
" 6 = LORA_PHY_IN865",
" 7 = LORA_PHY_KR920",
" 8 = LORA_PHY_US915",
" 9 = LORA_PHY_US915_HYBRID"],
"value": "0" "value": "0"
}, },
"over-the-air-activation": { "over-the-air-activation": {
@ -19,8 +10,8 @@
"value": true "value": true
}, },
"nb-trials": { "nb-trials": {
"help": "Indicates how many times join can be tried, default: 8", "help": "Indicates how many times join can be tried, default: 12",
"value": 8 "value": 12
}, },
"device-eui": { "device-eui": {
"help": "Mote device IEEE EUI", "help": "Mote device IEEE EUI",
@ -34,10 +25,6 @@
"help": "AES encryption/decryption cipher application key", "help": "AES encryption/decryption cipher application key",
"value": "{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}" "value": "{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}"
}, },
"network-id": {
"help": "Current network ID",
"value": 0
},
"device-address": { "device-address": {
"help": "Device address on the network", "help": "Device address on the network",
"value": "0x00000000" "value": "0x00000000"
@ -67,12 +54,12 @@
"value": true "value": true
}, },
"duty-cycle-on": { "duty-cycle-on": {
"help": "Enables/disables duty cycling. NOTE: Disable only for testing. Mandatory in many regions.", "help": "Enables/disables duty cycling. NOTE: Disable only for testing. Mandatory in many regions.",
"value": true "value": true
}, },
"lbt-on": { "lbt-on": {
"help": "Enables/disables LBT. NOTE: [This feature is not yet integrated].", "help": "Enables/disables LBT. NOTE: [This feature is not yet integrated].",
"value": false "value": false
} }
} }
} }

View File

@ -20,41 +20,45 @@ SPDX-License-Identifier: BSD-3-Clause
#include "lorawan/system/LoRaWANTimer.h" #include "lorawan/system/LoRaWANTimer.h"
static events::EventQueue *_queue = NULL; LoRaWANTimeHandler::LoRaWANTimeHandler()
: _queue(NULL)
{
}
void TimerTimeCounterInit(events::EventQueue *queue) LoRaWANTimeHandler::~LoRaWANTimeHandler()
{
}
void LoRaWANTimeHandler::activate_timer_subsystem(events::EventQueue *queue)
{ {
_queue = queue; _queue = queue;
} }
TimerTime_t TimerGetCurrentTime( void ) lorawan_time_t LoRaWANTimeHandler::get_current_time( void )
{ {
const uint32_t current_time = _queue->tick(); const uint32_t current_time = _queue->tick();
return (TimerTime_t)current_time; return (lorawan_time_t)current_time;
} }
TimerTime_t TimerGetElapsedTime( TimerTime_t savedTime ) lorawan_time_t LoRaWANTimeHandler::get_elapsed_time(lorawan_time_t saved_time)
{ {
return TimerGetCurrentTime() - savedTime; return get_current_time() - saved_time;
} }
void TimerInit( TimerEvent_t *obj, void ( *callback )( void ) ) void LoRaWANTimeHandler::init(timer_event_t &obj, mbed::Callback<void()> callback)
{ {
obj->value = 0; obj.callback = callback;
obj->Callback = callback; obj.timer_id = 0;
} }
void TimerStart( TimerEvent_t *obj ) void LoRaWANTimeHandler::start(timer_event_t &obj, const uint32_t timeout)
{ {
obj->Timer.get()->attach_us( mbed::callback( obj->Callback ), obj->value * 1000 ); obj.timer_id = _queue->call_in(timeout, obj.callback);
MBED_ASSERT(obj.timer_id != 0);
} }
void TimerStop( TimerEvent_t *obj ) void LoRaWANTimeHandler::stop(timer_event_t &obj)
{ {
obj->Timer.get()->detach( ); _queue->cancel(obj.timer_id);
} obj.timer_id = 0;
void TimerSetValue( TimerEvent_t *obj, uint32_t value )
{
obj->value = value;
} }

View File

@ -21,92 +21,63 @@ SPDX-License-Identifier: BSD-3-Clause
#ifndef MBED_LORAWAN_SYS_TIMER_H__ #ifndef MBED_LORAWAN_SYS_TIMER_H__
#define MBED_LORAWAN_SYS_TIMER_H__ #define MBED_LORAWAN_SYS_TIMER_H__
#include "drivers/Timer.h" #include <stdint.h>
#include "drivers/Ticker.h"
#include "lorawan/system/lorawan_data_structures.h" #include "lorawan/system/lorawan_data_structures.h"
#include "events/EventQueue.h" #include "events/EventQueue.h"
#include "platform/SingletonPtr.h"
/*! class LoRaWANTimeHandler
* \brief Timer object description
*/
typedef struct TimerEvent_s
{ {
uint32_t value; public:
void ( *Callback )( void ); LoRaWANTimeHandler();
SingletonPtr<mbed::Ticker> Timer; ~LoRaWANTimeHandler();
}TimerEvent_t;
/*! /** Activates the timer subsystem.
* \brief Initializes the timer object. *
* * Embeds EventQueue object to timer subsystem which is subsequently
* \remark The TimerSetValue function must be called before starting the timer. * used to extract timer information.
* This function initializes the timestamp and reloads the value at 0. *
* * @param [in] queue Handle to EventQueue object
* \param [in] obj The structure containing the timer object parameters. */
* \param [in] callback The function callback called at the end of the timeout. void activate_timer_subsystem(events::EventQueue *queue);
*/
void TimerInit( TimerEvent_t *obj, void ( *callback )( void ) );
/*! /** Read the current time.
* \brief Starts and adds the timer object to the list of timer events. *
* * @return time The current time.
* \param [in] obj The structure containing the timer object parameters. */
*/ lorawan_time_t get_current_time(void);
void TimerStart( TimerEvent_t *obj );
/*! /** Return the time elapsed since a fixed moment in time.
* \brief Stops and removes the timer object from the list of timer events. *
* * @param [in] saved_time The fixed moment in time.
* \param [in] obj The structure containing the timer object parameters. * @return time The elapsed time.
*/ */
void TimerStop( TimerEvent_t *obj ); lorawan_time_t get_elapsed_time(lorawan_time_t saved_time);
/*! /** Initializes the timer object.
* \brief Resets the timer object. *
* * @remark The TimerSetValue function must be called before starting the timer.
* \param [in] obj The structure containing the timer object parameters. * This function initializes the time-stamp and reloads the value at 0.
*/ *
void TimerReset( TimerEvent_t *obj ); * @param [in] obj The structure containing the timer object parameters.
* @param [in] callback The function callback called at the end of the timeout.
*/
void init(timer_event_t &obj, mbed::Callback<void()> callback);
/*! /** Starts and adds the timer object to the list of timer events.
* \brief Set a new timeout value. *
* * @param [in] obj The structure containing the timer object parameters.
* \param [in] obj The structure containing the timer object parameters. * @param [in] timeout The new timeout value.
* \param [in] value The new timeout value. */
*/ void start(timer_event_t &obj, const uint32_t timeout);
void TimerSetValue( TimerEvent_t *obj, uint32_t value );
/*! /** Stops and removes the timer object from the list of timer events.
* \brief Initializes the timer used to get the current time. *
* * @param [in] obj The structure containing the timer object parameters.
* \remark The current time corresponds to the time since system startup. */
* void stop(timer_event_t &obj);
* \param [in] queue Handle to EventQueue object
*/
void TimerTimeCounterInit(events::EventQueue *queue);
/*! private:
* \brief Read the current time. events::EventQueue *_queue;
* };
* \retval time The current time.
*/
TimerTime_t TimerGetCurrentTime( void );
/*!
* \brief Return the time elapsed since a fixed moment in time.
*
* \param [in] savedTime The fixed moment in time.
* \retval time The elapsed time.
*/
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__ #endif // MBED_LORAWAN_SYS_TIMER_H__

File diff suppressed because it is too large Load Diff