From 96e059d88a87ee07cf4052b6ff97ee3c0f15b20c Mon Sep 17 00:00:00 2001 From: Alexandre Abadie Date: Sun, 8 Oct 2017 12:47:17 +0200 Subject: [PATCH] pkg: add Semtech LoRaMAC package --- pkg/semtech-loramac/Makefile | 16 + pkg/semtech-loramac/Makefile.dep | 7 + pkg/semtech-loramac/Makefile.include | 3 + pkg/semtech-loramac/Makefile.loramac | 11 + pkg/semtech-loramac/Makefile.loramac_arch | 7 + pkg/semtech-loramac/Makefile.loramac_crypto | 3 + pkg/semtech-loramac/Makefile.loramac_mac | 5 + pkg/semtech-loramac/Makefile.loramac_region | 5 + pkg/semtech-loramac/contrib/Makefile | 8 + pkg/semtech-loramac/contrib/semtech_loramac.c | 615 ++++++++++++++++++ .../contrib/semtech_loramac_getset.c | 243 +++++++ .../contrib/semtech_loramac_radio.c | 253 +++++++ .../contrib/semtech_loramac_timer.c | 87 +++ pkg/semtech-loramac/doc.txt | 111 ++++ .../include/semtech-loramac/board.h | 54 ++ .../include/semtech-loramac/timer.h | 130 ++++ pkg/semtech-loramac/include/semtech_loramac.h | 303 +++++++++ .../patches/0001-adapt-for-RIOT.patch | 277 ++++++++ .../patches/0002-eu868-join-retries.patch | 30 + .../0003-adapt-utilities-functions.patch | 92 +++ 20 files changed, 2260 insertions(+) create mode 100644 pkg/semtech-loramac/Makefile create mode 100644 pkg/semtech-loramac/Makefile.dep create mode 100644 pkg/semtech-loramac/Makefile.include create mode 100644 pkg/semtech-loramac/Makefile.loramac create mode 100644 pkg/semtech-loramac/Makefile.loramac_arch create mode 100644 pkg/semtech-loramac/Makefile.loramac_crypto create mode 100644 pkg/semtech-loramac/Makefile.loramac_mac create mode 100644 pkg/semtech-loramac/Makefile.loramac_region create mode 100644 pkg/semtech-loramac/contrib/Makefile create mode 100644 pkg/semtech-loramac/contrib/semtech_loramac.c create mode 100644 pkg/semtech-loramac/contrib/semtech_loramac_getset.c create mode 100644 pkg/semtech-loramac/contrib/semtech_loramac_radio.c create mode 100644 pkg/semtech-loramac/contrib/semtech_loramac_timer.c create mode 100644 pkg/semtech-loramac/doc.txt create mode 100644 pkg/semtech-loramac/include/semtech-loramac/board.h create mode 100644 pkg/semtech-loramac/include/semtech-loramac/timer.h create mode 100644 pkg/semtech-loramac/include/semtech_loramac.h create mode 100644 pkg/semtech-loramac/patches/0001-adapt-for-RIOT.patch create mode 100644 pkg/semtech-loramac/patches/0002-eu868-join-retries.patch create mode 100644 pkg/semtech-loramac/patches/0003-adapt-utilities-functions.patch diff --git a/pkg/semtech-loramac/Makefile b/pkg/semtech-loramac/Makefile new file mode 100644 index 0000000000..2d9446a499 --- /dev/null +++ b/pkg/semtech-loramac/Makefile @@ -0,0 +1,16 @@ +PKG_NAME=semtech-loramac +PKG_URL=git://github.com/Lora-net/LoRaMac-node.git +PKG_VERSION=f42be67be402a40b3586724800771bfe13fb18e6 +PKG_LICENSE=BSD-3-Clause + +.PHONY: all + +all: git-download + cp Makefile.loramac $(PKG_BUILDDIR)/Makefile + cp Makefile.loramac_mac $(PKG_BUILDDIR)/src/mac/Makefile + cp Makefile.loramac_region $(PKG_BUILDDIR)/src/mac/region/Makefile + cp Makefile.loramac_crypto $(PKG_BUILDDIR)/src/system/crypto/Makefile + cp Makefile.loramac_arch $(PKG_BUILDDIR)/src/boards/mcu/stm32/Makefile + "$(MAKE)" -C $(PKG_BUILDDIR) + +include $(RIOTBASE)/pkg/pkg.mk diff --git a/pkg/semtech-loramac/Makefile.dep b/pkg/semtech-loramac/Makefile.dep new file mode 100644 index 0000000000..5037ad9660 --- /dev/null +++ b/pkg/semtech-loramac/Makefile.dep @@ -0,0 +1,7 @@ +USEMODULE += random + +USEMODULE += semtech_loramac_contrib +USEMODULE += semtech_loramac_mac +USEMODULE += semtech_loramac_mac_region +USEMODULE += semtech_loramac_crypto +USEMODULE += semtech_loramac_arch diff --git a/pkg/semtech-loramac/Makefile.include b/pkg/semtech-loramac/Makefile.include new file mode 100644 index 0000000000..ac4f5f463a --- /dev/null +++ b/pkg/semtech-loramac/Makefile.include @@ -0,0 +1,3 @@ +INCLUDES += -I$(RIOTBASE)/pkg/semtech-loramac/include + +DIRS += $(RIOTBASE)/pkg/semtech-loramac/contrib diff --git a/pkg/semtech-loramac/Makefile.loramac b/pkg/semtech-loramac/Makefile.loramac new file mode 100644 index 0000000000..75be4c5d20 --- /dev/null +++ b/pkg/semtech-loramac/Makefile.loramac @@ -0,0 +1,11 @@ +DIRS += src/mac +DIRS += src/mac/region +DIRS += src/system/crypto +DIRS += src/boards/mcu/stm32 + +INCLUDES += -I$(PKGDIRBASE)/semtech-loramac/src/mac \ + -I$(PKGDIRBASE)/semtech-loramac/src/boards/mcu/stm32 \ + -I$(PKGDIRBASE)/semtech-loramac/src/system/crypto \ + -I$(PKGDIRBASE)/semtech-loramac/src + +include $(RIOTBASE)/Makefile.base diff --git a/pkg/semtech-loramac/Makefile.loramac_arch b/pkg/semtech-loramac/Makefile.loramac_arch new file mode 100644 index 0000000000..da78e4622e --- /dev/null +++ b/pkg/semtech-loramac/Makefile.loramac_arch @@ -0,0 +1,7 @@ +MODULE := semtech_loramac_arch + +SRCS := utilities.c + +CFLAGS += -Wno-sign-compare + +include $(RIOTBASE)/Makefile.base diff --git a/pkg/semtech-loramac/Makefile.loramac_crypto b/pkg/semtech-loramac/Makefile.loramac_crypto new file mode 100644 index 0000000000..57f8f7ef1e --- /dev/null +++ b/pkg/semtech-loramac/Makefile.loramac_crypto @@ -0,0 +1,3 @@ +MODULE := semtech_loramac_crypto + +include $(RIOTBASE)/Makefile.base diff --git a/pkg/semtech-loramac/Makefile.loramac_mac b/pkg/semtech-loramac/Makefile.loramac_mac new file mode 100644 index 0000000000..87382dacb0 --- /dev/null +++ b/pkg/semtech-loramac/Makefile.loramac_mac @@ -0,0 +1,5 @@ +MODULE := semtech_loramac_mac + +CFLAGS += -Wno-sign-compare + +include $(RIOTBASE)/Makefile.base diff --git a/pkg/semtech-loramac/Makefile.loramac_region b/pkg/semtech-loramac/Makefile.loramac_region new file mode 100644 index 0000000000..3d0769944e --- /dev/null +++ b/pkg/semtech-loramac/Makefile.loramac_region @@ -0,0 +1,5 @@ +MODULE := semtech_loramac_mac_region + +CFLAGS += -Wno-missing-field-initializers -Wno-unused-parameter -Wno-sign-compare + +include $(RIOTBASE)/Makefile.base diff --git a/pkg/semtech-loramac/contrib/Makefile b/pkg/semtech-loramac/contrib/Makefile new file mode 100644 index 0000000000..a8321f21eb --- /dev/null +++ b/pkg/semtech-loramac/contrib/Makefile @@ -0,0 +1,8 @@ +MODULE := semtech_loramac_contrib + +INCLUDES += -I$(PKGDIRBASE)/semtech-loramac/src/mac \ + -I$(PKGDIRBASE)/semtech-loramac/src/boards/mcu/stm32 \ + -I$(PKGDIRBASE)/semtech-loramac/src/system/crypto \ + -I$(PKGDIRBASE)/semtech-loramac/src + +include $(RIOTBASE)/Makefile.base diff --git a/pkg/semtech-loramac/contrib/semtech_loramac.c b/pkg/semtech-loramac/contrib/semtech_loramac.c new file mode 100644 index 0000000000..55dc026850 --- /dev/null +++ b/pkg/semtech-loramac/contrib/semtech_loramac.c @@ -0,0 +1,615 @@ +/* + * Copyright (C) 2017 Inria + * 2017 Inria Chile + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @{ + * @ingroup pkg_semtech-loramac + * + * @file + * @brief Implementation of public API for Semtech LoRaMAC + * + * This implementation is an adaption of the applications provided on the + * Semtech Lora-net repository. + * + * The LoRaMAC stack and the SX127x driver run in their own thread and simple + * IPC messages are exchanged to control the MAC. + * + * @author Alexandre Abadie + * @author Jose Alamos + * @} + */ + +#include + +#include "msg.h" + +#include "net/netdev.h" +#include "net/loramac.h" + +#include "sx127x.h" +#include "sx127x_params.h" +#include "sx127x_netdev.h" + +#include "semtech_loramac.h" +#include "semtech-loramac/board.h" +#include "LoRaMac.h" +#include "region/Region.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + +#define LORAWAN_MAX_JOIN_RETRIES (3U) + +#if defined(REGION_EU868) +#define LORAWAN_DUTYCYCLE_ON (true) +#define USE_SEMTECH_DEFAULT_CHANNEL_LINEUP (1) + +#if (USE_SEMTECH_DEFAULT_CHANNEL_LINEUP) +#define LC4 { 867100000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 } +#define LC5 { 867300000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 } +#define LC6 { 867500000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 } +#define LC7 { 867700000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 } +#define LC8 { 867900000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 } +#define LC9 { 868800000, 0, { ( ( DR_7 << 4 ) | DR_7 ) }, 2 } +#define LC10 { 868300000, 0, { ( ( DR_6 << 4 ) | DR_6 ) }, 1 } +#endif /* USE_SEMTECH_DEFAULT_CHANNEL_LINEUP */ +#endif /* REGION_EU868 */ + +#define SEMTECH_LORAMAC_MSG_QUEUE (16U) +#define SEMTECH_LORAMAC_LORAMAC_STACKSIZE (THREAD_STACKSIZE_DEFAULT) +static char _semtech_loramac_stack[SEMTECH_LORAMAC_LORAMAC_STACKSIZE]; +kernel_pid_t semtech_loramac_pid; +kernel_pid_t semtech_loramac_handler_pid; + +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; + +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 *); + +/** + * @brief Struct containing a semtech loramac function call + * + * This function is called inside the semtech loramac thread context. + */ +typedef struct { + semtech_loramac_func_t func; /**< the function to call. */ + void *arg; /**< argument of the function **/ +} semtech_loramac_call_t; + +/* Prepares the payload of the frame */ +static bool _semtech_loramac_send(uint8_t cnf, uint8_t port, uint8_t dr, + uint8_t *payload, uint8_t len) +{ + DEBUG("[semtech-loramac] send frame %s\n", (char *)payload); + McpsReq_t mcpsReq; + LoRaMacTxInfo_t txInfo; + + if (LoRaMacQueryTxPossible(len, &txInfo) != LORAMAC_STATUS_OK) { + DEBUG("[semtech-loramac] empty frame in order to flush MAC commands\n"); + /* Send empty frame in order to flush MAC commands */ + mcpsReq.Type = MCPS_UNCONFIRMED; + mcpsReq.Req.Unconfirmed.fBuffer = NULL; + mcpsReq.Req.Unconfirmed.fBufferSize = 0; + mcpsReq.Req.Unconfirmed.Datarate = (int8_t)dr; + } + else { + if (cnf == LORAMAC_TX_UNCNF) { + DEBUG("[semtech-loramac] MCPS_UNCONFIRMED\n"); + mcpsReq.Type = MCPS_UNCONFIRMED; + mcpsReq.Req.Unconfirmed.fPort = port; + mcpsReq.Req.Unconfirmed.fBuffer = payload; + mcpsReq.Req.Unconfirmed.fBufferSize = len; + mcpsReq.Req.Unconfirmed.Datarate = (int8_t)dr; + } + else { + DEBUG("[semtech-loramac] MCPS_CONFIRMED\n"); + mcpsReq.Type = MCPS_CONFIRMED; + mcpsReq.Req.Confirmed.fPort = port; + mcpsReq.Req.Confirmed.fBuffer = payload; + mcpsReq.Req.Confirmed.fBufferSize = len; + mcpsReq.Req.Confirmed.NbTrials = 3; + mcpsReq.Req.Confirmed.Datarate = (int8_t)dr; + } + } + + if (LoRaMacMcpsRequest(&mcpsReq) == LORAMAC_STATUS_OK) { + DEBUG("[semtech-loramac] MCPS request OK\n"); + return false; + } + + return true; +} + +/* MCPS-Confirm event function */ +static void mcps_confirm(McpsConfirm_t *confirm) +{ + DEBUG("[semtech-loramac] MCPS confirm event\n"); + if (confirm->Status == LORAMAC_EVENT_INFO_STATUS_OK) { + DEBUG("[semtech-loramac] MCPS confirm event OK\n"); + + switch (confirm->McpsRequest) { + case MCPS_UNCONFIRMED: + { + /* Check Datarate + 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); + break; + } + + case MCPS_CONFIRMED: + /* Check Datarate + Check TxPower + Check AckReceived + Check NbTrials */ + DEBUG("[semtech-loramac] MCPS confirm event CONFIRMED\n"); + break; + + case MCPS_PROPRIETARY: + DEBUG("[semtech-loramac] MCPS confirm event PROPRIETARY\n"); + break; + + default: + DEBUG("[semtech-loramac] MCPS confirm event UNKNOWN\n"); + break; + } + } +} + +/* MCPS-Indication event function */ +static void mcps_indication(McpsIndication_t *indication) +{ + DEBUG("[semtech-loramac] MCPS indication event\n"); + if (indication->Status != LORAMAC_EVENT_INFO_STATUS_OK) { + DEBUG("[semtech-loramac] MCPS indication no OK\n"); + return; + } + + if (ENABLE_DEBUG) { + switch (indication->McpsIndication) { + case MCPS_UNCONFIRMED: + DEBUG("[semtech-loramac] MCPS indication Unconfirmed\n"); + break; + + case MCPS_CONFIRMED: + DEBUG("[semtech-loramac] MCPS indication Confirmed\n"); + break; + + case MCPS_PROPRIETARY: + DEBUG("[semtech-loramac] MCPS indication Proprietary\n"); + break; + + case MCPS_MULTICAST: + DEBUG("[semtech-loramac] MCPS indication Multicast\n"); + break; + + default: + break; + } + } + + 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; + } + else { + msg.content.value = SEMTECH_LORAMAC_TX_DONE; + } + msg_send(&msg, semtech_loramac_handler_pid); +} + +/*MLME-Confirm event function */ +static void mlme_confirm(MlmeConfirm_t *confirm) +{ + DEBUG("[semtech-loramac] MLME confirm event\n"); + switch (confirm->MlmeRequest) { + case MLME_JOIN: + if (confirm->Status == LORAMAC_EVENT_INFO_STATUS_OK) { + /* Status is OK, node has joined the network */ + DEBUG("[semtech-loramac] join succeeded\n"); + msg_t msg; + msg.type = MSG_TYPE_LORAMAC_NOTIFY; + msg.content.value = SEMTECH_LORAMAC_JOIN_SUCCEEDED; + msg_send(&msg, semtech_loramac_handler_pid); + } + else { + DEBUG("[semtech-loramac] join not successful\n"); + /* Join was not successful. */ + msg_t msg; + msg.type = MSG_TYPE_LORAMAC_NOTIFY; + msg.content.value = SEMTECH_LORAMAC_JOIN_FAILED; + msg_send(&msg, semtech_loramac_handler_pid); + } + break; + + default: + break; + } +} + +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) +{ + DEBUG("[semtech-loramac] initializing loramac\n"); + primitives->MacMcpsConfirm = mcps_confirm; + primitives->MacMcpsIndication = mcps_indication; + primitives->MacMlmeConfirm = mlme_confirm; +#if defined(REGION_AS923) + DEBUG("[semtech-loramac] initialize loramac for AS923 region\n"); + LoRaMacInitialization(&semtech_loramac_radio_events, primitives, callbacks, + LORAMAC_REGION_AS923); +#elif defined(REGION_AU915) + DEBUG("[semtech-loramac] initialize loramac for AU915 region\n"); + LoRaMacInitialization(&semtech_loramac_radio_events, primitives, callbacks, + LORAMAC_REGION_AU915); +#elif defined(REGION_CN779) + DEBUG("[semtech-loramac] initialize loramac for CN779 region\n"); + LoRaMacInitialization(&semtech_loramac_radio_events, primitives, callbacks, + LORAMAC_REGION_CN779); +#elif defined(REGION_EU868) + DEBUG("[semtech-loramac] initialize loramac for EU868 region\n"); + LoRaMacInitialization(&semtech_loramac_radio_events, primitives, callbacks, + LORAMAC_REGION_EU868); +#elif defined(REGION_IN865) + DEBUG("[semtech-loramac] initialize loramac for IN865 region\n"); + LoRaMacInitialization(&semtech_loramac_radio_events, primitives, callbacks, + LORAMAC_REGION_IN865); +#elif defined(REGION_KR920) + DEBUG("[semtech-loramac] initialize loramac for KR920 region\n"); + LoRaMacInitialization(&semtech_loramac_radio_events, primitives, callbacks, + LORAMAC_REGION_KR920); +#elif defined(REGION_US915) + DEBUG("[semtech-loramac] initialize loramac for US915 region\n"); + LoRaMacInitialization(&semtech_loramac_radio_events, primitives, callbacks, + LORAMAC_REGION_US915); +#elif defined(REGION_US915_HYBRID) + DEBUG("[semtech-loramac] initialize loramac for US915 hybrid region\n"); + LoRaMacInitialization(&semtech_loramac_radio_events, primitives, callbacks, + LORAMAC_REGION_US915_HYBRID); +#else +#error "Please define a region in the compiler options." +#endif + +#if defined(REGION_EU868) && USE_SEMTECH_DEFAULT_CHANNEL_LINEUP + DEBUG("[semtech-loramac] EU868 region: use default channels\n"); + LoRaMacChannelAdd(3, (ChannelParams_t)LC4); + LoRaMacChannelAdd(4, (ChannelParams_t)LC5); + LoRaMacChannelAdd(5, (ChannelParams_t)LC6); + LoRaMacChannelAdd(6, (ChannelParams_t)LC7); + LoRaMacChannelAdd(7, (ChannelParams_t)LC8); + LoRaMacChannelAdd(8, (ChannelParams_t)LC9); + LoRaMacChannelAdd(9, (ChannelParams_t)LC10); + + _loramac_set_rx2_params(LORAMAC_DEFAULT_RX2_FREQ, LORAMAC_DEFAULT_RX2_DR); +#endif +} + +static void _join_otaa(void) +{ + DEBUG("[semtech-loramac] starting OTAA join\n"); + + MibRequestConfirm_t mibReq; + mibReq.Type = MIB_NETWORK_JOINED; + mibReq.Param.IsNetworkJoined = false; + LoRaMacMibSetRequestConfirm(&mibReq); + + 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.NbTrials = LORAWAN_MAX_JOIN_RETRIES; + LoRaMacMlmeRequest(&mlmeReq); +} + +static void _join_abp(void) +{ + DEBUG("[semtech-loramac] starting ABP join\n"); + + 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]); + LoRaMacMibSetRequestConfirm(&mibReq); + + mibReq.Type = MIB_NWK_SKEY; + mibReq.Param.NwkSKey = semtech_loramac_nwk_skey; + LoRaMacMibSetRequestConfirm(&mibReq); + + mibReq.Type = MIB_APP_SKEY; + mibReq.Param.AppSKey = semtech_loramac_app_skey; + LoRaMacMibSetRequestConfirm(&mibReq); + + mibReq.Type = MIB_NETWORK_JOINED; + mibReq.Param.IsNetworkJoined = true; + LoRaMacMibSetRequestConfirm(&mibReq); +} + +static void _join(void *arg) +{ + (void) arg; + uint8_t join_type = *(uint8_t *)arg; + + switch (join_type) { + case LORAMAC_JOIN_OTAA: + _join_otaa(); + break; + + case LORAMAC_JOIN_ABP: + _join_abp(); + break; + } +} + +static void _send(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); +} + +static void _semtech_loramac_call(semtech_loramac_func_t func, void *arg) +{ + semtech_loramac_call_t call; + call.func = func; + call.arg = arg; + + msg_t msg; + msg.type = MSG_TYPE_LORAMAC_CMD; + msg.content.ptr = &call; + msg_send(&msg, semtech_loramac_pid); +} + +static void _semtech_loramac_event_cb(netdev_t *dev, netdev_event_t event) +{ + netdev_sx127x_lora_packet_info_t packet_info; + + msg_t msg; + msg.content.ptr = dev; + + switch (event) { + case NETDEV_EVENT_ISR: + msg.type = MSG_TYPE_ISR; + if (msg_send(&msg, semtech_loramac_pid) <= 0) { + DEBUG("[semtech-loramac] possibly lost interrupt.\n"); + } + break; + + case NETDEV_EVENT_TX_COMPLETE: + sx127x_set_sleep((sx127x_t *)dev); + semtech_loramac_radio_events.TxDone(); + DEBUG("[semtech-loramac] Transmission completed\n"); + break; + + case NETDEV_EVENT_TX_TIMEOUT: + msg.type = MSG_TYPE_TX_TIMEOUT; + if (msg_send(&msg, semtech_loramac_pid) <= 0) { + DEBUG("[semtech-loramac] TX timeout, possibly lost interrupt.\n"); + } + break; + + case NETDEV_EVENT_RX_COMPLETE: + { + size_t len; + 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); + break; + } + case NETDEV_EVENT_RX_TIMEOUT: + msg.type = MSG_TYPE_RX_TIMEOUT; + if (msg_send(&msg, semtech_loramac_pid) <= 0) { + DEBUG("[semtech-loramac] RX timeout, possibly lost interrupt.\n"); + } + break; + + case NETDEV_EVENT_CRC_ERROR: + DEBUG("[semtech-loramac] RX CRC error\n"); + semtech_loramac_radio_events.RxError(); + break; + + case NETDEV_EVENT_FHSS_CHANGE_CHANNEL: + DEBUG("[semtech-loramac] FHSS channel change\n"); + semtech_loramac_radio_events.FhssChangeChannel(((sx127x_t *)dev)->_internal.last_channel); + break; + + case NETDEV_EVENT_CAD_DONE: + DEBUG("[semtech-loramac] test: CAD done\n"); + semtech_loramac_radio_events.CadDone(((sx127x_t *)dev)->_internal.is_last_cad_success); + break; + + default: + DEBUG("[semtech-loramac] unexpected netdev event received: %d\n", + 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); + + 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; + + 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_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) +{ + dev->netdev.driver = &sx127x_driver; + dev->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, + "recv_thread"); + + if (semtech_loramac_pid <= KERNEL_PID_UNDEF) { + DEBUG("Creation of receiver thread failed\n"); + return -1; + } + + return 0; +} + +uint8_t semtech_loramac_join(uint8_t type) +{ + _semtech_loramac_call(_join, &type); + + if (type == LORAMAC_JOIN_OTAA) { + /* Wait until the OTAA join procedure is complete */ + msg_t msg; + msg_receive(&msg); + return (uint8_t)msg.content.value; + } + + /* ABP join procedure always works */ + 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) +{ + MibRequestConfirm_t mibReq; + mibReq.Type = MIB_NETWORK_JOINED; + LoRaMacMibGetRequestConfirm(&mibReq); + + if (!mibReq.Param.IsNetworkJoined) { + DEBUG("[semtech-loramac] network is not joined\n"); + return SEMTECH_LORAMAC_NOT_JOINED; + } + + 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; + + _semtech_loramac_call(_send, ¶ms); + + /* Wait until sending is fully done */ + 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)); + } + + return status; +} diff --git a/pkg/semtech-loramac/contrib/semtech_loramac_getset.c b/pkg/semtech-loramac/contrib/semtech_loramac_getset.c new file mode 100644 index 0000000000..6e1e418202 --- /dev/null +++ b/pkg/semtech-loramac/contrib/semtech_loramac_getset.c @@ -0,0 +1,243 @@ +/* + * Copyright (C) 2017 Inria + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @{ + * @ingroup pkg_semtech-loramac + * + * @file + * @brief Get/Set functions of the public API for Semtech LoRaMAC + * + * @author Alexandre Abadie + * @} + */ + +#include + +#include "net/loramac.h" + +#include "semtech-loramac/board.h" +#include "LoRaMac.h" + +#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) +{ + memcpy(semtech_loramac_dev_eui, eui, LORAMAC_DEVEUI_LEN); +} + +void semtech_loramac_get_deveui(uint8_t *eui) +{ + memcpy(eui, semtech_loramac_dev_eui, LORAMAC_DEVEUI_LEN); +} + +void semtech_loramac_set_appeui(const uint8_t *eui) +{ + memcpy(semtech_loramac_app_eui, eui, LORAMAC_APPEUI_LEN); +} + +void semtech_loramac_get_appeui(uint8_t *eui) +{ + memcpy(eui, semtech_loramac_app_eui, LORAMAC_APPEUI_LEN); +} + +void semtech_loramac_set_appkey(const uint8_t *key) +{ + memcpy(semtech_loramac_app_key, key, LORAMAC_APPKEY_LEN); +} + +void semtech_loramac_get_appkey(uint8_t *key) +{ + memcpy(key, semtech_loramac_app_key, LORAMAC_APPKEY_LEN); +} + +void semtech_loramac_set_appskey(const uint8_t *skey) +{ + memcpy(semtech_loramac_app_skey, skey, LORAMAC_APPSKEY_LEN); +} + +void semtech_loramac_get_appskey(uint8_t *skey) +{ + memcpy(skey, semtech_loramac_app_skey, LORAMAC_APPSKEY_LEN); +} + +void semtech_loramac_set_nwkskey(const uint8_t *skey) +{ + memcpy(semtech_loramac_nwk_skey, skey, LORAMAC_NWKSKEY_LEN); +} + +void semtech_loramac_get_nwkskey(uint8_t *skey) +{ + memcpy(skey, semtech_loramac_nwk_skey, LORAMAC_NWKSKEY_LEN); +} + +void semtech_loramac_set_devaddr(const uint8_t *addr) +{ + memcpy(semtech_loramac_dev_addr, addr, LORAMAC_DEVADDR_LEN); +} + +void semtech_loramac_get_devaddr(uint8_t *addr) +{ + memcpy(addr, semtech_loramac_dev_addr, LORAMAC_DEVADDR_LEN); +} + +void semtech_loramac_set_class(loramac_class_t cls) +{ + DEBUG("[semtech-loramac] set class %d\n", cls); + MibRequestConfirm_t mibReq; + mibReq.Type = MIB_DEVICE_CLASS; + mibReq.Param.Class = (DeviceClass_t)cls; + LoRaMacMibSetRequestConfirm(&mibReq); +} + +loramac_class_t semtech_loramac_get_class(void) +{ + DEBUG("[semtech-loramac] get device class\n"); + MibRequestConfirm_t mibReq; + mibReq.Type = MIB_DEVICE_CLASS; + LoRaMacMibGetRequestConfirm(&mibReq); + return (loramac_class_t)mibReq.Param.Class; +} + +void semtech_loramac_set_dr(uint8_t dr) +{ + DEBUG("[semtech-loramac] set dr %d\n", dr); + MibRequestConfirm_t mibReq; + mibReq.Type = MIB_CHANNELS_DEFAULT_DATARATE; + mibReq.Param.ChannelsDatarate = dr; + LoRaMacMibSetRequestConfirm(&mibReq); +} + +uint8_t semtech_loramac_get_dr(void) +{ + DEBUG("[semtech-loramac] get dr\n"); + MibRequestConfirm_t mibReq; + mibReq.Type = MIB_CHANNELS_DEFAULT_DATARATE; + LoRaMacMibGetRequestConfirm(&mibReq); + return (uint8_t)mibReq.Param.ChannelsDatarate; +} + +void semtech_loramac_set_adr(bool adr) +{ + DEBUG("[semtech-loramac] set adr %d\n", adr); + MibRequestConfirm_t mibReq; + mibReq.Type = MIB_ADR; + mibReq.Param.AdrEnable = adr; + LoRaMacMibSetRequestConfirm(&mibReq); +} + +bool semtech_loramac_get_adr(void) +{ + DEBUG("[semtech-loramac] get adr\n"); + MibRequestConfirm_t mibReq; + mibReq.Type = MIB_ADR; + LoRaMacMibGetRequestConfirm(&mibReq); + return mibReq.Param.AdrEnable; +} + +void semtech_loramac_set_public_network(bool public) +{ + DEBUG("[semtech-loramac] set public network %d\n", public); + MibRequestConfirm_t mibReq; + mibReq.Type = MIB_PUBLIC_NETWORK; + mibReq.Param.EnablePublicNetwork = public; + LoRaMacMibSetRequestConfirm(&mibReq); +} + +bool semtech_loramac_get_public_network(void) +{ + DEBUG("[semtech-loramac] get public network\n"); + MibRequestConfirm_t mibReq; + mibReq.Type = MIB_PUBLIC_NETWORK; + LoRaMacMibGetRequestConfirm(&mibReq); + return mibReq.Param.EnablePublicNetwork; +} + +void semtech_loramac_set_netid(uint32_t netid) +{ + DEBUG("[semtech-loramac] set NetID %lu\n", netid); + MibRequestConfirm_t mibReq; + mibReq.Type = MIB_NET_ID; + mibReq.Param.NetID = netid; + LoRaMacMibSetRequestConfirm(&mibReq); +} + +uint32_t semtech_loramac_get_netid(void) +{ + DEBUG("[semtech-loramac] get NetID\n"); + MibRequestConfirm_t mibReq; + mibReq.Type = MIB_NET_ID; + LoRaMacMibGetRequestConfirm(&mibReq); + return mibReq.Param.NetID; +} + +void semtech_loramac_set_tx_power(uint8_t power) +{ + DEBUG("[semtech-loramac] set TX power %d\n", power); + MibRequestConfirm_t mibReq; + mibReq.Type = MIB_CHANNELS_TX_POWER; + mibReq.Param.ChannelsTxPower = power; + LoRaMacMibSetRequestConfirm(&mibReq); +} + +uint8_t semtech_loramac_get_tx_power(void) +{ + DEBUG("[semtech-loramac] get TX power\n"); + MibRequestConfirm_t mibReq; + mibReq.Type = MIB_CHANNELS_TX_POWER; + LoRaMacMibGetRequestConfirm(&mibReq); + return (uint8_t)mibReq.Param.ChannelsTxPower; +} + +void semtech_loramac_set_rx2_freq(uint8_t freq) +{ + Rx2ChannelParams_t params; + 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); +} + +uint32_t semtech_loramac_get_rx2_freq(void) +{ + MibRequestConfirm_t mibReq; + mibReq.Type = MIB_RX2_DEFAULT_CHANNEL; + LoRaMacMibGetRequestConfirm(&mibReq); + return mibReq.Param.Rx2DefaultChannel.Frequency; +} + +void semtech_loramac_set_rx2_dr(uint8_t dr) +{ + Rx2ChannelParams_t params; + 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); +} + +uint8_t semtech_loramac_get_rx2_dr(void) +{ + MibRequestConfirm_t mibReq; + mibReq.Type = MIB_RX2_DEFAULT_CHANNEL; + LoRaMacMibGetRequestConfirm(&mibReq); + return mibReq.Param.Rx2DefaultChannel.Datarate; +} diff --git a/pkg/semtech-loramac/contrib/semtech_loramac_radio.c b/pkg/semtech-loramac/contrib/semtech_loramac_radio.c new file mode 100644 index 0000000000..84072a5658 --- /dev/null +++ b/pkg/semtech-loramac/contrib/semtech_loramac_radio.c @@ -0,0 +1,253 @@ +/* + * Copyright (C) 2017 Fundacion Inria Chile + * 2017 Inria + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @{ + * @ingroup pkg_semtech-loramac + * @file + * @brief Compatibility functions for controlling the radio driver + * + * @author Jose Ignacio Alamos + * @author Alexandre Abadie + * @author Francisco Molina + * @} + */ + +#include "net/lora.h" +#include "net/netdev.h" + +#include "sx127x.h" +#include "sx127x_internal.h" +#include "sx127x_netdev.h" + +#include "semtech-loramac/board.h" + +#include "radio/radio.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + +extern sx127x_t sx127x; + +#define LORAMAC_RX_WINDOW_DURATION (600UL * US_PER_MS) + +/* + * Radio driver functions implementation wrappers, the netdev2 object + * is known within the scope of the function + */ +void SX127XInit(RadioEvents_t *events) +{ + (void) events; + sx127x_init(&sx127x); +} + +RadioState_t SX127XGetStatus(void) +{ + return (RadioState_t)sx127x_get_state(&sx127x); +} + +void SX127XSetModem(RadioModems_t modem) +{ + sx127x_set_modem(&sx127x, (uint8_t)modem); +} + +void SX127XSetChannel(uint32_t freq) +{ + sx127x_set_channel(&sx127x, freq); +} + +bool SX127XIsChannelFree(RadioModems_t modem, uint32_t freq, + int16_t rssiThresh, uint32_t maxCarrierSenseTime ) +{ + (void) modem; + (void) maxCarrierSenseTime; + return sx127x_is_channel_free(&sx127x, freq, rssiThresh); +} + +uint32_t SX127XRandom(void) +{ + return sx127x_random(&sx127x); +} + +void SX127XSetRxConfig(RadioModems_t modem, uint32_t bandwidth, + uint32_t spreading_factor, uint8_t coding_rate, + uint32_t bandwidthAfc, uint16_t preambleLen, + uint16_t symbTimeout, bool fixLen, + uint8_t payloadLen, + bool crcOn, bool freqHopOn, uint8_t hopPeriod, + bool iqInverted, bool rxContinuous) +{ + (void) bandwidthAfc; + (void) symbTimeout; + (void) fixLen; + sx127x_set_modem(&sx127x, modem); + sx127x_set_bandwidth(&sx127x, bandwidth); + sx127x_set_spreading_factor(&sx127x, spreading_factor); + sx127x_set_coding_rate(&sx127x, coding_rate); + sx127x_set_preamble_length(&sx127x, preambleLen); + sx127x_set_fixed_header_len_mode(&sx127x, false); + sx127x_set_payload_length(&sx127x, payloadLen); + sx127x_set_crc(&sx127x, crcOn); + sx127x_set_freq_hop(&sx127x, freqHopOn); + sx127x_set_hop_period(&sx127x, hopPeriod); + sx127x_set_iq_invert(&sx127x, iqInverted); + sx127x_set_rx_timeout(&sx127x, LORAMAC_RX_WINDOW_DURATION); + sx127x_set_rx_single(&sx127x, !rxContinuous); + sx127x_set_rx(&sx127x); +} + +void SX127XSetTxConfig(RadioModems_t modem, int8_t power, uint32_t fdev, + uint32_t bandwidth, uint32_t spreading_factor, + uint8_t coding_rate, uint16_t preambleLen, + bool fixLen, bool crcOn, bool freqHopOn, + uint8_t hopPeriod, bool iqInverted, uint32_t timeout) +{ + (void) fdev; + (void) fixLen; + sx127x_set_modem(&sx127x, modem); + sx127x_set_freq_hop(&sx127x, freqHopOn); + sx127x_set_bandwidth(&sx127x, bandwidth); + sx127x_set_coding_rate(&sx127x, coding_rate); + sx127x_set_spreading_factor(&sx127x, spreading_factor); + sx127x_set_crc(&sx127x, crcOn); + sx127x_set_freq_hop(&sx127x, freqHopOn); + sx127x_set_hop_period(&sx127x, hopPeriod); + sx127x_set_fixed_header_len_mode(&sx127x, false); + sx127x_set_iq_invert(&sx127x, iqInverted); + sx127x_set_payload_length(&sx127x, 0); + sx127x_set_tx_power(&sx127x, power); + sx127x_set_preamble_length(&sx127x, preambleLen); + sx127x_set_rx_single(&sx127x, false); + sx127x_set_tx_timeout(&sx127x, timeout * US_PER_MS); /* base unit us, LoRaMAC ms */ +} + +uint32_t SX127XGetTimeOnAir(RadioModems_t modem, uint8_t pktLen) +{ + (void) modem; + return sx127x_get_time_on_air(&sx127x, pktLen); +} + +void SX127XSend(uint8_t *buffer, uint8_t size) +{ + netdev_t *dev = (netdev_t *)&sx127x; + struct iovec vec[1]; + vec[0].iov_base = buffer; + vec[0].iov_len = size; + dev->driver->send(dev, vec, 1); +} + +void SX127XSetSleep(void) +{ + sx127x_set_sleep(&sx127x); +} + +void SX127XSetStby(void) +{ + sx127x_set_standby(&sx127x); +} + +void SX127XSetRx(uint32_t timeout) +{ + (void) timeout; + sx127x_set_rx(&sx127x); +} + +void SX127XStartCad(void) +{ + sx127x_start_cad(&sx127x); +} + +int16_t SX127XReadRssi(RadioModems_t modem) +{ + sx127x_set_modem(&sx127x, (uint8_t)modem); + return sx127x_read_rssi(&sx127x); +} + +void SX127XWrite(uint8_t addr, uint8_t data) +{ + sx127x_reg_write(&sx127x, addr, data); +} + +uint8_t SX127XRead(uint8_t addr) +{ + return sx127x_reg_read(&sx127x, addr); +} + +void SX127XWriteBuffer(uint8_t addr, uint8_t *buffer, uint8_t size) +{ + sx127x_reg_write_burst(&sx127x, addr, buffer, size); +} + +void SX127XReadBuffer(uint8_t addr, uint8_t *buffer, uint8_t size) +{ + sx127x_reg_read_burst(&sx127x, addr, buffer, size); +} + +void SX127XSetMaxPayloadLength(RadioModems_t modem, uint8_t max) +{ + (void) modem; + sx127x_set_max_payload_len(&sx127x, max); +} + +bool SX127XCheckRfFrequency(uint32_t frequency) +{ + (void) frequency; + /* Implement check. Currently all frequencies are supported */ + return true; +} + +void SX127XSetTxContinuousWave(uint32_t freq, int8_t power, uint16_t time) +{ + (void) freq; + (void) power; + (void) time; + /* TODO */ +} + +void SX127XSetPublicNetwork(bool enable) +{ + if (enable) { + /* Use public network syncword */ + sx127x_set_syncword(&sx127x, LORA_SYNCWORD_PUBLIC); + } + else { + /* Use private network syncword */ + sx127x_set_syncword(&sx127x, LORA_SYNCWORD_PRIVATE); + } +} + +/** + * LoRa function callbacks + */ +const struct Radio_s Radio = +{ + SX127XInit, + SX127XGetStatus, + SX127XSetModem, + SX127XSetChannel, + SX127XIsChannelFree, + SX127XRandom, + SX127XSetRxConfig, + SX127XSetTxConfig, + SX127XCheckRfFrequency, + SX127XGetTimeOnAir, + SX127XSend, + SX127XSetSleep, + SX127XSetStby, + SX127XSetRx, + SX127XStartCad, + SX127XSetTxContinuousWave, + SX127XReadRssi, + SX127XWrite, + SX127XRead, + SX127XWriteBuffer, + SX127XReadBuffer, + SX127XSetMaxPayloadLength, + SX127XSetPublicNetwork +}; diff --git a/pkg/semtech-loramac/contrib/semtech_loramac_timer.c b/pkg/semtech-loramac/contrib/semtech_loramac_timer.c new file mode 100644 index 0000000000..885e16ca53 --- /dev/null +++ b/pkg/semtech-loramac/contrib/semtech_loramac_timer.c @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2017 Fundacion Inria Chile + * 2017 Inria + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @{ + * @ingroup pkg_semtech-loramac + * @file + * @brief Compatibility functions for controlling the LoRaMAC timers + * + * @author Jose Ignacio Alamos + * @author Alexandre Abadie + * @author Francisco Molina + * @} + */ + +#include "semtech-loramac/board.h" +#include "xtimer.h" +#include "thread.h" + +extern kernel_pid_t semtech_loramac_pid; + +void TimerInit(TimerEvent_t *obj, void (*cb)(void)) +{ + obj->dev.target = 0; + obj->running = 0; + obj->cb = cb; +} + +void TimerReset(TimerEvent_t *obj) +{ + TimerStop(obj); + TimerStart(obj); +} + +void TimerStart(TimerEvent_t *obj) +{ + obj->running = 1; + xtimer_t *timer = &(obj->dev); + msg_t *msg = &(obj->msg); + msg->type = MSG_TYPE_MAC_TIMEOUT; + msg->content.ptr = obj->cb; + xtimer_set_msg(timer, obj->timeout, msg, semtech_loramac_pid); +} + +void TimerStop(TimerEvent_t *obj) +{ + obj->running = 0; + xtimer_remove(&(obj->dev)); +} + +void TimerSetValue(TimerEvent_t *obj, uint32_t value) +{ + if (obj->running) { + xtimer_remove(&(obj->dev)); + } + + obj->timeout = (value - 50) * 1000; +} + +TimerTime_t TimerGetCurrentTime(void) +{ + uint64_t CurrentTime = xtimer_now_usec64(); + return (TimerTime_t)CurrentTime; +} + +TimerTime_t TimerGetElapsedTime(TimerTime_t savedTime) +{ + uint64_t CurrentTime = xtimer_now_usec64(); + return (TimerTime_t)(CurrentTime - savedTime); +} + +TimerTime_t TimerGetFutureTime(TimerTime_t eventInFuture) +{ + uint64_t CurrentTime = xtimer_now_usec64(); + return (TimerTime_t)(CurrentTime + eventInFuture); +} + +void TimerLowPowerHandler( void ) +{ + +} diff --git a/pkg/semtech-loramac/doc.txt b/pkg/semtech-loramac/doc.txt new file mode 100644 index 0000000000..85e5bf14d4 --- /dev/null +++ b/pkg/semtech-loramac/doc.txt @@ -0,0 +1,111 @@ +/** + * @defgroup pkg_semtech-loramac Semtech LoRaMAC implementation + * @ingroup pkg + * @ingroup net + * @brief Provides a RIOT adaption of Semtech LoRaMAC implementation + * + * # Introduction + * + * This package provides an API built on top of the + * [Semtech LoRaMAC-node](github.com/Lora-net/LoRaMac-node) reference + * implementation of a LoRa network. + * + * + * # Importing this package in an application + * + * This package only works with Semtech SX1272 and SX1276 radio devices. Thus, + * in order to use it properly, the application `Makefile` must import the + * corresponding device driver: + * ``` + * USEMODULE += sx1272 # for a SX1272 radio device + * USEMODULE += sx1276 # for a SX1276 radio device + * ``` + * + * In order to use this package in an application, add the following in + * the application `Makefile`: + * ``` + * USEPKG += semtech-loramac + * ``` + * + * Since the LoRa radio depends on regional parameters regarding the access + * to the physical support, the region where the device is used needs to be + * set at compile time. Example for EU868: + * ``` + * CFLAGS += -DREGION_EU868 + * ``` + * + * # Using the package API + * + * The package provides a simple API for initializing the MAC, setting/getting + * parameters, joining a network and sending/receiving packets to/from a LoRa + * Network. + * + * In your `main.c`, some header files must be first included: + * ```c + * #include "net/loramac.h" /* core loramac definitions */ + * #include "semtech-loramac.h" /* package API */ + * #include "sx127x.h" /* SX1272/6 device driver API */ + * #include "sx127x_params.h" /* SX1272/6 device driver initialization parameters */ + * ``` + * + * Then define global variables: + * ```c + * sx127x_t sx127x; /* SX1272/6 device descriptor */ + * /* define the required keys for OTAA, e.g over-the-air activation (the + * null arrays need to be updated with valid LoRa values) */ + * static uint8_t deveui[LORAMAC_DEVEUI_LEN] = { 0x00, 0x00, 0x00, 0x00, \ + * 0x00, 0x00, 0x00, 0x00 } + * static uint8_t appeui[LORAMAC_APPEUI_LEN] = { 0x00, 0x00, 0x00, 0x00, \ + * 0x00, 0x00, 0x00, 0x00 } + * static uint8_t appeui[LORAMAC_APPKEY_LEN] = { 0x00, 0x00, 0x00, 0x00, \ + * 0x00, 0x00, 0x00, 0x00, \ + * 0x00, 0x00, 0x00, 0x00, \ + * 0x00, 0x00, 0x00, 0x00 } + * ``` + * + * Now in the `main` function: + * 1. setup the radio driver with the initialization parameters (spi bus, pins, etc) + * 2. initialize the LoRaMAC MAC layer + * 3. set the LoRa keys + * 4. join the network + * 5. send some data to the network + * + * ```c + * int main(void) + * { + * /* 1. setup the radio driver */ + * sx127x_setup(&sx127x, &sx127x_params[0]); + * + * /* 2. initialize the LoRaMAC MAC layer */ + * semtech_loramac_init(&sx127x); + * + * /* 3. set the device required keys */ + * semtech_loramac_set_deveui(deveui); + * semtech_loramac_set_appeui(appeui); + * semtech_loramac_set_appkey(appkey); + * + * /* 4. join the network */ + * if (semtech_loramac_join(LORAMAC_JOIN_OTAA) != SEMTECH_LORAMAC_JOIN_SUCCEEDED) { + * puts("Join procedure failed"); + * } + * puts("Join procedure succeeded"); + * + * /* 5. send some data using confirmable mode on port 10 and assuming no + * data is received */ + * semtech_loramac_rx_data_t rx_data; + * semtech_loramac_send(LORAMAC_TX_CNF, 10, + (uint8_t *)"This is RIOT", 13, &rx_data); + * } + * ``` + * + * @warning It is not possible to directly call the original LoRaMAC-node API + * using this package. This package should only be considered as a + * wrapper around the original LoRaMAC-node API and only the API + * provided by this package should be used. + * + * # License + * + * The library is using the BSD 3-clause license. + * + * @see github.com/Lora-net/LoRaMac-node + */ \ No newline at end of file diff --git a/pkg/semtech-loramac/include/semtech-loramac/board.h b/pkg/semtech-loramac/include/semtech-loramac/board.h new file mode 100644 index 0000000000..279abe2a48 --- /dev/null +++ b/pkg/semtech-loramac/include/semtech-loramac/board.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2017 Fundacion Inria Chile + * 2017 Inria + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup pkg_semtech-loramac + * @brief Internal required Semtech LoRaMAC definitions for radio + * @{ + * + * @file + * + * @author José Ignacio Alamos + * @author Alexandre Abadie + * @author Francisco Molina + */ + +#ifndef SEMTECH_LORAMAC_BOARD_H +#define SEMTECH_LORAMAC_BOARD_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include "semtech-loramac/timer.h" + +/** + * @brief Radio wakeup time from SLEEP mode + */ +#define RADIO_OSC_STARTUP (1U) /* [ms] */ + +/** + * @brief Radio PLL lock and Mode Ready delay which can vary with the temperature + */ +#define RADIO_SLEEP_TO_RX (2U) /* [ms] */ + +/** + * @brief Radio complete Wake-up Time with margin for temperature compensation + */ +#define RADIO_WAKEUP_TIME ( RADIO_OSC_STARTUP + RADIO_SLEEP_TO_RX ) + +#ifdef __cplusplus +} +#endif + +#endif /* SEMTECH_LORAMAC_BOARD_H */ +/** @} */ diff --git a/pkg/semtech-loramac/include/semtech-loramac/timer.h b/pkg/semtech-loramac/include/semtech-loramac/timer.h new file mode 100644 index 0000000000..cce20f2083 --- /dev/null +++ b/pkg/semtech-loramac/include/semtech-loramac/timer.h @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2017 Fundacion Inria Chile + * 2017 Inria + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup pkg_semtech-loramac + * @brief Semtech LoRaMAC timer compatibility definitions + * @{ + * + * @file + * + * @author José Ignacio Alamos + * @author Alexandre Abadie + * @author Francisco Molina + */ + +#ifndef SEMTECH_LORAMAC_TIMER_H +#define SEMTECH_LORAMAC_TIMER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "xtimer.h" +#include "msg.h" + +#include "semtech_loramac.h" + +/** + * @brief Timer object description + */ +typedef struct TimerEvent_s { + uint32_t timeout; /**< Timer timeout in us */ + uint8_t running; /**< Check if timer is running */ + xtimer_t dev; /**< xtimer instance attached to this LoRaMAC timer */ + msg_t msg; /**< message attacher to this LoRaMAC timer */ + void (*cb)(void); /**< callback to call when timer timeout */ +} TimerEvent_t; + +/** + * @brief Timer time variable definition + */ +#ifndef TimerTime_t +typedef uint32_t TimerTime_t; +#endif + +/** + * @brief Initializes the timer object + * + * @remark TimerSetValue function must be called before starting the timer. + * this function initializes timestamp and reload value at 0. + * + * @param[in] obj Structure containing the timer object parameters + * @param[in] callback Function callback called at the end of the timeout + */ +void TimerInit(TimerEvent_t *obj, void (*callback)(void)); + +/** + * @brief Timer IRQ event handler + */ +void TimerIrqHandler(void); + +/** + * @brief Starts and adds the timer object to the list of timer events + * + * @param[in] obj Structure containing the timer object parameters + */ +void TimerStart(TimerEvent_t *obj); + +/** + * @brief Stops and removes the timer object from the list of timer events + * + * @param[in] obj Structure containing the timer object parameters + */ +void TimerStop(TimerEvent_t *obj); + +/** + * @brief Resets the timer object + * + * @param[in] obj Structure containing the timer object parameters + */ +void TimerReset(TimerEvent_t *obj); + +/** + * @brief Set timer new timeout value + * + * @param[in] obj Structure containing the timer object parameters + * @param[in] value New timer timeout value + */ +void TimerSetValue(TimerEvent_t *obj, uint32_t value); + +/** + * @brief Read the current time + * + * @return current time + */ +TimerTime_t TimerGetCurrentTime(void); + +/** + * @brief Return the time elapsed since a fix moment in Time + * + * @param[in] time fix moment in Time + * @return elapsed time + */ +TimerTime_t TimerGetElapsedTime(TimerTime_t time); + +/** + * @brief Return the time elapsed since a fix moment in time + * + * @param[in] time fix moment in the future + * @returns difference between now and future event + */ +TimerTime_t TimerGetFutureTime(TimerTime_t time); + +/** + * @brief Manages the entry into low power mode + */ +void TimerLowPowerHandler(void); + +#ifdef __cplusplus +} +#endif + +#endif /* SEMTECH_LORAMAC_TIMER_H */ +/** @} */ diff --git a/pkg/semtech-loramac/include/semtech_loramac.h b/pkg/semtech-loramac/include/semtech_loramac.h new file mode 100644 index 0000000000..ff15246ebf --- /dev/null +++ b/pkg/semtech-loramac/include/semtech_loramac.h @@ -0,0 +1,303 @@ +/* + * Copyright (C) 2017 Inria + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup pkg_semtech-loramac + * @brief Public API and definitions of the Semtech LoRaMAC + * @{ + * + * @file + * + * @author Alexandre Abadie + */ + +#ifndef SEMTECH_LORAMAC_H +#define SEMTECH_LORAMAC_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "net/loramac.h" + +#include "sx127x.h" + +/** + * @name Definitions for messages exchanged between the MAC and call threads + * @{ + */ +#define MSG_TYPE_ISR (0x3456) /**< radio device ISR */ +#define MSG_TYPE_RX_TIMEOUT (0x3457) /**< radio driver RX timeout */ +#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 */ +/** @} */ + +/** + * @brief Maximum payload size of a LoRaWAN application data + */ +#define LORAWAN_APP_DATA_MAX_SIZE (242U) + +/** + * @brief LoRaMAC 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_DONE, /**< Transmission completed */ + SEMTECH_LORAMAC_RX_DATA, /**< Data received */ +}; + +typedef struct { + uint8_t payload[LORAWAN_APP_DATA_MAX_SIZE]; /**< RX payload buffer */ + uint8_t payload_len; /**< Length of the RX payload */ + uint8_t port; /**< RX port */ +} semtech_loramac_rx_data_t; + +/** + * @brief Initializes semtech loramac + * + * @param[in] dev pointer to the radio device + * + * @return 0 on success + * @return -1 on failure + */ +int semtech_loramac_init(sx127x_t *dev); + +/** + * @brief Starts a LoRaWAN network join procedure + * + * @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 + */ +uint8_t semtech_loramac_join(uint8_t type); + +/** + * @brief Sends data to LoRaWAN + * + * @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 + * + * @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 + */ +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); + +/** + * @brief Sets the device EUI + * + * @param[in] eui The device EUI + */ +void semtech_loramac_set_deveui(const uint8_t *eui); + +/** + * @brief Gets the device EUI + * + * @param[out] eui The device EUI + */ +void semtech_loramac_get_deveui(uint8_t *eui); + +/** + * @brief Sets the application EUI + * + * @param[in] eui The application EUI + */ +void semtech_loramac_set_appeui(const uint8_t *eui); + +/** + * @brief Gets the application EUI + * + * @param[out] eui The application EUI + */ +void semtech_loramac_get_appeui(uint8_t *eui); + +/** + * @brief Sets the application key + * + * @param[in] key The application key + */ +void semtech_loramac_set_appkey(const uint8_t *key); + +/** + * @brief Gets the application key + * + * @param[in] key The application key + */ +void semtech_loramac_get_appkey(uint8_t *key); + +/** + * @brief Sets the application session key + * + * @param[in] key The application session key + */ +void semtech_loramac_set_appskey(const uint8_t *skey); + +/** + * @brief Gets the application session key + * + * @param[in] key The application session key + */ +void semtech_loramac_get_appskey(uint8_t *skey); + +/** + * @brief Sets the network session key + * + * @param[in] key The network session key + */ +void semtech_loramac_set_nwkskey(const uint8_t *skey); + +/** + * @brief Gets the network session key + * + * @param[in] key The network session key + */ +void semtech_loramac_get_nwkskey(uint8_t *skey); + +/** + * @brief Sets the device address + * + * @param[in] addr The device address + */ +void semtech_loramac_set_devaddr(const uint8_t *addr); + +/** + * @brief Gets the device address + * + * @param[in] addr The device address + */ +void semtech_loramac_get_devaddr(uint8_t *addr); + +/** + * @brief Sets the device class + * + * @param[in] cls The device class + */ +void semtech_loramac_set_class(loramac_class_t cls); + +/** + * @brief Gets the device class + * + * @return The device class + */ +loramac_class_t semtech_loramac_get_class(void); + +/** + * @brief Sets the channels datarate + * + * @param[in] dr The datarate (from 1 to 16) + */ +void semtech_loramac_set_dr(uint8_t dr); + +/** + * @brief Gets the channels datarate + * + * @return The datarate (from 1 to 16) + */ +uint8_t semtech_loramac_get_dr(void); + +/** + * @brief Enables/disable adaptive datarate + * + * @param[in] adr Adaptive datarate mode + */ +void semtech_loramac_set_adr(bool adr); + +/** + * @brief Checks if adaptive datarate is set + * + * @return true if adr is on, false otherwise + */ +bool semtech_loramac_get_adr(void); + +/** + * @brief Enable/disable the public network mode + * + * @param[in] public The public network mode + */ +void semtech_loramac_set_public_network(bool public); + +/** + * @brief Checks if public network is set + * + * @return true if public network is on, false otherwise + */ +bool semtech_loramac_get_public_network(void); + +/** + * @brief Sets the NetID (only useful with ABP join procedure) + * + * @param[in] network_id The NetID + */ +void semtech_loramac_set_netid(uint32_t netid); + +/** + * @brief Gets the NetID + * + * @return The NetID + */ +uint32_t semtech_loramac_get_netid(void); + +/** + * @brief Sets the channels TX power index + * + * @param[in] dr The TX power index (from 1 to 16) + */ +void semtech_loramac_set_tx_power(uint8_t power); + +/** + * @brief Gets the channels TX power index + * + * @return The TX power index (from 1 to 16) + */ +uint8_t semtech_loramac_get_tx_power(void); + +/** + * @brief Sets the RX2 frequency + * + * @param[in] freq The RX2 frequency + */ +void semtech_loramac_set_rx2_freq(uint8_t freq); + +/** + * @brief Gets the RX2 frequency + * + * @return The RX2 frequency + */ +uint32_t semtech_loramac_get_rx2_freq(void); + +/** + * @brief Sets the RX2 datarate + * + * @param[in] freq The RX2 datarate + */ +void semtech_loramac_set_rx2_dr(uint8_t dr); + +/** + * @brief Gets the RX2 datarate + * + * @return The RX2 datarate + */ +uint8_t semtech_loramac_get_rx2_dr(void); + +#ifdef __cplusplus +} +#endif + +#endif /* SEMTECH_LORAMAC_H */ +/** @} */ diff --git a/pkg/semtech-loramac/patches/0001-adapt-for-RIOT.patch b/pkg/semtech-loramac/patches/0001-adapt-for-RIOT.patch new file mode 100644 index 0000000000..ab230c8784 --- /dev/null +++ b/pkg/semtech-loramac/patches/0001-adapt-for-RIOT.patch @@ -0,0 +1,277 @@ +From 829210e7e7c4c2927fb9aa8cf18ba8aff04150b8 Mon Sep 17 00:00:00 2001 +From: Alexandre Abadie +Date: Wed, 13 Dec 2017 17:43:00 +0100 +Subject: [PATCH] adapt for RIOT + +--- + src/mac/LoRaMac.c | 28 +++++++++++----------------- + src/mac/LoRaMac.h | 4 +++- + src/mac/region/Region.c | 2 +- + src/mac/region/RegionAS923.c | 2 +- + src/mac/region/RegionAU915.c | 2 +- + src/mac/region/RegionCN470.c | 2 +- + src/mac/region/RegionCN779.c | 2 +- + src/mac/region/RegionCommon.c | 2 +- + src/mac/region/RegionEU433.c | 2 +- + src/mac/region/RegionEU868.c | 2 +- + src/mac/region/RegionIN865.c | 2 +- + src/mac/region/RegionKR920.c | 2 +- + src/mac/region/RegionUS915-Hybrid.c | 2 +- + src/mac/region/RegionUS915.c | 2 +- + 14 files changed, 26 insertions(+), 30 deletions(-) + +diff --git a/src/mac/LoRaMac.c b/src/mac/LoRaMac.c +index 0750ee5..3b9dbdf 100644 +--- a/src/mac/LoRaMac.c ++++ b/src/mac/LoRaMac.c +@@ -17,7 +17,8 @@ License: Revised BSD License, see LICENSE.TXT file include in the project + + Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE ) + */ +-#include "board.h" ++#include "semtech-loramac/board.h" ++#include "utilities.h" + + #include "LoRaMac.h" + #include "region/Region.h" +@@ -316,11 +317,6 @@ static LoRaMacPrimitives_t *LoRaMacPrimitives; + static LoRaMacCallback_t *LoRaMacCallbacks; + + /*! +- * Radio events function pointer +- */ +-static RadioEvents_t RadioEvents; +- +-/*! + * LoRaMac duty cycle delayed Tx timer + */ + static TimerEvent_t TxDelayedTimer; +@@ -687,8 +683,7 @@ static void PrepareRxDoneAbort( void ) + LoRaMacFlags.Bits.MacDone = 1; + + // Trig OnMacCheckTimerEvent call as soon as possible +- TimerSetValue( &MacStateCheckTimer, 1 ); +- TimerStart( &MacStateCheckTimer ); ++ OnMacStateCheckTimerEvent(); + } + + static void OnRadioRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr ) +@@ -1106,8 +1101,7 @@ static void OnRadioRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t + LoRaMacFlags.Bits.MacDone = 1; + + // Trig OnMacCheckTimerEvent call as soon as possible +- TimerSetValue( &MacStateCheckTimer, 1 ); +- TimerStart( &MacStateCheckTimer ); ++ OnMacStateCheckTimerEvent(); + } + + static void OnRadioTxTimeout( void ) +@@ -2285,7 +2279,7 @@ LoRaMacStatus_t SetTxContinuousWave1( uint16_t timeout, uint32_t frequency, uint + return LORAMAC_STATUS_OK; + } + +-LoRaMacStatus_t LoRaMacInitialization( LoRaMacPrimitives_t *primitives, LoRaMacCallback_t *callbacks, LoRaMacRegion_t region ) ++LoRaMacStatus_t LoRaMacInitialization( RadioEvents_t *radio_events, LoRaMacPrimitives_t *primitives, LoRaMacCallback_t *callbacks, LoRaMacRegion_t region ) + { + GetPhyParams_t getPhy; + PhyParam_t phyParam; +@@ -2416,12 +2410,12 @@ LoRaMacStatus_t LoRaMacInitialization( LoRaMacPrimitives_t *primitives, LoRaMacC + LoRaMacInitializationTime = TimerGetCurrentTime( ); + + // Initialize Radio driver +- RadioEvents.TxDone = OnRadioTxDone; +- RadioEvents.RxDone = OnRadioRxDone; +- RadioEvents.RxError = OnRadioRxError; +- RadioEvents.TxTimeout = OnRadioTxTimeout; +- RadioEvents.RxTimeout = OnRadioRxTimeout; +- Radio.Init( &RadioEvents ); ++ radio_events->TxDone = OnRadioTxDone; ++ radio_events->RxDone = OnRadioRxDone; ++ radio_events->RxError = OnRadioRxError; ++ radio_events->TxTimeout = OnRadioTxTimeout; ++ radio_events->RxTimeout = OnRadioRxTimeout; ++ Radio.Init( radio_events ); + + // Random seed initialization + srand1( Radio.Random( ) ); +diff --git a/src/mac/LoRaMac.h b/src/mac/LoRaMac.h +index 8e479d2..dde8712 100644 +--- a/src/mac/LoRaMac.h ++++ b/src/mac/LoRaMac.h +@@ -82,6 +82,8 @@ + #ifndef __LORAMAC_H__ + #define __LORAMAC_H__ + ++#include "radio/radio.h" ++ + /*! + * Check the Mac layer state every MAC_STATE_CHECK_TIMEOUT in ms + */ +@@ -1728,7 +1730,7 @@ static const uint8_t LoRaMacMaxEirpTable[] = { 8, 10, 12, 13, 14, 16, 18, 20, 21 + * \ref LORAMAC_STATUS_PARAMETER_INVALID, + * \ref LORAMAC_STATUS_REGION_NOT_SUPPORTED. + */ +-LoRaMacStatus_t LoRaMacInitialization( LoRaMacPrimitives_t *primitives, LoRaMacCallback_t *callbacks, LoRaMacRegion_t region ); ++LoRaMacStatus_t LoRaMacInitialization( RadioEvents_t *RadioEvents, LoRaMacPrimitives_t *primitives, LoRaMacCallback_t *callbacks, LoRaMacRegion_t region ); + + /*! + * \brief Queries the LoRaMAC if it is possible to send the next frame with +diff --git a/src/mac/region/Region.c b/src/mac/region/Region.c +index 1d0be81..f6ce9f5 100644 +--- a/src/mac/region/Region.c ++++ b/src/mac/region/Region.c +@@ -21,7 +21,7 @@ Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jae + #include + #include + +-#include "timer.h" ++#include "semtech-loramac/timer.h" + #include "LoRaMac.h" + + +diff --git a/src/mac/region/RegionAS923.c b/src/mac/region/RegionAS923.c +index 2677d0c..8312b46 100644 +--- a/src/mac/region/RegionAS923.c ++++ b/src/mac/region/RegionAS923.c +@@ -22,7 +22,7 @@ Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jae + #include + #include + +-#include "board.h" ++#include "semtech-loramac/board.h" + #include "LoRaMac.h" + + #include "utilities.h" +diff --git a/src/mac/region/RegionAU915.c b/src/mac/region/RegionAU915.c +index 4c8fc33..6b3817b 100644 +--- a/src/mac/region/RegionAU915.c ++++ b/src/mac/region/RegionAU915.c +@@ -22,7 +22,7 @@ Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jae + #include + #include + +-#include "board.h" ++#include "semtech-loramac/board.h" + #include "LoRaMac.h" + + #include "utilities.h" +diff --git a/src/mac/region/RegionCN470.c b/src/mac/region/RegionCN470.c +index dbbc745..2daddc9 100644 +--- a/src/mac/region/RegionCN470.c ++++ b/src/mac/region/RegionCN470.c +@@ -22,7 +22,7 @@ Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jae + #include + #include + +-#include "board.h" ++#include "semtech-loramac/board.h" + #include "LoRaMac.h" + + #include "utilities.h" +diff --git a/src/mac/region/RegionCN779.c b/src/mac/region/RegionCN779.c +index c5d9b7b..5c55ffd 100644 +--- a/src/mac/region/RegionCN779.c ++++ b/src/mac/region/RegionCN779.c +@@ -22,7 +22,7 @@ Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jae + #include + #include + +-#include "board.h" ++#include "semtech-loramac/board.h" + #include "LoRaMac.h" + + #include "utilities.h" +diff --git a/src/mac/region/RegionCommon.c b/src/mac/region/RegionCommon.c +index fb0b139..53e1e6c 100644 +--- a/src/mac/region/RegionCommon.c ++++ b/src/mac/region/RegionCommon.c +@@ -23,7 +23,7 @@ Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jae + #include + #include + +-#include "timer.h" ++#include "semtech-loramac/timer.h" + #include "utilities.h" + #include "LoRaMac.h" + #include "RegionCommon.h" +diff --git a/src/mac/region/RegionEU433.c b/src/mac/region/RegionEU433.c +index 5446c51..ca0fa9f 100644 +--- a/src/mac/region/RegionEU433.c ++++ b/src/mac/region/RegionEU433.c +@@ -22,7 +22,7 @@ Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jae + #include + #include + +-#include "board.h" ++#include "semtech-loramac/board.h" + #include "LoRaMac.h" + + #include "utilities.h" +diff --git a/src/mac/region/RegionEU868.c b/src/mac/region/RegionEU868.c +index f4385a5..3a27f42 100644 +--- a/src/mac/region/RegionEU868.c ++++ b/src/mac/region/RegionEU868.c +@@ -22,7 +22,7 @@ Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jae + #include + #include + +-#include "board.h" ++#include "semtech-loramac/board.h" + #include "LoRaMac.h" + + #include "utilities.h" +diff --git a/src/mac/region/RegionIN865.c b/src/mac/region/RegionIN865.c +index 75e2a4b..4770050 100644 +--- a/src/mac/region/RegionIN865.c ++++ b/src/mac/region/RegionIN865.c +@@ -22,7 +22,7 @@ Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jae + #include + #include + +-#include "board.h" ++#include "semtech-loramac/board.h" + #include "LoRaMac.h" + + #include "utilities.h" +diff --git a/src/mac/region/RegionKR920.c b/src/mac/region/RegionKR920.c +index eda6652..ca689d6 100644 +--- a/src/mac/region/RegionKR920.c ++++ b/src/mac/region/RegionKR920.c +@@ -22,7 +22,7 @@ Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jae + #include + #include + +-#include "board.h" ++#include "semtech-loramac/board.h" + #include "LoRaMac.h" + + #include "utilities.h" +diff --git a/src/mac/region/RegionUS915-Hybrid.c b/src/mac/region/RegionUS915-Hybrid.c +index 426e40d..3a3d085 100644 +--- a/src/mac/region/RegionUS915-Hybrid.c ++++ b/src/mac/region/RegionUS915-Hybrid.c +@@ -22,7 +22,7 @@ Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jae + #include + #include + +-#include "board.h" ++#include "semtech-loramac/board.h" + #include "LoRaMac.h" + + #include "utilities.h" +diff --git a/src/mac/region/RegionUS915.c b/src/mac/region/RegionUS915.c +index 8aa788a..97c3785 100644 +--- a/src/mac/region/RegionUS915.c ++++ b/src/mac/region/RegionUS915.c +@@ -22,7 +22,7 @@ Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jae + #include + #include + +-#include "board.h" ++#include "semtech-loramac/board.h" + #include "LoRaMac.h" + + #include "utilities.h" +-- +2.11.0 + diff --git a/pkg/semtech-loramac/patches/0002-eu868-join-retries.patch b/pkg/semtech-loramac/patches/0002-eu868-join-retries.patch new file mode 100644 index 0000000000..6365d3698d --- /dev/null +++ b/pkg/semtech-loramac/patches/0002-eu868-join-retries.patch @@ -0,0 +1,30 @@ +From 47b9fba23bedff6e28576271291a6ca7958a3caa Mon Sep 17 00:00:00 2001 +From: Alexandre Abadie +Date: Mon, 8 Jan 2018 10:45:28 +0100 +Subject: [PATCH] accept all join retries values in EU868 + +--- + src/mac/region/RegionEU868.c | 7 ++----- + 1 file changed, 2 insertions(+), 5 deletions(-) + +diff --git a/src/mac/region/RegionEU868.c b/src/mac/region/RegionEU868.c +index 3a27f42..e7e6f54 100644 +--- a/src/mac/region/RegionEU868.c ++++ b/src/mac/region/RegionEU868.c +@@ -393,11 +393,8 @@ bool RegionEU868Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute ) + } + case PHY_NB_JOIN_TRIALS: + { +- if( verify->NbJoinTrials < 48 ) +- { +- return false; +- } +- break; ++ /* accept all values */ ++ return true; + } + default: + return false; +-- +2.14.1 + diff --git a/pkg/semtech-loramac/patches/0003-adapt-utilities-functions.patch b/pkg/semtech-loramac/patches/0003-adapt-utilities-functions.patch new file mode 100644 index 0000000000..42aa1dd26c --- /dev/null +++ b/pkg/semtech-loramac/patches/0003-adapt-utilities-functions.patch @@ -0,0 +1,92 @@ +From 406e1900f38e6ca43e74c98a5de0c1ec0f3e3213 Mon Sep 17 00:00:00 2001 +From: Alexandre Abadie +Date: Tue, 16 Jan 2018 15:04:09 +0100 +Subject: [PATCH] patch utilities functions + +--- + src/boards/mcu/stm32/utilities.c | 48 +++++++++++----------------------------- + 1 file changed, 13 insertions(+), 35 deletions(-) + +diff --git a/src/boards/mcu/stm32/utilities.c b/src/boards/mcu/stm32/utilities.c +index 8861235..583cae1 100644 +--- a/src/boards/mcu/stm32/utilities.c ++++ b/src/boards/mcu/stm32/utilities.c +@@ -14,8 +14,10 @@ Maintainer: Miguel Luis and Gregory Cristian + */ + #include + #include +-#include "board.h" ++#include + #include "utilities.h" ++#include "semtech-loramac/board.h" ++#include "random.h" + + /*! + * Redefinition of rand() and srand() standard C functions. +@@ -34,52 +36,28 @@ int32_t rand1( void ) + + void srand1( uint32_t seed ) + { +- next = seed; +-} +-// Standard random functions redefinition end ++ (void) seed; ++}; + + int32_t randr( int32_t min, int32_t max ) + { +- return ( int32_t )rand1( ) % ( max - min + 1 ) + min; +-} ++ return random_uint32_range(min, max + 1); ++}; + + void memcpy1( uint8_t *dst, const uint8_t *src, uint16_t size ) + { +- while( size-- ) +- { +- *dst++ = *src++; +- } +-} ++ memcpy(dst, src, size); ++}; + + void memcpyr( uint8_t *dst, const uint8_t *src, uint16_t size ) + { +- dst = dst + ( size - 1 ); +- while( size-- ) +- { ++ dst = dst + (size - 1); ++ while (size--) { + *dst-- = *src++; + } + } + + void memset1( uint8_t *dst, uint8_t value, uint16_t size ) + { +- while( size-- ) +- { +- *dst++ = value; +- } +-} +- +-int8_t Nibble2HexChar( uint8_t a ) +-{ +- if( a < 10 ) +- { +- return '0' + a; +- } +- else if( a < 16 ) +- { +- return 'A' + ( a - 10 ); +- } +- else +- { +- return '?'; +- } +-} ++ memset(dst, value, size); ++} +\ No newline at end of file +-- +2.14.1 +