blob: 75d2a3170ae7040b94c407fb7aa9cf2bf5b14af6 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#include "os/mynewt.h"
#include <inttypes.h>
#include <string.h>
#include "shell/shell.h"
#include "console/console.h"
#include "parse/parse.h"
#include "node/lora_priv.h"
#if MYNEWT_VAL(LORA_NODE_CLI)
static int lora_cli_cmd_fn(int argc, char **argv);
static int lora_cli_set_freq(int argc, char **argv);
static int lora_cli_tx_cfg(int argc, char **argv);
static int lora_cli_rx_cfg(int argc, char **argv);
static int lora_cli_tx(int argc, char **argv);
static int lora_cli_rx(int argc, char **argv);
static int lora_cli_max_payload_len(int argc, char **argv);
static struct shell_cmd lora_cli_cmd = {
.sc_cmd = "lora",
.sc_cmd_func = lora_cli_cmd_fn,
};
static struct shell_cmd lora_cli_subcmds[] = {
{
.sc_cmd = "set_freq",
.sc_cmd_func = lora_cli_set_freq,
},
{
.sc_cmd = "tx_cfg",
.sc_cmd_func = lora_cli_tx_cfg,
},
{
.sc_cmd = "rx_cfg",
.sc_cmd_func = lora_cli_rx_cfg,
},
{
.sc_cmd = "tx",
.sc_cmd_func = lora_cli_tx,
},
{
.sc_cmd = "rx",
.sc_cmd_func = lora_cli_rx,
},
{
.sc_cmd = "max_payload_len",
.sc_cmd_func = lora_cli_max_payload_len,
},
};
static int
lora_cli_cmd_fn(int argc, char **argv)
{
const struct shell_cmd *subcmd;
const char *err;
int rc;
int i;
if (argc <= 1) {
rc = 1;
err = NULL;
goto err;
}
for (i = 0;
i < sizeof lora_cli_subcmds / sizeof lora_cli_subcmds[0];
i++) {
subcmd = lora_cli_subcmds + i;
if (strcmp(argv[1], subcmd->sc_cmd) == 0) {
rc = subcmd->sc_cmd_func(argc - 1, argv + 1);
return rc;
}
}
rc = 1;
err = "invalid lora command";
err:
if (err != NULL) {
console_printf("error: %s\n", err);
}
console_printf(
"usage:\n"
" lora set_freq\n"
" lora tx_cfg\n"
" lora rx_cfg\n"
" lora tx\n"
" lora rx\n"
" lora max_payload_len\n");
return rc;
}
static int
lora_cli_set_freq(int argc, char **argv)
{
const char *err;
uint32_t freq;
int rc;
if (argc <= 1) {
rc = 1;
err = NULL;
goto err;
}
freq = parse_ull(argv[1], &rc);
if (rc != 0) {
err = "invalid frequency";
goto err;
}
Radio.SetChannel(freq);
return 0;
err:
if (err != NULL) {
console_printf("error: %s\n", err);
}
console_printf(
"usage:\n"
" lora set_freq <hz>\n");
return rc;
}
static int
lora_cli_tx_cfg(int argc, char **argv)
{
RadioModems_t modem;
const char *err;
char **arg;
uint32_t bandwidth;
uint32_t datarate;
uint32_t timeout;
uint32_t fdev;
uint16_t preamble_len;
uint8_t hop_period;
uint8_t coderate;
int8_t power;
int freq_hop_on;
int iq_inverted;
int fix_len;
int crc_on;
int rc;
if (argc <= 13) {
rc = 1;
err = NULL;
goto err;
}
arg = argv + 1;
modem = parse_ull_bounds(*arg, 0, 1, &rc);
if (rc != 0) {
goto err;
}
arg++;
power = parse_ll_bounds(*arg, INT8_MIN, INT8_MAX, &rc);
if (rc != 0) {
goto err;
}
arg++;
fdev = parse_ull_bounds(*arg, 0, UINT32_MAX, &rc);
if (rc != 0) {
goto err;
}
arg++;
bandwidth = parse_ull_bounds(*arg, 0, UINT32_MAX, &rc);
if (rc != 0) {
goto err;
}
arg++;
datarate = parse_ull_bounds(*arg, 0, UINT32_MAX, &rc);
if (rc != 0) {
goto err;
}
arg++;
coderate = parse_ull_bounds(*arg, 0, UINT8_MAX, &rc);
if (rc != 0) {
goto err;
}
arg++;
preamble_len = parse_ull_bounds(*arg, 0, UINT16_MAX, &rc);
if (rc != 0) {
goto err;
}
arg++;
fix_len = parse_ull_bounds(*arg, 0, 1, &rc);
if (rc != 0) {
goto err;
}
arg++;
crc_on = parse_ull_bounds(*arg, 0, 1, &rc);
if (rc != 0) {
goto err;
}
arg++;
freq_hop_on = parse_ull_bounds(*arg, 0, 1, &rc);
if (rc != 0) {
goto err;
}
arg++;
hop_period = parse_ull_bounds(*arg, 0, UINT8_MAX, &rc);
if (rc != 0) {
goto err;
}
arg++;
iq_inverted = parse_ull_bounds(*arg, 0, 1, &rc);
if (rc != 0) {
goto err;
}
arg++;
timeout = parse_ull_bounds(*arg, 0, UINT32_MAX, &rc);
if (rc != 0) {
goto err;
}
arg++;
Radio.SetTxConfig(modem,
power,
fdev,
bandwidth,
datarate,
coderate,
preamble_len,
fix_len,
crc_on,
freq_hop_on,
hop_period,
iq_inverted,
timeout);
return 0;
err:
if (err != NULL) {
console_printf("error: %s\n", err);
}
console_printf(
"usage:\n"
" lora tx_cfg <modem-type (0/1)> <power> <frequency-deviation>\n"
" <bandwidth> <data-rate> <code-rate> <preamble-length>\n"
" <fixed-length (0/1)> <crc-on (0/1)>\n"
" <frequency-hopping (0/1)> <hop-period> <iq-inverted (0/1)>\n"
" <timeout>\n");
return rc;
}
static int
lora_cli_rx_cfg(int argc, char **argv)
{
RadioModems_t modem;
const char *err;
char **arg;
uint32_t bandwidth_afc;
uint32_t bandwidth;
uint32_t datarate;
uint16_t preamble_len;
uint16_t symb_timeout;
uint8_t payload_len;
uint8_t hop_period;
uint8_t coderate;
int rx_continuous;
int freq_hop_on;
int iq_inverted;
int fix_len;
int crc_on;
int rc;
if (argc <= 14) {
rc = 1;
err = NULL;
goto err;
}
arg = argv + 1;
modem = parse_ull_bounds(*arg, 0, 1, &rc);
if (rc != 0) {
err = "invalid modem type";
goto err;
}
arg++;
bandwidth = parse_ull_bounds(*arg, 0, UINT32_MAX, &rc);
if (rc != 0) {
err = "invalid bandwidth";
goto err;
}
arg++;
datarate = parse_ull_bounds(*arg, 0, UINT32_MAX, &rc);
if (rc != 0) {
err = "invalid data rate";
goto err;
}
arg++;
coderate = parse_ull_bounds(*arg, 0, UINT8_MAX, &rc);
if (rc != 0) {
err = "invalid code rate";
goto err;
}
arg++;
bandwidth_afc = parse_ull_bounds(*arg, 0, UINT32_MAX, &rc);
if (rc != 0) {
err = "invalid bandwidtch_afc";
goto err;
}
arg++;
preamble_len = parse_ull_bounds(*arg, 0, UINT16_MAX, &rc);
if (rc != 0) {
err = "invalid preamble length";
goto err;
}
arg++;
symb_timeout = parse_ull_bounds(*arg, 0, UINT16_MAX, &rc);
if (rc != 0) {
err = "invalid symbol timeout";
goto err;
}
arg++;
fix_len = parse_ull_bounds(*arg, 0, 1, &rc);
if (rc != 0) {
err = "invalid fixed length value";
goto err;
}
arg++;
payload_len = parse_ull_bounds(*arg, 0, UINT8_MAX, &rc);
if (rc != 0) {
err = "invalid payload length";
goto err;
}
arg++;
crc_on = parse_ull_bounds(*arg, 0, 1, &rc);
if (rc != 0) {
err = "invalid crc on value";
goto err;
}
arg++;
freq_hop_on = parse_ull_bounds(*arg, 0, 1, &rc);
if (rc != 0) {
err = "invalid frequency hopping value";
goto err;
}
arg++;
hop_period = parse_ull_bounds(*arg, 0, UINT8_MAX, &rc);
if (rc != 0) {
err = "invalid hop period";
goto err;
}
arg++;
iq_inverted = parse_ull_bounds(*arg, 0, 1, &rc);
if (rc != 0) {
err = "invalid iq inverted value";
goto err;
}
arg++;
rx_continuous = parse_ull_bounds(*arg, 0, 1, &rc);
if (rc != 0) {
err = "invalid rx continuous value";
goto err;
}
arg++;
Radio.SetRxConfig(modem,
bandwidth,
datarate,
coderate,
bandwidth_afc,
preamble_len,
symb_timeout,
fix_len,
payload_len,
crc_on,
freq_hop_on,
hop_period,
iq_inverted,
rx_continuous);
return 0;
err:
if (err != NULL) {
console_printf("error: %s\n", err);
}
console_printf(
"usage:\n"
" lora rx_cfg <modem-type (0/1)> <bandwidth> <data-rate> <code-rate>\n"
" <bandwidtch-afc> <preamble-length> <symbol-timeout>\n"
" <fixed-length (0/1)> <payload-length> <crc-on (0/1)>\n"
" <frequency-hopping (0/1)> <hop-period> <iq-inverted (0/1)>\n"
" <rx-continuous (0/1)>\n");
return rc;
}
static int
lora_cli_tx(int argc, char **argv)
{
uint8_t buf[UINT8_MAX];
const char *err;
int buf_sz;
int rc;
if (argc <= 1) {
rc = 1;
err = NULL;
goto err;
}
rc = parse_byte_stream(argv[1], sizeof buf, buf, &buf_sz);
if (rc != 0) {
err = "invalid payload";
goto err;
}
Radio.Send(buf, buf_sz);
return 0;
err:
if (err != NULL) {
console_printf("error: %s\n", err);
}
console_printf(
"usage:\n"
" lora tx <0xXX:0xXX:...>\n");
return rc;
}
static int
lora_cli_rx(int argc, char **argv)
{
const char *err;
uint32_t timeout;
int rc;
if (argc <= 1) {
rc = 1;
err = NULL;
goto err;
}
timeout = parse_ull_bounds(argv[1], 0, UINT32_MAX, &rc);
if (rc != 0) {
err = "invalid timeout";
goto err;
}
Radio.Rx(timeout);
return 0;
err:
if (err != NULL) {
console_printf("error: %s\n", err);
}
console_printf(
"usage:\n"
" lora rx <timeout>\n");
return rc;
}
static int
lora_cli_max_payload_len(int argc, char **argv)
{
RadioModems_t modem;
const char *err;
uint8_t len;
int rc;
if (argc <= 2) {
rc = 1;
err = NULL;
goto err;
}
modem = parse_ull_bounds(argv[1], 0, 1, &rc);
if (rc != 0) {
err = "invalid modem type";
goto err;
}
len = parse_ull_bounds(argv[2], 0, UINT8_MAX, &rc);
if (rc != 0) {
err = "invalid length";
goto err;
}
Radio.SetMaxPayloadLength(modem, len);
return 0;
err:
if (err != NULL) {
console_printf("error: %s\n", err);
}
console_printf(
"usage:\n"
" lora max_payload_len <length>\n");
return rc;
}
void
lora_cli_init(void)
{
int rc;
rc = shell_cmd_register(&lora_cli_cmd);
SYSINIT_PANIC_ASSERT_MSG(rc == 0, "Failed to register lora CLI command");
}
#endif /* MYNEWT_VAL(LORA_NODE_CLI) */
#if MYNEWT_VAL(LORA_NODE_LOG_CLI) == 1
#if MYNEWT_VAL(LORA_NODE_LOG_CLI) == 1
static int lora_cli_log_cmd(int argc, char **argv);
static struct shell_cmd lora_node_log_cmd = {
.sc_cmd = "ln_log",
.sc_cmd_func = lora_cli_log_cmd
};
#endif
int
lora_cli_log_cmd(int argc, char **argv)
{
#ifdef LORA_NODE_DEBUG_LOG
uint16_t i;
uint16_t lines_logged;
console_printf("Lora node log\n");
i = g_lnd_log_index;
lines_logged = 0;
while (lines_logged != LORA_NODE_DEBUG_LOG_ENTRIES) {
/* Do not display empty log lines */
if (g_lnd_log[i].lnd_id == 0) {
goto next_entry;
}
console_printf("index=%u ", i);
switch (g_lnd_log[i].lnd_id) {
case LORA_NODE_LOG_TX_DONE:
console_printf("TX_DONE chan=%u done_time=%lu",
g_lnd_log[i].lnd_p8, g_lnd_log[i].lnd_p32);
break;
case LORA_NODE_LOG_TX_SETUP:
console_printf("TX_SETUP phytxpwr=%d sf=%u bw=%u freq=%lu",
(int8_t)g_lnd_log[i].lnd_p8,
(uint8_t)(g_lnd_log[i].lnd_p16 >> 8),
(uint8_t)g_lnd_log[i].lnd_p16,
g_lnd_log[i].lnd_p32);
break;
case LORA_NODE_LOG_TX_START:
console_printf("TX_START pwr=%d dr=%u chan=%u airtime=%lu",
(int8_t)g_lnd_log[i].lnd_p8,
(uint8_t)(g_lnd_log[i].lnd_p16 >> 8),
(uint8_t)g_lnd_log[i].lnd_p16,
g_lnd_log[i].lnd_p32);
break;
case LORA_NODE_LOG_TX_DELAY:
console_printf("TX_DELAY dc=%u delay_usecs=%lu",
(int8_t)g_lnd_log[i].lnd_p8, g_lnd_log[i].lnd_p32);
break;
case LORA_NODE_LOG_TX_PREP_FRAME:
console_printf("TX_PREP_FRAME cmdbytes=%u uplink=%u mhdr=%x",
g_lnd_log[i].lnd_p8, g_lnd_log[i].lnd_p16,
(uint8_t)g_lnd_log[i].lnd_p32);
break;
case LORA_NODE_LOG_RX_WIN1_SETUP:
console_printf("RX_WIN1_SETUP dr=%u chan=%u timeout=%lu",
g_lnd_log[i].lnd_p8, g_lnd_log[i].lnd_p16,
g_lnd_log[i].lnd_p32);
break;
case LORA_NODE_LOG_RX_TIMEOUT:
console_printf("RX_TIMEOUT chan=%u rxslot=%u",
g_lnd_log[i].lnd_p8, g_lnd_log[i].lnd_p16);
break;
case LORA_NODE_LOG_RX_DONE:
console_printf("RX_DONE chan=%u size=%u slot=%u machdr=%x",
g_lnd_log[i].lnd_p8, g_lnd_log[i].lnd_p16,
(uint8_t)(g_lnd_log[i].lnd_p32 >> 8),
(uint8_t)g_lnd_log[i].lnd_p32);
break;
case LORA_NODE_LOG_RADIO_TIMEOUT_IRQ:
break;
case LORA_NODE_LOG_RX_CFG:
console_printf("RX_CFG bw=%u dr=%u sf=%u freq=%lu",
(int8_t)g_lnd_log[i].lnd_p8,
(uint8_t)(g_lnd_log[i].lnd_p16 >> 8),
(uint8_t)g_lnd_log[i].lnd_p16,
g_lnd_log[i].lnd_p32);
break;
case LORA_NODE_LOG_RX_PORT:
console_printf("RX_PORT port=%u len=%u dwnlink_cntr=%lu",
g_lnd_log[i].lnd_p8, g_lnd_log[i].lnd_p16,
g_lnd_log[i].lnd_p32);
break;
case LORA_NODE_LOG_RX_WIN2:
console_printf("RX_WIN2 rxslot=%u cont=%u freq=%lu",
g_lnd_log[i].lnd_p8, g_lnd_log[i].lnd_p16,
g_lnd_log[i].lnd_p32);
break;
case LORA_NODE_LOG_APP_TX:
console_printf("APP_TX pktlen=%u om=%lx",
g_lnd_log[i].lnd_p16, g_lnd_log[i].lnd_p32);
break;
case LORA_NODE_LOG_RTX_TIMEOUT:
console_printf("RTX_TIMEOUT macflags=%x", g_lnd_log[i].lnd_p8);
break;
case LORA_NODE_LOG_RX_ADR_REQ:
console_printf("RX_ADR_REQ dr=%u txpwr=%u chmassk=%u nbrep=%u",
g_lnd_log[i].lnd_p8, g_lnd_log[i].lnd_p16,
(uint16_t)(g_lnd_log[i].lnd_p32 >> 16),
(uint16_t)g_lnd_log[i].lnd_p32);
break;
case LORA_NODE_LOG_PROC_MAC_CMD:
console_printf("PROC_MAC_CMD index=%u snr=%u cmd_size=%lu",
g_lnd_log[i].lnd_p8, g_lnd_log[i].lnd_p16,
g_lnd_log[i].lnd_p32);
break;
case LORA_NODE_LOG_LINK_CHK:
console_printf("LINK_CHK status=%lu", g_lnd_log[i].lnd_p32);
break;
default:
console_printf("id=%u p8=%u p16=%u p32=%lu",
g_lnd_log[i].lnd_id, g_lnd_log[i].lnd_p8,
g_lnd_log[i].lnd_p16, g_lnd_log[i].lnd_p32);
break;
}
console_printf(" cputime=%lu\n", g_lnd_log[i].lnd_cputime);
next_entry:
++i;
if (i == LORA_NODE_DEBUG_LOG_ENTRIES) {
i = 0;
}
++lines_logged;
}
#else
console_printf("No Lora node log available\n");
#endif
return 0;
}
void
lora_cli_init(void)
{
int rc;
rc = shell_cmd_register(&lora_node_log_cmd);
assert(rc == 0);
}
#endif /* MYNEWT_VAL(LORA_NODE_LOG_CLI) */