1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

Merge pull request #15070 from fjmolinas/pr_uwb_core

pkg/uwb_core: initial support
This commit is contained in:
Alexandre Abadie 2020-11-12 14:04:51 +01:00 committed by GitHub
commit 153c52754d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
78 changed files with 4708 additions and 3 deletions

View File

@ -77,9 +77,9 @@ extern "C" {
* @name DW1000 UWB transceiver
* @{
*/
#define DW1000_PARAM_SPI_DEV SPI_DEV(1)
#define DW1000_PARAM_CS_PIN GPIO_DEV(0, 17)
#define DW1000_PARAM_INT_PIN GPIO_DEV(0, 19)
#define DW1000_PARAM_SPI SPI_DEV(1)
#define DW1000_PARAM_CS_PIN GPIO_PIN(0, 17)
#define DW1000_PARAM_INT_PIN GPIO_PIN(0, 19)
/** @} */
#ifdef __cplusplus

View File

@ -0,0 +1,57 @@
APPLICATION = twr-aloha
# If no BOARD is found in the environment, use this default:
BOARD ?= dwm1001
# This has to be the absolute path to the RIOT base directory:
RIOTBASE ?= $(CURDIR)/../..
# Change this to 0 show compiler invocation lines by default:
QUIET ?= 1
# Comment this out to disable code in RIOT that does safety checking
# which is not needed in a production environment but helps in the
# development process:
DEVELHELP ?= 1
# Include uwb-core, uwb-dw1000
USEPKG += uwb-core
USEPKG += uwb-dw1000
# Include all ranging algorithms
USEMODULE += uwb-core_twr_ss
USEMODULE += uwb-core_twr_ss_ack
USEMODULE += uwb-core_twr_ss_ext
USEMODULE += uwb-core_twr_ds
USEMODULE += uwb-core_twr_ds_ext
USEMODULE += shell
USEMODULE += shell_commands
USEMODULE += ps
# Set the device role: 0x0 for tag, 0x4 for an anchor
DW1000_ROLE ?= 0x00
CFLAGS += -DDW1000_ROLE_DEFAULT=$(DW1000_ROLE)
# All uwb-core applications need to enable `-fms-extensions`
CFLAGS += -fms-extensions
ifneq (,$(filter llvm,$(TOOLCHAIN)))
CFLAGS += -Wno-microsoft-anon-tag
endif
# Enable verbose mode to get all logs
CFLAGS += -DMYNEWT_VAL_RNG_VERBOSE=2
# Enable RX diagnostics
CFLAGS += -DDW1000_RX_DIAGNOSTIC=1
# Fix the TWR algorithm:
# - UWB_DATA_CODE_SS_TWR
# - UWB_DATA_CODE_SS_TWR_EXT
# - UWB_DATA_CODE_SS_TWR_ACK
# - UWB_DATA_CODE_DS_TWR
# - UWB_DATA_CODE_DS_TWR_EXT
UWB_TWR_ALGORITHM_ONLY_ONE ?= UWB_DATA_CODE_SS_TWR
# Uncomment to fix the TWR algoritm
# CFLAGS += -DUWB_TWR_ALGORITHM_ONLY_ONE=$(UWB_TWR_ALGORITHM_ONLY_ONE)
include $(RIOTBASE)/Makefile.include

View File

@ -0,0 +1,12 @@
BOARD_INSUFFICIENT_MEMORY := \
i-nucleo-lrwan1 \
nucleo-f031k6 \
nucleo-f042k6 \
nucleo-l011k4 \
nucleo-l031k6 \
nucleo-l053r8 \
stk3200 \
stm32f030f4-demo \
stm32f0discovery \
stm32l0538-disco \
#

View File

@ -0,0 +1,68 @@
## Decawave TWR_ALOHA Example
This example allows testing different two-way ranging algorithms between
two boards supporting a dw1000 device. This makes use of the uwb-core
pkg. This example is based on the twr-aloha example in
[uwb-apps](https://github.com/Decawave/uwb-apps/tree/master/apps/twr_aloha).
### Setup
1. Flash one node as the tag (Default configuration)
$ make -C examples/twr_aloha/ flash term
2. Flash the second node as an anchor
$ DW1000_ROLE=0x4 make -C examples/twr_aloha/ flash term
3. On the tag node begin ranging, you will see ranging estimations where
the "raz" field is "range" in meters.
```
main(): This is RIOT! (Version: 2020.10-devel-1384-g5b7ad-wip/uwb-dw1000)
pkg uwb-dw1000 + uwb-core test application
{"utime": 49412,"exec": "/home/francisco/workspace/RIOT/examples/twr_aloha/control.c"}
{"device_id"="deca0130","panid="DECA","addr"="1303","part_id"="cad11303","lot_id"="402c188"}
{"utime": 49412,"msg": "frame_duration = 201 usec"}
{"utime": 49412,"msg": "SHR_duration = 139 usec"}
{"utime": 49412,"msg": "holdoff = 821 usec"}
Node role: TAG
{"utime": 120995,"c": 274,"uid": 4867,"ouid": 4660,"raz": [0.766359],"los": [1.000000]}
> range start
range start
Start ranging
{"utime": 5214098,"c": 274,"uid": 4867,"ouid": 4660,"raz": [0.778875],"los": [1.000000]}
{"utime": 5232368,"c": 274,"uid": 4867,"ouid": 4660,"raz": [0.777146],"los": [1.000000]}
{"utime": 5250631,"c": 274,"uid": 4867,"ouid": 4660,"raz": [0.796009],"los": [1.000000]}
{"utime": 5268894,"c": 274,"uid": 4867,"ouid": 4660,"raz": [0.756952],"los": [1.000000]}
{"utime": 5287157,"c": 274,"uid": 4867,"ouid": 4660,"raz": [0.787994],"los": [1.000000]}
```
4. Trying different ranging algorithms
The algorithm used for ranging is selected by modifying the `mode` variable
in the uwb_ev_cb function in main.c. If multiple modes are enabled it will switch among them.
To use only one algorithm, compile as follows:
$ UWB_TWR_ALGORITHM_ONLY_ONE=UWB_DATA_CODE_SS_TWR make -C examples/twr_aloha/ flash term
The different algorithm options are:
- UWB_DATA_CODE_SS_TWR
- UWB_DATA_CODE_SS_TWR_EXT
- UWB_DATA_CODE_SS_TWR_ACK
- UWB_DATA_CODE_DS_TWR
- UWB_DATA_CODE_DS_TWR_EXT
### Notes
The application example fixes the `short_address` of the anchor to
`ANCHOR_ADDRESS`, by default `0x1234`. All tags will send ranging requests
to that address.
This value can be overridden with a `CFLAG += -DANCHOR_ADDRESS=$(VALUE)`.
Ranging request are sent every 40ms, this value can also be overridden
by changing the default value of `RANGE_REQUEST_T_US`, e.g:
`CFLAG += -DRANGE_REQUEST_T_US=10000` to set it at 10ms.

View File

@ -0,0 +1,260 @@
/*
* Copyright (C) 2020 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 examples
* @{
*
* @file
*
* @author Francisco Molina <francois-xavier.molina@inria.fr>
*
* @}
*/
#include <assert.h>
#include <math.h>
#include <string.h>
#include <stdio.h>
#include "uwb/uwb.h"
#include "uwb_rng/uwb_rng.h"
#include "dpl/dpl.h"
#include "control.h"
#include "shell_commands.h"
#include "shell.h"
#include "xtimer.h"
static struct dpl_callout _rng_req_callout;
static uint8_t _ranging_enabled_flag;
static struct dpl_event _slot_event;
/* forward declaration */
static void _slot_complete_cb(struct dpl_event *ev);
static bool _complete_cb(struct uwb_dev *inst, struct uwb_mac_interface *cbs);
static bool _rx_timeout_cb(struct uwb_dev *inst, struct uwb_mac_interface *cbs);
static int _range_cli_cmd(int argc, char **argv)
{
(void)argc;
if (!strcmp(argv[1], "start")) {
printf("Start ranging\n");
dpl_callout_reset(&_rng_req_callout, RANGE_REQUEST_T_US);
_ranging_enabled_flag = 1;
}
else if (!strcmp(argv[1], "stop")) {
printf("Stop ranging\n");
dpl_callout_stop(&_rng_req_callout);
_ranging_enabled_flag = 0;
}
else {
puts("Usage:");
puts("\trange start: to start ranging");
puts("\trange stop: to stop ranging");
}
return 0;
}
static const shell_command_t shell_commands[] = {
{ "range", "Control command", _range_cli_cmd },
{ NULL, NULL, NULL }
};
/* Structure of extension callbacks common for mac layer */
static struct uwb_mac_interface _uwb_mac_cbs = (struct uwb_mac_interface){
.id = UWBEXT_APP0,
.complete_cb = _complete_cb,
.rx_timeout_cb = _rx_timeout_cb,
};
/**
* @brief Range request complete callback.
*
* This callback is part of the struct uwb_mac_interface extension
* interface and invoked of the completion of a range request in the
* context of this example. The struct uwb_mac_interface is in the
* interrupt context and is used to schedule events an event queue.
*
* Processing should be kept to a minimum given the interrupt context.
* All algorithms activities should be deferred to a thread on an event
* queue. The callback should return true if and only if it can determine
* if it is the sole recipient of this event.
*
* @note The MAC extension interface is a linked-list of callbacks,
* subsequentcallbacks on the list will be not be called if the callback
* returns true.
*
* @param[in] inst Pointer to struct uwb_dev.
* @param[in] cbs Pointer to struct uwb_mac_interface.
* *
* @return true if valid recipient for the event, false otherwise
*/
static bool _complete_cb(struct uwb_dev *inst, struct uwb_mac_interface *cbs)
{
(void)cbs;
if (inst->fctrl != FCNTL_IEEE_RANGE_16 &&
inst->fctrl != (FCNTL_IEEE_RANGE_16 | UWB_FCTRL_ACK_REQUESTED)) {
return false;
}
/* on completion of a range request setup an event to keep listening,
if is anchor */
dpl_eventq_put(dpl_eventq_dflt_get(), &_slot_event);
return true;
}
/**
* @brief API for receive timeout callback.
*
* @param[in] inst Pointer to struct uwb_dev.
* @param[in] cbs Pointer to struct uwb_mac_interface.
*
* @return true on success
*/
static bool _rx_timeout_cb(struct uwb_dev *inst, struct uwb_mac_interface *cbs)
{
struct uwb_rng_instance *rng = (struct uwb_rng_instance *)cbs->inst_ptr;
if (inst->role & UWB_ROLE_ANCHOR) {
/* Restart receiver */
uwb_phy_forcetrxoff(inst);
uwb_rng_listen(rng, 0xfffff, UWB_NONBLOCKING);
}
return true;
}
/**
* @brief In the example this function represents the event context
* processing of the received range request which has been offloaded from
* ISR context to an event queue.
*/
static void _slot_complete_cb(struct dpl_event *ev)
{
assert(ev != NULL);
struct uwb_rng_instance *rng = (struct uwb_rng_instance *)
dpl_event_get_arg(ev);
struct uwb_dev *inst = rng->dev_inst;
if (inst->role & UWB_ROLE_ANCHOR) {
uwb_rng_listen(rng, 0xfffff, UWB_NONBLOCKING);
}
}
/**
* @brief An event callback to send range request every RANGE_REQUEST_T_US.
* On every request it will switch the used ranging algorithm.
*/
static void uwb_ev_cb(struct dpl_event *ev)
{
struct uwb_rng_instance *rng = (struct uwb_rng_instance *)ev->arg;
struct uwb_dev *inst = rng->dev_inst;
if (inst->role & UWB_ROLE_ANCHOR) {
if (dpl_sem_get_count(&rng->sem) == 1) {
uwb_rng_listen(rng, 0xfffff, UWB_NONBLOCKING);
}
}
else {
int mode_v[8] = { 0 }, mode_i = 0, mode = -1;
static int last_used_mode = 0;
if (IS_USED(MODULE_UWB_CORE_TWR_SS)) {
mode_v[mode_i++] = UWB_DATA_CODE_SS_TWR;
}
if (IS_USED(MODULE_UWB_CORE_TWR_SS_ACK)) {
mode_v[mode_i++] = UWB_DATA_CODE_SS_TWR_ACK;
}
if (IS_USED(MODULE_UWB_CORE_TWR_SS_EXT)) {
mode_v[mode_i++] = UWB_DATA_CODE_SS_TWR_EXT;
}
if (IS_USED(MODULE_UWB_CORE_TWR_DS)) {
mode_v[mode_i++] = UWB_DATA_CODE_DS_TWR;
}
if (IS_USED(MODULE_UWB_CORE_TWR_DS_EXT)) {
mode_v[mode_i++] = UWB_DATA_CODE_DS_TWR_EXT;
}
if (++last_used_mode >= mode_i) {
last_used_mode = 0;
}
mode = mode_v[last_used_mode];
#ifdef UWB_TWR_ALGORITHM_ONLY_ONE
mode = UWB_TWR_ALGORITHM_ONLY_ONE;
#endif
if (mode > 0) {
uwb_rng_request(rng, ANCHOR_ADDRESS, mode);
}
}
/* reset the callback if ranging is enabled */
if (_ranging_enabled_flag) {
dpl_callout_reset(&_rng_req_callout, RANGE_REQUEST_T_US);
}
}
void init_ranging(void)
{
struct uwb_dev *udev = uwb_dev_idx_lookup(0);
struct uwb_rng_instance *rng =
(struct uwb_rng_instance *)uwb_mac_find_cb_inst_ptr(udev, UWBEXT_RNG);
assert(rng);
/* set up local mac callbacks */
_uwb_mac_cbs.inst_ptr = rng;
uwb_mac_append_interface(udev, &_uwb_mac_cbs);
uint32_t utime = xtimer_now_usec();
printf("{\"utime\": %" PRIu32 ",\"exec\": \"%s\"}\n", utime, __FILE__);
printf("{\"device_id\"=\"%" PRIx32 "\"", udev->device_id);
printf(",\"panid=\"%X\"", udev->pan_id);
printf(",\"addr\"=\"%X\"", udev->uid);
printf(",\"part_id\"=\"%" PRIx32 "\"",
(uint32_t)(udev->euid & 0xffffffff));
printf(",\"lot_id\"=\"%" PRIx32 "\"}\n", (uint32_t)(udev->euid >> 32));
printf("{\"utime\": %"PRIu32",\"msg\": \"frame_duration = %d usec\"}\n",
utime, uwb_phy_frame_duration(udev, sizeof(twr_frame_final_t)));
printf("{\"utime\": %"PRIu32",\"msg\": \"SHR_duration = %d usec\"}\n",
utime, uwb_phy_SHR_duration(udev));
printf("{\"utime\": %"PRIu32",\"msg\": \"holdoff = %d usec\"}\n", utime,
(uint16_t)ceilf(uwb_dwt_usecs_to_usecs(rng->config.
tx_holdoff_delay)));
if (IS_USED(MODULE_UWB_CORE_TWR_SS_ACK)) {
uwb_set_autoack(udev, true);
uwb_set_autoack_delay(udev, 12);
}
dpl_callout_init(&_rng_req_callout, dpl_eventq_dflt_get(),
uwb_ev_cb, rng);
dpl_callout_reset(&_rng_req_callout, RANGE_REQUEST_T_US);
dpl_event_init(&_slot_event, _slot_complete_cb, rng);
/* Apply config */
uwb_mac_config(udev, NULL);
uwb_txrf_config(udev, &udev->config.txrf);
if ((udev->role & UWB_ROLE_ANCHOR)) {
printf("Node role: ANCHOR \n");
udev->my_short_address = ANCHOR_ADDRESS;
uwb_set_uid(udev, udev->my_short_address);
/* anchor starts listening by default */
_ranging_enabled_flag = 1;
}
else {
_ranging_enabled_flag = 0;
printf("Node role: TAG \n");
}
/* define buffer to be used by the shell */
char line_buf[SHELL_DEFAULT_BUFSIZE];
shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE);
}

View File

@ -0,0 +1,53 @@
/*
* Copyright (C) 2020 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 examples
* @{
*
* @file
*
* @author Francisco Molina <francois-xavier.molina@inria.fr>
*
* @}
*/
#ifndef CONTROL_H
#define CONTROL_H
#ifdef __cplusplus
extern "C" {
#endif
#include "timex.h"
/**
* @brief Anchor address
*/
#ifndef ANCHOR_ADDRESS
#define ANCHOR_ADDRESS 0x1234
#endif
/**
* @brief Range request period
*/
#ifndef RANGE_REQUEST_T_US
#define RANGE_REQUEST_T_US (40 * US_PER_MS)
#endif
/**
* @brief Starts ranging
*/
void init_ranging(void);
#ifdef __cplusplus
}
#endif
#endif /* CONTROL_H */

31
examples/twr_aloha/main.c Normal file
View File

@ -0,0 +1,31 @@
/*
* Copyright (C) 2020 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 examples
* @{
*
* @file
* @brief Two way ranging example
*
* @author Francisco Molina <francois-xavier.molina@inria.fr>
*
* @}
*/
#include <stdio.h>
#include "control.h"
int main(void)
{
puts("pkg uwb-dw1000 + uwb-core test application");
/* this should start ranging... */
init_ranging();
return 1;
}

53
pkg/uwb-core/Makefile Normal file
View File

@ -0,0 +1,53 @@
PKG_NAME=uwb-core
PKG_URL=https://github.com/Decawave/uwb-core
PKG_VERSION=8ffba63755a932a89d841872ce5bdf35b9c78777
PKG_LICENSE=Apache-2.0
include $(RIOTBASE)/pkg/pkg.mk
CFLAGS += -Wno-implicit-int
CFLAGS += -Wno-int-conversion
CFLAGS += -Wno-strict-prototypes
CFLAGS += -Wno-maybe-uninitialized
CFLAGS += -Wno-missing-braces
CFLAGS += -Wno-missing-declarations
CFLAGS += -Wno-missing-field-initializers
CFLAGS += -Wno-old-style-definition
CFLAGS += -Wno-return-type
CFLAGS += -Wno-sign-compare
CFLAGS += -Wno-unused-but-set-variable
CFLAGS += -Wno-unused-parameter
CFLAGS += -Wno-unused-variable
CFLAGS += -fms-extensions
ifneq (,$(filter llvm,$(TOOLCHAIN)))
CFLAGS += -Wno-microsoft-anon-tag
endif
IGNORE_MODULES := uwb-core_dpl \
uwb-core_config \
uwb-core_contrib \
#
UWB_CORE_MODULES := $(filter-out $(IGNORE_MODULES),$(filter uwb-core%,$(USEMODULE)))
UWB_CORE_PATH_dsp = lib/dsp/src
UWB_CORE_PATH_uwb_json = lib/json/src
UWB_CORE_PATH_uwbcfg = sys/uwbcfg/src/
UWB_CORE_PATH_rng = lib/uwb_rng/src
UWB_CORE_PATH_rng_math = lib/rng_math/src
UWB_CORE_PATH_twr_ss = lib/twr_ss/src
UWB_CORE_PATH_twr_ss_ack = lib/twr_ss_ack/src
UWB_CORE_PATH_twr_ss_ext = lib/twr_ss_ext/src
UWB_CORE_PATH_twr_ds = lib/twr_ds/src
UWB_CORE_PATH_twr_ds_ext = lib/twr_ds_ext/src
all: $(UWB_CORE_MODULES)
"$(MAKE)" -C $(PKG_SOURCE_DIR)/hw/drivers/uwb/src -f $(RIOTBASE)/Makefile.base MODULE=$(PKG_NAME)
uwb-core_config:
"$(MAKE)" -C $(PKG_SOURCE_DIR)/porting/dpl/riot/src -f $(RIOTBASE)/Makefile.base MODULE=$@
uwb-core_uwbcfg: uwb-core_config
uwb-core_%:
"$(MAKE)" -C $(PKG_SOURCE_DIR)/$(UWB_CORE_PATH_$*) -f $(RIOTBASE)/Makefile.base MODULE=$@

36
pkg/uwb-core/Makefile.dep Normal file
View File

@ -0,0 +1,36 @@
USEMODULE += uwb-core_dpl
USEMODULE += uwb-core_contrib
DEFAULT_MODULE += auto_init_uwb-core
USEMODULE += sema
USEMODULE += event_callback
USEMODULE += xtimer
USEMODULE += fmt
FEATURES_REQUIRED += periph_gpio_irq
FEATURES_REQUIRED += periph_spi
ifneq (,$(filter uwb-core_twr_%,$(USEMODULE)))
USEMODULE += uwb-core_rng
endif
ifneq (,$(filter uwb-core_rng,$(USEMODULE)))
USEMODULE += uwb-core_rng_math
USEMODULE += uwb-core_dsp
USEMODULE += uwb-core_uwb_json
endif
ifneq (,$(filter uwb-core_uwbcfg,$(USEMODULE)))
USEMODULE += uwb-core_config
endif
# Some stdlib functions used by the pkg are not in avr-gcc
FEATURES_BLACKLIST += arch_avr8
# uwb-core has specific compilation sources when compiling kernel
# libraries these introduce additional compilation issues that have not
# been addressed in this port
FEATURES_BLACKLIST += arch_native
# LLVM ARM shows issues with missing definitions for stdatomic
TOOLCHAINS_BLACKLIST += llvm

View File

@ -0,0 +1,22 @@
INCLUDES += -I$(PKGDIRBASE)/uwb-core/hw/drivers/uwb/include/ \
-I$(PKGDIRBASE)/uwb-core/lib/euclid/include \
-I$(PKGDIRBASE)/uwb-core/lib/dsp/include \
-I$(PKGDIRBASE)/uwb-core/lib/json/include \
-I$(PKGDIRBASE)/uwb-core/lib/rng_math/include \
-I$(PKGDIRBASE)/uwb-core/lib/twr_ss/include \
-I$(PKGDIRBASE)/uwb-core/lib/twr_ss_ext/include \
-I$(PKGDIRBASE)/uwb-core/lib/twr_ss_ack/include \
-I$(PKGDIRBASE)/uwb-core/lib/twr_ds/include \
-I$(PKGDIRBASE)/uwb-core/lib/twr_ds_ext/include \
-I$(PKGDIRBASE)/uwb-core/lib/uwb_rng/include \
-I$(PKGDIRBASE)/uwb-core/porting/dpl/riot/include/ \
-I$(PKGDIRBASE)/uwb-core/sys/uwbcfg/include \
-I$(RIOTPKG)/uwb-core/include \
#
DIRS += $(RIOTPKG)/uwb-core/dpl \
$(RIOTPKG)/uwb-core/contrib \
#
# A cflag to indicate in pkg code that we are building for RIOT
CFLAGS += -DRIOT

View File

@ -0,0 +1,9 @@
MODULE = uwb-core_contrib
SRC = uwb_core.c
ifneq (,$(filter auto_init_uwb-core,$(USEMODULE)))
SRC += uwb_core_init.c
endif
include $(RIOTBASE)/Makefile.base

View File

@ -0,0 +1,61 @@
/*
* Copyright (C) 2020 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_uwb_core
* @{
*
* @file
* @brief uwb-core bootstrapping functions
*
* @author Francisco Molina <francois-xavier.molina@inria.fr>
* @}
*/
#include <stdatomic.h>
#include "thread.h"
#include "event.h"
#include "event/callback.h"
#include "uwb_core.h"
#ifndef UWB_CORE_STACKSIZE
#define UWB_CORE_STACKSIZE (THREAD_STACKSIZE_LARGE)
#endif
#ifndef UWB_CORE_PRIO
#define UWB_CORE_PRIO (THREAD_PRIORITY_MAIN - 5)
#endif
static char _stack_uwb_core[UWB_CORE_STACKSIZE];
static event_queue_t _queue;
atomic_uint dpl_in_critical = 0;
static void *_uwb_core_thread(void *arg)
{
(void)arg;
event_queue_init(&_queue);
event_loop(&_queue);
/* never reached */
return NULL;
}
event_queue_t *uwb_core_get_eventq(void)
{
return &_queue;
}
void uwb_core_riot_init(void)
{
thread_create(_stack_uwb_core, sizeof(_stack_uwb_core),
UWB_CORE_PRIO,
THREAD_CREATE_STACKTEST,
_uwb_core_thread, NULL,
"uwb_core");
}

View File

@ -0,0 +1,79 @@
/*
* Copyright (C) 2020 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_uwb_core
* @{
*
* @file
* @brief uwb-core bootstrapping core
*
* @author Francisco Molina <francois-xavier.molina@inria.fr>
* @}
*/
#include "thread.h"
#include "dpl/dpl.h"
#include "uwb_core.h"
#include "uwb_dw1000.h"
#include "uwb_dw1000_params.h"
#include "twr_ss/twr_ss.h"
#include "twr_ss_ext/twr_ss_ext.h"
#include "twr_ss_ack/twr_ss_ack.h"
#include "twr_ds/twr_ds.h"
#include "twr_ds_ext/twr_ds_ext.h"
static dw1000_dev_instance_t dev;
static uint8_t _dw1000_rx_buffer[MYNEWT_VAL(UWB_RX_BUFFER_SIZE)];
static uint8_t _dw1000_tx_buffer[MYNEWT_VAL(DW1000_HAL_SPI_BUFFER_SIZE)];
void uwb_core_init(void)
{
/* this will start the thread handling the event queue for uwb-core */
uwb_core_riot_init();
/* inits the dw1000 devices linked list */
uwb_dw1000_init();
/* set preallocated buffers to avoid malloc/calloc */
uwb_dw1000_set_buffs(&dev, _dw1000_tx_buffer, _dw1000_rx_buffer);
/* setup dw1000 device */
uwb_dw1000_setup(&dev, (void *) &dw1000_params[0]);
/* this will start a thread handling dw1000 device*/
uwb_dw1000_config_and_start(&dev);
/* init uwb pkg's */
if (IS_USED(MODULE_UWB_CORE_RNG)) {
extern void uwb_rng_pkg_init(void);
uwb_rng_pkg_init();
}
/* uwb configuration module */
if (IS_USED(MODULE_UWB_CORE_UWBCFG)) {
extern int uwbcfg_pkg_init(void);
uwbcfg_pkg_init();
}
/* ranging algorithms */
if (IS_USED(MODULE_UWB_CORE_RNG)) {
twr_ss_pkg_init();
}
if (IS_USED(MODULE_UWB_CORE_RNG)) {
twr_ss_ack_pkg_init();
}
if (IS_USED(MODULE_UWB_CORE_RNG)) {
twr_ss_ext_pkg_init();
}
if (IS_USED(MODULE_UWB_CORE_RNG)) {
twr_ds_pkg_init();
}
if (IS_USED(MODULE_UWB_CORE_RNG)) {
twr_ds_ext_pkg_init();
}
}

121
pkg/uwb-core/doc.txt Normal file
View File

@ -0,0 +1,121 @@
/**
* @defgroup pkg_uwb_core Device driver model for the Decawave Impulse Radio-Ultra Wideband (IR-UWB) transceiver(s)
* @ingroup pkg
* @brief Hardware and architecture agnostic platform for IoT
* Location Based Services (LBS)
* @see https://github.com/Decawave/uwb-core
*/
# Decawave uwb-core RIOT Port
The distribution https://github.com/decawave/uwb-core contains the
device driver model for the Decawave Impulse Radio-Ultra Wideband
(IR-UWB) transceiver(s). The driver includes hardware abstraction
layers (HAL), media access control (MAC) layer, Ranging Services (RNG).
The uwb-core driver and RIOT combine to create a hardware and
architecture agnostic platform for IoT Location Based Services (LBS).
## Abstraction details
uwb-core is meant as a hardware and architecture agnostic library. It
was developed with MyNewt as its default OS, but its abstractions are
well defined which makes it easy to use with another OS.
A porting layer DPL (Decawave Porting Layer) has been implemented that
wraps around OS functionalities and modules: mutex, semaphores, threads,
etc.. In most cases the mapping is direct although some specific
functionalities might not be supported.
Since the library was used on top of mynewt most configuration values
are prefixed with `MYNEWT_VAL_%`, all configurations can be found under
`pkg/uwb-core/include/syscfg`.
In MyNewt there is always a default event thread, since we don't have
this in RIOT when using this pkg an event thread is started which will
run as this default event thread.
To work this library needs to be built on top of an UWB device
implementing the `uwb` api (see [uwb](https://github.com/Decawave/uwb-core/tree/master/hw/drivers/uwb).
This port uses [uwb-dw1000](https://github.com/Decawave/uwb-dw1000) as
device driver for dw1000 modules.
The library can be used by directly including the different module headers.
## Current support
uwb-core comes with many utility libraries, only ranging related libraries
are described here. For more info refer to [uwb-core](https://github.com/Decawave/uwb-core).
- uwb-core_uwb: The uwb-core driver implements the MAC layers and
exports a MAC extension interface for additional services.
In the case of this port the api implementation is provided mainly by
the uwb-dw1000 pkg.
- uwb-core_rng: ranging base class, provides the api to perform ranging.
It can use any of the twr_% ranging algorithms mentioned below,
for details on each algorithm refer to the pertinent literature.
- uwb-core_twr_ss: single side two way ranging
- uwb-core_twr_ss_ack: : single side two way ranging using hardware
generated ACK as the response.
- uwb-core_twr_ss_ext: single side two way ranging with extended frames.
- uwb-core_twr_ds: double side two-way ranging
- uwb-core_twr_ds_ext: double side wo way ranging with extended frames.
## Usage example
The most simple examples would be a tdoa blinking tag, here the device
is considered awake.
```c
// IEEE 802.15.4e standard blink
ieee_blink_frame_t tdoa_blink_frame = {
.fctrl = 0xC5, /* frame type (0xC5 for a blink) using 64-bit addressing */
.seq_num = 0, /* sequence number, incremented for each new frame. */
.long_address = 0, /* device ID */
};
// Set device address
tdoa_blink_frame.long_address = udev->my_long_address;
// Write tx data and start transmission
uwb_write_tx(udev, tdoa_blink_frame.array, 0, sizeof(ieee_blink_frame_t));
uwb_start_tx(udev);
// Increase sequence number
tdoa_blink_frame.seq_num++;
```
The following can be wrapped into a timer callback to setup a blinking tag.
For more examples check the [uwb-apps](https://github.com/Decawave/uwb-apps)
repository as well as [examples/twr_aloha](https://github.com/RIOT-OS/RIOT/tree/master/examples/twr-aloha)
## Watchout!
uwb-core uses anonymous structures, therefore any application using this
pkg must also set at application level:
CFLAGS += -fms-extensions
If building with llvm then also `CFLAGS += -Wno-microsoft-anon-tag` must
be added, although it is currently blacklisted because of missing stdatomic
definitions.
## Todos
The uwb-core pkg comes with a wide range of feature that are currently
untested and not supported in this port, these will be incrementally
included:
- [ ] `uwb_cpp`: Clock Calibration Packet (CCP) Service
- [ ] `tdma`: uwb-core offers TDMA support
- [ ] `uwb_wcs`: Wireless Clock Synchronization (WCS) Service
- [ ] `rtdoa`: Reverse Time Difference of Arrival profiles
- [ ] `cir`: Circular impulse response
- [ ] `nrng`: N-ranges support
- [ ] other modules in `lib`
uwb-core uses dynamic allocation for some of its internal modules. It
would be nice to make this optional when possible.

View File

@ -0,0 +1,3 @@
MODULE = uwb-core_dpl
include $(RIOTBASE)/Makefile.base

View File

@ -0,0 +1,58 @@
/*
* Copyright (C) 2020 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_uwb_core
* @{
*
* @file
* @brief uwb-core DPL (Decawave Porting Layer) callout
*
* @author Francisco Molina <francois-xavier.molina@inria.fr>
* @}
*/
#include <assert.h>
#include "xtimer.h"
#include "dpl/dpl_callout.h"
static void _dpl_callout_timer_cb(void* arg)
{
struct dpl_callout *c = (struct dpl_callout *) arg;
assert(c);
/* post the event if there is a queue, otherwise call the callback
here */
if (c->c_q) {
dpl_eventq_put(c->c_q, &c->c_e);
} else {
c->c_e.e.callback(&c->c_e);
}
}
void dpl_callout_init(struct dpl_callout *c, struct dpl_eventq *q,
dpl_event_fn *e_cb, void *e_arg)
{
dpl_event_init(&c->c_e, e_cb, e_arg);
c->c_q = q;
c->timer.callback = _dpl_callout_timer_cb;
c->timer.arg = (void*) c;
}
dpl_error_t dpl_callout_reset(struct dpl_callout *c, dpl_time_t ticks)
{
xtimer_ticks32_t val = {.ticks32 = ticks};
xtimer_set(&(c->timer), xtimer_usec_from_ticks(val));
return DPL_OK;
}
void dpl_callout_stop(struct dpl_callout *c)
{
xtimer_remove(&(c->timer));
}

View File

@ -0,0 +1,58 @@
/*
* Copyright (C) 2020 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_uwb_core
* @{
*
* @file
* @brief Decawave Porting Layer mutex RIOT wrapper
*
* @author Francisco Molina <francois-xavier.molina@inria.fr>
* @}
*/
#include "mutex.h"
#include "dpl/dpl_mutex.h"
dpl_error_t dpl_mutex_init(struct dpl_mutex *mu)
{
if (!mu) {
return DPL_INVALID_PARAM;
}
mutex_init(&mu->mutex);
return DPL_OK;
}
dpl_error_t dpl_mutex_release(struct dpl_mutex *mu)
{
if (!mu) {
return DPL_INVALID_PARAM;
}
mutex_unlock(&mu->mutex);
return DPL_OK;
}
dpl_error_t dpl_mutex_pend(struct dpl_mutex *mu, uint32_t timeout)
{
int rc = DPL_OK;
if (!mu) {
return DPL_INVALID_PARAM;
}
if (!timeout) {
rc = mutex_trylock(&mu->mutex);
}
else {
/* TODO: no timeout equivalent */
mutex_lock(&mu->mutex);
}
return rc;
}

View File

@ -0,0 +1,60 @@
/*
* Copyright (C) 2020 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_uwb_core
* @{
*
* @file
* @brief Decawave Porting Layer semaphore RIOT wrapper
*
* @author Francisco Molina <francois-xavier.molina@inria.fr>
* @}
*/
#include <stdio.h>
#include "irq.h"
#include "dpl/dpl_sem.h"
dpl_error_t dpl_sem_init(struct dpl_sem *sem, uint16_t tokens)
{
if (!sem) {
return DPL_INVALID_PARAM;
}
sema_create(&sem->sema, tokens);
return DPL_OK;
}
dpl_error_t dpl_sem_release(struct dpl_sem *sem)
{
int ret;
if (!sem) {
return DPL_INVALID_PARAM;
}
ret = sema_post(&sem->sema);
return (ret) ? DPL_ERROR : DPL_OK;
}
uint16_t dpl_sem_get_count(struct dpl_sem *sem)
{
unsigned state = irq_disable();
unsigned int value = sem->sema.value;
irq_restore(state);
return value;
}
dpl_error_t dpl_sem_pend(struct dpl_sem *sem, dpl_time_t timeout)
{
int ret = sema_wait_timed(&sem->sema, timeout);
return (ret) ? DPL_ERROR : DPL_OK;
}

View File

@ -0,0 +1,68 @@
/*
* Copyright (C) 2020 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_uwb_core
* @{
*
* @file
* @brief Decawave Porting Layer tasks RIOT wrapper
*
* @author Francisco Molina <francois-xavier.molina@inria.fr>
* @}
*/
#include "dpl/dpl_error.h"
#include "dpl/dpl_tasks.h"
#include "thread.h"
#ifndef LOG_LEVEL
#define LOG_LEVEL LOG_INFO
#endif
#include "log.h"
#ifdef __cplusplus
extern "C" {
#endif
int dpl_task_init(struct dpl_task *t, const char *name, dpl_task_func_t func,
void *arg, uint8_t prio, dpl_time_t sanity_itvl,
dpl_stack_t *stack_bottom, uint16_t stack_size)
{
(void) sanity_itvl;
LOG_INFO("dpl: starting thread %s\n", name);
kernel_pid_t pid = thread_create(stack_bottom, (int) stack_size,
prio, THREAD_CREATE_STACKTEST,
func, arg, name);
t->pid = pid;
return (pid) ? DPL_ERROR : DPL_OK;;
}
int dpl_task_remove(struct dpl_task *t)
{
thread_zombify();
return thread_kill_zombie(t->pid);
}
uint8_t dpl_task_count(void)
{
return sched_num_threads;
}
void dpl_task_yield(void)
{
thread_yield();
}
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,40 @@
/*
* Copyright (C) 2020 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_uwb_core
* @{
*
* @file
* @brief Abstraction layer for RIOT adaption
*
* @author Francisco Molina <francois-xavier.molina@inria.fr>
* @}
*/
#ifndef DPL_DPL_H
#define DPL_DPL_H
#include "syscfg/syscfg.h"
#include "dpl/dpl_types.h"
#include "dpl/dpl_error.h"
#include "dpl/dpl_eventq.h"
#include "dpl/dpl_callout.h"
#include "dpl/dpl_cputime.h"
#include "dpl/dpl_mutex.h"
#include "dpl/dpl_os.h"
#include "dpl/dpl_sem.h"
#include "dpl/dpl_tasks.h"
#include "dpl/dpl_time.h"
#include "kernel_defines.h"
#ifdef __cplusplus
extern "C" {
#endif
#endif /* DPL_DPL_H */

View File

@ -0,0 +1,83 @@
/*
* Copyright (C) 2020 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_uwb_core
* @{
*
* @file
* @brief uwb-core DPL (Decawave Porting Layer) callout abstraction
*
* Callout sets a timer that on expiration will post an event to an
* event queue. This mimics the same as MyNewt callout api.
*
* @author Francisco Molina <francois-xavier.molina@inria.fr>
* @}
*/
#ifndef DPL_DPL_CALLOUT_H
#define DPL_DPL_CALLOUT_H
#include "xtimer.h"
#include "dpl/dpl_types.h"
#include "dpl/dpl_eventq.h"
#include "dpl/dpl_error.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief callout structure
*/
struct dpl_callout {
xtimer_t timer; /**< timer */
struct dpl_event c_e; /**< callout event */
struct dpl_eventq *c_q; /**< callout event queue */
};
/**
* @brief Initialize a callout.
*
* Callouts are used to schedule events in the future onto an event
* queue. Callout timers are scheduled using the dpl_callout_reset()
* function. When the timer expires, an event is posted to the event
* queue specified in dpl_callout_init(). The event argument given here
* is posted in the ev_arg field of that event.
*
* @param[out] c callout to initialize
* @param[in] q event queue to queue event in
* @param[in] e_cb callback function
* @param[in] e_arg callback function argument
*/
void dpl_callout_init(struct dpl_callout *c, struct dpl_eventq *q,
dpl_event_fn *e_cb, void *e_arg);
/**
* @brief Reset the callout to fire off in 'ticks' ticks.
*
* @param[in] c callout to reset
* @param[in] ticks number of ticks to wait before posting an event
*
* @return 0 on success, non-zero on failure
*/
dpl_error_t dpl_callout_reset(struct dpl_callout *c, dpl_time_t ticks);
/**
* @brief Stops the callout from firing.
*
* @param[in] c the callout to stop
*/
void dpl_callout_stop(struct dpl_callout *c);
#ifdef __cplusplus
}
#endif
#endif /* DPL_DPL_CALLOUT_H */

View File

@ -0,0 +1,162 @@
/*
* Copyright (C) 2020 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_uwb_core
* @{
*
* @file
* @brief uwb-core DPL (Decawave Porting Layer) cputime abstraction
*
* @author Francisco Molina <francois-xavier.molina@inria.fr>
* @}
*/
#ifndef DPL_DPL_CPUTIME_H
#define DPL_DPL_CPUTIME_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include "xtimer.h"
#include "hal/hal_timer.h"
/**
* Returns the low 32 bits of cputime.
*
* @return uint32_t The lower 32 bits of cputime
*/
static inline uint32_t dpl_cputime_get32(void)
{
return xtimer_now().ticks32;
}
/**
* Converts the given number of microseconds into cputime ticks.
*
* @param usecs The number of microseconds to convert to ticks
*
* @return uint32_t The number of ticks corresponding to 'usecs'
*/
static inline uint32_t dpl_cputime_usecs_to_ticks(uint32_t usecs)
{
return xtimer_ticks_from_usec(usecs).ticks32;
}
/**
* Convert the given number of ticks into microseconds.
*
* @param ticks The number of ticks to convert to microseconds.
*
* @return uint32_t The number of microseconds corresponding to 'ticks'
*/
static inline uint32_t dpl_cputime_ticks_to_usecs(uint32_t ticks)
{
xtimer_ticks32_t val = {.ticks32 = ticks};
return xtimer_usec_from_ticks(val);
}
/**
* Wait until the number of ticks has elapsed. This is a blocking delay.
*
* @param ticks The number of ticks to wait.
*/
static inline void dpl_cputime_delay_ticks(uint32_t ticks)
{
xtimer_ticks32_t val = {.ticks32 = ticks};
xtimer_tsleep32((xtimer_ticks32_t) val);
}
/**
* Wait until 'usecs' microseconds has elapsed. This is a blocking delay.
*
* @param usecs The number of usecs to wait.
*/
static inline void dpl_cputime_delay_usecs(uint32_t usecs)
{
xtimer_usleep(usecs);
}
/**
* Initialize a CPU timer, using the given HAL timer.
*
* @param timer The timer to initialize. Cannot be NULL.
* @param fp The timer callback function. Cannot be NULL.
* @param arg Pointer to data object to pass to timer.
*/
static inline void dpl_cputime_timer_init(struct hal_timer *timer, hal_timer_cb fp,
void *arg)
{
timer->timer.callback = fp;
timer->timer.arg = arg;
}
/**
* Start a cputimer that will expire at 'cputime'. If cputime has already
* passed, the timer callback will still be called (at interrupt context).
*
* NOTE: This must be called when the timer is stopped.
*
* @param timer Pointer to timer to start. Cannot be NULL.
* @param cputime The cputime at which the timer should expire.
*
* @return int 0 on success; EINVAL if timer already started or timer struct
* invalid
*
*/
static inline int dpl_cputime_timer_start(struct hal_timer *timer, uint32_t cputime)
{
xtimer_set(&timer->timer, xtimer_now_usec() + cputime);
return 0;
}
/**
* Sets a cpu timer that will expire 'usecs' microseconds from the current
* cputime.
*
* NOTE: This must be called when the timer is stopped.
*
* @param timer Pointer to timer. Cannot be NULL.
* @param usecs The number of usecs from now at which the timer will expire.
*
* @return int 0 on success; EINVAL if timer already started or timer struct
* invalid
*/
static inline int dpl_cputime_timer_relative(struct hal_timer *timer, uint32_t usecs)
{
uint32_t now = xtimer_now_usec();
if (now > usecs) {
xtimer_set(&timer->timer, now);
} else {
xtimer_set(&timer->timer, 0);
}
return 0;
}
/**
* @brief Stops a cputimer from running.
*
* The timer is removed from the timer queue and interrupts are disabled
* if no timers are left on the queue. Can be called even if timer is
* not running.
*
* @param timer Pointer to cputimer to stop. Cannot be NULL.
*/
static inline void dpl_cputime_timer_stop(struct hal_timer *timer)
{
xtimer_remove(&timer->timer);
}
#ifdef __cplusplus
}
#endif
#endif /* DPL_DPL_CPUTIME_H */

View File

@ -0,0 +1,55 @@
/*
* Copyright (C) 2020 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_uwb_core
* @{
*
* @file
* @brief uwb-core DPL (Decawave Porting Layer) error types
*
* @author Francisco Molina <francois-xavier.molina@inria.fr>
* @}
*/
#ifndef DPL_DPL_ERROR_H
#define DPL_DPL_ERROR_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief DPL error types
*/
enum dpl_error {
DPL_OK = 0,
DPL_ENOMEM = 1,
DPL_EINVAL = 2,
DPL_INVALID_PARAM = 3,
DPL_MEM_NOT_ALIGNED = 4,
DPL_BAD_MUTEX = 5,
DPL_TIMEOUT = 6,
DPL_ERR_IN_ISR = 7,
DPL_ERR_PRIV = 8,
DPL_OS_NOT_STARTED = 9,
DPL_ENOENT = 10,
DPL_EBUSY = 11,
DPL_ERROR = 12,
};
/**
* @brief dep error type
*/
typedef enum dpl_error dpl_error_t;
#ifdef __cplusplus
}
#endif
#endif /* DPL_DPL_ERROR_H */

View File

@ -0,0 +1,241 @@
/*
* Copyright (C) 2020 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_uwb_core
* @{
*
* @file
* @brief uwb-core DPL (Decawave Porting Layer) event queue wrappers
*
* @author Francisco Molina <francois-xavier.molina@inria.fr>
* @}
*/
#ifndef DPL_DPL_EVENTQ_H
#define DPL_DPL_EVENTQ_H
#include <dpl/dpl_types.h>
#include "uwb_core.h"
#include "event/callback.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief dpl event wrapper
*/
struct dpl_event
{
event_callback_t e; /**< the event callback */
void *arg; /**< the event argument */
};
/**
* @brief dpl event queue wrapper
*/
struct dpl_eventq
{
event_queue_t q; /**< the event queue */
};
/**
* @brief dpl event callback function
*/
typedef void dpl_event_fn(struct dpl_event *ev);
/**
* @brief Init a event
*
* @param[in] ev pointer to event to set
* @param[in] fn event callback function
* @param[in] arg event argument
*/
static inline void dpl_event_init(struct dpl_event *ev, dpl_event_fn * fn,
void *arg)
{
/*
* Need to clear list_node manually since init function below does not do
* this.
*/
ev->e.super.list_node.next = NULL;
event_callback_init(&ev->e, (void(*)(void *))fn, ev);
ev->arg = arg;
}
/**
* @brief Check if event is in queue
*
* @param[in] ev event to check
*
* @return true if event is queues, false otherwise
*/
static inline bool dpl_event_is_queued(struct dpl_event *ev)
{
return (ev->e.super.list_node.next != NULL);
}
/**
* @brief Runs an event
*
* @param[in] ev event to run
*/
static inline void *dpl_event_get_arg(struct dpl_event *ev)
{
return ev->arg;
}
/**
* @brief Set the vent arg
*
* @param[in] ev event
* @param[in] arg arg to set event
*/
static inline void dpl_event_set_arg(struct dpl_event *ev, void *arg)
{
ev->arg = arg;
}
/**
* @brief Runs an event
*
* @param[in] ev event to run
*/
static inline void dpl_event_run(struct dpl_event *ev)
{
ev->e.super.handler(&ev->e.super);
}
/**
* @brief Initialize the event queue
*
* @param[in] evq The event queue to initialize
*/
static inline void dpl_eventq_init(struct dpl_eventq *evq)
{
event_queue_init_detached(&evq->q);
}
/**
* @brief Check whether the event queue is initialized.
*
* @param[in] evq the event queue to check
*/
static inline int dpl_eventq_inited(struct dpl_eventq *evq)
{
return evq->q.waiter != NULL;
}
/**
* @brief Deinitialize an event queue
*
* @note Not supported in RIOT
*
* @param[in] evq the event queue to deinit
*/
static inline void dpl_eventq_deinit(struct dpl_eventq *evq)
{
(void) evq;
/* Can't deinit an eventq in RIOT */
}
/**
* @brief Get next event from event queue, blocking.
*
* @param[in] evq the event queue to pull an event from
*
* @return the event from the queue
*/
static inline struct dpl_event * dpl_eventq_get(struct dpl_eventq *evq)
{
if (evq->q.waiter == NULL) {
event_queue_claim(&evq->q);
}
return (struct dpl_event *) event_wait(&evq->q);
}
/**
* @brief Get next event from event queue, non-blocking
*
* @return event from the queue, or NULL if none available.
*/
static inline struct dpl_event * dpl_eventq_get_no_wait(struct dpl_eventq *evq)
{
if (evq->q.waiter == NULL) {
event_queue_claim(&evq->q);
}
return (struct dpl_event *) event_get(&evq->q);
}
/**
* @brief Put an event on the event queue.
*
* @param[in] evq event queue
* @param[in] ev event to put in queue
*/
static inline void dpl_eventq_put(struct dpl_eventq *evq, struct dpl_event *ev)
{
event_post(&evq->q, &ev->e.super);
}
/**
* @brief Remove an event from the queue.
*
* @param[in] evq event queue to remove the event from
* @param[in] ev event to remove from the queue
*/
static inline void dpl_eventq_remove(struct dpl_eventq *evq, struct dpl_event *ev)
{
event_cancel(&evq->q, &ev->e.super);
}
/**
* @brief Gets and runs an event from the queue callback.
*
* @param[in] evq The event queue to pull the item off.
*/
static inline void dpl_eventq_run(struct dpl_eventq *evq)
{
struct dpl_event *ev = dpl_eventq_get(evq);
dpl_event_run(ev);
}
/**
* @brief Check if queue is empty
*
* @param[in] evq the event queue to check
*
* @return true if empty, false otherwise
*/
static inline bool dpl_eventq_is_empty(struct dpl_eventq *evq)
{
return clist_count(&(evq->q.event_list)) == 0;
}
/**
* @brief Retrieves the default event queue.
*
* As there is no default event queue in RIOT, uwb-core will start and
* handle a default event queue.
*
* @return the default event queue.
*/
static inline struct dpl_eventq * dpl_eventq_dflt_get(void)
{
return (struct dpl_eventq*) uwb_core_get_eventq();
}
#ifdef __cplusplus
}
#endif
#endif /* DPL_DPL_EVENTQ_H */

View File

@ -0,0 +1,74 @@
/*
* Copyright (C) 2020 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_uwb_core
* @{
*
* @file
* @brief uwb-core DPL (Decawave Porting Layer) mutex wrappers
*
* @author Francisco Molina <francois-xavier.molina@inria.fr>
* @}
*/
#ifndef DPL_DPL_MUTEX_H
#define DPL_DPL_MUTEX_H
#include "dpl_types.h"
#include "dpl_error.h"
#include "mutex.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief dpl mutex wrapper
*/
struct dpl_mutex {
mutex_t mutex; /**< the mutex */
};
/**
* @brief Initializes a mutex object.
*
* @param[out] mu pre-allocated mutex structure, must not be NULL.
*/
dpl_error_t dpl_mutex_init(struct dpl_mutex *mu);
/**
* @brief Pend (wait) for a mutex.
*
* @param[in] mu Pointer to mutex.
* @param[in] timeout Timeout, in os ticks.
* A timeout of 0 means do not wait if not available.
* A timeout of OS_TIMEOUT_NEVER means wait forever.
*
* @return dpl_error_t
* DPL_INVALID_PARM mutex passed in was NULL
* DPL_OK no error
*/
dpl_error_t dpl_mutex_pend(struct dpl_mutex *mu, dpl_time_t timeout);
/**
*
* @brief Release a mutex.
*
* @return dpl_error_t
* DPL_INVALID_PARM mutex was NULL
* DPL_OK no error
*/
dpl_error_t dpl_mutex_release(struct dpl_mutex *mu);
#ifdef __cplusplus
}
#endif
#endif /* DPL_DPL_MUTEX_H */

View File

@ -0,0 +1,97 @@
/*
* Copyright (C) 2020 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_uwb_core
* @{
*
* @file
* @brief uwb-core DPL (Decawave Porting Layer) error types
*
* @author Francisco Molina <francois-xavier.molina@inria.fr>
* @}
*/
#ifndef DPL_DPL_OS_H
#define DPL_DPL_OS_H
#include <assert.h>
#include <stdint.h>
#include <stdatomic.h>
#include "irq.h"
#include "dpl/dpl_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @name Entering and exiting critical section defines
* @{
*/
#define DPL_ENTER_CRITICAL(_sr) (_sr = dpl_hw_enter_critical())
#define DPL_EXIT_CRITICAL(_sr) (dpl_hw_exit_critical(_sr))
#define DPL_ASSERT_CRITICAL() assert(dpl_hw_is_in_critical())
/** @} */
/**
* @brief variable to check if ISR are disabled
*/
extern atomic_uint dpl_in_critical;
/**
* @brief CPU status register
*/
typedef uint32_t dpl_sr_t;
/**
* @brief Disable ISRs
*
* @return current isr context
*/
static inline uint32_t dpl_hw_enter_critical(void)
{
uint32_t ctx = irq_disable();
unsigned int count = atomic_load(&dpl_in_critical);
atomic_store(&dpl_in_critical, count + 1);
return ctx;
}
/**
* @brief Restores ISR context
*
* @param[in] ctx ISR context to restore.
*/
static inline void dpl_hw_exit_critical(uint32_t ctx)
{
unsigned int count = atomic_load(&dpl_in_critical);
atomic_store(&dpl_in_critical, count - 1);
irq_restore((unsigned)ctx);
}
/**
* @brief Check if is in critical section
*
* @return true, if in critical section, false otherwise
*/
static inline bool dpl_hw_is_in_critical(void)
{
/*
* XXX Currently RIOT does not support an API for finding out if interrupts
* are currently disabled, hence in a critical section in this context.
* So for now, we use this global variable to keep this state for us.
*/
return (atomic_load(&dpl_in_critical) > 0);
}
#ifdef __cplusplus
}
#endif
#endif /* DPL_DPL_OS_H */

View File

@ -0,0 +1,89 @@
/*
* Copyright (C) 2020 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_uwb_core
* @{
*
* @file
* @brief uwb-core DPL (Decawave Porting Layer) semapahore wrappers
*
* @author Francisco Molina <francois-xavier.molina@inria.fr>
* @}
*/
#ifndef DPL_DPL_SEM_H
#define DPL_DPL_SEM_H
#include <stdint.h>
#include "dpl_types.h"
#include "dpl_error.h"
#include "sema.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief dpl semaphore wrapper
*/
struct dpl_sem {
sema_t sema; /**< the semaphore */
};
/**
* @brief Initialize a semaphore
*
* @param[in] sem pointer to semaphore
* @param[in] tokens # of tokens the semaphore should contain initially.
*
* @return dpl_error_t
* DPL_INVALID_PARM Semaphore passed in was NULL.
* DPL_OK no error.
*/
dpl_error_t dpl_sem_init(struct dpl_sem *sem, uint16_t tokens);
/**
* @brief Pend (wait) for a semaphore.
*
* @param[in] sem pointer to semaphore.
* @param[in] timeout timeout, in os ticks.
* A timeout of 0 means do not wait if not available.
* A timeout of DPL_TIMEOUT_NEVER means wait forever.
*
*
* @return dpl_error_t
* DPL_INVALID_PARM semaphore passed in was NULL.
* DPL_TIMEOUT semaphore was owned by another task and timeout=0
* DPL_OK no error
*/
dpl_error_t dpl_sem_pend(struct dpl_sem *sem, dpl_time_t timeout);
/**
* @brief Release a semaphore.
*
* @param[in] sem pointer to the semaphore to be released
*
* @return dpl_error_t
* DPL_INVALID_PARM semaphore passed in was NULL.
* DPL_OK no error
*/
dpl_error_t dpl_sem_release(struct dpl_sem *sem);
/**
* @brief Get current semaphore's count
*/
uint16_t dpl_sem_get_count(struct dpl_sem *sem);
#ifdef __cplusplus
}
#endif
#endif /* DPL_DPL_SEM_H */

View File

@ -0,0 +1,90 @@
/*
* Copyright (C) 2020 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_uwb_core
* @{
*
* @file
* @brief uwb-core DPL (Decawave Porting Layer) thread/task wrappers
*
* @author Francisco Molina <francois-xavier.molina@inria.fr>
* @}
*/
#ifndef DPL_DPL_TASKS_H
#define DPL_DPL_TASKS_H
#include "dpl_types.h"
#include "kernel_types.h"
#include "thread.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief dpl task wrapper
*/
struct dpl_task {
kernel_pid_t pid; /**< the process id */
};
/**
* @brief dpl task function
*/
typedef thread_task_func_t dpl_task_func_t;
/**
* @brief Initialize a task.
*
* This function initializes the task structure pointed to by t,
* clearing and setting it's stack pointer, provides sane defaults
* and sets the task as ready to run, and inserts it into the operating
* system scheduler.
*
* @param[in] t the task to initialize
* @param[in] name task name
* @param[in] func task function to call
* @param[in] arg argument to pass in task init function
* @param[in] prio task priority
* @param[in] sanity_itvl UNUSED
* @param[in] stack_bottom pointer to bottom of the stack
* @param[in] stack_size task stack size
*
* @return 0 on success, non-zero on failure.
*/
int dpl_task_init(struct dpl_task *t, const char *name, dpl_task_func_t func,
void *arg, uint8_t prio, dpl_time_t sanity_itvl,
dpl_stack_t *stack_bottom, uint16_t stack_size);
/**
* @brief removes specified task
*
* NOTE: This interface is currently experimental and not ready for common use
*/
int dpl_task_remove(struct dpl_task *t);
/**
* @brief Return the number of tasks initialized.
*
* @return number of tasks initialized
*/
uint8_t dpl_task_count(void);
/**
* @brief Lets current thread yield.
*/
void dpl_task_yield(void);
#ifdef __cplusplus
}
#endif
#endif /* DPL_DPL_TASKS_H */

View File

@ -0,0 +1,113 @@
/*
* Copyright (C) 2020 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_uwb_core
* @{
*
* @file
* @brief uwb-core DPL (Decawave Porting Layer) time abstraction
*
* @author Francisco Molina <francois-xavier.molina@inria.fr>
* @}
*/
#ifndef DPL_DPL_TIME_H
#define DPL_DPL_TIME_H
#include "xtimer.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief DPL ticks per seconds
*/
#define DPL_TICKS_PER_SEC (XTIMER_HZ)
/**
* @brief Returns the low 32 bits of cputime.
*
* @return uint32_t The lower 32 bits of cputime
*/
static inline dpl_time_t dpl_time_get(void)
{
return xtimer_now().ticks32;
}
/**
* @brief Converts the given number of milliseconds into cputime ticks.
*
* @param[in] ms The number of milliseconds to convert to ticks
* @param[out] out_ticks The number of ticks corresponding to 'ms'
*
* @return dpl_error_t DPL_OK - no error
*/
static inline dpl_error_t dpl_time_ms_to_ticks(uint32_t ms, dpl_time_t *out_ticks)
{
*out_ticks = xtimer_ticks_from_usec(ms * US_PER_MS).ticks32;
return DPL_OK;
}
/**
* @brief Convert the given number of ticks into milliseconds.
*
* @param[in] ticks The number of ticks to convert to milliseconds.
* @param[out] out_ms The converted milliseconds from 'ticks'
*
* @return dpl_error_t DPL_OK - no error
*/
static inline dpl_error_t dpl_time_ticks_to_ms(dpl_time_t ticks, uint32_t *out_ms)
{
xtimer_ticks32_t val = {.ticks32 = ticks};
*out_ms = xtimer_usec_from_ticks(val) * US_PER_MS;
return DPL_OK;
}
/**
* @brief Converts the given number of milliseconds into cputime ticks.
*
* @param[in] ms The number of milliseconds to convert to ticks
*
* @return uint32_t The number of ticks corresponding to 'ms'
*/
static inline dpl_time_t dpl_time_ms_to_ticks32(uint32_t ms)
{
return xtimer_ticks_from_usec(ms * US_PER_MS).ticks32;
}
/**
* @brief Convert the given number of ticks into milliseconds.
*
* @param[in] ticks The number of ticks to convert to milliseconds.
*
* @return uint32_t The number of milliseconds corresponding to 'ticks'
*/
static inline dpl_time_t dpl_time_ticks_to_ms32(dpl_time_t ticks)
{
xtimer_ticks32_t val = {.ticks32 = ticks};
return xtimer_usec_from_ticks(val) * US_PER_MS;
}
/**
* @brief Wait until the number of ticks has elapsed, BLOICKING.
*
* @param[in] ticks The number of ticks to wait.
*/
static inline void dpl_time_delay(dpl_time_t ticks)
{
xtimer_ticks32_t val = {.ticks32 = ticks};
xtimer_tsleep32((xtimer_ticks32_t) val);
}
#ifdef __cplusplus
}
#endif
#endif /* DPL_DPL_TIME_H */

View File

@ -0,0 +1,118 @@
/*
* Copyright (C) 2020 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_uwb_core
* @{
*
* @file
* @brief uwb-core DPL (Decawave Porting Layer) types
*
* @author Francisco Molina <francois-xavier.molina@inria.fr>
* @}
*/
#ifndef DPL_DPL_TYPES_H
#define DPL_DPL_TYPES_H
#include <stdint.h>
#include <math.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief PI approximated value macro definition
*/
#ifndef M_PI
#define M_PI 3.1415926535
#endif
/**
* @name Macro to wait forever on events and mutexes
* @{
*/
#define DPL_TIMEOUT_NEVER (UINT32_MAX)
#define DPL_WAIT_FOREVER (DPL_TIMEOUT_NEVER)
/** @} */
/**
* @name Decawave porting layer (DPL) stack alignment requirement
* @{
*/
#define DPL_STACK_ALIGNMENT (4)
/** @} */
/**
* @brief dpl time type
*/
typedef uint32_t dpl_time_t;
/**
* @brief dpl stack buffer type
*/
typedef char dpl_stack_t;
/**
* @brief dpl float 32 type
*/
typedef float dpl_float32_t;
/**
* @brief dpl float 64 type
*/
typedef double dpl_float64_t;
/**
* @name Decawave porting layer (DPL) float type macros
* @{
*/
#define DPL_FLOAT32_INIT(__X) ((float)__X)
#define DPL_FLOAT64_INIT(__X) ((double)__X)
#define DPL_FLOAT64TO32(__X) (float)(__X)
#define DPL_FLOAT32_I32_TO_F32(__X) (float)(__X)
#define DPL_FLOAT64_I32_TO_F64(__X) ((double)(__X))
#define DPL_FLOAT64_I64_TO_F64(__X) ((double)(__X))
#define DPL_FLOAT64_U64_TO_F64(__X) ((double)(__X))
#define DPL_FLOAT64_F64_TO_U64(__X) ((uint64_t)(__X))
#define DPL_FLOAT32_INT(__X) ((int32_t)__X)
#define DPL_FLOAT64_INT(__X) ((int64_t)__X)
#define DPL_FLOAT64_FROM_F32(__X) (double)(__X)
#define DPL_FLOAT32_FROM_F64(__X) (float)(__X)
#define DPL_FLOAT32_CEIL(__X) (ceilf(__X))
#define DPL_FLOAT64_CEIL(__X) (ceil(__X))
#define DPL_FLOAT32_FABS(__X) fabsf(__X)
#define DPL_FLOAT32_FMOD(__X, __Y) fmodf(__X, __Y)
#define DPL_FLOAT64_FMOD(__X, __Y) fmod(__X, __Y)
#define DPL_FLOAT32_NAN() nanf("")
#define DPL_FLOAT64_NAN() nan("")
#define DPL_FLOAT32_ISNAN(__X) isnan(__X)
#define DPL_FLOAT64_ISNAN(__X) DPL_FLOAT32_ISNAN(__X)
#define DPL_FLOAT32_LOG10(__X) (log10f(__X))
#define DPL_FLOAT64_LOG10(__X) (log10(__X))
#define DPL_FLOAT64_ASIN(__X) asin(__X)
#define DPL_FLOAT64_ATAN(__X) atan(__X)
#define DPL_FLOAT32_SUB(__X, __Y) ((__X)-(__Y))
#define DPL_FLOAT64_SUB(__X, __Y) ((__X)-(__Y))
#define DPL_FLOAT32_ADD(__X, __Y) ((__X)+(__Y))
#define DPL_FLOAT64_ADD(__X, __Y) ((__X)+(__Y))
#define DPL_FLOAT32_MUL(__X, __Y) ((__X)*(__Y))
#define DPL_FLOAT64_MUL(__X, __Y) ((__X)*(__Y))
#define DPL_FLOAT32_DIV(__X, __Y) ((__X)/(__Y))
#define DPL_FLOAT64_DIV(__X, __Y) ((__X)/(__Y))
#define DPL_FLOAT32_PRINTF_PRIM "%s%d.%03d"
#define DPL_FLOAT32_PRINTF_VALS(__X) (__X)<0?"-":"", (int)(fabsf(__X)), (int)(fabsf((__X)-(int)(__X))*1000)
#define DPL_FLOAT64_PRINTF_PRIM "%s%d.%06d"
#define DPL_FLOAT64_PRINTF_VALS(__X) (__X)<0?"-":"", (int)(fabs(__X)), (int)(fabs((__X)-(int)(__X))*1000000)
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* DPL_DPL_TYPES_H */

View File

@ -0,0 +1,48 @@
/*
* Copyright (C) 2020 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_uwb_core
* @{
*
* @file
* @brief System logging header for uwb-core
*
* @author Francisco Molina <francois-xavier.molina@inria.fr>
* @}
*/
#ifndef LOG_DPL_LOG_H
#define LOG_DPL_LOG_H
#ifdef __cplusplus
extern "C" {
#endif
#include "log.h"
/**
* @name Logging convenience defines wrappers
* @{
*/
#define LOG_WARN(...) LOG(LOG_WARNING, __VA_ARGS__)
#define LOG_CRITICAL(...) LOG(LOG_ERROR, __VA_ARGS__)
#define log_register(__X, __Y, __Z, __A, __B) {}
/** @} */
/**
* @brief Empty log structure
*/
struct log {
};
#ifdef __cplusplus
}
#endif
#endif /* LOG_DPL_LOG_H */

View File

@ -0,0 +1,33 @@
/*
* Copyright (C) 2020 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_uwb_core
* @{
*
* @file
* @brief Abstraction layer for RIOT adaption
*
* @author Francisco Molina <francois-xavier.molina@inria.fr>
* @}
*/
#ifndef MCU_MCU_H
#define MCU_MCU_H
#ifdef __cplusplus
extern "C" {
#endif
/* empty header */
#ifdef __cplusplus
}
#endif
#endif /* MCU_MCU_H */

View File

@ -0,0 +1,30 @@
/*
* Copyright (C) 2020 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_uwb_core
* @{
*
* @file
* @brief Abstraction layer for RIOT adaption
*
* @author Francisco Molina <francois-xavier.molina@inria.fr>
* @}
*/
#ifndef OS_OS_H
#define OS_OS_H
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif /* OS_OS_H */

View File

@ -0,0 +1,52 @@
/*
* Copyright (C) 2020 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_uwb_core
* @{
*
* @file
* @brief Abstraction layer for RIOT adaption
*
* @author Francisco Molina <francois-xavier.molina@inria.fr>
* @}
*/
#ifndef OS_OS_DEV_H
#define OS_OS_DEV_H
#include "dpl/dpl.h"
#include "dpl/queue.h"
#include "net/ieee802154.h"
#include "net/netdev.h"
#include "net/netdev/ieee802154.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Device structure.
*/
struct os_dev {
netdev_ieee802154_t netdev; /**< Netdev parent struct */
};
/**
* @brief Unused define, void cast
*/
#define OS_DEV_SETHANDLERS(__dev, __open, __close) \
(void) __dev; \
(void) __open; \
(void) __close;
#ifdef __cplusplus
}
#endif
#endif /* OS_OS_DEV_H */

View File

@ -0,0 +1,33 @@
/*
* Copyright (C) 2020 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_uwb_core
* @{
*
* @file
* @brief Abstraction layer for RIOT adaption
*
* @author Francisco Molina <francois-xavier.molina@inria.fr>
* @}
*/
#ifndef STATS_STATS_H
#define STATS_STATS_H
#ifdef __cplusplus
extern "C" {
#endif
/* empty header */
#ifdef __cplusplus
}
#endif
#endif /* STATS_STATS_H */

View File

@ -0,0 +1,75 @@
/*
* Copyright (C) 2020 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_uwb_core
* @{
*
* @file
* @brief uwb-core system configurations
*
* @author Francisco Molina <francois-xavier.molina@inria.fr>
* @}
*/
#ifndef SYSCFG_SYSCFG_H
#define SYSCFG_SYSCFG_H
#include "kernel_defines.h"
/**
* @name MyNewt header inclusion macro definitions
* @{
*
* This macro exists to ensure code includes this header when needed. If code
* checks the existence of a setting directly via ifdef without including this
* header, the setting macro will silently evaluate to 0. In contrast, an
* attempt to use these macros without including this header will result in a
* compiler error.
*/
#define MYNEWT_VAL(_name) MYNEWT_VAL_ ## _name
#define MYNEWT_VAL_CHOICE(_name, _val) MYNEWT_VAL_ ## _name ## __ ## _val
/** @} */
/*** @decawave-uwb-core/hw/drivers/uwb */
#include "syscfg_uwb.h"
/*** @decawave-uwb-core/lib/twr_ds */
#include "syscfg_twr_ds.h"
/*** @decawave-uwb-core/lib/twr_ds_ext */
#include "syscfg_twr_ds_ext.h"
/*** @decawave-uwb-core/lib/twr_ss */
#include "syscfg_twr_ss.h"
/*** @decawave-uwb-core/lib/twr_ss_ack */
#include "syscfg_twr_ss_ack.h"
/*** @decawave-uwb-core/lib/twr_ss_ext */
#include "syscfg_twr_ss_ext.h"
/*** @decawave-uwb-core/lib/uwb_rng */
#include "syscfg_uwb_rng.h"
/*** @decawave-uwb-core/sys/uwbcfg */
#include "syscfg_uwbcfg.h"
/*** @decawave-uwb-dw1000/hw/drivers/uwb/uwb_dw1000 */
#include "syscfg_uwb_dw1000.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif /* SYSCFG_SYSCFG_H */

View File

@ -0,0 +1,53 @@
/*
* Copyright (C) 2020 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_uwb_core
* @{
*
* @file
* @brief uwb-dw100 double side two-way ranging module configurations
* taken from decawave-uwb-core/lib/twr_ds/syscfg.yml
*
* @author Francisco Molina <francois-xavier.molina@inria.fr>
* @}
*/
#ifndef SYSCFG_SYSCFG_TWR_DS_H
#define SYSCFG_SYSCFG_TWR_DS_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Enable toplevel ranging services
*/
#ifndef MYNEWT_VAL_TWR_DS_ENABLED
#define MYNEWT_VAL_TWR_DS_ENABLED (IS_ACTIVE(MODULE_UWB_CORE_TWR_DS))
#endif
/**
* @brief TOA timeout delay for DS TWR (usec)
*/
#ifndef MYNEWT_VAL_TWR_DS_RX_TIMEOUT
#define MYNEWT_VAL_TWR_DS_RX_TIMEOUT (((uint16_t)0x30))
#endif
/**
* @brief tx holdoff delay for DS TWR (usec)
*/
#ifndef MYNEWT_VAL_TWR_DS_TX_HOLDOFF
#define MYNEWT_VAL_TWR_DS_TX_HOLDOFF (((uint32_t)0x0300))
#endif
#ifdef __cplusplus
}
#endif
#endif /* SYSCFG_SYSCFG_TWR_DS_H */

View File

@ -0,0 +1,53 @@
/*
* Copyright (C) 2020 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_uwb_core
* @{
*
* @file
* @brief uwb-core double side extended two-way ranging module configurations
* taken from decawave-uwb-core/lib/twr_ds_ext/syscfg.yml
*
* @author Francisco Molina <francois-xavier.molina@inria.fr>
* @}
*/
#ifndef SYSCFG_SYSCFG_TWR_DS_EXT_H
#define SYSCFG_SYSCFG_TWR_DS_EXT_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Enable double sided extended two way ranging
*/
#ifndef MYNEWT_VAL_TWR_DS_EXT_ENABLED
#define MYNEWT_VAL_TWR_DS_EXT_ENABLED IS_ACTIVE(MODULE_UWB_CORE_TWR_DS_EXT)
#endif
/**
* @brief Enable double sided extended two way ranging
*/
#ifndef MYNEWT_VAL_TWR_DS_EXT_RX_TIMEOUT
#define MYNEWT_VAL_TWR_DS_EXT_RX_TIMEOUT (((uint16_t)0x40))
#endif
/**
* @brief tx holdoff delay for DS TWR extended frame (usec)
*/
#ifndef MYNEWT_VAL_TWR_DS_EXT_TX_HOLDOFF
#define MYNEWT_VAL_TWR_DS_EXT_TX_HOLDOFF (((uint32_t)0x0400))
#endif
#ifdef __cplusplus
}
#endif
#endif /* SYSCFG_SYSCFG_TWR_DS_EXT_H */

View File

@ -0,0 +1,53 @@
/*
* Copyright (C) 2020 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_uwb_core
* @{
*
* @file
* @brief uwb-core single-sided two-way ranging module configurations
* taken from decawave-uwb-core/lib/twr_ss/syscfg.yml
*
* @author Francisco Molina <francois-xavier.molina@inria.fr>
* @}
*/
#ifndef SYSCFG_SYSCFG_TWR_SS_H
#define SYSCFG_SYSCFG_TWR_SS_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Enable ranging services
*/
#ifndef MYNEWT_VAL_TWR_SS_ENABLED
#define MYNEWT_VAL_TWR_SS_ENABLED (IS_ACTIVE(MODULE_UWB_CORE_TWR_SS))
#endif
/**
* @brief TOA timeout delay for SS TWR (usec)
*/
#ifndef MYNEWT_VAL_TWR_SS_RX_TIMEOUT
#define MYNEWT_VAL_TWR_SS_RX_TIMEOUT (((uint16_t)0x30))
#endif
/**
* @brief tx holdoff delay for SS TWR (usec)
*/
#ifndef MYNEWT_VAL_TWR_SS_TX_HOLDOFF
#define MYNEWT_VAL_TWR_SS_TX_HOLDOFF (((uint32_t)0x0300))
#endif
#ifdef __cplusplus
}
#endif
#endif /* SYSCFG_SYSCFG_TWR_SS_H */

View File

@ -0,0 +1,53 @@
/*
* Copyright (C) 2020 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_uwb_core
* @{
*
* @file
* @brief Single sided ranging using a hw generated ack module configurations
* taken from decawave-uwb-core/lib/twr_ss_ack/syscfg.yml
*
* @author Francisco Molina <francois-xavier.molina@inria.fr>
* @}
*/
#ifndef SYSCFG_SYSCFG_TWR_SS_ACK_H
#define SYSCFG_SYSCFG_TWR_SS_ACK_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Enable toplevel ranging services
*/
#ifndef MYNEWT_VAL_TWR_SS_ACK_ENABLED
#define MYNEWT_VAL_TWR_SS_ACK_ENABLED (IS_ACTIVE(MODULE_UWB_CORE_TWR_SS_ACK))
#endif
/**
* @brief tx holdoff delay used to know how long to wait for SS TWR ACK message (usec)
*/
#ifndef MYNEWT_VAL_TWR_SS_ACK_RX_TIMEOUT
#define MYNEWT_VAL_TWR_SS_ACK_RX_TIMEOUT (((uint16_t)0x100))
#endif
/**
* @brief TOA timeout delay for SS TWR (usec)
*/
#ifndef MYNEWT_VAL_TWR_SS_ACK_TX_HOLDOFF
#define MYNEWT_VAL_TWR_SS_ACK_TX_HOLDOFF (((uint32_t)0x800))
#endif
#ifdef __cplusplus
}
#endif
#endif /* SYSCFG_SYSCFG_TWR_SS_ACK_H */

View File

@ -0,0 +1,53 @@
/*
* Copyright (C) 2020 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_uwb_core
* @{
*
* @file
* @brief uwb-core single-sided two-way ranging module configurations
* taken from decawave-uwb-core/lib/twr_ss_ext/syscfg.yml
*
* @author Francisco Molina <francois-xavier.molina@inria.fr>
* @}
*/
#ifndef SYSCFG_SYSCFG_TWR_SS_EXT_H
#define SYSCFG_SYSCFG_TWR_SS_EXT_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Enable Single Sided extended ranging services
*/
#ifndef MYNEWT_VAL_TWR_SS_EXT_ENABLED
#define MYNEWT_VAL_TWR_SS_EXT_ENABLED (IS_ACTIVE(MODULE_UWB_CORE_TWR_SS_EXT))
#endif
/**
* @brief TOA timeout delay for SS EXT TWR (usec)
*/
#ifndef MYNEWT_VAL_TWR_SS_EXT_RX_TIMEOUT
#define MYNEWT_VAL_TWR_SS_EXT_RX_TIMEOUT (((uint16_t)0x40))
#endif
/**
* @brief tx holdoff delay for SS EXT TWR (usec)
*/
#ifndef MYNEWT_VAL_TWR_SS_EXT_TX_HOLDOFF
#define MYNEWT_VAL_TWR_SS_EXT_TX_HOLDOFF (((uint32_t)0x0400))
#endif
#ifdef __cplusplus
}
#endif
#endif /* SYSCFG_SYSCFG_TWR_SS_EXT_H */

View File

@ -0,0 +1,144 @@
/*
* Copyright (C) 2020 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_uwb_core
* @{
*
* @file
* @brief uwb-core uwb module configurations
* taken from decawave-uwb-core/hw/drivers/uwb/syscfg.yml
*
* @author Francisco Molina <francois-xavier.molina@inria.fr>
* @}
*/
#ifndef SYSCFG_SYSCFG_UWB_H
#define SYSCFG_SYSCFG_UWB_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Interrupt task priority for instance 0
*/
#ifndef MYNEWT_VAL_UWB_DEV_TASK_PRIO
#define MYNEWT_VAL_UWB_DEV_TASK_PRIO (THREAD_PRIORITY_MAIN - 5)
#endif
/**
* @brief Size of interrupt task stack
*/
#ifndef MYNEWT_VAL_UWB_DEV_TASK_STACK_SZ
#define MYNEWT_VAL_UWB_DEV_TASK_STACK_SZ (1024)
#endif
/**
* @brief Size of the rx buffer in the uwb_dev
*/
#ifndef MYNEWT_VAL_UWB_RX_BUFFER_SIZE
#define MYNEWT_VAL_UWB_RX_BUFFER_SIZE (1024)
#endif
/**
* @brief Enable init messages showing each package has been initialised
*/
#ifndef MYNEWT_VAL_UWB_PKG_INIT_LOG
#define MYNEWT_VAL_UWB_PKG_INIT_LOG (1)
#endif
/**
* @brief Maximum size of rxdiag structure
*/
#ifndef MYNEWT_VAL_UWB_DEV_RXDIAG_MAXLEN
#define MYNEWT_VAL_UWB_DEV_RXDIAG_MAXLEN (20)
#endif
/**
* @brief UWB_0 Device Enable. BSP uses this to enable the specific uwb device
*
* @note in uwb-core you need to tell exactly how many uwb-device there
* are, ideally thus would be done different
*/
#ifndef MYNEWT_VAL_UWB_DEVICE_0
#define MYNEWT_VAL_UWB_DEVICE_0 (1)
#endif
/**
* @brief Max number of UWB_DEVICES allowed in system
*
* @note uwb-core uses arrays to keep track of devices, currently se use
* linked list, this is temporary...
*/
#ifndef MYNEWT_VAL_UWB_DEVICE_MAX
#define MYNEWT_VAL_UWB_DEVICE_MAX (3)
#endif
/**
* @brief If ipatov and sts timestamps differ by more than this value
* they are considered invalid
*/
#ifndef MYNEWT_VAL_UWB_STS_TS_MATCH_THRESHOLD
#define MYNEWT_VAL_UWB_STS_TS_MATCH_THRESHOLD (30)
#endif
/**
* @brief Default Anchor X Coordinate
*/
#ifndef MYNEWT_VAL_LOCAL_COORDINATE_X
#define MYNEWT_VAL_LOCAL_COORDINATE_X (((float)0.0f))
#endif
/**
* @brief Default Anchor Y Coordinate
*/
#ifndef MYNEWT_VAL_LOCAL_COORDINATE_Y
#define MYNEWT_VAL_LOCAL_COORDINATE_Y (((float)0.0f))
#endif
/**
* @brief Default Anchor Z Coordinate
*/
#ifndef MYNEWT_VAL_LOCAL_COORDINATE_Z
#define MYNEWT_VAL_LOCAL_COORDINATE_Z (((float)0.0f))
#endif
/**
* @brief Range Measurement Variance
*/
#ifndef MYNEWT_VAL_RANGE_VARIANCE
#define MYNEWT_VAL_RANGE_VARIANCE (((float)5.4444e-04))
#endif
/**
* @brief Azimuth Measurement Variance
*/
#ifndef MYNEWT_VAL_AZIMUTH_VARIANCE
#define MYNEWT_VAL_AZIMUTH_VARIANCE (((float)2.91e-2))
#endif
/**
* @brief OS Latency Guardband (usec)
*/
#ifndef MYNEWT_VAL_OS_LATENCY
#define MYNEWT_VAL_OS_LATENCY (((uint32_t)800))
#endif
/**
* @brief Default Pan ID
*/
#ifndef MYNEWT_VAL_PANID
#define MYNEWT_VAL_PANID (((const uint16_t)0xdeca))
#endif
#ifdef __cplusplus
}
#endif
#endif /* SYSCFG_SYSCFG_UWB_H */

View File

@ -0,0 +1,67 @@
/*
* Copyright (C) 2020 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_uwb_core
* @{
*
* @file
* @brief uwb-core uwb_rng module configurations
* taken from decawave-uwb-core/lib/uwb_rng/syscfg.yml
*
* @author Francisco Molina <francois-xavier.molina@inria.fr>
* @}
*/
#ifndef SYSCFG_SYSCFG_UWB_RNG_H
#define SYSCFG_SYSCFG_UWB_RNG_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief uwb-core uwb_rng module is enabled
*/
#ifndef MYNEWT_VAL_UWB_RNG_ENABLED
#define MYNEWT_VAL_UWB_RNG_ENABLED ((IS_ACTIVE(MODULE_UWB_CORE_RNG)))
#endif
/**
* @brief TOA timeout delay for TWR (usec)
*/
#ifndef MYNEWT_VAL_RNG_RX_TIMEOUT
#define MYNEWT_VAL_RNG_RX_TIMEOUT (((uint16_t)0x20))
#endif
/**
* @brief worstcase tx holdoff delay for all TWR modes (usec)
*/
#ifndef MYNEWT_VAL_RNG_TX_HOLDOFF
#define MYNEWT_VAL_RNG_TX_HOLDOFF (((uint32_t)0x0320))
#endif
/**
* @brief Show debug output from postprocess
*/
#ifndef MYNEWT_VAL_RNG_VERBOSE
#define MYNEWT_VAL_RNG_VERBOSE (0)
#endif
/**
* @brief JSON buffer size
*/
#ifndef MYNEWT_VAL_UWB_RNG_JSON_BUFSIZE
#define MYNEWT_VAL_UWB_RNG_JSON_BUFSIZE (256)
#endif
#ifdef __cplusplus
}
#endif
#endif /* SYSCFG_SYSCFG_UWB_RNG_H */

View File

@ -0,0 +1,241 @@
/*
* Copyright (C) 2020 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_uwb_core
* @{
*
* @file
* @brief uwb-core uwbcfg module configurations
* taken from decawave-uwb-core/sys/uwbcfg/syscfg.yml
*
* @author Francisco Molina <francois-xavier.molina@inria.fr>
* @}
*/
#ifndef SYSCFG_SYSCFG_UWBCFG_H
#define SYSCFG_SYSCFG_UWBCFG_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Enable uwbcfg module
*/
#ifndef MYNEWT_VAL_UWBCFG_ENABLED
#define MYNEWT_VAL_UWBCFG_ENABLED (IS_ACTIVE(MODULE_UWB_CORE_UWBCFG))
#endif
/**
* @brief Apply configuration on uwbcfg module setup
*/
#ifndef MYNEWT_VAL_UWBCFG_APPLY_AT_INIT
#define MYNEWT_VAL_UWBCFG_APPLY_AT_INIT (1)
#endif
/**
* @brief Default channel
*/
#ifndef MYNEWT_VAL_UWBCFG_DEF_CH
#define MYNEWT_VAL_UWBCFG_DEF_CH ("5")
#endif
/**
* @brief Default UWB PRF (MHz)
*/
#ifndef MYNEWT_VAL_UWBCFG_DEF_PRF
#define MYNEWT_VAL_UWBCFG_DEF_PRF ("64")
#endif
/**
* @brief Default UWB Datarate (110k, 850k, 6m8)
*/
#ifndef MYNEWT_VAL_UWBCFG_DEF_DATARATE
#define MYNEWT_VAL_UWBCFG_DEF_DATARATE ("6m8")
#endif
/**
* @brief Default UWB PAC Length (8, 16, 32, 64)
*/
#ifndef MYNEWT_VAL_UWBCFG_DEF_PACLEN
#define MYNEWT_VAL_UWBCFG_DEF_PACLEN ("8")
#endif
/**
* @brief Default UWB External clock delay
*/
#ifndef MYNEWT_VAL_UWBCFG_DEF_EXT_CLKDLY
#define MYNEWT_VAL_UWBCFG_DEF_EXT_CLKDLY ("0")
#endif
/**
* @brief Default MAC FrameFilter (0x0000 = no filter)
*/
#ifndef MYNEWT_VAL_UWBCFG_DEF_FRAME_FILTER
#define MYNEWT_VAL_UWBCFG_DEF_FRAME_FILTER ("0x0000")
#endif
/**
* @brief Default UWB Role
*
* - Tag "0x00"
* - Node "0x01"
* - Pan master "0x02"
* - Anchor "0x04"
* - Panmaster "0x07"
*/
#ifndef MYNEWT_VAL_UWBCFG_DEF_ROLE
#define MYNEWT_VAL_UWBCFG_DEF_ROLE ("0x0")
#endif
/**
* @brief Default UWB RX Antenna delay
*/
#ifndef MYNEWT_VAL_UWBCFG_DEF_RX_ANTDLY
#define MYNEWT_VAL_UWBCFG_DEF_RX_ANTDLY ("0x4050")
#endif
/**
* @brief Default UWB RX Antenna separation distance in m
*/
#ifndef MYNEWT_VAL_UWBCFG_DEF_RX_ANTSEP
#define MYNEWT_VAL_UWBCFG_DEF_RX_ANTSEP ("0.0205")
#endif
/**
* @brief UWBCFG_DEF_RX_DIAG_EN
*/
#ifndef MYNEWT_VAL_UWBCFG_DEF_RX_DIAG_EN
#define MYNEWT_VAL_UWBCFG_DEF_RX_DIAG_EN ("0x1")
#endif
/**
* @brief Default UWB PDOA Mode (0, 1, 2, 3)
*/
#ifndef MYNEWT_VAL_UWBCFG_DEF_RX_PDOA_MODE
#define MYNEWT_VAL_UWBCFG_DEF_RX_PDOA_MODE ("0")
#endif
/**
* @brief Default UWB PHR Mode (s, e)
*/
#ifndef MYNEWT_VAL_UWBCFG_DEF_RX_PHR_MODE
#define MYNEWT_VAL_UWBCFG_DEF_RX_PHR_MODE ("e")
#endif
/**
* @brief Default UWB PHR Rate (0 = std, 1 = data)
*/
#ifndef MYNEWT_VAL_UWBCFG_DEF_RX_PHR_RATE
#define MYNEWT_VAL_UWBCFG_DEF_RX_PHR_RATE ("0")
#endif
/**
* @brief Default UWB RX Preamble Code Index
*/
#ifndef MYNEWT_VAL_UWBCFG_DEF_RX_PREAM_CIDX
#define MYNEWT_VAL_UWBCFG_DEF_RX_PREAM_CIDX ("9")
#endif
/**
* @brief Default UWB SFD Timeout (-1=auto, timeout in symbols)
*/
#ifndef MYNEWT_VAL_UWBCFG_DEF_RX_SFD_TO
#define MYNEWT_VAL_UWBCFG_DEF_RX_SFD_TO ("-1")
#endif
/**
* @brief Default UWB SFD Type (0, 1)
*/
#ifndef MYNEWT_VAL_UWBCFG_DEF_RX_SFD_TYPE
#define MYNEWT_VAL_UWBCFG_DEF_RX_SFD_TYPE ("1")
#endif
/**
* @brief Default UWB Sts Length (32-2040 in steps of 8)
*/
#ifndef MYNEWT_VAL_UWBCFG_DEF_RX_STS_LEN
#define MYNEWT_VAL_UWBCFG_DEF_RX_STS_LEN ("64")
#endif
/**
* @brief Default UWB Sts Mode (0, 1, 2, sdc, 4z)
*/
#ifndef MYNEWT_VAL_UWBCFG_DEF_RX_STS_MODE
#define MYNEWT_VAL_UWBCFG_DEF_RX_STS_MODE ("0")
#endif
/**
* @brief Default UWB Coarse TX Power (0,3,6,..,18)
*/
#ifndef MYNEWT_VAL_UWBCFG_DEF_TXRF_POWER_COARSE
#define MYNEWT_VAL_UWBCFG_DEF_TXRF_POWER_COARSE ("15")
#endif
/**
* @brief Default UWB FINE TX Power (0,1,2,..,31)
*/
#ifndef MYNEWT_VAL_UWBCFG_DEF_TXRF_POWER_FINE
#define MYNEWT_VAL_UWBCFG_DEF_TXRF_POWER_FINE ("22")
#endif
/**
* @brief Default UWB FINE TX Power (0,1,2,..,31)
*/
#ifndef MYNEWT_VAL_UWBCFG_DEF_TXRF_VCM_LO
#define MYNEWT_VAL_UWBCFG_DEF_TXRF_VCM_LO ("15")
#endif
/**
* @brief Default UWB TX Antenna delay
*/
#ifndef MYNEWT_VAL_UWBCFG_DEF_TX_ANTDLY
#define MYNEWT_VAL_UWBCFG_DEF_TX_ANTDLY ("0x4050")
#endif
/**
* @brief Default UWB RX Antenna separation distance in m
*/
#ifndef MYNEWT_VAL_UWBCFG_DEF_TX_PREAM_CIDX
#define MYNEWT_VAL_UWBCFG_DEF_TX_PREAM_CIDX ("9")
#endif
/**
* @brief Default UWB Preamble Length
*/
#ifndef MYNEWT_VAL_UWBCFG_DEF_TX_PREAM_LEN
#define MYNEWT_VAL_UWBCFG_DEF_TX_PREAM_LEN ("128")
#endif
/**
* @brief Default XTAL Trim value (0xff = no trim, or use OTP value)
*/
#ifndef MYNEWT_VAL_UWBCFG_DEF_XTAL_TRIM
#define MYNEWT_VAL_UWBCFG_DEF_XTAL_TRIM ("0xff")
#endif
/**
* @brief Offset relative leading edge to start extracting CIR from
*/
#ifndef MYNEWT_VAL_UWBCFG_DEF_CIR_OFFSET
#define MYNEWT_VAL_UWBCFG_DEF_CIR_OFFSET ("0")
#endif
/**
* @brief Number of bins to extract from CIR
*/
#ifndef MYNEWT_VAL_UWBCFG_DEF_CIR_SIZE
#define MYNEWT_VAL_UWBCFG_DEF_CIR_SIZE ("0")
#endif
#ifdef __cplusplus
}
#endif
#endif /* SYSCFG_SYSCFG_UWBCFG_H */

View File

@ -0,0 +1,38 @@
/*
* Copyright (C) 2020 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_uwb_core
* @{
*
* @file
* @brief sysinit abstraction layer for RIOT adaption
*
* @author Francisco Molina <francois-xavier.molina@inria.fr>
* @}
*/
#ifndef SYSINIT_SYSINIT_H
#define SYSINIT_SYSINIT_H
#include "assert.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief DPL assert macro
*/
#define SYSINIT_PANIC_ASSERT(rc) assert(rc);
#ifdef __cplusplus
}
#endif
#endif /* SYSINIT_SYSINIT_H */

View File

@ -0,0 +1,63 @@
/*
* Copyright (C) 2020 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_uwb_core
*
* @{
*
* @file
*
* @author Francisco Molina <francois-xavier.molina@inria.fr>
*/
#ifndef UWB_CORE_H
#define UWB_CORE_H
#include <stdint.h>
#include "event.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Priority used for
*/
#ifndef UWB_CORE__PRIO
#define UWB_CORE__PRIO (THREAD_PRIORITY_MAIN - 2)
#endif
/**
* @brief Stacksize used for
*/
#ifndef UWB_CORE__STACKSIZE
#define UWB_CORE__STACKSIZE (THREAD_STACKSIZE_DEFAULT)
#endif
/**
* @brief Setup and run uwb-core thread
*/
void uwb_core_riot_init(void);
/**
* @brief Retrieves the default event queue.
*
* As there is no default event queue in RIOT, uwb-core will start and
* handle a default event queue.
*
* @return the default event queue.
*/
event_queue_t *uwb_core_get_eventq(void);
#ifdef __cplusplus
}
#endif
#endif /* UWB_CORE_H */
/** @} */

26
pkg/uwb-dw1000/Makefile Normal file
View File

@ -0,0 +1,26 @@
PKG_NAME=uwb-dw1000
PKG_URL=https://github.com/Decawave/uwb-dw1000/
PKG_VERSION=6eaa85e6d429450d19a6ddeb2de05303016c0dd2
PKG_LICENSE=Apache-2.0
include $(RIOTBASE)/pkg/pkg.mk
CFLAGS += -Wno-address-of-packed-member
CFLAGS += -Wno-enum-conversion
CFLAGS += -Wno-maybe-uninitialized
CFLAGS += -Wno-missing-braces
CFLAGS += -Wno-missing-declarations
CFLAGS += -Wno-sign-compare
CFLAGS += -Wno-return-type
CFLAGS += -Wno-unused-but-set-variable
CFLAGS += -Wno-unused-function
CFLAGS += -Wno-unused-parameter
CFLAGS += -Wno-unused-variable
CFLAGS += -fms-extensions
ifneq (,$(filter llvm,$(TOOLCHAIN)))
CFLAGS += -Wno-microsoft-anon-tag
endif
all:
"$(MAKE)" -C $(PKG_SOURCE_DIR)/hw/drivers/uwb/uwb_dw1000/src -f $(RIOTPKG)/uwb-dw1000/uwb-dw1000.mk MODULE=uwb-dw1000

View File

@ -0,0 +1,13 @@
USEMODULE += uwb-dw1000_hal
DEFAULT_MODULE += auto_init_uwb-dw1000
USEMODULE += xtimer
FEATURES_REQUIRED += periph_gpio_irq
FEATURES_REQUIRED += periph_spi
# Some of the pkg operation would overflow on 16bit
FEATURES_REQUIRED += arch_32bit
# LLVM ARM shows issues with missing definitions for stdatomic
TOOLCHAINS_BLACKLIST += llvm

View File

@ -0,0 +1,5 @@
INCLUDES += -I$(PKGDIRBASE)/uwb-dw1000/hw/drivers/uwb/uwb_dw1000/include \
-I$(RIOTPKG)/uwb-dw1000/include \
#
DIRS += $(RIOTPKG)/uwb-dw1000/hal

0
pkg/uwb-dw1000/README.md Normal file
View File

41
pkg/uwb-dw1000/doc.txt Normal file
View File

@ -0,0 +1,41 @@
/**
* @defgroup pkg_uwb_dw1000 Driver implementation for the uwb-core driver for Decawave DW1000 transceiver
* @ingroup pkg
* @brief uwb-core driver for Decawave DW1000 transceiver
* @see https://github.com/Decawave/uwb-dw1000
*/
# Decawave uwb-dw1000 RIOT Port
The distribution https://github.com/decawave/uwb-core contains the
device driver implementation for the Decawave Impulse Radio-Ultra
Wideband (IR-UWB) transceiver(s). The driver includes hardware abstraction
layers (HAL), media access control (MAC) layer, Ranging Services (RNG).
## Abstraction details
uwb-dw1000 is meant as a hardware and architecture agnostic driver. It
was developed with MyNewt as its default OS, but its abstractions are
well defined which makes it easy to use with another OS.
A porting layer DPL (Decawave Porting Layer) has been implemented that
wraps around OS functionalities and modules: mutex, semaphores, threads,
etc.. In most cases the mapping is direct although some specific
functionalities might not be supported. This layer is found in the uwb-core
pkg.
A hardware abstraction layer is defined under `hal` which wraps around
modules such as: periph_gpio, periph_spi, etc.
Since the library was used on top of mynewt most configuration values
are prefixed with `MYNEWT_VAL_%`, all configurations can be found under
`pkg/uwb-dw1000/include/syscfg`.
## Todos
The uwb-dw1000 can be used to provide a netdev driver for the dw1000
module.
uwb-dw1000 repository uses fixed length arrays to keep track of the
devices that are present. This port uses linked list but some of the
upstream code is not compatible with this.

View File

@ -0,0 +1,3 @@
MODULE = uwb-dw1000_hal
include $(RIOTBASE)/Makefile.base

View File

@ -0,0 +1,170 @@
/*
* Copyright (C) 2020 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_uwb_dw1000
* @{
*
* @file
* @brief Glue code for running uwb-core for RIOT
*
* @author Francisco Molina <francois-xavier.molina@inria.fr>
* @}
*/
#include "dpl/dpl.h"
#include "dw1000/dw1000_phy.h"
#include "dw1000/dw1000_hal.h"
#include "uwb_dw1000.h"
#include "uwb_dw1000_config.h"
#include "uwb/uwb.h"
#include "uwb/uwb_mac.h"
#include "utlist.h"
#include "thread.h"
#ifndef LOG_LEVEL
#define LOG_LEVEL LOG_NONE
#endif
#include "log.h"
#ifndef DW1000_THREAD_PRIORITY
#define DW1000_THREAD_PRIORITY MYNEWT_VAL_UWB_DEV_TASK_PRIO
#endif
/* Link list head */
static struct _dw1000_dev_instance_t * dw1000_instance_head;
/* Default instance configuration */
static const dw1000_dev_instance_t dw1000_instance_config_default = {
.uwb_dev = {
.idx = 0,
.role = DW1000_ROLE_DEFAULT,
.task_prio = DW1000_THREAD_PRIORITY,
.status = {0},
.rx_ant_separation = DW1000_RX_ANTSEP_DEFAULT,
.attrib = {
.nsfd = DW1000_NSFD_DEFAULT,
.nsync = DW1000_NSYNC_DEFAULT,
.nphr = DW1000_NPHR_DEFAULT ,
},
.config = {
.channel = DW1000_CHANNEL_DEFAULT,
.prf = DW1000_PRF_DEFAULT,
.dataRate = DW1000_DATARATE_DEFAULT,
.rx = {
.pacLength = DW1000_PACLEN_DEFAULT,
.preambleCodeIndex = DW1000_RX_PREAM_CIDX_DEFAULT,
.sfdType = DW1000_RX_SFD_TYPE_DEFAULT,
.phrMode = DW1000_RX_PHR_MODE_DEFAULT,
.sfdTimeout = DW1000_RX_SFD_TO_DEFAULT,
.timeToRxStable = DW1000_RX_STABLE_TIME_US ,
.frameFilter = DW1000_FRAME_FILTER_DEFAULT,
.xtalTrim = DW1000_XTAL_TRIM_DEFAULT,
},
.tx ={
.preambleCodeIndex = DW1000_TX_PREAM_CIDX_DEAULT,
.preambleLength = DW1000_TX_PREAM_LEN_DEFAULT,
},
.txrf={
.PGdly = DW1000_CHANNEL_DEFAULT,
.BOOSTNORM = dw1000_power_value(DW1000_txrf_config_9db, 2.5),
.BOOSTP500 = dw1000_power_value(DW1000_txrf_config_9db, 2.5),
.BOOSTP250 = dw1000_power_value(DW1000_txrf_config_9db, 2.5),
.BOOSTP125 = dw1000_power_value(DW1000_txrf_config_9db, 2.5)
},
.trxoff_enable = DW1000_TRXOFF_ENABLE,
.rxdiag_enable = DW1000_RX_DIAGNOSTIC,
.dblbuffon_enabled = DW1000_DOUBLE_BUFFER_ENABLE,
.LDE_enable = DW1000_LDE_ENABLE,
.LDO_enable = DW1000_LDO_ENABLE,
.sleep_enable = DW1000_SLEEP_ENABLE,
.wakeup_rx_enable = DW1000_WAKEUP_RX_ENABLE,
.rxauto_enable = DW1000_RX_AUTO_ENABLE,
.cir_enable = 0, /**< Default behavior for CIR interface */
.cir_pdoa_slave = 0, /**< First instance should not act as pdoa slave */
.blocking_spi_transfers = 1, /**< Nonblocking spi transfers are not supported */
},
}
};
void _uwb_dw1000_set_idx(dw1000_dev_instance_t* dev)
{
int count = 0;
dw1000_dev_instance_t *elt = NULL;
LL_COUNT(dw1000_instance_head, elt, count);
dev->uwb_dev.idx = count++;
/* prepend to list */
LL_PREPEND(dw1000_instance_head, dev);
}
void uwb_dw1000_setup(dw1000_dev_instance_t* dev, dw1000_params_t* params)
{
/* set semaphore */
dpl_sem_init(params->spi_sem, 0x1);
/* set default uwb config */
memcpy(dev, &dw1000_instance_config_default,
sizeof(dw1000_dev_instance_t));
/* set uwb_dev idx */
_uwb_dw1000_set_idx(dev);
/* this will set the configuration and init uwb_dev which ATM only
allocates an RX and TX buffer if none is yet available */
dw1000_dev_init((struct os_dev *) dev, (void *) params);
}
void uwb_dw1000_config_and_start(dw1000_dev_instance_t* dev)
{
dw1000_dev_config(dev);
}
void uwb_dw1000_set_buffs(dw1000_dev_instance_t* dev, uint8_t* tx_buf,
uint8_t* rx_buf)
{
dev->uwb_dev.rxbuf = rx_buf;
dev->uwb_dev.txbuf = tx_buf;
}
void uwb_dw1000_init(void)
{
dw1000_instance_head = NULL;
}
struct uwb_dev* uwb_dev_idx_lookup(int idx)
{
dw1000_dev_instance_t *current = dw1000_instance_head;
while (current) {
if (current->uwb_dev.idx == idx) {
LOG_DEBUG("uwb_dev: found dev of idx %d\n", idx);
break;
}
current = current->next;
}
return (struct uwb_dev*) &current->uwb_dev;
}
/**
* API to choose DW1000 instances based on parameters.
*
* @param idx Indicates number of instances for the chosen bsp.
* @return dw1000_dev_instance_t
*/
struct _dw1000_dev_instance_t * hal_dw1000_inst(uint8_t idx)
{
dw1000_dev_instance_t *current = dw1000_instance_head;
for (uint8_t i = 0; i < idx; i++) {
current = current->next;
}
return current;
}

View File

@ -0,0 +1,92 @@
/*
* Copyright (C) 2020 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_uwb_dw1000
* @{
*
* @file
* @brief SPI abstraction layer implementation
*
* @author Francisco Molina <francois-xavier.molina@inria.fr>
* @}
*/
#include "hal/hal_spi.h"
#include "periph/spi.h"
static uint32_t spi_clk[SPI_NUMOF] = { SPI_CLK_1MHZ };
static uint32_t spi_mode[SPI_NUMOF] = { SPI_MODE_0 };
int hal_spi_set_txrx_cb(int spi_num, hal_spi_txrx_cb txrx_cb, void *arg)
{
(void) txrx_cb;
(void) spi_num;
(void) arg;
return 0;
}
int hal_spi_init(int spi_num, void *cfg, uint8_t spi_type)
{
(void) cfg;
(void) spi_type;
spi_init(spi_num);
return 0;
}
int hal_spi_config(int spi_num, struct hal_spi_settings *settings)
{
spi_clk[spi_num] = settings->baudrate;
spi_mode[spi_num] = settings->data_mode;
return 0;
}
int hal_spi_enable(int spi_num)
{
(void) spi_num;
return 0;
}
int hal_spi_disable(int spi_num)
{
(void) spi_num;
return 0;
}
int hal_spi_txrx(int spi_num, void *txbuf, void *rxbuf, int cnt)
{
spi_acquire(spi_num,
SPI_CS_UNDEF,
spi_mode[spi_num],
spi_clk[spi_num]);
spi_transfer_bytes(spi_num,
SPI_CS_UNDEF,
false,
txbuf,
rxbuf,
cnt);
spi_release(spi_num);
return 0;
}
int hal_spi_txrx_noblock(int spi_num, void *txbuf, void *rxbuf, int cnt)
{
(void) spi_num;
(void) txbuf;
(void) rxbuf;
(void) cnt;
return 0;
}
int hal_spi_deinit(int spi_num)
{
(void) spi_num;
return 0;
}

View File

@ -0,0 +1,197 @@
/*
* Copyright (C) 2020 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_uwb_dw1000
* @{
*
* @file
* @brief GPIO abstraction layer RIOT adaption
*
* @author Francisco Molina <francois-xavier.molina@inria.fr>
* @}
*/
#ifndef HAL_HAL_GPIO_H
#define HAL_HAL_GPIO_H
#include "periph/gpio.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Map hal_gpio_pull_t enum types to gpio_mode_t enum types
*/
enum {
/** Pull-up/down not enabled */
HAL_GPIO_PULL_NONE = GPIO_IN,
/** Pull-up enabled */
HAL_GPIO_PULL_UP = GPIO_IN_PU,
/** Pull-down enabled */
HAL_GPIO_PULL_DOWN = GPIO_IN_PD
};
/**
* @brief hal_gpio_pull type
*/
typedef gpio_mode_t hal_gpio_pull_t;
/**
* @brief Map hal_gpio_irq_trig_t enum types to gpio_flank_t enum types
*/
enum {
#ifdef GPIO_NONE
HAL_GPIO_TRIG_NONE = GPIO_NONE,
#endif
/** IRQ occurs on rising edge */
HAL_GPIO_TRIG_RISING = GPIO_RISING,
/** IRQ occurs on falling edge */
HAL_GPIO_TRIG_FALLING = GPIO_FALLING,
/** IRQ occurs on either edge */
HAL_GPIO_TRIG_BOTH = GPIO_BOTH,
/** IRQ occurs when line is low */
#ifdef GPIO_LOW
HAL_GPIO_TRIG_LOW = GPIO_LOW,
#endif
/** IRQ occurs when line is high */
#ifdef GPIO_HIGH
HAL_GPIO_TRIG_HIGH = GPIO_HIGH
#endif
};
/**
* @brief hal_gpio_irq_trig type
*/
typedef gpio_flank_t hal_gpio_irq_trig_t;
/**
* @brief Function proto for GPIO irq handler functions
*/
typedef gpio_cb_t hal_gpio_irq_handler_t;
/**
* Initializes the specified pin as an input
*
* @param pin Pin number to set as input
* @param pull pull type
*
* @return int 0: no error; -1 otherwise.
*/
static inline int hal_gpio_init_in(gpio_t pin, hal_gpio_pull_t pull)
{
return gpio_init(pin, pull);
}
/**
* Initialize the specified pin as an output, setting the pin to the specified
* value.
*
* @param pin Pin number to set as output
* @param val Value to set pin
*
* @return int 0: no error; -1 otherwise.
*/
static inline int hal_gpio_init_out(gpio_t pin, int val)
{
int res = gpio_init(pin, GPIO_OUT);
gpio_write(pin, val);
return res;
}
/**
* Write a value (either high or low) to the specified pin.
*
* @param pin Pin to set
* @param val Value to set pin (0:low 1:high)
*/
static inline void hal_gpio_write(gpio_t pin, int val)
{
gpio_write(pin, val);
}
/**
* Reads the specified pin.
*
* @param pin Pin number to read
*
* @return int 0: low, 1: high
*/
static inline int hal_gpio_read(gpio_t pin)
{
return gpio_read(pin);
}
/**
* Toggles the specified pin
*
* @param pin Pin number to toggle
*
* @return current gpio state int 0: low, 1: high
*/
static inline int hal_gpio_toggle(gpio_t pin)
{
gpio_toggle(pin);
return gpio_read(pin);
}
/**
* Initialize a given pin to trigger a GPIO IRQ callback.
*
* @param pin The pin to trigger GPIO interrupt on
* @param handler The handler function to call
* @param arg The argument to provide to the IRQ handler
* @param trig The trigger mode (e.g. rising, falling)
* @param pull The mode of the pin (e.g. pullup, pulldown)
*
* @return 0 on success, non-zero error code on failure.
*/
static inline int hal_gpio_irq_init(gpio_t pin,
hal_gpio_irq_handler_t handler,
void *arg,
hal_gpio_irq_trig_t trig,
hal_gpio_pull_t pull)
{
return gpio_init_int(pin, pull, trig, handler, arg);
}
/**
* Release a pin from being configured to trigger IRQ on state change.
*
* @param pin The pin to release
*/
static inline void hal_gpio_irq_release(gpio_t pin)
{
/* can't release the interrupt so ar least disable it */
gpio_irq_disable(pin);
}
/**
* Enable IRQs on the passed pin
*
* @param pin The pin to enable IRQs on
*/
static inline void hal_gpio_irq_enable(gpio_t pin)
{
gpio_irq_enable(pin);
}
/**
* Disable IRQs on the passed pin
*
* @param pin The pin to disable IRQs on
*/
static inline void hal_gpio_irq_disable(gpio_t pin)
{
gpio_irq_disable(pin);
}
#ifdef __cplusplus
}
#endif
#endif /* HAL_HAL_GPIO_H */

View File

@ -0,0 +1,169 @@
/*
* Copyright (C) 2020 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_uwb_dw1000
* @{
*
* @file
* @brief SPI abstraction layer RIOT adaption
*
* @author Francisco Molina <francois-xavier.molina@inria.fr>
* @}
*/
#ifndef HAL_HAL_SPI_H
#define HAL_HAL_SPI_H
#include "periph/spi.h"
#ifdef __cplusplus
extern "C" {
#endif
/** SPI mode 0 */
#define HAL_SPI_MODE0 (SPI_MODE_0)
/** SPI mode 1 */
#define HAL_SPI_MODE1 (SPI_MODE_1)
/** SPI mode 2 */
#define HAL_SPI_MODE2 (SPI_MODE_2)
/** SPI mode 3 */
#define HAL_SPI_MODE3 (SPI_MODE_3)
/**
* @brief Prototype for tx/rx callback
*/
typedef void (*hal_spi_txrx_cb)(void *arg, int len);
/**
* @brief since one spi device can control multiple devices, some configuration
* can be changed on the fly from the hal
*/
struct hal_spi_settings {
/** Data mode of SPI driver, defined by HAL_SPI_MODEn */
spi_mode_t data_mode;
/** Baudrate in kHz */
spi_clk_t baudrate;
};
/**
* @brief Configure the spi. Must be called after the spi is initialized (after
* hal_spi_init is called) and when the spi is disabled (user must call
* hal_spi_disable if the spi has been enabled through hal_spi_enable prior
* to calling this function). Can also be used to reconfigure an initialized
* SPI (assuming it is disabled as described previously).
*
* @param spi_num The number of the SPI to configure.
* @param psettings The settings to configure this SPI with
*
* @return int 0 on success, non-zero error code on failure.
*/
int hal_spi_config(int spi_num, struct hal_spi_settings *psettings);
/**
* @brief Sets the txrx callback (executed at interrupt context) when the
* buffer is transferred by the master or the slave using the non-blocking API.
* Cannot be called when the spi is enabled. This callback will also be called
* when chip select is de-asserted on the slave.
*
* NOTE: This callback is only used for the non-blocking interface and must
* be called prior to using the non-blocking API.
*
* @param spi_num SPI interface on which to set callback
* @param txrx_cb Callback function
* @param arg Argument to be passed to callback function
*
* @return int 0 on success, non-zero error code on failure.
*/
int hal_spi_set_txrx_cb(int spi_num, hal_spi_txrx_cb txrx_cb, void *arg);
/**
* @brief Enables the SPI. This does not start a transmit or receive operation;
* it is used for power mgmt. Cannot be called when a SPI transfer is in
* progress.
*
* @param spi_num
*
* @return int 0 on success, non-zero error code on failure.
*/
int hal_spi_enable(int spi_num);
/**
* @brief Disables the SPI. Used for power mgmt. It will halt any current SPI transfers
* in progress.
*
* @param spi_num
*
* @return int 0 on success, non-zero error code on failure.
*/
int hal_spi_disable(int spi_num);
/**
* @brief Blocking interface to send a buffer and store the received values from the
* slave. The transmit and receive buffers are either arrays of 8-bit (uint8_t)
* values or 16-bit values depending on whether the spi is configured for 8 bit
* data or more than 8 bits per value. The 'cnt' parameter is the number of
* 8-bit or 16-bit values. Thus, if 'cnt' is 10, txbuf/rxbuf would point to an
* array of size 10 (in bytes) if the SPI is using 8-bit data; otherwise
* txbuf/rxbuf would point to an array of size 20 bytes (ten, uint16_t values).
*
* NOTE: these buffers are in the native endian-ness of the platform.
*
* MASTER: master sends all the values in the buffer and stores the
* stores the values in the receive buffer if rxbuf is not NULL.
* The txbuf parameter cannot be NULL.
* SLAVE: cannot be called for a slave; returns -1
*
* @param spi_num SPI interface to use
* @param txbuf Pointer to buffer where values to transmit are stored.
* @param rxbuf Pointer to buffer to store values received from peer.
* @param cnt Number of 8-bit or 16-bit values to be transferred.
*
* @return int 0 on success, non-zero error code on failure.
*/
int hal_spi_txrx(int spi_num, void *txbuf, void *rxbuf, int cnt);
/**
* @brief Non-blocking interface to send a buffer and store received values. Can be
* used for both master and slave SPI types. The user must configure the
* callback (using hal_spi_set_txrx_cb); the txrx callback is executed at
* interrupt context when the buffer is sent.
*
* The transmit and receive buffers are either arrays of 8-bit (uint8_t)
* values or 16-bit values depending on whether the spi is configured for 8 bit
* data or more than 8 bits per value. The 'cnt' parameter is the number of
* 8-bit or 16-bit values. Thus, if 'cnt' is 10, txbuf/rxbuf would point to an
* array of size 10 (in bytes) if the SPI is using 8-bit data; otherwise
* txbuf/rxbuf would point to an array of size 20 bytes (ten, uint16_t values).
*
* NOTE: these buffers are in the native endian-ness of the platform.
*
* MASTER: master sends all the values in the buffer and stores the
* stores the values in the receive buffer if rxbuf is not NULL.
* The txbuf parameter cannot be NULL
* SLAVE: Slave "preloads" the data to be sent to the master (values
* stored in txbuf) and places received data from master in rxbuf
* (if not NULL). The txrx callback occurs when len values are
* transferred or master de-asserts chip select. If txbuf is NULL,
* the slave transfers its default byte. Both rxbuf and txbuf cannot
* be NULL.
*
* @param spi_num SPI interface to use
* @param txbuf Pointer to buffer where values to transmit are stored.
* @param rxbuf Pointer to buffer to store values received from peer.
* @param cnt Number of 8-bit or 16-bit values to be transferred.
*
* @return int 0 on success, non-zero error code on failure.
*/
int hal_spi_txrx_noblock(int spi_num, void *txbuf, void *rxbuf, int cnt);
#ifdef __cplusplus
}
#endif
#endif /* HAL_HAL_SPI_H */

View File

@ -0,0 +1,45 @@
/*
* Copyright (C) 2020 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_uwb_dw1000
* @{
*
* @file
* @brief Timer abstraction layer RIOT adaption
*
* @author Francisco Molina <francois-xavier.molina@inria.fr>
* @}
*/
#ifndef HAL_HAL_TIMER_H
#define HAL_HAL_TIMER_H
#include "xtimer.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief HAL timer callback
*/
typedef xtimer_callback_t hal_timer_cb;
/**
* @brief The HAL timer structure.
*/
struct hal_timer {
xtimer_t timer; /**< the timer */
};
#ifdef __cplusplus
}
#endif
#endif /* HAL_HAL_TIMER_H */

View File

@ -0,0 +1,120 @@
/*
* Copyright (C) 2020 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_uwb_core
* @{
*
* @file
* @brief uwb-dw1000 module configurations
* taken from decawave-uwb-dw1000/hw/drivers/uwb/uwb_dw1000
*
* @author Francisco Molina <francois-xavier.molina@inria.fr>
* @}
*/
#ifndef SYSCFG_UWB_DW1000_H
#define SYSCFG_UWB_DW1000_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Used to check that the UWB_DEV has been setup correctly
* at compile time.
* @note (UWB_DEV_RXDIAG_MAXLEN > 19)
*/
#ifndef MYNEWT_VAL_UWB_DW1000_API_CHECKS
#define MYNEWT_VAL_UWB_DW1000_API_CHECKS (1)
#endif
/**
* @brief Size of spi read/write buffer, sets the
* maximum allowed nonblocking read operation
*/
#ifndef MYNEWT_VAL_DW1000_HAL_SPI_BUFFER_SIZE
#define MYNEWT_VAL_DW1000_HAL_SPI_BUFFER_SIZE (256)
#endif
/**
* @brief The maximum number of bytes in a single transfer that the
* SPI hardware supports.
*
* @note RIOT spi implementation will take care of splitting if this max
* value is exceeded. If asynchronous (non-blocking) spi is ever
* added to RIOT this value will need to be adapted to the platform
* specific value.
*/
#ifndef MYNEWT_VAL_DW1000_HAL_SPI_MAX_CNT
#define MYNEWT_VAL_DW1000_HAL_SPI_MAX_CNT (1024)
#endif
/**
* @brief Max size spi read in bytes that is always done with blocking io.
* Reads longer than this value will be done with non-blocking io.
* @note Ignore in RIOT since non-blocking SPI is not yet enabled
*/
#ifndef MYNEWT_VAL_DW1000_DEVICE_SPI_RD_MAX_NOBLOCK
#define MYNEWT_VAL_DW1000_DEVICE_SPI_RD_MAX_NOBLOCK (9)
#endif
/**
* @brief Enable range bias correction polynomial
*/
#ifndef MYNEWT_VAL_DW1000_BIAS_CORRECTION_ENABLED
#define MYNEWT_VAL_DW1000_BIAS_CORRECTION_ENABLED (0)
#endif
/**
* @brief Tx Power dBm
*/
#ifndef MYNEWT_VAL_DW1000_DEVICE_TX_PWR
#define MYNEWT_VAL_DW1000_DEVICE_TX_PWR (((float)-14.3f))
#endif
/**
* @brief Antenna Gain dB
*/
#ifndef MYNEWT_VAL_DW1000_DEVICE_ANT_GAIN
#define MYNEWT_VAL_DW1000_DEVICE_ANT_GAIN (((float)1.0f))
#endif
/**
* @brief Enable showing rx and tx activity on leds
*/
#ifndef MYNEWT_VAL_DW1000_RXTX_LEDS
#define MYNEWT_VAL_DW1000_RXTX_LEDS (1)
#endif
/**
* @brief Enable showing rx and tx activity on gpios
*/
#ifndef MYNEWT_VAL_DW1000_RXTX_GPIO
#define MYNEWT_VAL_DW1000_RXTX_GPIO (0)
#endif
/**
* @brief Toggle LED_1 for every range packet received
*/
#ifndef MYNEWT_VAL_DW1000_RNG_INDICATE_LED
#define MYNEWT_VAL_DW1000_RNG_INDICATE_LED (0)
#endif
/**
* @brief Expose event counter cli api
*/
#ifndef MYNEWT_VAL_DW1000_CLI_EVENT_COUNTERS
#define MYNEWT_VAL_DW1000_CLI_EVENT_COUNTERS (0)
#endif
#ifdef __cplusplus
}
#endif
#endif /* SYSCFG_UWB_DW1000_H */

View File

@ -0,0 +1,87 @@
/*
* Copyright (C) 2020 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_uwb_dw1000
*
* @{
*
* @file
* @brief Abstraction layer for RIOT adaption
*
* @author Francisco Molina <francois-xavier.molina@inria.fr>
* @}
*/
#ifndef UWB_DW1000_H
#define UWB_DW1000_H
#include <stdint.h>
#include "dw1000/dw1000_dev.h"
#include "dw1000/dw1000_hal.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Device initialization parameters
*/
typedef struct dw1000_dev_cfg dw1000_params_t;
/**
* @brief Device descriptor for the driver
*/
typedef struct {
dw1000_dev_instance_t dev; /**< dwDevice parent struct */
} uwb_dw1000_t;
/**
* @brief Sets device linked list to 0, not really needed...
*/
void uwb_dw1000_init(void);
/**
* @brief Sets the tx and rx buffer for the uwb_dev in the dw1000 instance
*
* @note If this is not set before uwb_dw1000_setup() is called then
* the buffers will be dynamically allocated.
*
* @param[in] dev dw1000 device instance pointer
* @param[in] tx_buf transmit buffer
* @param[in] rx_buf receive buffer
*/
void uwb_dw1000_set_buffs(dw1000_dev_instance_t* dev, uint8_t* tx_buf,
uint8_t* rx_buf);
/**
* @brief Setup a dw1000 device
*
* This will setup the dw1000 dev instance and the uwb_dev instance within.
*
* @param[out] dev dw1000 device descriptor
* @param[in] params receive buffer
*/
void uwb_dw1000_setup(dw1000_dev_instance_t* dev, dw1000_params_t* params);
/**
* @brief Configure and start the dw1000
*
* This will wakeup and setup the dw1000 device, configure the mac and
* phy. Setting up the mac will also call dw1000_tasks_init() that will
* handle the device interrupts.
*
* @param[out] dev dw1000 device descriptor
*/
void uwb_dw1000_config_and_start(dw1000_dev_instance_t* dev);
#ifdef __cplusplus
}
#endif
#endif /* UWB_DW1000_H */

View File

@ -0,0 +1,263 @@
/*
* Copyright (C) 2020 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_uwb_core
* @{
*
* @file
* @brief uwb-dw1000 radio configurations
*
* @author Francisco Molina <francois-xavier.molina@inria.fr>
* @}
*/
#ifndef UWB_DW1000_CONFIG_H
#define UWB_DW1000_CONFIG_H
#include "dw1000/dw1000_regs.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Default UWB Role
*
* - Tag "0x00"
* - Node "0x01"
* - Pan master "0x02"
* - Anchor "0x04"
* - Panmaster "0x07"
*/
#ifndef DW1000_ROLE_DEFAULT
#define DW1000_ROLE_DEFAULT 0x0
#endif
/**
* @brief Default Number of symbols in start of frame delimiter
*/
#ifndef DW1000_NSFD_DEFAULT
#define DW1000_NSFD_DEFAULT 8
#endif
/**
* @brief Default Number of symbols in preamble sequence
*/
#ifndef DW1000_NSYNC_DEFAULT
#define DW1000_NSYNC_DEFAULT 128
#endif
/**
* @brief Default Number of symbols in phy header
*/
#ifndef DW1000_NPHR_DEFAULT
#define DW1000_NPHR_DEFAULT 21
#endif
/**
* @brief Default channel
*/
#ifndef DW1000_CHANNEL_DEFAULT
#define DW1000_CHANNEL_DEFAULT 5
#if DW1000_CHANNEL_DEFAULT > 7 || DW1000_CHANNEL_DEFAULT < 1
#error "DW1000_CHANNEL_DEFAULT must be 1..7"
#endif
#endif
/**
* @brief Default Pulse generator delay
*/
#ifndef DW1000_TX_PGDELAY_DEFAULT
#if DW1000_CHANNEL_DEFAULT == 1
#define DW1000_TX_PGDELAY_DEFAULT TC_PGDELAY_CH1
#elif DW1000_CHANNEL_DEFAULT == 2
#define DW1000_TX_PGDELAY_DEFAULT TC_PGDELAY_CH2
#elif DW1000_CHANNEL_DEFAULT == 3
#define DW1000_TX_PGDELAY_DEFAULT TC_PGDELAY_CH3
#elif DW1000_CHANNEL_DEFAULT == 4
#define DW1000_TX_PGDELAY_DEFAULT TC_PGDELAY_CH4
#elif DW1000_CHANNEL_DEFAULT == 5
#define DW1000_TX_PGDELAY_DEFAULT TC_PGDELAY_CH5
#elif DW1000_CHANNEL_DEFAULT == 6
#define DW1000_TX_PGDELAY_DEFAULT TC_PGDELAY_CH7
#elif DW1000_CHANNEL_DEFAULT == 7
#define DW1000_TX_PGDELAY_DEFAULT TC_PGDELAY_CH7
#endif
#endif
/**
* @brief Default UWB Pulse Repetition Frequency (MHz)
*
* - DWT_PRF_16M
* - DWT_PRF_64M
*/
#ifndef DW1000_PRF_DEFAULT
#define DW1000_PRF_DEFAULT DWT_PRF_64M
#endif
/**
* @brief Default UWB Datarate (110k, 850k, 6m8)
*
* - DWT_BR_110K
* - DWT_BR_850K
* - DWT_BR_6M8
*/
#ifndef DW1000_DATARATE_DEFAULT
#define DW1000_DATARATE_DEFAULT DWT_BR_6M8
#endif
/**
* @brief Default UWB Acquisition Chunk Size (Relates to RX preamble length)
*
* - 8
* - 16
* - 32
* - 64
*/
#ifndef DW1000_PACLEN_DEFAULT
#define DW1000_PACLEN_DEFAULT DWT_PAC8
#endif
/**
* @brief Default UWB RX Preamble Code Index
*/
#ifndef DW1000_RX_PREAM_CIDX_DEFAULT
#define DW1000_RX_PREAM_CIDX_DEFAULT 9
#endif
/**
* @brief Default UWB SFD Type
*
* - true: use non standard SFD for better performance
* - false: use standard SFD
*/
#ifndef DW1000_RX_SFD_TYPE_DEFAULT
#define DW1000_RX_SFD_TYPE_DEFAULT true
#endif
/**
* @brief Default UWB SFD Timeout (-1=auto, timeout in symbols)
*
*/
#ifndef DW1000_RX_SFD_TO_DEFAULT
#define DW1000_RX_SFD_TO_DEFAULT (128 + 1 + 8 - 8) /* (preamble length + 1 + SFD length - PAC size) */
#endif
/**
* @brief Default UWB PHR Mode
*
* - 0x0 - standard DWT_PHRMODE_STD
* - 0x3 - extended frames DWT_PHRMODE_EXT
*/
#ifndef DW1000_RX_PHR_MODE_DEFAULT
#define DW1000_RX_PHR_MODE_DEFAULT DWT_PHRMODE_EXT
#endif
/**
* @brief Enable RX Frame Quality diagnositics (rssi, fppl, etc.)
*/
#ifndef DW1000_RX_DIAGNOSTIC
#define DW1000_RX_DIAGNOSTIC 0
#endif
/**
* @brief Default UWB RX Antenna separation distance in m
*/
#ifndef DW1000_TX_PREAM_CIDX_DEAULT
#define DW1000_TX_PREAM_CIDX_DEAULT 9
#endif
/**
* @brief Default UWB Preamble Length
*
* - DWT_PLEN_4096 : Standard preamble length 4096 symbols
* - DWT_PLEN_2048 : Non-standard preamble length 2048 symbols
* - DWT_PLEN_1536 : Non-standard preamble length 1536 symbols
* - DWT_PLEN_1024 : Standard preamble length 1024 symbols
* - DWT_PLEN_512 : Non-standard preamble length 512 symbols
* - DWT_PLEN_256 : Non-standard preamble length 256 symbols
* - DWT_PLEN_128 : Non-standard preamble length 128 symbols
* - DWT_PLEN_64 : Standard preamble length 64 symbols
* - DWT_PLEN_32 : When setting length 32 symbols this is 0x0, which is programmed to byte 2 of the TX_FCTRL register
* - DWT_PLEN_72 : Non-standard length 72
*/
#ifndef DW1000_TX_PREAM_LEN_DEFAULT
#define DW1000_TX_PREAM_LEN_DEFAULT DWT_PLEN_128
#endif
/**
* @brief Default UWB RX Antenna separation distance in m
*/
#ifndef DW1000_RX_ANTSEP_DEFAULT
#define DW1000_RX_ANTSEP_DEFAULT 0.0205
#endif
/**
* @brief Default MAC FrameFilter (0x0000 = no filter)
*/
#ifndef DW1000_FRAME_FILTER_DEFAULT
#define DW1000_FRAME_FILTER_DEFAULT 0x0000
#endif
/**
* @brief Default MAC FrameFilter Crystal Trim value, 0xff == not set
*/
#ifndef DW1000_XTAL_TRIM_DEFAULT
#define DW1000_XTAL_TRIM_DEFAULT 0x10
#endif
/**
* @brief Time until the Receiver is stable, (in us)
*/
#ifndef DW1000_RX_STABLE_TIME_US
#define DW1000_RX_STABLE_TIME_US 6
#endif
/**
* @brief Enables forced TRXOFF in start_tx and start_tx interface
*/
#define DW1000_TRXOFF_ENABLE 1
/**
* @brief Enables double buffer
*/
#define DW1000_DOUBLE_BUFFER_ENABLE false
/**
* @brief Load LDE microcode on wake up
*/
#define DW1000_LDE_ENABLE true
/**
* @brief Load the LDO tune value on wake up
*/
#define DW1000_LDO_ENABLE false
/**
* @brief Enable sleep
*/
#define DW1000_SLEEP_ENABLE true
/**
* @brief Wakeup to Rx state
*/
#define DW1000_WAKEUP_RX_ENABLE true
/**
* @brief On error re-enable
*/
#define DW1000_RX_AUTO_ENABLE true
#ifdef __cplusplus
}
#endif
#endif /* UWB_DW1000_CONFIG_H */

View File

@ -0,0 +1,96 @@
/*
* Copyright (C) 2020 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_uwb_dw1000
*
* @{
* @file
* @brief Default configuration
*
* @author Francisco Molina <francois-xavier.molina@inria.fr>
*/
#ifndef UWB_DW1000_PARAMS_H
#define UWB_DW1000_PARAMS_H
#include "board.h"
#include "uwb_dw1000.h"
#include "dpl/dpl_sem.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @name Set default configuration parameters
* @{
*/
#ifndef DW1000_SPI_SEM
static struct dpl_sem sem_spi;
#define DW1000_SPI_SEM &sem_spi
#endif
#ifndef DW1000_PARAM_SPI
#define DW1000_PARAM_SPI (SPI_DEV(1))
#endif
#ifndef DW1000_PARAM_SPI_CLK_LOW
#define DW1000_PARAM_SPI_CLK_LOW (SPI_CLK_1MHZ)
#endif
#ifndef DW1000_PARAM_SPI_CLK_HIGH
#define DW1000_PARAM_SPI_CLK_HIGH (SPI_CLK_10MHZ)
#endif
#ifndef DW1000_SPI_MODE
#define DW1000_SPI_MODE (SPI_MODE_0)
#endif
#ifndef DW1000_PARAM_CS_PIN
#define DW1000_PARAM_CS_PIN (GPIO_PIN(0, 17))
#endif
#ifndef DW1000_PARAM_IRQ_PIN
#define DW1000_PARAM_IRQ_PIN (GPIO_PIN(0, 19))
#endif
#ifndef DW1000_PARAM_RESET_PIN
#define DW1000_PARAM_RESET_PIN (GPIO_PIN(0, 24))
#endif
#ifndef DW1000_RX_ANTENNA_DELAY
#define DW1000_RX_ANTENNA_DELAY (0x4042)
#endif
#ifndef DW1000_TX_ANTENNA_DELAY
#define DW1000_TX_ANTENNA_DELAY (0x4042)
#endif
#ifndef DW1000_EXT_CLOCK_DELAY
#define DW1000_EXT_CLOCK_DELAY (0)
#endif
#ifndef DW1000_PARAMS
#define DW1000_PARAMS { .spi_sem = DW1000_SPI_SEM, \
.spi_baudrate = DW1000_PARAM_SPI_CLK_HIGH, \
.spi_baudrate_low = DW1000_PARAM_SPI_CLK_LOW, \
.spi_num = DW1000_PARAM_SPI, \
.rst_pin = DW1000_PARAM_RESET_PIN, \
.irq_pin = DW1000_PARAM_IRQ_PIN, \
.ss_pin = DW1000_PARAM_CS_PIN, \
.rx_antenna_delay = DW1000_RX_ANTENNA_DELAY, \
.tx_antenna_delay = DW1000_TX_ANTENNA_DELAY, \
.ext_clock_delay = DW1000_EXT_CLOCK_DELAY }
#endif
/**@}*/
/**
* @brief Configuration struct
*/
static const dw1000_params_t dw1000_params[] =
{
DW1000_PARAMS
};
#ifdef __cplusplus
}
#endif
#endif /* UWB_DW1000_PARAMS_H */
/** @} */

View File

@ -0,0 +1,13 @@
# exclude submodule sources from *.c wildcard source selection
IGNORE_SRC = \
dw1000_pkg.c \
dw1000_cli.c \
dw1000_cli_priv.c \
dw1000_sysfs.c \
dw1000_debugfs.c \
#
SRC := $(filter-out $(IGNORE_SRC),$(wildcard *.c))
include $(RIOTBASE)/Makefile.base

View File

@ -113,6 +113,11 @@ void auto_init(void)
extern void openwsn_bootstrap(void);
openwsn_bootstrap();
}
if (IS_USED(MODULE_AUTO_INIT_UWB_CORE)) {
LOG_DEBUG("Bootstrapping uwb core.\n");
extern void uwb_core_init(void);
uwb_core_init();
}
if (IS_USED(MODULE_GCOAP) &&
!IS_ACTIVE(CONFIG_GCOAP_NO_AUTO_INIT)) {
LOG_DEBUG("Auto init gcoap.\n");