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:
parent
689333ff04
commit
5b76fdf46e
@ -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, ¶ms);
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user