1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/examples/twr_aloha/twr_shell.c
Marian Buschsieweke 5ea582b3dd
sys/shell_commands: convert to SHELL_COMMAND()
Make use of XFA for shell commands
2022-06-07 09:25:04 +02:00

221 lines
7.2 KiB
C

/*
* Copyright (C) 2021 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 "net/ieee802154.h"
#include "net/l2util.h"
#include "shell.h"
#include "ztimer.h"
#include "control.h"
#define IEEE802154_LONG_ADDRESS_LEN_STR_MAX \
(sizeof("00:00:00:00:00:00:00:00"))
#define IEEE802154_SHORT_ADDRESS_LEN_STR_MAX \
(sizeof("00:00"))
/* See 7.2.31.1 Units of TX Power Control */
#define DW1000_TX_POWER_COARSE_SHIFT (5)
#define DW1000_TX_POWER_COARSE_MASK (0xE0)
#define DW1000_TX_POWER_FINE_MASK (0x1F)
#define DW1000_TX_POWER_MULTI (10)
#define DW1000_TX_POWER_COARSE_STEP (30) /* 3dbM * 10 */
#define DW1000_TX_POWER_FINE_STEP (5) /* 0.5dbM * 10 */
int _twr_ifconfig(int argc, char **argv)
{
(void)argc;
(void)argv;
char addr_str[IEEE802154_LONG_ADDRESS_LEN_STR_MAX];
struct uwb_dev *udev = uwb_dev_idx_lookup(0);
uint8_t buffer[IEEE802154_LONG_ADDRESS_LEN];
printf("Iface %d", udev->task_str.t.pid);
byteorder_htobebufs(buffer, udev->uid);
printf("\tHWaddr: %s ",
l2util_addr_to_str(buffer, IEEE802154_SHORT_ADDRESS_LEN, addr_str));
byteorder_htobebufs(buffer, udev->pan_id);
printf("Channel: %d ", udev->config.channel);
printf("NID: %s\n\n",
l2util_addr_to_str(buffer, IEEE802154_SHORT_ADDRESS_LEN, addr_str));
byteorder_htobebufll(buffer, udev->euid);
printf("\t\tLong HWaddr: %s\n",
l2util_addr_to_str(buffer, IEEE802154_LONG_ADDRESS_LEN, addr_str));
/* 000 -> 18dBM gain, 110 -> 0dBm gain */
int tx_power =
DW1000_TX_POWER_COARSE_STEP *
(6 -
((udev->config.txrf.BOOSTNORM & DW1000_TX_POWER_COARSE_MASK) >>
DW1000_TX_POWER_COARSE_SHIFT)) +
(udev->config.txrf.BOOSTNORM & DW1000_TX_POWER_FINE_MASK) *
DW1000_TX_POWER_FINE_STEP;
printf("\t\tTX-Power: %d.%ddBm ", tx_power / DW1000_TX_POWER_MULTI,
tx_power > (tx_power / DW1000_TX_POWER_MULTI) * DW1000_TX_POWER_MULTI ? 5 : 0);
printf("TC-PGdelay: 0x%02x\n", udev->config.txrf.PGdly);
return 0;
}
static void _print_usage(void)
{
puts("Usage:");
puts("\ttwr req <short_addr> [-p <proto>] [-c <count>] [-h]"
"[-i <ms interval>] ");
puts("\t - short_addr: short address of request destination");
puts("\t - count: number of requests (default: 1)");
puts("\t - ms interval: wait interval milliseconds between requests"
"(default: 1000)");
puts("\t - proto: twr protocol (ss|ss-ext|ss-ack|ds|ds-ext, default: ss)");
puts("\ttwr lst on: start listening for ranging requests");
puts("\ttwr lst off: stop listening for ranging requests");
}
int _twr_handler(int argc, char **argv)
{
if (argc < 2) {
_print_usage();
return -1;
}
if (!strcmp(argv[1], "lst")) {
if (argc == 3) {
if (!strcmp(argv[2], "on")) {
puts("[twr]: start listening");
uwb_core_rng_listen_enable();
return 0;
}
else if (!strcmp(argv[2], "off")) {
puts("[twr]: stop listening");
uwb_core_rng_listen_disable();
return 0;
}
}
_print_usage();
return -1;
}
if (!strcmp(argv[1], "req")) {
uint32_t count = 1;
uint32_t interval_ms = 1000;
int proto = UWB_DATA_CODE_SS_TWR;
uint8_t addr[IEEE802154_SHORT_ADDRESS_LEN];
uint16_t short_addr = 0x0000;
int res = 0;
if (argc < 3) {
_print_usage();
return -1;
}
/* parse command line arguments */
for (int i = 2; i < argc; i++) {
char *arg = argv[i];
if (arg[0] != '-') {
size_t addr_len = l2util_addr_from_str(arg, addr);
if (addr_len != 2) {
puts("[Error]: unable to parse address.\n"
"Must be of format [0-9a-fA-F]{2}(:[0-9a-fA-F]{2})*\n"
"(hex pairs delimited by colons)");
res = 1;
}
short_addr = addr[1] + (addr[0] << 8);
if (short_addr == 0x0000) {
printf("[ERROR]: invalid addr %s\n", arg);
res = 1;
}
}
else {
switch (arg[1]) {
case 'c':
if (((i++) + 1) < argc) {
count = atoi(argv[i]);
if (count > 0) {
continue;
}
res = 1;
}
/* intentionally falls through */
case 'h':
res = 1;
continue;
/* intentionally falls through */
case 'p':
if ((++i) < argc) {
if (!strcmp(argv[i], "ss")) {
proto = UWB_DATA_CODE_SS_TWR;
continue;
}
else if (!strcmp(argv[i], "ss-ack")) {
proto = UWB_DATA_CODE_SS_TWR_ACK;
continue;
}
else if (!strcmp(argv[i], "ss-ext")) {
proto = UWB_DATA_CODE_SS_TWR_EXT;
continue;
}
else if (!strcmp(argv[i], "ds")) {
proto = UWB_DATA_CODE_DS_TWR;
continue;
}
else if (!strcmp(argv[i], "ds-ext")) {
proto = UWB_DATA_CODE_DS_TWR_EXT;
continue;
}
else {
printf("[ERROR]: invalid protocol %s\n", argv[i]);
res = 1;
}
}
/* intentionally falls through */
case 'i':
if ((++i) < argc) {
interval_ms = atoi(argv[i]);
continue;
}
/* intentionally falls through */
default:
res = 1;
break;
}
}
}
if (res != 0 || (short_addr == 0x0000)) {
_print_usage();
return 1;
}
puts("[twr]: start ranging");
uwb_core_rng_start(short_addr, proto, interval_ms, count);
if (IS_ACTIVE(CONFIG_TWR_SHELL_BLOCKING)) {
while (uwb_core_rng_req_remaining()) {
ztimer_sleep(ZTIMER_MSEC, interval_ms);
}
/* some time to finish up */
ztimer_sleep(ZTIMER_MSEC, 100 + interval_ms);
}
return 0;
}
_print_usage();
return -1;
}