1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-01-18 12:52:44 +01:00

pkg/semtech-loramac: refactor API to make it thread-safe

This commit is contained in:
Alexandre Abadie 2018-03-19 08:27:16 +01:00
parent 689333ff04
commit 5b76fdf46e
4 changed files with 532 additions and 277 deletions

View File

@ -28,6 +28,7 @@
#include <string.h>
#include "msg.h"
#include "mutex.h"
#include "net/netdev.h"
#include "net/loramac.h"
@ -63,30 +64,21 @@
#define SEMTECH_LORAMAC_MSG_QUEUE (16U)
#define SEMTECH_LORAMAC_LORAMAC_STACKSIZE (THREAD_STACKSIZE_DEFAULT)
static msg_t _semtech_loramac_msg_queue[SEMTECH_LORAMAC_MSG_QUEUE];
static char _semtech_loramac_stack[SEMTECH_LORAMAC_LORAMAC_STACKSIZE];
kernel_pid_t semtech_loramac_pid;
kernel_pid_t semtech_loramac_handler_pid;
sx127x_t sx127x;
RadioEvents_t semtech_loramac_radio_events;
uint8_t semtech_loramac_dev_eui[LORAMAC_DEVEUI_LEN];
uint8_t semtech_loramac_app_eui[LORAMAC_APPEUI_LEN];
uint8_t semtech_loramac_app_key[LORAMAC_APPKEY_LEN];
uint8_t semtech_loramac_nwk_skey[LORAMAC_NWKSKEY_LEN];
uint8_t semtech_loramac_app_skey[LORAMAC_APPSKEY_LEN];
uint8_t semtech_loramac_dev_addr[LORAMAC_DEVADDR_LEN];
static uint8_t _semtech_loramac_radio_payload[SX127X_RX_BUFFER_SIZE];
static semtech_loramac_rx_data_t _semtech_loramac_rx_data;
LoRaMacPrimitives_t semtech_loramac_primitives;
LoRaMacCallback_t semtech_loramac_callbacks;
typedef struct {
uint8_t port;
uint8_t cnf;
uint8_t dr;
uint8_t *payload;
uint8_t len;
} loramac_send_params_t;
typedef void (*semtech_loramac_func_t)(void *);
typedef void (*semtech_loramac_func_t)(semtech_loramac_t *, void *);
/**
* @brief Struct containing a semtech loramac function call
@ -99,12 +91,13 @@ typedef struct {
} semtech_loramac_call_t;
/* Prepares the payload of the frame */
static bool _semtech_loramac_send(uint8_t cnf, uint8_t port, uint8_t dr,
static bool _semtech_loramac_send(semtech_loramac_t *mac,
uint8_t *payload, uint8_t len)
{
DEBUG("[semtech-loramac] send frame %s\n", (char *)payload);
McpsReq_t mcpsReq;
LoRaMacTxInfo_t txInfo;
uint8_t dr = semtech_loramac_get_dr(mac);
if (LoRaMacQueryTxPossible(len, &txInfo) != LORAMAC_STATUS_OK) {
DEBUG("[semtech-loramac] empty frame in order to flush MAC commands\n");
@ -115,10 +108,10 @@ static bool _semtech_loramac_send(uint8_t cnf, uint8_t port, uint8_t dr,
mcpsReq.Req.Unconfirmed.Datarate = (int8_t)dr;
}
else {
if (cnf == LORAMAC_TX_UNCNF) {
if (mac->cnf == LORAMAC_TX_UNCNF) {
DEBUG("[semtech-loramac] MCPS_UNCONFIRMED\n");
mcpsReq.Type = MCPS_UNCONFIRMED;
mcpsReq.Req.Unconfirmed.fPort = port;
mcpsReq.Req.Unconfirmed.fPort = mac->port;
mcpsReq.Req.Unconfirmed.fBuffer = payload;
mcpsReq.Req.Unconfirmed.fBufferSize = len;
mcpsReq.Req.Unconfirmed.Datarate = (int8_t)dr;
@ -126,7 +119,7 @@ static bool _semtech_loramac_send(uint8_t cnf, uint8_t port, uint8_t dr,
else {
DEBUG("[semtech-loramac] MCPS_CONFIRMED\n");
mcpsReq.Type = MCPS_CONFIRMED;
mcpsReq.Req.Confirmed.fPort = port;
mcpsReq.Req.Confirmed.fPort = mac->port;
mcpsReq.Req.Confirmed.fBuffer = payload;
mcpsReq.Req.Confirmed.fBufferSize = len;
mcpsReq.Req.Confirmed.NbTrials = 3;
@ -156,9 +149,8 @@ static void mcps_confirm(McpsConfirm_t *confirm)
Check TxPower */
DEBUG("[semtech-loramac] MCPS confirm event UNCONFIRMED\n");
msg_t msg;
msg.type = MSG_TYPE_LORAMAC_NOTIFY;
msg.content.value = SEMTECH_LORAMAC_TX_DONE;
msg_send(&msg, semtech_loramac_handler_pid);
msg.type = MSG_TYPE_LORAMAC_TX_DONE;
msg_send(&msg, semtech_loramac_pid);
break;
}
@ -214,28 +206,15 @@ static void mcps_indication(McpsIndication_t *indication)
}
msg_t msg;
msg.type = MSG_TYPE_LORAMAC_NOTIFY;
if (indication->RxData) {
indication->Buffer[indication->BufferSize] = '\0';
memcpy(_semtech_loramac_rx_data.payload, indication->Buffer,
indication->BufferSize);
_semtech_loramac_rx_data.payload[indication->BufferSize] = 0;
_semtech_loramac_rx_data.payload_len = indication->BufferSize;
_semtech_loramac_rx_data.port = indication->Port;
DEBUG("[semtech-loramac] MCPS indication:\n"
" - Payload: %s\n"
" - Size: %d\n"
" - Port: %d\n",
(char *)_semtech_loramac_rx_data.payload,
_semtech_loramac_rx_data.payload_len,
_semtech_loramac_rx_data.port
);
msg.content.value = SEMTECH_LORAMAC_RX_DATA;
DEBUG("[semtech-loramac] MCPS indication: data received\n");
msg.type = MSG_TYPE_LORAMAC_RX;
msg.content.ptr = indication;
}
else {
msg.content.value = SEMTECH_LORAMAC_TX_DONE;
msg.type = MSG_TYPE_LORAMAC_TX_DONE;
}
msg_send(&msg, semtech_loramac_handler_pid);
msg_send(&msg, semtech_loramac_pid);
}
/*MLME-Confirm event function */
@ -248,17 +227,17 @@ static void mlme_confirm(MlmeConfirm_t *confirm)
/* Status is OK, node has joined the network */
DEBUG("[semtech-loramac] join succeeded\n");
msg_t msg;
msg.type = MSG_TYPE_LORAMAC_NOTIFY;
msg.type = MSG_TYPE_LORAMAC_JOIN;
msg.content.value = SEMTECH_LORAMAC_JOIN_SUCCEEDED;
msg_send(&msg, semtech_loramac_handler_pid);
msg_send(&msg, semtech_loramac_pid);
}
else {
DEBUG("[semtech-loramac] join not successful\n");
/* Join was not successful. */
msg_t msg;
msg.type = MSG_TYPE_LORAMAC_NOTIFY;
msg.type = MSG_TYPE_LORAMAC_JOIN;
msg.content.value = SEMTECH_LORAMAC_JOIN_FAILED;
msg_send(&msg, semtech_loramac_handler_pid);
msg_send(&msg, semtech_loramac_pid);
}
break;
@ -267,24 +246,10 @@ static void mlme_confirm(MlmeConfirm_t *confirm)
}
}
void _loramac_set_rx2_params(uint32_t freq, uint8_t dr)
{
Rx2ChannelParams_t params;
params.Frequency = freq;
params.Datarate = dr;
MibRequestConfirm_t mibReq;
mibReq.Type = MIB_RX2_DEFAULT_CHANNEL;
mibReq.Param.Rx2DefaultChannel = params;
LoRaMacMibSetRequestConfirm(&mibReq);
mibReq.Type = MIB_RX2_CHANNEL;
mibReq.Param.Rx2Channel = params;
LoRaMacMibSetRequestConfirm(&mibReq);
}
void _init_loramac(LoRaMacPrimitives_t * primitives, LoRaMacCallback_t *callbacks)
void _init_loramac(semtech_loramac_t *mac,
LoRaMacPrimitives_t * primitives, LoRaMacCallback_t *callbacks)
{
mutex_lock(&mac->lock);
DEBUG("[semtech-loramac] initializing loramac\n");
primitives->MacMcpsConfirm = mcps_confirm;
primitives->MacMcpsIndication = mcps_indication;
@ -324,9 +289,11 @@ void _init_loramac(LoRaMacPrimitives_t * primitives, LoRaMacCallback_t *callback
#else
#error "Please define a region in the compiler options."
#endif
mutex_unlock(&mac->lock);
#if defined(REGION_EU868) && USE_SEMTECH_DEFAULT_CHANNEL_LINEUP
DEBUG("[semtech-loramac] EU868 region: use default channels\n");
mutex_lock(&mac->lock);
LoRaMacChannelAdd(3, (ChannelParams_t)LC4);
LoRaMacChannelAdd(4, (ChannelParams_t)LC5);
LoRaMacChannelAdd(5, (ChannelParams_t)LC6);
@ -334,15 +301,25 @@ void _init_loramac(LoRaMacPrimitives_t * primitives, LoRaMacCallback_t *callback
LoRaMacChannelAdd(7, (ChannelParams_t)LC8);
LoRaMacChannelAdd(8, (ChannelParams_t)LC9);
LoRaMacChannelAdd(9, (ChannelParams_t)LC10);
mutex_unlock(&mac->lock);
_loramac_set_rx2_params(LORAMAC_DEFAULT_RX2_FREQ, LORAMAC_DEFAULT_RX2_DR);
semtech_loramac_set_rx2_dr(mac, LORAMAC_DEFAULT_RX2_DR);
semtech_loramac_set_rx2_freq(mac, LORAMAC_DEFAULT_RX2_FREQ);
#endif
semtech_loramac_set_dr(mac, LORAMAC_DEFAULT_DR);
semtech_loramac_set_adr(mac, LORAMAC_DEFAULT_ADR);
semtech_loramac_set_public_network(mac, LORAMAC_DEFAULT_PUBLIC_NETWORK);
semtech_loramac_set_class(mac, LORAMAC_DEFAULT_DEVICE_CLASS);
semtech_loramac_set_tx_port(mac, LORAMAC_DEFAULT_TX_PORT);
semtech_loramac_set_tx_mode(mac, LORAMAC_DEFAULT_TX_MODE);
}
static void _join_otaa(void)
static void _join_otaa(semtech_loramac_t *mac)
{
DEBUG("[semtech-loramac] starting OTAA join\n");
mutex_lock(&mac->lock);
MibRequestConfirm_t mibReq;
mibReq.Type = MIB_NETWORK_JOINED;
mibReq.Param.IsNetworkJoined = false;
@ -350,65 +327,69 @@ static void _join_otaa(void)
MlmeReq_t mlmeReq;
mlmeReq.Type = MLME_JOIN;
mlmeReq.Req.Join.DevEui = semtech_loramac_dev_eui;
mlmeReq.Req.Join.AppEui = semtech_loramac_app_eui;
mlmeReq.Req.Join.AppKey = semtech_loramac_app_key;
mlmeReq.Req.Join.DevEui = mac->deveui;
mlmeReq.Req.Join.AppEui = mac->appeui;
mlmeReq.Req.Join.AppKey = mac->appkey;
mlmeReq.Req.Join.NbTrials = LORAWAN_MAX_JOIN_RETRIES;
LoRaMacMlmeRequest(&mlmeReq);
mutex_unlock(&mac->lock);
}
static void _join_abp(void)
static void _join_abp(semtech_loramac_t *mac)
{
DEBUG("[semtech-loramac] starting ABP join\n");
semtech_loramac_set_netid(mac, LORAMAC_DEFAULT_NETID);
mutex_lock(&mac->lock);
MibRequestConfirm_t mibReq;
mibReq.Type = MIB_NETWORK_JOINED;
mibReq.Param.IsNetworkJoined = false;
LoRaMacMibSetRequestConfirm(&mibReq);
semtech_loramac_set_netid(LORAMAC_DEFAULT_NETID);
mibReq.Type = MIB_DEV_ADDR;
mibReq.Param.DevAddr = ((uint32_t)semtech_loramac_dev_addr[0] << 24 |
(uint32_t)semtech_loramac_dev_addr[1] << 16 |
(uint32_t)semtech_loramac_dev_addr[2] << 8 |
(uint32_t)semtech_loramac_dev_addr[3]);
mibReq.Param.DevAddr = ((uint32_t)mac->devaddr[0] << 24 |
(uint32_t)mac->devaddr[1] << 16 |
(uint32_t)mac->devaddr[2] << 8 |
(uint32_t)mac->devaddr[3]);
LoRaMacMibSetRequestConfirm(&mibReq);
mibReq.Type = MIB_NWK_SKEY;
mibReq.Param.NwkSKey = semtech_loramac_nwk_skey;
mibReq.Param.NwkSKey = mac->nwkskey;
LoRaMacMibSetRequestConfirm(&mibReq);
mibReq.Type = MIB_APP_SKEY;
mibReq.Param.AppSKey = semtech_loramac_app_skey;
mibReq.Param.AppSKey = mac->appskey;
LoRaMacMibSetRequestConfirm(&mibReq);
mibReq.Type = MIB_NETWORK_JOINED;
mibReq.Param.IsNetworkJoined = true;
LoRaMacMibSetRequestConfirm(&mibReq);
/* switch back to idle state now*/
mac->state = SEMTECH_LORAMAC_STATE_IDLE;
mutex_unlock(&mac->lock);
}
static void _join(void *arg)
static void _join(semtech_loramac_t *mac, void *arg)
{
(void) arg;
uint8_t join_type = *(uint8_t *)arg;
switch (join_type) {
case LORAMAC_JOIN_OTAA:
_join_otaa();
_join_otaa(mac);
break;
case LORAMAC_JOIN_ABP:
_join_abp();
_join_abp(mac);
break;
}
}
static void _send(void *arg)
static void _send(semtech_loramac_t *mac, void *arg)
{
loramac_send_params_t params = *(loramac_send_params_t *)arg;
_semtech_loramac_send(params.cnf, params.port, params.dr,
params.payload, params.len);
_semtech_loramac_send(mac, params.payload, params.len);
}
static void _semtech_loramac_call(semtech_loramac_func_t func, void *arg)
@ -417,10 +398,10 @@ static void _semtech_loramac_call(semtech_loramac_func_t func, void *arg)
call.func = func;
call.arg = arg;
msg_t msg;
msg_t msg, msg_resp;
msg.type = MSG_TYPE_LORAMAC_CMD;
msg.content.ptr = &call;
msg_send(&msg, semtech_loramac_pid);
msg_send_receive(&msg, &msg_resp, semtech_loramac_pid);
}
static void _semtech_loramac_event_cb(netdev_t *dev, netdev_event_t event)
@ -454,12 +435,12 @@ static void _semtech_loramac_event_cb(netdev_t *dev, netdev_event_t event)
case NETDEV_EVENT_RX_COMPLETE:
{
size_t len;
uint8_t radio_payload[SX127X_RX_BUFFER_SIZE];
len = dev->driver->recv(dev, NULL, 0, 0);
dev->driver->recv(dev, _semtech_loramac_radio_payload, len, &packet_info);
semtech_loramac_radio_events.RxDone(_semtech_loramac_radio_payload,
len,
packet_info.rssi,
packet_info.snr);
dev->driver->recv(dev, radio_payload, len, &packet_info);
semtech_loramac_radio_events.RxDone(radio_payload,
len, packet_info.rssi,
packet_info.snr);
break;
}
case NETDEV_EVENT_RX_TIMEOUT:
@ -492,69 +473,105 @@ static void _semtech_loramac_event_cb(netdev_t *dev, netdev_event_t event)
void *_semtech_loramac_event_loop(void *arg)
{
(void) arg;
static msg_t _msg_q[SEMTECH_LORAMAC_MSG_QUEUE];
msg_init_queue(_msg_q, SEMTECH_LORAMAC_MSG_QUEUE);
LoRaMacPrimitives_t primitives;
LoRaMacCallback_t callbacks;
_init_loramac(&primitives, &callbacks);
semtech_loramac_set_dr(LORAMAC_DEFAULT_DR);
semtech_loramac_set_adr(LORAMAC_DEFAULT_ADR);
semtech_loramac_set_public_network(LORAMAC_DEFAULT_PUBLIC_NETWORK);
semtech_loramac_set_class(LORAMAC_DEFAULT_DEVICE_CLASS);
msg_init_queue(_semtech_loramac_msg_queue, SEMTECH_LORAMAC_MSG_QUEUE);
semtech_loramac_t *mac = (semtech_loramac_t *)arg;
while (1) {
msg_t msg;
msg_receive(&msg);
switch (msg.type) {
case MSG_TYPE_ISR:
{
netdev_t *dev = msg.content.ptr;
dev->driver->isr(dev);
break;
}
case MSG_TYPE_RX_TIMEOUT:
DEBUG("[semtech-loramac] RX timer timeout\n");
semtech_loramac_radio_events.RxTimeout();
break;
if (msg.type == MSG_TYPE_ISR) {
netdev_t *dev = msg.content.ptr;
dev->driver->isr(dev);
}
else {
switch (msg.type) {
case MSG_TYPE_RX_TIMEOUT:
DEBUG("[semtech-loramac] RX timer timeout\n");
semtech_loramac_radio_events.RxTimeout();
break;
case MSG_TYPE_TX_TIMEOUT:
DEBUG("[semtech-loramac] TX timer timeout\n");
semtech_loramac_radio_events.TxTimeout();
break;
case MSG_TYPE_TX_TIMEOUT:
DEBUG("[semtech-loramac] TX timer timeout\n");
semtech_loramac_radio_events.TxTimeout();
break;
case MSG_TYPE_MAC_TIMEOUT:
{
DEBUG("[semtech-loramac] MAC timer timeout\n");
void (*callback)(void) = msg.content.ptr;
callback();
break;
case MSG_TYPE_MAC_TIMEOUT:
{
DEBUG("[semtech-loramac] MAC timer timeout\n");
void (*callback)(void) = msg.content.ptr;
callback();
break;
}
case MSG_TYPE_LORAMAC_CMD:
{
msg_t msg_resp;
DEBUG("[semtech-loramac] loramac cmd\n");
mac->state = SEMTECH_LORAMAC_STATE_BUSY;
semtech_loramac_call_t *call = msg.content.ptr;
call->func(mac, call->arg);
msg_reply(&msg, &msg_resp);
break;
}
case MSG_TYPE_LORAMAC_JOIN:
{
DEBUG("[semtech-loramac] loramac join notification\n");
msg_t msg_ret;
msg_ret.content.value = msg.content.value;
msg_send(&msg_ret, mac->caller_pid);
/* switch back to idle state now*/
mac->state = SEMTECH_LORAMAC_STATE_IDLE;
break;
}
case MSG_TYPE_LORAMAC_TX_DONE:
{
DEBUG("[semtech-loramac] loramac TX done\n");
msg_t msg_ret;
msg_ret.type = MSG_TYPE_LORAMAC_TX_DONE;
msg_send(&msg_ret, mac->caller_pid);
/* switch back to idle state now*/
mac->state = SEMTECH_LORAMAC_STATE_IDLE;
break;
}
case MSG_TYPE_LORAMAC_RX:
{
msg_t msg_ret;
msg_ret.type = MSG_TYPE_LORAMAC_RX;
McpsIndication_t *indication = (McpsIndication_t *)msg.content.ptr;
memcpy(mac->rx_data.payload,
indication->Buffer, indication->BufferSize);
mac->rx_data.payload_len = indication->BufferSize;
mac->rx_data.port = indication->Port;
DEBUG("[semtech-loramac] loramac RX data:\n"
" - Payload: %s\n"
" - Size: %d\n"
" - Port: %d\n",
(char *)mac->rx_data.payload,
mac->rx_data.payload_len,
mac->rx_data.port);
msg_send(&msg_ret, mac->caller_pid);
/* switch back to idle state now*/
mac->state = SEMTECH_LORAMAC_STATE_IDLE;
break;
}
default:
DEBUG("[semtech-loramac] Unexpected msg type '%04x'\n",
msg.type);
}
case MSG_TYPE_LORAMAC_CMD:
{
DEBUG("[semtech-loramac] loramac cmd\n");
semtech_loramac_call_t *call = msg.content.ptr;
call->func(call->arg);
break;
}
default:
DEBUG("[semtech-loramac] Unexpected msg type '%04x'\n", msg.type);
}
}
}
int semtech_loramac_init(sx127x_t *dev)
int semtech_loramac_init(semtech_loramac_t *mac)
{
dev->netdev.driver = &sx127x_driver;
dev->netdev.event_callback = _semtech_loramac_event_cb;
sx127x_setup(&sx127x, &sx127x_params[0]);
sx127x.netdev.driver = &sx127x_driver;
sx127x.netdev.event_callback = _semtech_loramac_event_cb;
semtech_loramac_handler_pid = thread_getpid();
semtech_loramac_pid = thread_create(_semtech_loramac_stack,
sizeof(_semtech_loramac_stack),
THREAD_PRIORITY_MAIN - 1,
THREAD_CREATE_STACKTEST,
_semtech_loramac_event_loop, NULL,
_semtech_loramac_event_loop, mac,
"recv_thread");
if (semtech_loramac_pid <= KERNEL_PID_UNDEF) {
@ -562,17 +579,29 @@ int semtech_loramac_init(sx127x_t *dev)
return -1;
}
_init_loramac(mac, &semtech_loramac_primitives, &semtech_loramac_callbacks);
return 0;
}
uint8_t semtech_loramac_join(uint8_t type)
uint8_t semtech_loramac_join(semtech_loramac_t *mac, uint8_t type)
{
DEBUG("Starting join procedure: %d\n", type);
if (mac->state != SEMTECH_LORAMAC_STATE_IDLE) {
DEBUG("[semtech-loramac] internal mac is busy\n");
return SEMTECH_LORAMAC_BUSY;
}
mac->caller_pid = thread_getpid();
_semtech_loramac_call(_join, &type);
if (type == LORAMAC_JOIN_OTAA) {
/* Wait until the OTAA join procedure is complete */
msg_t msg;
msg_receive(&msg);
mac->state = SEMTECH_LORAMAC_STATE_IDLE;
return (uint8_t)msg.content.value;
}
@ -580,36 +609,47 @@ uint8_t semtech_loramac_join(uint8_t type)
return SEMTECH_LORAMAC_JOIN_SUCCEEDED;
}
uint8_t semtech_loramac_send(uint8_t cnf, uint8_t port,
uint8_t *tx_buf, uint8_t tx_len,
semtech_loramac_rx_data_t *rx_data)
uint8_t semtech_loramac_send(semtech_loramac_t *mac, uint8_t *data, uint8_t len)
{
mutex_lock(&mac->lock);
MibRequestConfirm_t mibReq;
mibReq.Type = MIB_NETWORK_JOINED;
LoRaMacMibGetRequestConfirm(&mibReq);
bool is_joined = mibReq.Param.IsNetworkJoined;
mutex_unlock(&mac->lock);
if (!mibReq.Param.IsNetworkJoined) {
if (!is_joined) {
DEBUG("[semtech-loramac] network is not joined\n");
return SEMTECH_LORAMAC_NOT_JOINED;
}
if (mac->state != SEMTECH_LORAMAC_STATE_IDLE) {
DEBUG("[semtech-loramac] internal mac is busy\n");
return SEMTECH_LORAMAC_BUSY;
}
loramac_send_params_t params;
params.cnf = cnf;
params.port = port;
params.dr = semtech_loramac_get_dr();
params.payload = tx_buf;
params.len = tx_len;
params.payload = data;
params.len = len;
_semtech_loramac_call(_send, &params);
/* Wait until sending is fully done */
return SEMTECH_LORAMAC_TX_SCHEDULED;
}
uint8_t semtech_loramac_recv(semtech_loramac_t *mac)
{
mac->caller_pid = thread_getpid();
/* Wait until the mac receive some information */
msg_t msg;
msg_receive(&msg);
uint8_t status = (uint8_t)msg.content.value;
if (status == SEMTECH_LORAMAC_RX_DATA) {
memcpy(rx_data, &_semtech_loramac_rx_data,
sizeof(semtech_loramac_rx_data_t));
uint8_t ret = SEMTECH_LORAMAC_TX_DONE;
if (msg.type == MSG_TYPE_LORAMAC_RX) {
ret = SEMTECH_LORAMAC_DATA_RECEIVED;
}
return status;
DEBUG("[semtech-loramac] MAC reply received: %d\n", ret);
return ret;
}

View File

@ -19,6 +19,8 @@
#include <string.h>
#include "mutex.h"
#include "net/loramac.h"
#include "semtech-loramac/board.h"
@ -27,217 +29,302 @@
#define ENABLE_DEBUG (0)
#include "debug.h"
extern uint8_t semtech_loramac_dev_eui[LORAMAC_DEVEUI_LEN];
extern uint8_t semtech_loramac_app_eui[LORAMAC_APPEUI_LEN];
extern uint8_t semtech_loramac_app_key[LORAMAC_APPKEY_LEN];
extern uint8_t semtech_loramac_nwk_skey[LORAMAC_NWKSKEY_LEN];
extern uint8_t semtech_loramac_app_skey[LORAMAC_APPSKEY_LEN];
extern uint8_t semtech_loramac_dev_addr[LORAMAC_DEVADDR_LEN];
extern void _loramac_set_rx2_params(uint32_t freq, uint8_t dr);
void semtech_loramac_set_deveui(const uint8_t *eui)
void semtech_loramac_set_deveui(semtech_loramac_t *mac, const uint8_t *eui)
{
memcpy(semtech_loramac_dev_eui, eui, LORAMAC_DEVEUI_LEN);
memcpy(mac->deveui, eui, LORAMAC_DEVEUI_LEN);
}
void semtech_loramac_get_deveui(uint8_t *eui)
void semtech_loramac_get_deveui(const semtech_loramac_t *mac, uint8_t *eui)
{
memcpy(eui, semtech_loramac_dev_eui, LORAMAC_DEVEUI_LEN);
memcpy(eui, mac->deveui, LORAMAC_DEVEUI_LEN);
}
void semtech_loramac_set_appeui(const uint8_t *eui)
void semtech_loramac_set_appeui(semtech_loramac_t *mac, const uint8_t *eui)
{
memcpy(semtech_loramac_app_eui, eui, LORAMAC_APPEUI_LEN);
memcpy(mac->appeui, eui, LORAMAC_APPEUI_LEN);
}
void semtech_loramac_get_appeui(uint8_t *eui)
void semtech_loramac_get_appeui(const semtech_loramac_t *mac, uint8_t *eui)
{
memcpy(eui, semtech_loramac_app_eui, LORAMAC_APPEUI_LEN);
memcpy(eui, mac->appeui, LORAMAC_APPEUI_LEN);
}
void semtech_loramac_set_appkey(const uint8_t *key)
void semtech_loramac_set_appkey(semtech_loramac_t *mac, const uint8_t *key)
{
memcpy(semtech_loramac_app_key, key, LORAMAC_APPKEY_LEN);
memcpy(mac->appkey, key, LORAMAC_APPKEY_LEN);
}
void semtech_loramac_get_appkey(uint8_t *key)
void semtech_loramac_get_appkey(const semtech_loramac_t *mac, uint8_t *key)
{
memcpy(key, semtech_loramac_app_key, LORAMAC_APPKEY_LEN);
memcpy(key, mac->appkey, LORAMAC_APPKEY_LEN);
}
void semtech_loramac_set_appskey(const uint8_t *skey)
void semtech_loramac_set_appskey(semtech_loramac_t *mac, const uint8_t *skey)
{
memcpy(semtech_loramac_app_skey, skey, LORAMAC_APPSKEY_LEN);
memcpy(mac->appskey, skey, LORAMAC_APPSKEY_LEN);
}
void semtech_loramac_get_appskey(uint8_t *skey)
void semtech_loramac_get_appskey(const semtech_loramac_t *mac, uint8_t *skey)
{
memcpy(skey, semtech_loramac_app_skey, LORAMAC_APPSKEY_LEN);
memcpy(skey, mac->appskey, LORAMAC_APPSKEY_LEN);
}
void semtech_loramac_set_nwkskey(const uint8_t *skey)
void semtech_loramac_set_nwkskey(semtech_loramac_t *mac, const uint8_t *skey)
{
memcpy(semtech_loramac_nwk_skey, skey, LORAMAC_NWKSKEY_LEN);
memcpy(mac->nwkskey, skey, LORAMAC_NWKSKEY_LEN);
}
void semtech_loramac_get_nwkskey(uint8_t *skey)
void semtech_loramac_get_nwkskey(const semtech_loramac_t *mac, uint8_t *skey)
{
memcpy(skey, semtech_loramac_nwk_skey, LORAMAC_NWKSKEY_LEN);
memcpy(skey, mac->nwkskey, LORAMAC_NWKSKEY_LEN);
}
void semtech_loramac_set_devaddr(const uint8_t *addr)
void semtech_loramac_set_devaddr(semtech_loramac_t *mac, const uint8_t *addr)
{
memcpy(semtech_loramac_dev_addr, addr, LORAMAC_DEVADDR_LEN);
memcpy(mac->devaddr, addr, LORAMAC_DEVADDR_LEN);
}
void semtech_loramac_get_devaddr(uint8_t *addr)
void semtech_loramac_get_devaddr(const semtech_loramac_t *mac, uint8_t *addr)
{
memcpy(addr, semtech_loramac_dev_addr, LORAMAC_DEVADDR_LEN);
memcpy(addr, mac->devaddr, LORAMAC_DEVADDR_LEN);
}
void semtech_loramac_set_class(loramac_class_t cls)
void semtech_loramac_set_class(semtech_loramac_t *mac, loramac_class_t cls)
{
mutex_lock(&mac->lock);
DEBUG("[semtech-loramac] set class %d\n", cls);
MibRequestConfirm_t mibReq;
mibReq.Type = MIB_DEVICE_CLASS;
mibReq.Param.Class = (DeviceClass_t)cls;
LoRaMacMibSetRequestConfirm(&mibReq);
mutex_unlock(&mac->lock);
}
loramac_class_t semtech_loramac_get_class(void)
loramac_class_t semtech_loramac_get_class(semtech_loramac_t *mac)
{
mutex_lock(&mac->lock);
loramac_class_t cls;
DEBUG("[semtech-loramac] get device class\n");
MibRequestConfirm_t mibReq;
mibReq.Type = MIB_DEVICE_CLASS;
LoRaMacMibGetRequestConfirm(&mibReq);
return (loramac_class_t)mibReq.Param.Class;
cls = (loramac_class_t)mibReq.Param.Class;
mutex_unlock(&mac->lock);
return cls;
}
void semtech_loramac_set_dr(uint8_t dr)
void semtech_loramac_set_dr(semtech_loramac_t *mac, uint8_t dr)
{
mutex_lock(&mac->lock);
DEBUG("[semtech-loramac] set dr %d\n", dr);
MibRequestConfirm_t mibReq;
mibReq.Type = MIB_CHANNELS_DEFAULT_DATARATE;
mibReq.Param.ChannelsDatarate = dr;
LoRaMacMibSetRequestConfirm(&mibReq);
mutex_unlock(&mac->lock);
}
uint8_t semtech_loramac_get_dr(void)
uint8_t semtech_loramac_get_dr(semtech_loramac_t *mac)
{
mutex_lock(&mac->lock);
DEBUG("[semtech-loramac] get dr\n");
uint8_t datarate;
MibRequestConfirm_t mibReq;
mibReq.Type = MIB_CHANNELS_DEFAULT_DATARATE;
LoRaMacMibGetRequestConfirm(&mibReq);
return (uint8_t)mibReq.Param.ChannelsDatarate;
datarate = (uint8_t)mibReq.Param.ChannelsDatarate;
mutex_unlock(&mac->lock);
return datarate;
}
void semtech_loramac_set_adr(bool adr)
void semtech_loramac_set_adr(semtech_loramac_t *mac, bool adr)
{
mutex_lock(&mac->lock);
DEBUG("[semtech-loramac] set adr %d\n", adr);
MibRequestConfirm_t mibReq;
mibReq.Type = MIB_ADR;
mibReq.Param.AdrEnable = adr;
LoRaMacMibSetRequestConfirm(&mibReq);
mutex_unlock(&mac->lock);
}
bool semtech_loramac_get_adr(void)
bool semtech_loramac_get_adr(semtech_loramac_t *mac)
{
mutex_lock(&mac->lock);
bool enable;
DEBUG("[semtech-loramac] get adr\n");
MibRequestConfirm_t mibReq;
mibReq.Type = MIB_ADR;
LoRaMacMibGetRequestConfirm(&mibReq);
return mibReq.Param.AdrEnable;
enable = mibReq.Param.AdrEnable;
mutex_unlock(&mac->lock);
return enable;
}
void semtech_loramac_set_public_network(bool public)
void semtech_loramac_set_public_network(semtech_loramac_t *mac, bool public)
{
mutex_lock(&mac->lock);
DEBUG("[semtech-loramac] set public network %d\n", public);
MibRequestConfirm_t mibReq;
mibReq.Type = MIB_PUBLIC_NETWORK;
mibReq.Param.EnablePublicNetwork = public;
LoRaMacMibSetRequestConfirm(&mibReq);
mutex_unlock(&mac->lock);
}
bool semtech_loramac_get_public_network(void)
bool semtech_loramac_get_public_network(semtech_loramac_t *mac)
{
mutex_lock(&mac->lock);
bool enable;
DEBUG("[semtech-loramac] get public network\n");
MibRequestConfirm_t mibReq;
mibReq.Type = MIB_PUBLIC_NETWORK;
LoRaMacMibGetRequestConfirm(&mibReq);
return mibReq.Param.EnablePublicNetwork;
enable = mibReq.Param.EnablePublicNetwork;
mutex_unlock(&mac->lock);
return enable;
}
void semtech_loramac_set_netid(uint32_t netid)
void semtech_loramac_set_netid(semtech_loramac_t *mac, uint32_t netid)
{
mutex_lock(&mac->lock);
DEBUG("[semtech-loramac] set NetID %lu\n", netid);
MibRequestConfirm_t mibReq;
mibReq.Type = MIB_NET_ID;
mibReq.Param.NetID = netid;
LoRaMacMibSetRequestConfirm(&mibReq);
mutex_unlock(&mac->lock);
}
uint32_t semtech_loramac_get_netid(void)
uint32_t semtech_loramac_get_netid(semtech_loramac_t *mac)
{
mutex_lock(&mac->lock);
uint32_t netid;
DEBUG("[semtech-loramac] get NetID\n");
MibRequestConfirm_t mibReq;
mibReq.Type = MIB_NET_ID;
LoRaMacMibGetRequestConfirm(&mibReq);
return mibReq.Param.NetID;
netid = mibReq.Param.NetID;
mutex_unlock(&mac->lock);
return netid;
}
void semtech_loramac_set_tx_power(uint8_t power)
void semtech_loramac_set_tx_power(semtech_loramac_t *mac, uint8_t power)
{
mutex_lock(&mac->lock);
DEBUG("[semtech-loramac] set TX power %d\n", power);
MibRequestConfirm_t mibReq;
mibReq.Type = MIB_CHANNELS_TX_POWER;
mibReq.Param.ChannelsTxPower = power;
LoRaMacMibSetRequestConfirm(&mibReq);
mutex_unlock(&mac->lock);
}
uint8_t semtech_loramac_get_tx_power(void)
uint8_t semtech_loramac_get_tx_power(semtech_loramac_t *mac)
{
mutex_lock(&mac->lock);
uint8_t tx_power;
DEBUG("[semtech-loramac] get TX power\n");
MibRequestConfirm_t mibReq;
mibReq.Type = MIB_CHANNELS_TX_POWER;
LoRaMacMibGetRequestConfirm(&mibReq);
return (uint8_t)mibReq.Param.ChannelsTxPower;
tx_power = (uint8_t)mibReq.Param.ChannelsTxPower;
mutex_unlock(&mac->lock);
return tx_power;
}
void semtech_loramac_set_rx2_freq(uint8_t freq)
void semtech_loramac_set_tx_port(semtech_loramac_t *mac, uint8_t port)
{
Rx2ChannelParams_t params;
mac->port = port;
}
uint8_t semtech_loramac_get_tx_port(semtech_loramac_t *mac)
{
return mac->port;
}
void semtech_loramac_set_tx_mode(semtech_loramac_t *mac, uint8_t mode)
{
mac->cnf = mode;
}
uint8_t semtech_loramac_get_tx_mode(semtech_loramac_t *mac)
{
return mac->cnf;
}
static void _semtech_loramac_set_rx2_params(semtech_loramac_channel_params_t params)
{
Rx2ChannelParams_t p;
p.Frequency = params.frequency;
p.Datarate = params.datarate;
MibRequestConfirm_t mibReq;
mibReq.Type = MIB_RX2_DEFAULT_CHANNEL;
mibReq.Param.Rx2DefaultChannel = p;
LoRaMacMibSetRequestConfirm(&mibReq);
mibReq.Type = MIB_RX2_CHANNEL;
mibReq.Param.Rx2Channel = p;
LoRaMacMibSetRequestConfirm(&mibReq);
}
void semtech_loramac_set_rx2_freq(semtech_loramac_t *mac, uint32_t freq)
{
mutex_lock(&mac->lock);
DEBUG("[semtech-loramac] setting RX2 freq to %lu\n", freq);
Rx2ChannelParams_t p;
MibRequestConfirm_t mibReq;
mibReq.Type = MIB_RX2_DEFAULT_CHANNEL;
LoRaMacMibGetRequestConfirm(&mibReq);
params.Frequency = freq;
params.Datarate = mibReq.Param.Rx2DefaultChannel.Datarate;
_loramac_set_rx2_params(params.Frequency, params.Datarate);
p.Frequency = freq;
p.Datarate = mibReq.Param.Rx2DefaultChannel.Datarate;
semtech_loramac_channel_params_t params;
params.frequency = freq;
params.datarate = p.Datarate;
_semtech_loramac_set_rx2_params(params);
mutex_unlock(&mac->lock);
}
uint32_t semtech_loramac_get_rx2_freq(void)
uint32_t semtech_loramac_get_rx2_freq(semtech_loramac_t *mac)
{
mutex_lock(&mac->lock);
uint32_t freq;
DEBUG("[semtech-loramac] getting RX2 freq\n");
MibRequestConfirm_t mibReq;
mibReq.Type = MIB_RX2_DEFAULT_CHANNEL;
LoRaMacMibGetRequestConfirm(&mibReq);
return mibReq.Param.Rx2DefaultChannel.Frequency;
freq = mibReq.Param.Rx2DefaultChannel.Frequency;
mutex_unlock(&mac->lock);
return freq;
}
void semtech_loramac_set_rx2_dr(uint8_t dr)
void semtech_loramac_set_rx2_dr(semtech_loramac_t *mac, uint8_t dr)
{
Rx2ChannelParams_t params;
mutex_lock(&mac->lock);
DEBUG("[semtech-loramac] setting RX2 datarate to %d\n", dr);
Rx2ChannelParams_t p;
MibRequestConfirm_t mibReq;
mibReq.Type = MIB_RX2_DEFAULT_CHANNEL;
LoRaMacMibGetRequestConfirm(&mibReq);
params.Datarate = dr;
params.Frequency = mibReq.Param.Rx2DefaultChannel.Frequency;
_loramac_set_rx2_params(params.Frequency, params.Datarate);
p.Datarate = dr;
p.Frequency = mibReq.Param.Rx2DefaultChannel.Frequency;
semtech_loramac_channel_params_t params;
params.datarate = dr;
params.frequency = p.Frequency;
_semtech_loramac_set_rx2_params(params);
mutex_unlock(&mac->lock);
}
uint8_t semtech_loramac_get_rx2_dr(void)
uint8_t semtech_loramac_get_rx2_dr(semtech_loramac_t *mac)
{
mutex_lock(&mac->lock);
uint8_t datarate;
DEBUG("[semtech-loramac] getting RX2 datarate\n");
MibRequestConfirm_t mibReq;
mibReq.Type = MIB_RX2_DEFAULT_CHANNEL;
LoRaMacMibGetRequestConfirm(&mibReq);
return mibReq.Param.Rx2DefaultChannel.Datarate;
datarate = mibReq.Param.Rx2DefaultChannel.Datarate;
mutex_unlock(&mac->lock);
return datarate;
}

View File

@ -60,6 +60,10 @@ void TimerSetValue(TimerEvent_t *obj, uint32_t value)
xtimer_remove(&(obj->dev));
}
/* According to the lorawan specifications, the data sent from the gateway
could arrive with a short shift in time of +/- 20ms. Here the timeout is
triggered 50ms in advance to make sure the radio switches to RX mode on
time and doesn't miss any downlink messages. */
obj->timeout = (value - 50) * 1000;
}

View File

@ -24,6 +24,10 @@ extern "C" {
#endif
#include <inttypes.h>
#include "mutex.h"
#include "net/netdev.h"
#include "net/loramac.h"
#include "sx127x.h"
@ -37,7 +41,9 @@ extern "C" {
#define MSG_TYPE_TX_TIMEOUT (0x3458) /**< radio driver TX timeout */
#define MSG_TYPE_MAC_TIMEOUT (0x3459) /**< MAC timers timeout */
#define MSG_TYPE_LORAMAC_CMD (0x3460) /**< Command sent to the MAC */
#define MSG_TYPE_LORAMAC_NOTIFY (0x3461) /**< MAC notifications */
#define MSG_TYPE_LORAMAC_JOIN (0x3461) /**< MAC join event */
#define MSG_TYPE_LORAMAC_TX_DONE (0x3462) /**< MAC TX completes */
#define MSG_TYPE_LORAMAC_RX (0x3463) /**< Some data received */
/** @} */
/**
@ -46,16 +52,34 @@ extern "C" {
#define LORAWAN_APP_DATA_MAX_SIZE (242U)
/**
* @brief LoRaMAC status
* @brief LoRaMAC return status
*/
enum {
SEMTECH_LORAMAC_JOIN_SUCCEEDED, /**< Join procedure succeeded */
SEMTECH_LORAMAC_JOIN_FAILED, /**< Join procedure failed */
SEMTECH_LORAMAC_NOT_JOINED, /**< MAC is not joined */
SEMTECH_LORAMAC_TX_SCHEDULED, /**< TX data scheduled */
SEMTECH_LORAMAC_TX_DONE, /**< Transmission completed */
SEMTECH_LORAMAC_RX_DATA, /**< Data received */
SEMTECH_LORAMAC_DATA_RECEIVED, /**< Data received */
SEMTECH_LORAMAC_BUSY /**< Internal MAC is busy */
};
/**
* @brief LoRaMAC internal state
*/
enum {
SEMTECH_LORAMAC_STATE_IDLE = 0,
SEMTECH_LORAMAC_STATE_BUSY
};
/**
* @brief LoRaMAC channel radio parameters
*/
typedef struct {
uint32_t frequency; /**< channel center frequency */
uint8_t datarate; /**< channel datarate */
} semtech_loramac_channel_params_t;
/**
* @brief Structure containing LoRaWAN RX data
*/
@ -66,237 +90,337 @@ typedef struct {
} semtech_loramac_rx_data_t;
/**
* @brief Initializes semtech loramac
* @brief Semtech LoRaMAC descriptor
*/
typedef struct {
mutex_t lock; /**< loramac access lock */
uint8_t state; /**< internal loramac state */
uint8_t caller_pid; /**< pid of caller thread */
uint8_t port; /**< application TX port */
uint8_t cnf; /**< enable/disable confirmable messages */
uint8_t deveui[LORAMAC_DEVEUI_LEN]; /**< device EUI */
uint8_t appeui[LORAMAC_APPEUI_LEN]; /**< application EUI */
uint8_t appkey[LORAMAC_APPKEY_LEN]; /**< application key */
uint8_t appskey[LORAMAC_APPSKEY_LEN]; /**< application session key */
uint8_t nwkskey[LORAMAC_NWKSKEY_LEN]; /**< network session key */
uint8_t devaddr[LORAMAC_DEVADDR_LEN]; /**< device address */
semtech_loramac_rx_data_t rx_data; /**< struct handling the RX data */
} semtech_loramac_t;
/**
* @brief Initializes the semtech loramac mac
*
* @param[in] dev pointer to the radio device
* @param[in] mac Pointer to loramac descriptor
*
* @return 0 on success
* @return -1 on failure
*/
int semtech_loramac_init(sx127x_t *dev);
int semtech_loramac_init(semtech_loramac_t *mac);
/**
* @brief Starts a LoRaWAN network join procedure
*
* This function blocks until the join procedure succeeds or fails.
*
* @param[in] mac Pointer to the mac
* @param[in] type The type of join procedure (otaa or abp)
*
* @return SEMTECH_LORAMAC_JOIN_SUCCEEDED on success
* @return SEMTECH_LORAMAC_JOIN_FAILED on failure
* @return SEMTECH_LORAMAC_BUSY when the mac is already active (join or tx in progress)
*/
uint8_t semtech_loramac_join(uint8_t type);
uint8_t semtech_loramac_join(semtech_loramac_t *mac, uint8_t type);
/**
* @brief Sends data to LoRaWAN
* @brief Sends data to the LoRaWAN network
*
* @param[in] cnf Use confirmable/unconfirmable send type
* @param[in] port The send port to use (between 1 and 223)
* @param[in] tx_buf The TX buffer
* @param[in] tx_len The length of the TX buffer
* @param[out] rx_data The RX data descriptor
* This function returns immediately and leave the mac in busy state until a
* message is received from the network (with RX1 and RX2 receive windows).
* @see semtech_loramac_recv
*
* @param[in] mac Pointer to the mac
* @param[in] data The TX data
* @param[in] len The length of the TX data
*
* @return SEMTECH_LORAMAC_NOT_JOINED when the network is not joined
* @return SEMTECH_LORAMAC_TX_DONE when TX has completed, no data received
* @return SEMTECH_LORAMAC_RX_DATA when TX has completed and data is received
* @return SEMTECH_LORAMAC_BUSY when the mac is already active (join or tx in progress)
* @return SEMTECH_LORAMAC_TX_SCHEDULED when the TX is scheduled in the mac
*/
uint8_t semtech_loramac_send(uint8_t cnf, uint8_t port,
uint8_t *tx_buf, uint8_t tx_len,
semtech_loramac_rx_data_t *rx_data);
uint8_t semtech_loramac_send(semtech_loramac_t *mac, uint8_t *data, uint8_t len);
/**
* @brief Wait for a message sent by the LoRaWAN network
*
* This function blocks until a single message is received by the mac (RX1 and
* RX2 windows).
* With a class A device, a message can only be received after a send. With a
* class C device, a message can be received at any time. In this case, this
* function can be used in a dedicated listener thread.
*
* @see semtech_loramac_send
*
* @param[in] mac Pointer to the mac
*
* @return SEMTECH_LORAMAC_TX_DONE when TX has completed, no data received
* @return SEMTECH_LORAMAC_DATA_RECEIVED when TX has completed and data is received
*/
uint8_t semtech_loramac_recv(semtech_loramac_t *mac);
/**
* @brief Sets the device EUI
*
* @param[in] eui The device EUI
* @param[in] mac Pointer to the mac
* @param[in] eui The device EUI
*/
void semtech_loramac_set_deveui(const uint8_t *eui);
void semtech_loramac_set_deveui(semtech_loramac_t *mac, const uint8_t *eui);
/**
* @brief Gets the device EUI
*
* @param[out] eui The device EUI
* @param[in] mac Pointer to the mac
* @param[out] eui The device EUI
*/
void semtech_loramac_get_deveui(uint8_t *eui);
void semtech_loramac_get_deveui(const semtech_loramac_t *mac, uint8_t *eui);
/**
* @brief Sets the application EUI
*
* @param[in] eui The application EUI
* @param[in] mac Pointer to the mac
* @param[in] eui The application EUI
*/
void semtech_loramac_set_appeui(const uint8_t *eui);
void semtech_loramac_set_appeui(semtech_loramac_t *mac, const uint8_t *eui);
/**
* @brief Gets the application EUI
*
* @param[out] eui The application EUI
* @param[in] mac Pointer to the mac
* @param[out] eui The application EUI
*/
void semtech_loramac_get_appeui(uint8_t *eui);
void semtech_loramac_get_appeui(const semtech_loramac_t *mac, uint8_t *eui);
/**
* @brief Sets the application key
*
* @param[in] key The application key
* @param[in] mac Pointer to the mac
* @param[in] key The application key
*/
void semtech_loramac_set_appkey(const uint8_t *key);
void semtech_loramac_set_appkey(semtech_loramac_t *mac, const uint8_t *key);
/**
* @brief Gets the application key
*
* @param[in] key The application key
* @param[in] mac Pointer to the mac
* @param[in] key The application key
*/
void semtech_loramac_get_appkey(uint8_t *key);
void semtech_loramac_get_appkey(const semtech_loramac_t *mac, uint8_t *key);
/**
* @brief Sets the application session key
*
* @param[in] skey The application session key
* @param[in] mac Pointer to the mac
* @param[in] skey The application session key
*/
void semtech_loramac_set_appskey(const uint8_t *skey);
void semtech_loramac_set_appskey(semtech_loramac_t *mac, const uint8_t *skey);
/**
* @brief Gets the application session key
*
* @param[in] skey The application session key
* @param[in] mac Pointer to the mac
* @param[in] skey The application session key
*/
void semtech_loramac_get_appskey(uint8_t *skey);
void semtech_loramac_get_appskey(const semtech_loramac_t *mac, uint8_t *skey);
/**
* @brief Sets the network session key
*
* @param[in] skey The network session key
* @param[in] mac Pointer to the mac
* @param[in] skey The network session key
*/
void semtech_loramac_set_nwkskey(const uint8_t *skey);
void semtech_loramac_set_nwkskey(semtech_loramac_t *mac, const uint8_t *skey);
/**
* @brief Gets the network session key
*
* @param[in] skey The network session key
* @param[in] mac Pointer to the mac
* @param[in] skey The network session key
*/
void semtech_loramac_get_nwkskey(uint8_t *skey);
void semtech_loramac_get_nwkskey(const semtech_loramac_t *mac, uint8_t *skey);
/**
* @brief Sets the device address
*
* @param[in] addr The device address
* @param[in] mac Pointer to the mac
* @param[in] addr The device address
*/
void semtech_loramac_set_devaddr(const uint8_t *addr);
void semtech_loramac_set_devaddr(semtech_loramac_t *mac, const uint8_t *addr);
/**
* @brief Gets the device address
*
* @param[in] addr The device address
* @param[in] mac Pointer to the mac
* @param[in] addr The device address
*/
void semtech_loramac_get_devaddr(uint8_t *addr);
void semtech_loramac_get_devaddr(const semtech_loramac_t *mac, uint8_t *addr);
/**
* @brief Sets the device class
*
* @param[in] cls The device class
* @param[in] mac Pointer to the mac
* @param[in] cls The device class
*/
void semtech_loramac_set_class(loramac_class_t cls);
void semtech_loramac_set_class(semtech_loramac_t *mac, loramac_class_t cls);
/**
* @brief Gets the device class
*
* @param[in] mac Pointer to the mac
* @return The device class
*/
loramac_class_t semtech_loramac_get_class(void);
loramac_class_t semtech_loramac_get_class(semtech_loramac_t *mac);
/**
* @brief Sets the channels datarate
*
* @param[in] mac Pointer to the mac
* @param[in] dr The datarate (from 1 to 16)
*/
void semtech_loramac_set_dr(uint8_t dr);
void semtech_loramac_set_dr(semtech_loramac_t *mac, uint8_t dr);
/**
* @brief Gets the channels datarate
*
* @param[in] mac Pointer to the mac
* @return The datarate (from 1 to 16)
*/
uint8_t semtech_loramac_get_dr(void);
uint8_t semtech_loramac_get_dr(semtech_loramac_t *mac);
/**
* @brief Enables/disable adaptive datarate
*
* @param[in] adr Adaptive datarate mode
* @param[in] mac Pointer to the mac
* @param[in] adr Adaptive datarate mode
*/
void semtech_loramac_set_adr(bool adr);
void semtech_loramac_set_adr(semtech_loramac_t *mac, bool adr);
/**
* @brief Checks if adaptive datarate is set
*
* @return true if adr is on, false otherwise
* @param[in] mac Pointer to the mac
* @return true if adr is on, false otherwise
*/
bool semtech_loramac_get_adr(void);
bool semtech_loramac_get_adr(semtech_loramac_t *mac);
/**
* @brief Enable/disable the public network mode
*
* @param[in] public The public network mode
* @param[in] mac Pointer to the mac
* @param[in] public The public network mode
*/
void semtech_loramac_set_public_network(bool public);
void semtech_loramac_set_public_network(semtech_loramac_t *mac, bool public);
/**
* @brief Checks if public network is set
*
* @param[in] mac Pointer to the mac
* @return true if public network is on, false otherwise
*/
bool semtech_loramac_get_public_network(void);
bool semtech_loramac_get_public_network(semtech_loramac_t *mac);
/**
* @brief Sets the NetID (only useful with ABP join procedure)
*
* @param[in] mac Pointer to the mac
* @param[in] netid The NetID
*/
void semtech_loramac_set_netid(uint32_t netid);
void semtech_loramac_set_netid(semtech_loramac_t *mac, uint32_t netid);
/**
* @brief Gets the NetID
*
* @param[in] mac Pointer to the mac
* @return The NetID
*/
uint32_t semtech_loramac_get_netid(void);
uint32_t semtech_loramac_get_netid(semtech_loramac_t *mac);
/**
* @brief Sets the channels TX power index
*
* @param[in] mac Pointer to the mac
* @param[in] power The TX power index (from 1 to 16)
*/
void semtech_loramac_set_tx_power(uint8_t power);
void semtech_loramac_set_tx_power(semtech_loramac_t *mac, uint8_t power);
/**
* @brief Gets the channels TX power index
*
* @param[in] mac Pointer to the mac
* @return The TX power index (from 1 to 16)
*/
uint8_t semtech_loramac_get_tx_power(void);
uint8_t semtech_loramac_get_tx_power(semtech_loramac_t *mac);
/**
* @brief Sets the TX application port
*
* @param[in] mac Pointer to the mac
* @param[in] port The TX application port
*/
void semtech_loramac_set_tx_port(semtech_loramac_t *mac, uint8_t port);
/**
* @brief Gets the TX application port
*
* @param[in] mac Pointer to the mac
* @return The TX application port
*/
uint8_t semtech_loramac_get_tx_port(semtech_loramac_t *mac);
/**
* @brief Sets the TX confirmable mode
*
* @param[in] mac Pointer to the mac
* @param[in] mode The TX mode (confirmable or not confirmable)
*/
void semtech_loramac_set_tx_mode(semtech_loramac_t *mac, uint8_t mode);
/**
* @brief Gets the TX confirmable mode
*
* @param[in] mac Pointer to the mac
* @return The TX mode (confirmable or not confirmable)
*/
uint8_t semtech_loramac_get_tx_mode(semtech_loramac_t *mac);
/**
* @brief Sets the RX2 frequency
*
* @param[in] mac Pointer to the mac
* @param[in] freq The RX2 frequency
*/
void semtech_loramac_set_rx2_freq(uint8_t freq);
void semtech_loramac_set_rx2_freq(semtech_loramac_t *mac, uint32_t freq);
/**
* @brief Gets the RX2 frequency
*
* @param[in] mac Pointer to the mac
* @return The RX2 frequency
*/
uint32_t semtech_loramac_get_rx2_freq(void);
uint32_t semtech_loramac_get_rx2_freq(semtech_loramac_t *mac);
/**
* @brief Sets the RX2 datarate
*
* @param[in] mac Pointer to the mac
* @param[in] dr The RX2 datarate
*/
void semtech_loramac_set_rx2_dr(uint8_t dr);
void semtech_loramac_set_rx2_dr(semtech_loramac_t *mac, uint8_t dr);
/**
* @brief Gets the RX2 datarate
*
* @param[in] mac Pointer to the mac
* @return The RX2 datarate
*/
uint8_t semtech_loramac_get_rx2_dr(void);
uint8_t semtech_loramac_get_rx2_dr(semtech_loramac_t *mac);
#ifdef __cplusplus
}