v2.0.0
> #### New features * Added support for USB interface between the HOST and the concentrator, for sx1250 based concentrator only. * Added support for Listen-Before-Talk for AS923 region, using the additional sx1261 radio from the Semtech Corecell reference design v3. * Added support for Spectral Scan with additional sx1261 radio from the Semtech Corecell reference design v3. * Added support for SX1303 chip, for further Fine Timestamping support. * Merged the master-fdd-cn490 branch to bring support for CN490 Full-Duplex reference design. It is an integration of the releases v1.1.0, v1.1.1, v1.1.2 described below. > #### Changes * HAL: Reworked the complete communication layer. A new loragw_com module has been introduced to handle switching from a USB or a SPI communication interface, aligned function prototypes for sx125x, sx1250 and sx1261 radios. For USB, a mode has been added to group SPI write commands request to the STM32 MCU, in order to optimize latency during time critical configuration phases. * HAL: Added preliminary support for Fine Timestamping for TDOA localization. * HAL: Updated AGC firmware to v6: add configurable delay for PA to start, add Listen-Before-Talk support. * HAL: Added new API function lgw_demod_setconf() to set global demodulator settings. * HAL: Added new API functions for Spectral Scan. * Packet Forwarder: The type of interface is configurable in the global_conf.json file: com_type can be "USB" or "SPI". * Packet Forwarder: Changed the parameters to configure fine timestamping in the global_conf.json. * Packet Forwarder: Added sections to configure the spectral scan and Listen-Before-Talk features. * Packet Forwarder: Added a new thread for background spectral scan example, to show how to use the spectral scan API provided by the HAL, without interfering with the main tasks of the gateway (aka Receive uplinks and transmit downlinks). * Packet Forwarder: Added "nhdr" field parsing from "txpk" JSON downlink request in order to be able to send beacon request from Network Server. * Packet Forwarder: Added chan_multiSF_All in global_conf.json to choose which spreading factors to enable for multi-sf demodulators. * Packet Forwarder: Updated PROTOCOL.md to v1.6. * Tools: added util_spectral_scan, a standalone spectral scanner utility. > #### Notes * This release has been validated on the Semtech Corecell reference design v3 with USB interface. v1.1.2 > Integrated in ***v2.0.0*** from ***master-fdd-cn490*** branch. * packet forwarder: updated global_conf.json.sx1255.CN490.full-duplex with RSSI temperature compensation coefficients, and updated RSSI offset for radio 1. v1.1.1 > Integrated in ***v2.0.0*** from ***master-fdd-cn490*** branch. * HAL: Updated SX1302 LNA/PA LUT configuration for Full Duplex CN490 reference design. * test_loragw_hal_rx/tx: added --fdd option to enable Full Duplex * packet forwarder: updated global_conf.json.sx1255.CN490.full-duplex for CN490 reference design. v1.1.0 > Integrated in ***v2.0.0*** from ***master-fdd-cn490*** branch. * HAL: Added support for CN490 full duplex reference design.
This commit is contained in:
parent
6291e62ef9
commit
2c14708bdb
107 changed files with 13516 additions and 3249 deletions
|
|
@ -7,7 +7,7 @@
|
|||
(C)2019 Semtech
|
||||
|
||||
Description:
|
||||
Minimum test program for HAL calibration
|
||||
Minimum test program for HAL calibration for sx1255/sx1257 radios
|
||||
|
||||
License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*/
|
||||
|
|
@ -35,6 +35,7 @@ License: Revised BSD License, see LICENSE.TXT file include in the project
|
|||
|
||||
#include "loragw_hal.h"
|
||||
#include "loragw_reg.h"
|
||||
#include "loragw_com.h"
|
||||
#include "loragw_sx1302.h"
|
||||
#include "loragw_sx125x.h"
|
||||
#include "loragw_aux.h"
|
||||
|
|
@ -45,13 +46,14 @@ License: Revised BSD License, see LICENSE.TXT file include in the project
|
|||
|
||||
#define RAND_RANGE(min, max) (rand() % (max + 1 - min) + min)
|
||||
|
||||
#define DEBUG_MSG(str) fprintf(stderr, str)
|
||||
#define DEBUG_PRINTF(fmt, args...) fprintf(stderr,"%s:%d: "fmt, __FUNCTION__, __LINE__, args)
|
||||
#define DEBUG_MSG(str) fprintf(stdout, str)
|
||||
#define DEBUG_PRINTF(fmt, args...) fprintf(stdout,"%s:%d: "fmt, __FUNCTION__, __LINE__, args)
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE CONSTANTS ---------------------------------------------------- */
|
||||
|
||||
#define LINUXDEV_PATH_DEFAULT "/dev/spidev0.0"
|
||||
#define COM_TYPE_DEFAULT LGW_COM_SPI
|
||||
#define COM_PATH_DEFAULT "/dev/spidev0.0"
|
||||
|
||||
#define DEFAULT_CLK_SRC 0
|
||||
#define DEFAULT_FREQ_HZ 868500000U
|
||||
|
|
@ -98,13 +100,12 @@ void usage(void) {
|
|||
//printf("Library version information: %s\n", lgw_version_info());
|
||||
printf("Available options:\n");
|
||||
printf(" -h print this help\n");
|
||||
printf(" -d <path> use Linux SPI device driver\n");
|
||||
printf(" => default path: " LINUXDEV_PATH_DEFAULT "\n");
|
||||
printf(" -u Set COM type as USB (default is SPI)\n");
|
||||
printf(" -d [path] Path to the COM interface\n");
|
||||
printf(" => default path: " COM_PATH_DEFAULT "\n");
|
||||
printf(" -k <uint> Concentrator clock source (Radio A or Radio B) [0..1]\n");
|
||||
printf(" -c <uint> RF chain to be used for TX (Radio A or Radio B) [0..1]\n");
|
||||
printf(" -r <uint> Radio type (1255, 1257, 1250)\n");
|
||||
printf(" -j Set radio in single input mode (SX1250 only)\n");
|
||||
printf(" -f <float> Radio TX frequency in MHz\n");
|
||||
printf(" -r <uint> Radio type (1255, 1257)\n");
|
||||
printf( "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" );
|
||||
printf(" --pa <uint> PA gain [0..3]\n");
|
||||
printf(" --dig <uint> sx1302 digital gain [0..3]\n");
|
||||
|
|
@ -149,32 +150,32 @@ int setup_tx_dc_offset(uint8_t rf_chain, uint32_t freq_hz, uint8_t dac_gain, uin
|
|||
DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d FOR RADIO TYPE\n", radio_type);
|
||||
return LGW_HAL_ERROR;
|
||||
}
|
||||
lgw_sx125x_reg_w(SX125x_REG_FRF_RX_MSB, 0xFF & rx_freq_int, rf_chain);
|
||||
lgw_sx125x_reg_w(SX125x_REG_FRF_RX_MID, 0xFF & (rx_freq_frac >> 8), rf_chain);
|
||||
lgw_sx125x_reg_w(SX125x_REG_FRF_RX_LSB, 0xFF & rx_freq_frac, rf_chain);
|
||||
lgw_sx125x_reg_w(SX125x_REG_FRF_TX_MSB, 0xFF & tx_freq_int, rf_chain);
|
||||
lgw_sx125x_reg_w(SX125x_REG_FRF_TX_MID, 0xFF & (tx_freq_frac >> 8), rf_chain);
|
||||
lgw_sx125x_reg_w(SX125x_REG_FRF_TX_LSB, 0xFF & tx_freq_frac, rf_chain);
|
||||
sx125x_reg_w(SX125x_REG_FRF_RX_MSB, 0xFF & rx_freq_int, rf_chain);
|
||||
sx125x_reg_w(SX125x_REG_FRF_RX_MID, 0xFF & (rx_freq_frac >> 8), rf_chain);
|
||||
sx125x_reg_w(SX125x_REG_FRF_RX_LSB, 0xFF & rx_freq_frac, rf_chain);
|
||||
sx125x_reg_w(SX125x_REG_FRF_TX_MSB, 0xFF & tx_freq_int, rf_chain);
|
||||
sx125x_reg_w(SX125x_REG_FRF_TX_MID, 0xFF & (tx_freq_frac >> 8), rf_chain);
|
||||
sx125x_reg_w(SX125x_REG_FRF_TX_LSB, 0xFF & tx_freq_frac, rf_chain);
|
||||
|
||||
/* Radio settings for calibration */
|
||||
//lgw_sx125x_reg_w(SX125x_RX_ANA_GAIN__LNA_ZIN, 1, rf_chain); /* Default: 1 */
|
||||
//lgw_sx125x_reg_w(SX125x_RX_ANA_GAIN__BB_GAIN, 15, rf_chain); /* Default: 15 */
|
||||
//lgw_sx125x_reg_w(SX125x_RX_ANA_GAIN__LNA_GAIN, 1, rf_chain); /* Default: 1 */
|
||||
lgw_sx125x_reg_w(SX125x_REG_RX_BW__BB_BW, 0, rf_chain);
|
||||
lgw_sx125x_reg_w(SX125x_REG_RX_BW__ADC_TRIM, 6, rf_chain);
|
||||
//lgw_sx125x_reg_w(SX125x_RX_BW__ADC_BW, 7, rf_chain); /* Default: 7 */
|
||||
lgw_sx125x_reg_w(SX125x_REG_RX_PLL_BW__PLL_BW, 0, rf_chain);
|
||||
lgw_sx125x_reg_w(SX125x_REG_TX_BW__PLL_BW, 0, rf_chain);
|
||||
//lgw_sx125x_reg_w(SX125x_TX_BW__ANA_BW, 0, rf_chain); /* Default: 0 */
|
||||
lgw_sx125x_reg_w(SX125x_REG_TX_DAC_BW, 5, rf_chain);
|
||||
lgw_sx125x_reg_w(SX125x_REG_CLK_SELECT__DAC_CLK_SELECT, 1, rf_chain); /* Use external clock from SX1302 */
|
||||
lgw_sx125x_reg_w(SX125x_REG_TX_GAIN__DAC_GAIN, dac_gain, rf_chain);
|
||||
lgw_sx125x_reg_w(SX125x_REG_TX_GAIN__MIX_GAIN, mix_gain, rf_chain);
|
||||
lgw_sx125x_reg_w(SX125x_REG_CLK_SELECT__RF_LOOPBACK_EN, 1, rf_chain);
|
||||
lgw_sx125x_reg_w(SX125x_REG_MODE, 15, rf_chain);
|
||||
//sx125x_reg_w(SX125x_RX_ANA_GAIN__LNA_ZIN, 1, rf_chain); /* Default: 1 */
|
||||
//sx125x_reg_w(SX125x_RX_ANA_GAIN__BB_GAIN, 15, rf_chain); /* Default: 15 */
|
||||
//sx125x_reg_w(SX125x_RX_ANA_GAIN__LNA_GAIN, 1, rf_chain); /* Default: 1 */
|
||||
sx125x_reg_w(SX125x_REG_RX_BW__BB_BW, 0, rf_chain);
|
||||
sx125x_reg_w(SX125x_REG_RX_BW__ADC_TRIM, 6, rf_chain);
|
||||
//sx125x_reg_w(SX125x_RX_BW__ADC_BW, 7, rf_chain); /* Default: 7 */
|
||||
sx125x_reg_w(SX125x_REG_RX_PLL_BW__PLL_BW, 0, rf_chain);
|
||||
sx125x_reg_w(SX125x_REG_TX_BW__PLL_BW, 0, rf_chain);
|
||||
//sx125x_reg_w(SX125x_TX_BW__ANA_BW, 0, rf_chain); /* Default: 0 */
|
||||
sx125x_reg_w(SX125x_REG_TX_DAC_BW, 5, rf_chain);
|
||||
sx125x_reg_w(SX125x_REG_CLK_SELECT__DAC_CLK_SELECT, 1, rf_chain); /* Use external clock from SX1302 */
|
||||
sx125x_reg_w(SX125x_REG_TX_GAIN__DAC_GAIN, dac_gain, rf_chain);
|
||||
sx125x_reg_w(SX125x_REG_TX_GAIN__MIX_GAIN, mix_gain, rf_chain);
|
||||
sx125x_reg_w(SX125x_REG_CLK_SELECT__RF_LOOPBACK_EN, 1, rf_chain);
|
||||
sx125x_reg_w(SX125x_REG_MODE, 15, rf_chain);
|
||||
wait_ms(1);
|
||||
lgw_sx125x_reg_r(SX125x_REG_MODE_STATUS__RX_PLL_LOCKED, &rx_pll_locked, rf_chain);
|
||||
lgw_sx125x_reg_r(SX125x_REG_MODE_STATUS__TX_PLL_LOCKED, &tx_pll_locked, rf_chain);
|
||||
sx125x_reg_r(SX125x_REG_MODE_STATUS__RX_PLL_LOCKED, &rx_pll_locked, rf_chain);
|
||||
sx125x_reg_r(SX125x_REG_MODE_STATUS__TX_PLL_LOCKED, &tx_pll_locked, rf_chain);
|
||||
if ((rx_pll_locked == 0) || (tx_pll_locked == 0)) {
|
||||
DEBUG_MSG("ERROR: PLL failed to lock\n");
|
||||
return LGW_HAL_ERROR;
|
||||
|
|
@ -460,22 +461,17 @@ int test_capture_ram(uint8_t rf_chain) {
|
|||
int main(int argc, char **argv)
|
||||
{
|
||||
int i, x;
|
||||
uint32_t ft = DEFAULT_FREQ_HZ;
|
||||
double arg_d = 0.0;
|
||||
unsigned int arg_u;
|
||||
uint8_t clocksource = 0;
|
||||
uint8_t rf_chain = 0;
|
||||
lgw_radio_type_t radio_type = LGW_RADIO_TYPE_NONE;
|
||||
bool single_input_mode = false;
|
||||
|
||||
struct lgw_conf_board_s boardconf;
|
||||
struct lgw_conf_rxrf_s rfconf;
|
||||
lgw_radio_type_t radio_type = LGW_RADIO_TYPE_SX1257;
|
||||
|
||||
static struct sigaction sigact; /* SIGQUIT&SIGINT&SIGTERM signal handling */
|
||||
|
||||
/* SPI interfaces */
|
||||
const char spidev_path_default[] = LINUXDEV_PATH_DEFAULT;
|
||||
const char * spidev_path = spidev_path_default;
|
||||
const char com_path_default[] = COM_PATH_DEFAULT;
|
||||
const char * com_path = com_path_default;
|
||||
lgw_com_type_t com_type = COM_TYPE_DEFAULT;
|
||||
|
||||
/* Initialize TX gain LUT */
|
||||
txlut.size = 1;
|
||||
|
|
@ -492,22 +488,26 @@ int main(int argc, char **argv)
|
|||
};
|
||||
|
||||
/* parse command line options */
|
||||
while ((i = getopt_long (argc, argv, "hjf:k:r:c:d:", long_options, &option_index)) != -1) {
|
||||
while ((i = getopt_long (argc, argv, "hk:r:c:d:u", long_options, &option_index)) != -1) {
|
||||
switch (i) {
|
||||
case 'h':
|
||||
usage();
|
||||
return -1;
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
com_type = LGW_COM_USB;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
if (optarg != NULL) {
|
||||
spidev_path = optarg;
|
||||
com_path = optarg;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'r': /* <uint> Radio type */
|
||||
i = sscanf(optarg, "%u", &arg_u);
|
||||
if ((i != 1) || ((arg_u != 1255) && (arg_u != 1257) && (arg_u != 1250))) {
|
||||
if ((i != 1) || ((arg_u != 1255) && (arg_u != 1257))) {
|
||||
printf("ERROR: argument parsing of -r argument. Use -h to print help\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
|
|
@ -518,8 +518,8 @@ int main(int argc, char **argv)
|
|||
case 1257:
|
||||
radio_type = LGW_RADIO_TYPE_SX1257;
|
||||
break;
|
||||
default: /* 1250 */
|
||||
radio_type = LGW_RADIO_TYPE_SX1250;
|
||||
default:
|
||||
/* should not happen */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -545,20 +545,6 @@ int main(int argc, char **argv)
|
|||
}
|
||||
break;
|
||||
|
||||
case 'j':
|
||||
single_input_mode = true;
|
||||
break;
|
||||
|
||||
case 'f': /* <float> Radio TX frequency in MHz */
|
||||
i = sscanf(optarg, "%lf", &arg_d);
|
||||
if (i != 1) {
|
||||
printf("ERROR: argument parsing of -f argument. Use -h to print help\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
ft = (uint32_t)((arg_d*1e6) + 0.5); /* .5 Hz offset to get rounding instead of truncating */
|
||||
}
|
||||
break;
|
||||
|
||||
case 0:
|
||||
if (strcmp(long_options[option_index].name, "dac") == 0) {
|
||||
i = sscanf(optarg, "%u", &arg_u);
|
||||
|
|
@ -599,50 +585,17 @@ int main(int argc, char **argv)
|
|||
sigaction( SIGINT, &sigact, NULL );
|
||||
sigaction( SIGTERM, &sigact, NULL );
|
||||
|
||||
/* Board reset */
|
||||
if (system("./reset_lgw.sh start") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
/* USB is currently not supported for sx1255/sx1257 radios */
|
||||
if (com_type == LGW_COM_USB) {
|
||||
printf("ERROR: USB interface is currently not supported for sx1255/sx1257 radios\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Configure the gateway */
|
||||
memset(&boardconf, 0, sizeof boardconf);
|
||||
boardconf.lorawan_public = true;
|
||||
boardconf.clksrc = clocksource;
|
||||
boardconf.full_duplex = false;
|
||||
strncpy(boardconf.spidev_path, spidev_path, sizeof boardconf.spidev_path);
|
||||
boardconf.spidev_path[sizeof boardconf.spidev_path - 1] = '\0'; /* ensure string termination */
|
||||
if (lgw_board_setconf(&boardconf) != LGW_HAL_SUCCESS) {
|
||||
printf("ERROR: failed to configure board\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
memset(&rfconf, 0, sizeof rfconf);
|
||||
rfconf.enable = ((rf_chain == 0) ? true : false);
|
||||
rfconf.freq_hz = ft;
|
||||
rfconf.type = radio_type;
|
||||
rfconf.tx_enable = true;
|
||||
rfconf.single_input_mode = single_input_mode;
|
||||
if (lgw_rxrf_setconf(0, &rfconf) != LGW_HAL_SUCCESS) {
|
||||
printf("ERROR: failed to configure rxrf 0\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
memset(&rfconf, 0, sizeof rfconf);
|
||||
rfconf.enable = ((rf_chain == 1) ? true : false);
|
||||
rfconf.freq_hz = ft;
|
||||
rfconf.type = radio_type;
|
||||
rfconf.tx_enable = true;
|
||||
rfconf.single_input_mode = single_input_mode;
|
||||
if (lgw_rxrf_setconf(1, &rfconf) != LGW_HAL_SUCCESS) {
|
||||
printf("ERROR: failed to configure rxrf 1\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (txlut.size > 0) {
|
||||
if (lgw_txgain_setconf(rf_chain, &txlut) != LGW_HAL_SUCCESS) {
|
||||
printf("ERROR: failed to configure txgain lut\n");
|
||||
return EXIT_FAILURE;
|
||||
if (com_type == LGW_COM_SPI) {
|
||||
/* Board reset */
|
||||
if (system("./reset_lgw.sh start") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -650,15 +603,15 @@ int main(int argc, char **argv)
|
|||
fp = fopen("log.txt", "w+");
|
||||
|
||||
/* connect the gateway */
|
||||
x = lgw_connect(spidev_path);
|
||||
x = lgw_connect(com_type, com_path);
|
||||
if (x != 0) {
|
||||
printf("ERROR: failed to connect the gateway\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
sx1302_radio_reset(rf_chain, LGW_RADIO_TYPE_SX1257);
|
||||
sx1302_radio_reset(rf_chain, radio_type);
|
||||
sx1302_radio_clock_select(clocksource);
|
||||
sx1302_radio_set_mode(rf_chain, LGW_RADIO_TYPE_SX1257);
|
||||
sx1302_radio_set_mode(rf_chain, radio_type);
|
||||
|
||||
printf("Loading CAL fw for sx125x\n");
|
||||
if (sx1302_agc_load_firmware(cal_firmware_sx125x) != LGW_HAL_SUCCESS) {
|
||||
|
|
@ -680,8 +633,8 @@ int main(int argc, char **argv)
|
|||
|
||||
//test_capture_ram(rf_chain);
|
||||
|
||||
sx1302_radio_reset(0, LGW_RADIO_TYPE_SX1257);
|
||||
sx1302_radio_reset(1, LGW_RADIO_TYPE_SX1257);
|
||||
sx1302_radio_reset(0, radio_type);
|
||||
sx1302_radio_reset(1, radio_type);
|
||||
|
||||
/* disconnect the gateway */
|
||||
x = lgw_disconnect();
|
||||
|
|
@ -693,10 +646,12 @@ int main(int argc, char **argv)
|
|||
/* Close log file */
|
||||
fclose(fp);
|
||||
|
||||
/* Board reset */
|
||||
if (system("./reset_lgw.sh stop") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
if (com_type == LGW_COM_SPI) {
|
||||
/* Board reset */
|
||||
if (system("./reset_lgw.sh stop") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
printf("=========== Test End ===========\n");
|
||||
|
|
@ -23,14 +23,13 @@ License: Revised BSD License, see LICENSE.TXT file include in the project
|
|||
#define _XOPEN_SOURCE 500
|
||||
#endif
|
||||
|
||||
|
||||
// #include <stdint.h>
|
||||
#include <stdio.h> /* printf */
|
||||
#include <stdlib.h>
|
||||
#include <signal.h> /* sigaction */
|
||||
#include <getopt.h> /* getopt_long */
|
||||
|
||||
#include "loragw_hal.h"
|
||||
#include "loragw_com.h"
|
||||
#include "loragw_reg.h"
|
||||
#include "loragw_aux.h"
|
||||
#include "loragw_sx1250.h"
|
||||
|
|
@ -40,11 +39,11 @@ License: Revised BSD License, see LICENSE.TXT file include in the project
|
|||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE MACROS ------------------------------------------------------- */
|
||||
|
||||
#define DEBUG_MSG(str) fprintf(stderr, str)
|
||||
#define DEBUG_MSG(str) fprintf(stdout, str)
|
||||
|
||||
#define LINUXDEV_PATH_DEFAULT "/dev/spidev0.0"
|
||||
#define COM_TYPE_DEFAULT LGW_COM_SPI
|
||||
#define COM_PATH_DEFAULT "/dev/spidev0.0"
|
||||
|
||||
#define FULL_INIT 0
|
||||
#define CAPTURE_RAM_SIZE 0x4000
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
|
@ -56,21 +55,6 @@ static int quit_sig = 0; /* 1 -> application terminates without shutting down th
|
|||
|
||||
uint32_t sampling_frequency[] = {4e6, 4e6, 4e6, 4e6, 4e6, 4e6, 4e6, 0, 0, 1e6, 125e3, 125e3, 125e3, 125e3, 125e3, 125e3, 125e3, 125e3, 8e6, 125e3, 125e3, 125e3, 0, 32e6, 32e6, 0, 32e6, 32e6, 0, 32e6, 32e6, 32e6};
|
||||
|
||||
#if FULL_INIT
|
||||
#include "src/text_agc_sx1250_27_Nov_1.var"
|
||||
#include "src/text_agc_sx1257_19_Nov_1.var"
|
||||
#include "src/text_arb_sx1302_13_Nov_3.var"
|
||||
|
||||
#define FW_VERSION_CAL 0 /* Expected version of calibration firmware */ /* TODO */
|
||||
#define FW_VERSION_AGC 1 /* Expected version of AGC firmware */
|
||||
#define FW_VERSION_ARB 1 /* Expected version of arbiter firmware */
|
||||
|
||||
static bool rf_enable[LGW_RF_CHAIN_NB];
|
||||
static uint32_t rf_rx_freq[LGW_RF_CHAIN_NB]; /* absolute, in Hz */
|
||||
static lgw_radio_type_t rf_radio_type[LGW_RF_CHAIN_NB];
|
||||
static uint8_t rf_clkout = 0;
|
||||
#endif
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE FUNCTIONS ---------------------------------------------------- */
|
||||
|
||||
|
|
@ -79,8 +63,8 @@ void usage(void)
|
|||
{
|
||||
printf("Available options:\n");
|
||||
printf(" -h print this help\n");
|
||||
printf(" -d <path> use Linux SPI device driver\n");
|
||||
printf(" => default path: " LINUXDEV_PATH_DEFAULT "\n");
|
||||
printf(" -d [path] Path to the SPI interface (USB is not supported)\n");
|
||||
printf(" => default path: " COM_PATH_DEFAULT "\n");
|
||||
printf(" -s <uint> Capture source [0..31]\n");
|
||||
}
|
||||
|
||||
|
|
@ -105,16 +89,14 @@ int main(int argc, char **argv)
|
|||
uint8_t capture_source = 0;
|
||||
uint16_t period_value = 0;
|
||||
int16_t real = 0, imag = 0;
|
||||
#if FULL_INIT
|
||||
uint32_t val1, val2;
|
||||
#endif
|
||||
uint8_t capture_ram_buffer[CAPTURE_RAM_SIZE];
|
||||
|
||||
static struct sigaction sigact; /* SIGQUIT&SIGINT&SIGTERM signal handling */
|
||||
|
||||
/* SPI interfaces */
|
||||
const char spidev_path_default[] = LINUXDEV_PATH_DEFAULT;
|
||||
const char * spidev_path = spidev_path_default;
|
||||
const char com_path_default[] = COM_PATH_DEFAULT;
|
||||
const char * com_path = com_path_default;
|
||||
lgw_com_type_t com_type = COM_TYPE_DEFAULT;
|
||||
|
||||
/* Parameter parsing */
|
||||
int option_index = 0;
|
||||
|
|
@ -132,7 +114,7 @@ int main(int argc, char **argv)
|
|||
|
||||
case 'd':
|
||||
if (optarg != NULL) {
|
||||
spidev_path = optarg;
|
||||
com_path = optarg;
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
@ -161,105 +143,17 @@ int main(int argc, char **argv)
|
|||
sigaction( SIGINT, &sigact, NULL );
|
||||
sigaction( SIGTERM, &sigact, NULL );
|
||||
|
||||
#if FULL_INIT
|
||||
/* Board reset */
|
||||
if (system("./reset_lgw.sh start") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Initialize memory for capture */
|
||||
for (i = 0; i < CAPTURE_RAM_SIZE; i++) {
|
||||
capture_ram_buffer[i] = i%256;
|
||||
}
|
||||
|
||||
reg_stat = lgw_connect(spidev_path);
|
||||
reg_stat = lgw_connect(com_type, com_path);
|
||||
if (reg_stat == LGW_REG_ERROR) {
|
||||
DEBUG_MSG("ERROR: FAIL TO CONNECT BOARD\n");
|
||||
return LGW_HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Manual init */
|
||||
#if FULL_INIT
|
||||
rf_radio_type[0] = LGW_RADIO_TYPE_SX1250;
|
||||
rf_radio_type[1] = LGW_RADIO_TYPE_SX1257;
|
||||
rf_enable[0] = false;
|
||||
rf_enable[1] = true;
|
||||
rf_clkout = 1;
|
||||
rf_rx_freq[1] = 863700000;
|
||||
|
||||
/* setup radios */
|
||||
for (i=0; i < 2; i++)
|
||||
{
|
||||
if (rf_enable[i] == true) {
|
||||
sx1302_radio_reset(i, rf_radio_type[i]);
|
||||
switch (radio_type) {
|
||||
case LGW_RADIO_TYPE_SX1250:
|
||||
sx1250_setup(i, rf_rx_freq[i], false);
|
||||
break;
|
||||
case LGW_RADIO_TYPE_SX1255:
|
||||
case LGW_RADIO_TYPE_SX1257:
|
||||
sx125x_setup(i, rf_clkout, true, rf_radio_type[i], rf_rx_freq[i]);
|
||||
break;
|
||||
default:
|
||||
DEBUG_MSG("ERROR: RADIO TYPE NOT SUPPORTED\n");
|
||||
return LGW_HAL_ERROR;
|
||||
}
|
||||
sx1302_radio_set_mode(i, radio_type);
|
||||
}
|
||||
}
|
||||
|
||||
/* Select the radio which provides the clock to the sx1302 */
|
||||
sx1302_radio_clock_select(rf_clkout);
|
||||
|
||||
/* Check that the SX1302 timestamp counter is running */
|
||||
lgw_get_instcnt(&val1);
|
||||
lgw_get_instcnt(&val2);
|
||||
if (val1 == val2) {
|
||||
printf("ERROR: SX1302 timestamp counter is not running (val:%u)\n", (uint32_t)val1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Configure Radio FE */
|
||||
sx1302_radio_fe_configure();
|
||||
|
||||
/* give radio control to AGC MCU */
|
||||
lgw_reg_w(SX1302_REG_COMMON_CTRL0_HOST_RADIO_CTRL, 0x00);
|
||||
|
||||
/* Load firmware */
|
||||
switch (rf_radio_type[rf_clkout]) {
|
||||
case LGW_RADIO_TYPE_SX1250:
|
||||
printf("Loading AGC fw for sx1250\n");
|
||||
if (sx1302_agc_load_firmware(agc_firmware_sx1250) != LGW_HAL_SUCCESS) {
|
||||
return LGW_HAL_ERROR;
|
||||
}
|
||||
if (sx1302_agc_start(FW_VERSION_AGC, SX1302_RADIO_TYPE_SX1250, SX1302_AGC_RADIO_GAIN_AUTO, SX1302_AGC_RADIO_GAIN_AUTO, 0) != LGW_HAL_SUCCESS) {
|
||||
return LGW_HAL_ERROR;
|
||||
}
|
||||
break;
|
||||
case LGW_RADIO_TYPE_SX1257:
|
||||
printf("Loading AGC fw for sx125x\n");
|
||||
if (sx1302_agc_load_firmware(agc_firmware_sx125x) != LGW_HAL_SUCCESS) {
|
||||
return LGW_HAL_ERROR;
|
||||
}
|
||||
if (sx1302_agc_start(FW_VERSION_AGC, SX1302_RADIO_TYPE_SX125X, SX1302_AGC_RADIO_GAIN_AUTO, SX1302_AGC_RADIO_GAIN_AUTO, 0) != LGW_HAL_SUCCESS) {
|
||||
// if (sx1302_agc_start(FW_VERSION_AGC, SX1302_RADIO_TYPE_SX125X, 1, 7, 0) != LGW_HAL_SUCCESS) {
|
||||
return LGW_HAL_ERROR;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
printf("Loading ARB fw\n");
|
||||
if (sx1302_arb_load_firmware(arb_firmware) != LGW_HAL_SUCCESS) {
|
||||
return LGW_HAL_ERROR;
|
||||
}
|
||||
if (sx1302_arb_start(FW_VERSION_ARB) != LGW_HAL_SUCCESS) {
|
||||
return LGW_HAL_ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
// lgw_reg_w(SX1302_REG_CAPTURE_RAM_CLOCK_GATE_OVERRIDE_CLK_OVERRIDE, 3);
|
||||
|
||||
/* Configure the Capture Ram block */
|
||||
|
|
@ -270,12 +164,9 @@ int main(int argc, char **argv)
|
|||
lgw_reg_w(SX1302_REG_CAPTURE_RAM_CAPTURE_SOURCE_A_SOURCEMUX, capture_source);
|
||||
|
||||
printf("Sampling frequency: %d\n", sampling_frequency[capture_source]);
|
||||
if (sampling_frequency[capture_source] != 0)
|
||||
{
|
||||
if (sampling_frequency[capture_source] != 0) {
|
||||
period_value = (32e6/sampling_frequency[capture_source]) - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
fprintf(stderr ,"ERROR: Sampling frequency is null\n");
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -295,7 +186,7 @@ int main(int argc, char **argv)
|
|||
// lgw_reg_w(SX1302_REG_CAPTURE_RAM_CAPTURE_CFG_CAPTUREFORCETRIGGER, 1);
|
||||
|
||||
/* Poll Status.CapComplete */
|
||||
do{
|
||||
do {
|
||||
lgw_reg_r(SX1302_REG_CAPTURE_RAM_STATUS_CAPCOMPLETE, &val);
|
||||
|
||||
wait_ms(10);
|
||||
|
|
@ -305,7 +196,6 @@ int main(int argc, char **argv)
|
|||
} while (val != 1);
|
||||
lgw_reg_w(SX1302_REG_CAPTURE_RAM_CAPTURE_CFG_CAPTURESTART, 0);
|
||||
|
||||
|
||||
// lgw_reg_r(SX1302_REG_CAPTURE_RAM_LAST_RAM_ADDR_0_LASTRAMADDR, &val);
|
||||
// fprintf(stdout, "SX1302_REG_CAPTURE_RAM_LAST_RAM_ADDR_0_LASTRAMADDR value: %02x\n", val);
|
||||
// lgw_reg_r(SX1302_REG_CAPTURE_RAM_LAST_RAM_ADDR_1_LASTRAMADDR, &val);
|
||||
|
|
@ -316,54 +206,34 @@ int main(int argc, char **argv)
|
|||
lgw_reg_w(SX1302_REG_COMMON_PAGE_PAGE, 0);
|
||||
|
||||
printf("Data:\n");
|
||||
for (i = 0; i < CAPTURE_RAM_SIZE; i += 4)
|
||||
{
|
||||
if (((capture_source >= 2) && (capture_source <= 3)) || (capture_source == 9))
|
||||
{
|
||||
for (i = 0; i < CAPTURE_RAM_SIZE; i += 4) {
|
||||
if (((capture_source >= 2) && (capture_source <= 3)) || (capture_source == 9)) {
|
||||
real = (int16_t)((((uint16_t)(capture_ram_buffer[i+3]) << 8) & 0xFF00) + ((uint16_t)capture_ram_buffer[i+2] & 0x00FF));
|
||||
imag = (int16_t)((((uint16_t)(capture_ram_buffer[i+1]) << 8) & 0xFF00) + ((uint16_t)capture_ram_buffer[i+0] & 0x00FF));
|
||||
real >>= 4; // 12 bits I
|
||||
imag >>= 4; // 12 bits Q
|
||||
}
|
||||
else if ((capture_source >= 4) && (capture_source <= 6))
|
||||
{
|
||||
real = (int16_t)((((uint16_t)(capture_ram_buffer[i+3]) << 8) & 0xFF00) + ((uint16_t)capture_ram_buffer[i+2] & 0x00FF)); // 16 bits I
|
||||
imag = (int16_t)((((uint16_t)(capture_ram_buffer[i+1]) << 8) & 0xFF00) + ((uint16_t)capture_ram_buffer[i+0] & 0x00FF)); // 16 bits Q
|
||||
}
|
||||
else if ((capture_source >= 10) && (capture_source <= 17))
|
||||
{
|
||||
real = (int8_t)(capture_ram_buffer[i+3]); // 8 bits I
|
||||
imag = (int8_t)(capture_ram_buffer[i+1]); // 8 bits Q
|
||||
}
|
||||
else
|
||||
{
|
||||
real >>= 4; // 12 bits I
|
||||
imag >>= 4; // 12 bits Q
|
||||
} else if ((capture_source >= 4) && (capture_source <= 6)) {
|
||||
real = (int16_t)((((uint16_t)(capture_ram_buffer[i+3]) << 8) & 0xFF00) + ((uint16_t)capture_ram_buffer[i+2] & 0x00FF)); // 16 bits I
|
||||
imag = (int16_t)((((uint16_t)(capture_ram_buffer[i+1]) << 8) & 0xFF00) + ((uint16_t)capture_ram_buffer[i+0] & 0x00FF)); // 16 bits Q
|
||||
} else if ((capture_source >= 10) && (capture_source <= 17)) {
|
||||
real = (int8_t)(capture_ram_buffer[i+3]); // 8 bits I
|
||||
imag = (int8_t)(capture_ram_buffer[i+1]); // 8 bits Q
|
||||
} else {
|
||||
real = 0;
|
||||
imag = 0;
|
||||
}
|
||||
|
||||
if (((capture_source >= 2) && (capture_source <= 6)) || ((capture_source >= 9) && (capture_source <= 17)))
|
||||
{
|
||||
if (((capture_source >= 2) && (capture_source <= 6)) || ((capture_source >= 9) && (capture_source <= 17))) {
|
||||
fprintf(stdout, "%d", real);
|
||||
if (imag >= 0)
|
||||
{
|
||||
if (imag >= 0) {
|
||||
fprintf(stdout, "+");
|
||||
}
|
||||
fprintf(stdout, "%di\n", imag);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
printf("%02X ", capture_ram_buffer[i]);
|
||||
}
|
||||
}
|
||||
printf("End of Data\n");
|
||||
|
||||
#if FULL_INIT
|
||||
/* Board reset */
|
||||
if (system("./reset_lgw.sh stop") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
427
libloragw/tst/test_loragw_com.c
Normal file
427
libloragw/tst/test_loragw_com.c
Normal file
|
|
@ -0,0 +1,427 @@
|
|||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2019 Semtech
|
||||
|
||||
Description:
|
||||
Minimum test program for the loragw_com module
|
||||
|
||||
License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*/
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- DEPENDANCIES --------------------------------------------------------- */
|
||||
|
||||
/* Fix an issue between POSIX and C99 */
|
||||
#if __STDC_VERSION__ >= 199901L
|
||||
#define _XOPEN_SOURCE 600
|
||||
#else
|
||||
#define _XOPEN_SOURCE 500
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <signal.h> /* sigaction */
|
||||
#include <unistd.h> /* getopt, access */
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "loragw_com.h"
|
||||
#include "loragw_aux.h"
|
||||
#include "loragw_hal.h"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE MACROS ------------------------------------------------------- */
|
||||
|
||||
#define RAND_RANGE(min, max) (rand() % (max + 1 - min) + min)
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE CONSTANTS ---------------------------------------------------- */
|
||||
|
||||
#define BUFF_SIZE_SPI 1024
|
||||
#define BUFF_SIZE_USB 4096
|
||||
|
||||
#define SX1302_AGC_MCU_MEM 0x0000
|
||||
#define SX1302_REG_COMMON 0x5600
|
||||
#define SX1302_REG_AGC_MCU 0x5780
|
||||
|
||||
#define COM_TYPE_DEFAULT LGW_COM_SPI
|
||||
#define COM_PATH_DEFAULT "/dev/spidev0.0"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- GLOBAL VARIABLES ----------------------------------------------------- */
|
||||
|
||||
/* Signal handling variables */
|
||||
static int exit_sig = 0; /* 1 -> application terminates cleanly (shut down hardware, close open files, etc) */
|
||||
static int quit_sig = 0; /* 1 -> application terminates without shutting down the hardware */
|
||||
|
||||
/* Buffers */
|
||||
static uint8_t * test_buff = NULL;
|
||||
static uint8_t * read_buff = NULL;
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- SUBFUNCTIONS DECLARATION --------------------------------------------- */
|
||||
|
||||
static void sig_handler(int sigio);
|
||||
static void usage(void);
|
||||
static void exit_failure(void);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- MAIN FUNCTION -------------------------------------------------------- */
|
||||
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
static struct sigaction sigact; /* SIGQUIT&SIGINT&SIGTERM signal handling */
|
||||
|
||||
uint16_t max_buff_size;
|
||||
uint8_t data = 0;
|
||||
int cycle_number = 0;
|
||||
int i, x;
|
||||
uint16_t size;
|
||||
|
||||
/* COM interfaces */
|
||||
const char com_path_default[] = COM_PATH_DEFAULT;
|
||||
const char * com_path = com_path_default;
|
||||
lgw_com_type_t com_type = COM_TYPE_DEFAULT;
|
||||
|
||||
/* Parse command line options */
|
||||
while ((i = getopt(argc, argv, "hd:u")) != -1) {
|
||||
switch (i) {
|
||||
case 'h':
|
||||
usage();
|
||||
return EXIT_SUCCESS;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
if (optarg != NULL) {
|
||||
com_path = optarg;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
com_type = LGW_COM_USB;
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("ERROR: argument parsing options, use -h option for help\n");
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Configure signal handling */
|
||||
sigemptyset( &sigact.sa_mask );
|
||||
sigact.sa_flags = 0;
|
||||
sigact.sa_handler = sig_handler;
|
||||
sigaction( SIGQUIT, &sigact, NULL );
|
||||
sigaction( SIGINT, &sigact, NULL );
|
||||
sigaction( SIGTERM, &sigact, NULL );
|
||||
|
||||
/* Board reset */
|
||||
if (com_type == LGW_COM_SPI) {
|
||||
if (system("./reset_lgw.sh start") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
printf("Beginning of test for loragw_com.c\n");
|
||||
x = lgw_com_open(com_type, com_path);
|
||||
if (x != 0) {
|
||||
printf("ERROR: failed to open COM device %s\n", com_path);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* normal R/W test */
|
||||
/* TODO */
|
||||
|
||||
/* burst R/W test, small bursts << LGW_BURST_CHUNK */
|
||||
/* TODO */
|
||||
|
||||
/* burst R/W test, large bursts >> LGW_BURST_CHUNK */
|
||||
/* TODO */
|
||||
|
||||
x = lgw_com_r(LGW_SPI_MUX_TARGET_SX1302, SX1302_REG_COMMON + 6, &data);
|
||||
if (x != 0) {
|
||||
printf("ERROR (%d): failed to read register\n", __LINE__);
|
||||
exit_failure();
|
||||
}
|
||||
printf("SX1302 version: 0x%02X\n", data);
|
||||
|
||||
x = lgw_com_r(LGW_SPI_MUX_TARGET_SX1302, SX1302_REG_AGC_MCU + 0, &data);
|
||||
if (x != 0) {
|
||||
printf("ERROR (%d): failed to read register\n", __LINE__);
|
||||
exit_failure();
|
||||
}
|
||||
x = lgw_com_w(LGW_SPI_MUX_TARGET_SX1302, SX1302_REG_AGC_MCU + 0, 0x06); /* mcu_clear, host_prog */
|
||||
if (x != 0) {
|
||||
printf("ERROR (%d): failed to write register\n", __LINE__);
|
||||
exit_failure();
|
||||
}
|
||||
|
||||
srand(time(NULL));
|
||||
|
||||
/* Allocate buffers according to com type capabilities */
|
||||
max_buff_size = (com_type == LGW_COM_SPI) ? BUFF_SIZE_SPI : BUFF_SIZE_USB;
|
||||
test_buff = (uint8_t*)malloc(max_buff_size * sizeof(uint8_t));
|
||||
if (test_buff == NULL) {
|
||||
printf("ERROR: failed to allocate memory for test_buff - %s\n", strerror(errno));
|
||||
exit_failure();
|
||||
}
|
||||
read_buff = (uint8_t*)malloc(max_buff_size * sizeof(uint8_t));
|
||||
if (read_buff == NULL) {
|
||||
printf("ERROR: failed to allocate memory for read_buff - %s\n", strerror(errno));
|
||||
exit_failure();
|
||||
}
|
||||
|
||||
/* databuffer R/W stress test */
|
||||
while ((quit_sig != 1) && (exit_sig != 1)) {
|
||||
/*************************************************
|
||||
*
|
||||
* WRITE BURST TEST
|
||||
*
|
||||
* ***********************************************/
|
||||
|
||||
size = rand() % max_buff_size;
|
||||
for (i = 0; i < size; ++i) {
|
||||
test_buff[i] = rand() & 0xFF;
|
||||
}
|
||||
printf("Cycle %i> ", cycle_number);
|
||||
|
||||
/* Write burst with random data */
|
||||
x = lgw_com_wb(LGW_SPI_MUX_TARGET_SX1302, SX1302_AGC_MCU_MEM, test_buff, size);
|
||||
if (x != 0) {
|
||||
printf("ERROR (%d): failed to write burst\n", __LINE__);
|
||||
exit_failure();
|
||||
}
|
||||
|
||||
/* Read back */
|
||||
x = lgw_com_rb(LGW_SPI_MUX_TARGET_SX1302, SX1302_AGC_MCU_MEM, read_buff, size);
|
||||
if (x != 0) {
|
||||
printf("ERROR (%d): failed to read burst\n", __LINE__);
|
||||
exit_failure();
|
||||
}
|
||||
|
||||
/* Compare read / write buffers */
|
||||
for (i=0; ((i<size) && (test_buff[i] == read_buff[i])); ++i);
|
||||
if (i != size) {
|
||||
printf("error during the buffer comparison\n");
|
||||
|
||||
/* Print what has been written */
|
||||
printf("Written values:\n");
|
||||
for (i=0; i<size; ++i) {
|
||||
printf(" %02X ", test_buff[i]);
|
||||
if (i%16 == 15) printf("\n");
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
/* Print what has been read back */
|
||||
printf("Read values:\n");
|
||||
for (i=0; i<size; ++i) {
|
||||
printf(" %02X ", read_buff[i]);
|
||||
if (i%16 == 15) printf("\n");
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
/* exit */
|
||||
exit_failure();
|
||||
} else {
|
||||
printf("did a %i-byte R/W on a data buffer with no error\n", size);
|
||||
++cycle_number;
|
||||
}
|
||||
|
||||
/*************************************************
|
||||
*
|
||||
* WRITE SINGLE BYTE TEST
|
||||
*
|
||||
* ***********************************************/
|
||||
|
||||
/* Single byte r/w test */
|
||||
printf("Cycle %i> ", cycle_number);
|
||||
|
||||
test_buff[0] = rand() & 0xFF;
|
||||
|
||||
/* Write single byte */
|
||||
x = lgw_com_w(LGW_SPI_MUX_TARGET_SX1302, SX1302_AGC_MCU_MEM, test_buff[0]);
|
||||
if (x != 0) {
|
||||
printf("ERROR (%d): failed to write burst\n", __LINE__);
|
||||
exit_failure();
|
||||
}
|
||||
|
||||
/* Read back */
|
||||
x = lgw_com_r(LGW_SPI_MUX_TARGET_SX1302, SX1302_AGC_MCU_MEM, &read_buff[0]);
|
||||
if (x != 0) {
|
||||
printf("ERROR (%d): failed to read burst\n", __LINE__);
|
||||
exit_failure();
|
||||
}
|
||||
|
||||
/* Compare read / write bytes */
|
||||
if (test_buff[0] != read_buff[0]) {
|
||||
printf("error during the byte comparison\n");
|
||||
|
||||
/* Print what has been written */
|
||||
printf("Written value: %02X\n", test_buff[0]);
|
||||
|
||||
/* Print what has been read back */
|
||||
printf("Read values: %02X\n", read_buff[0]);
|
||||
|
||||
/* exit */
|
||||
exit_failure();
|
||||
} else {
|
||||
printf("did a 1-byte R/W on a data buffer with no error\n");
|
||||
++cycle_number;
|
||||
}
|
||||
|
||||
/*************************************************
|
||||
*
|
||||
* WRITE WITH BULK (USB only mode)
|
||||
*
|
||||
* ***********************************************/
|
||||
x = lgw_com_set_write_mode(LGW_COM_WRITE_MODE_BULK);
|
||||
if (x != 0) {
|
||||
printf("ERROR (%d): failed to set bulk write mode\n", __LINE__);
|
||||
exit_failure();
|
||||
}
|
||||
|
||||
uint16_t num_req = RAND_RANGE(1, 254); /* keep one req for remaining bytes */
|
||||
size = RAND_RANGE(num_req, max_buff_size / 2); /* TODO: test proper limit */
|
||||
for (i = 0; i < size; i++) {
|
||||
test_buff[i] = rand() & 0xFF;
|
||||
}
|
||||
uint16_t size_per_req = size / num_req;
|
||||
uint16_t size_remaining = size - (num_req * size_per_req);
|
||||
printf("Cycle %i> ", cycle_number);
|
||||
|
||||
uint16_t size_written = 0;
|
||||
for (i = 0; i < num_req; i++) {
|
||||
x = lgw_com_wb(LGW_SPI_MUX_TARGET_SX1302, SX1302_AGC_MCU_MEM + size_written, test_buff + size_written, size_per_req);
|
||||
if (x != 0) {
|
||||
printf("ERROR (%d): failed to write burst\n", __LINE__);
|
||||
exit_failure();
|
||||
}
|
||||
size_written += (size_per_req);
|
||||
}
|
||||
if (size_remaining > 0) {
|
||||
x = lgw_com_wb(LGW_SPI_MUX_TARGET_SX1302, SX1302_AGC_MCU_MEM + size_written, test_buff + size_written, size_remaining);
|
||||
if (x != 0) {
|
||||
printf("ERROR (%d): failed to write burst\n", __LINE__);
|
||||
exit_failure();
|
||||
}
|
||||
}
|
||||
|
||||
/* Send data to MCU (UBS mode only) */
|
||||
x = lgw_com_flush();
|
||||
if (x != 0) {
|
||||
printf("ERROR (%d): failed to flush write\n", __LINE__);
|
||||
exit_failure();
|
||||
}
|
||||
|
||||
/* Read back */
|
||||
x = lgw_com_rb(LGW_SPI_MUX_TARGET_SX1302, SX1302_AGC_MCU_MEM, read_buff, size);
|
||||
if (x != 0) {
|
||||
printf("ERROR (%d): failed to read burst\n", __LINE__);
|
||||
exit_failure();
|
||||
}
|
||||
|
||||
/* Compare read / write buffers */
|
||||
for (i=0; ((i<size) && (test_buff[i] == read_buff[i])); ++i);
|
||||
if (i != size) {
|
||||
printf("error during the buffer comparison\n");
|
||||
|
||||
/* Print what has been written */
|
||||
printf("Written values:\n");
|
||||
for (i=0; i<size; ++i) {
|
||||
printf(" %02X ", test_buff[i]);
|
||||
if (i%16 == 15) printf("\n");
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
/* Print what has been read back */
|
||||
printf("Read values:\n");
|
||||
for (i=0; i<size; ++i) {
|
||||
printf(" %02X ", read_buff[i]);
|
||||
if (i%16 == 15) printf("\n");
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
/* exit */
|
||||
exit_failure();
|
||||
} else {
|
||||
printf("did a %i-byte bulk R/W on a data buffer with no error\n", size);
|
||||
++cycle_number;
|
||||
}
|
||||
}
|
||||
|
||||
lgw_com_close();
|
||||
printf("End of test for loragw_com.c\n");
|
||||
|
||||
/* deallocate buffers */
|
||||
if (test_buff != NULL) {
|
||||
free(test_buff);
|
||||
test_buff = NULL;
|
||||
}
|
||||
if (read_buff != NULL) {
|
||||
free(read_buff);
|
||||
read_buff = NULL;
|
||||
}
|
||||
|
||||
if (com_type == LGW_COM_SPI) {
|
||||
/* Board reset */
|
||||
if (system("./reset_lgw.sh stop") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- SUBFUNCTIONS DEFINITION ---------------------------------------------- */
|
||||
|
||||
static void sig_handler(int sigio) {
|
||||
if (sigio == SIGQUIT) {
|
||||
quit_sig = 1;
|
||||
} else if((sigio == SIGINT) || (sigio == SIGTERM)) {
|
||||
exit_sig = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
static void exit_failure(void) {
|
||||
lgw_com_close();
|
||||
printf("End of test for loragw_com.c\n");
|
||||
|
||||
/* deallocate buffers */
|
||||
if (test_buff != NULL) {
|
||||
free(test_buff);
|
||||
test_buff = NULL;
|
||||
}
|
||||
if (read_buff != NULL) {
|
||||
free(read_buff);
|
||||
read_buff = NULL;
|
||||
}
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
static void usage(void) {
|
||||
printf("~~~ Library version string~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
|
||||
printf(" %s\n", lgw_version_info());
|
||||
printf("~~~ Available options ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
|
||||
printf(" -h print this help\n");
|
||||
printf(" -u set COM type as USB (default is SPI)\n");
|
||||
printf(" -d <path> COM path to be used to connect the concentrator\n");
|
||||
printf(" => default path (SPI): " COM_PATH_DEFAULT "\n");
|
||||
}
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
||||
|
|
@ -7,7 +7,7 @@
|
|||
(C)2019 Semtech
|
||||
|
||||
Description:
|
||||
Minimum test program for the sx1250 module
|
||||
Minimum test program for the sx1250_com module
|
||||
|
||||
License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*/
|
||||
|
|
@ -30,8 +30,8 @@ License: Revised BSD License, see LICENSE.TXT file include in the project
|
|||
#include <signal.h> /* sigaction */
|
||||
#include <unistd.h> /* getopt, access */
|
||||
|
||||
#include "loragw_spi.h"
|
||||
#include "loragw_aux.h"
|
||||
#include "loragw_com.h"
|
||||
#include "loragw_reg.h"
|
||||
#include "loragw_hal.h"
|
||||
#include "loragw_sx1250.h"
|
||||
|
|
@ -45,7 +45,8 @@ License: Revised BSD License, see LICENSE.TXT file include in the project
|
|||
|
||||
#define BUFF_SIZE 16
|
||||
|
||||
#define LINUXDEV_PATH_DEFAULT "/dev/spidev0.0"
|
||||
#define COM_TYPE_DEFAULT LGW_COM_SPI
|
||||
#define COM_PATH_DEFAULT "/dev/spidev0.0"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- GLOBAL VARIABLES ----------------------------------------------------- */
|
||||
|
|
@ -59,6 +60,7 @@ static int quit_sig = 0; /* 1 -> application terminates without shutting down th
|
|||
|
||||
static void sig_handler(int sigio);
|
||||
static void usage(void);
|
||||
static void exit_failure();
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- MAIN FUNCTION -------------------------------------------------------- */
|
||||
|
|
@ -73,12 +75,13 @@ int main(int argc, char ** argv)
|
|||
int cycle_number = 0;
|
||||
int i, x;
|
||||
|
||||
/* SPI interfaces */
|
||||
const char spidev_path_default[] = LINUXDEV_PATH_DEFAULT;
|
||||
const char * spidev_path = spidev_path_default;
|
||||
/* COM interfaces */
|
||||
const char com_path_default[] = COM_PATH_DEFAULT;
|
||||
const char * com_path = com_path_default;
|
||||
lgw_com_type_t com_type = COM_TYPE_DEFAULT;
|
||||
|
||||
/* Parse command line options */
|
||||
while ((i = getopt(argc, argv, "hd:")) != -1) {
|
||||
while ((i = getopt(argc, argv, "hd:u")) != -1) {
|
||||
switch (i) {
|
||||
case 'h':
|
||||
usage();
|
||||
|
|
@ -87,10 +90,14 @@ int main(int argc, char ** argv)
|
|||
|
||||
case 'd':
|
||||
if (optarg != NULL) {
|
||||
spidev_path = optarg;
|
||||
com_path = optarg;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
com_type = LGW_COM_USB;
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("ERROR: argument parsing options, use -h option for help\n");
|
||||
usage();
|
||||
|
|
@ -106,15 +113,18 @@ int main(int argc, char ** argv)
|
|||
sigaction( SIGINT, &sigact, NULL );
|
||||
sigaction( SIGTERM, &sigact, NULL );
|
||||
|
||||
|
||||
/* Board reset */
|
||||
if (system("./reset_lgw.sh start") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
if (com_type == LGW_COM_SPI) {
|
||||
if (system("./reset_lgw.sh start") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
x = lgw_connect(spidev_path);
|
||||
x = lgw_connect(com_type, com_path);
|
||||
if (x != LGW_REG_SUCCESS) {
|
||||
printf("ERROR: Failed to connect to the concentrator using SPI %s\n", spidev_path);
|
||||
printf("ERROR: Failed to connect to the concentrator using COM %s\n", com_path);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
|
|
@ -137,14 +147,30 @@ int main(int argc, char ** argv)
|
|||
|
||||
/* Set Radio in Standby mode */
|
||||
test_buff[0] = (uint8_t)STDBY_XOSC;
|
||||
sx1250_write_command(0, SET_STANDBY, test_buff, 1);
|
||||
sx1250_write_command(1, SET_STANDBY, test_buff, 1);
|
||||
x = sx1250_reg_w(SET_STANDBY, test_buff, 1, 0);
|
||||
if (x != LGW_REG_SUCCESS) {
|
||||
printf("ERROR(%d): Failed to configure sx1250_0\n", __LINE__);
|
||||
exit_failure();
|
||||
}
|
||||
x = sx1250_reg_w(SET_STANDBY, test_buff, 1, 1);
|
||||
if (x != LGW_REG_SUCCESS) {
|
||||
printf("ERROR(%d): Failed to configure sx1250_1\n", __LINE__);
|
||||
exit_failure();
|
||||
}
|
||||
wait_ms(10);
|
||||
|
||||
test_buff[0] = 0x00;
|
||||
sx1250_read_command(0, GET_STATUS, test_buff, 1);
|
||||
x = sx1250_reg_r(GET_STATUS, test_buff, 1, 0);
|
||||
if (x != LGW_REG_SUCCESS) {
|
||||
printf("ERROR(%d): Failed to get sx1250_0 status\n", __LINE__);
|
||||
exit_failure();
|
||||
}
|
||||
printf("Radio0: get_status: 0x%02X\n", test_buff[0]);
|
||||
sx1250_read_command(1, GET_STATUS, test_buff, 1);
|
||||
x = sx1250_reg_r(GET_STATUS, test_buff, 1, 1);
|
||||
if (x != LGW_REG_SUCCESS) {
|
||||
printf("ERROR(%d): Failed to get sx1250_1 status\n", __LINE__);
|
||||
exit_failure();
|
||||
}
|
||||
printf("Radio1: get_status: 0x%02X\n", test_buff[0]);
|
||||
|
||||
/* databuffer R/W stress test */
|
||||
|
|
@ -154,7 +180,7 @@ int main(int argc, char ** argv)
|
|||
test_buff[2] = rand() & 0xFF;
|
||||
test_buff[3] = rand() & 0xFF;
|
||||
test_val = (test_buff[0] << 24) | (test_buff[1] << 16) | (test_buff[2] << 8) | (test_buff[3] << 0);
|
||||
sx1250_write_command(0, SET_RF_FREQUENCY, test_buff, 4);
|
||||
sx1250_reg_w(SET_RF_FREQUENCY, test_buff, 4, 0);
|
||||
|
||||
read_buff[0] = 0x08;
|
||||
read_buff[1] = 0x8B;
|
||||
|
|
@ -163,7 +189,7 @@ int main(int argc, char ** argv)
|
|||
read_buff[4] = 0x00;
|
||||
read_buff[5] = 0x00;
|
||||
read_buff[6] = 0x00;
|
||||
sx1250_read_command(0, READ_REGISTER, read_buff, 7);
|
||||
sx1250_reg_r(READ_REGISTER, read_buff, 7, 0);
|
||||
read_val = (read_buff[3] << 24) | (read_buff[4] << 16) | (read_buff[5] << 8) | (read_buff[6] << 0);
|
||||
|
||||
printf("Cycle %i > ", cycle_number);
|
||||
|
|
@ -182,10 +208,12 @@ int main(int argc, char ** argv)
|
|||
lgw_disconnect();
|
||||
printf("End of test for loragw_spi_sx1250.c\n");
|
||||
|
||||
/* Board reset */
|
||||
if (system("./reset_lgw.sh stop") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
if (com_type == LGW_COM_SPI) {
|
||||
/* Board reset */
|
||||
if (system("./reset_lgw.sh stop") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -204,13 +232,24 @@ static void sig_handler(int sigio) {
|
|||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
static void exit_failure() {
|
||||
lgw_disconnect();
|
||||
|
||||
printf("End of test for loragw_spi_sx1250.c\n");
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
static void usage(void) {
|
||||
printf("~~~ Library version string~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
|
||||
printf(" %s\n", lgw_version_info());
|
||||
printf("~~~ Available options ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
|
||||
printf(" -h print this help\n");
|
||||
printf(" -d <path> use Linux SPI device driver\n");
|
||||
printf(" => default path: " LINUXDEV_PATH_DEFAULT "\n");
|
||||
printf(" -d <path> path of the COM device used to access the concentrator\n");
|
||||
printf(" => default path: " COM_PATH_DEFAULT "\n");
|
||||
printf(" -u set COM type as USB (default is SPI)\n");
|
||||
}
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
||||
|
|
@ -7,7 +7,7 @@
|
|||
(C)2019 Semtech
|
||||
|
||||
Description:
|
||||
Minimum test program for the loragw_spi module
|
||||
Minimum test program for the sx1261_com module
|
||||
|
||||
License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*/
|
||||
|
|
@ -29,11 +29,12 @@ License: Revised BSD License, see LICENSE.TXT file include in the project
|
|||
#include <string.h>
|
||||
#include <signal.h> /* sigaction */
|
||||
#include <unistd.h> /* getopt, access */
|
||||
#include <time.h>
|
||||
|
||||
#include "loragw_spi.h"
|
||||
#include "loragw_aux.h"
|
||||
#include "loragw_hal.h"
|
||||
#include "loragw_reg.h"
|
||||
#include "loragw_com.h"
|
||||
#include "loragw_sx1261.h"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE MACROS ------------------------------------------------------- */
|
||||
|
|
@ -41,13 +42,11 @@ License: Revised BSD License, see LICENSE.TXT file include in the project
|
|||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE CONSTANTS ---------------------------------------------------- */
|
||||
|
||||
#define BUFF_SIZE 1024
|
||||
#define BUFF_SIZE 16
|
||||
|
||||
#define SX1302_AGC_MCU_MEM 0x0000
|
||||
#define SX1302_REG_COMMON 0x5600
|
||||
#define SX1302_REG_AGC_MCU 0x5780
|
||||
|
||||
#define LINUXDEV_PATH_DEFAULT "/dev/spidev0.0"
|
||||
#define COM_TYPE_DEFAULT LGW_COM_SPI
|
||||
#define COM_PATH_DEFAULT "/dev/spidev0.0"
|
||||
#define SX1261_PATH_DEFAULT "/dev/spidev0.1"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- GLOBAL VARIABLES ----------------------------------------------------- */
|
||||
|
|
@ -61,6 +60,7 @@ static int quit_sig = 0; /* 1 -> application terminates without shutting down th
|
|||
|
||||
static void sig_handler(int sigio);
|
||||
static void usage(void);
|
||||
static void exit_failure();
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- MAIN FUNCTION -------------------------------------------------------- */
|
||||
|
|
@ -69,20 +69,19 @@ int main(int argc, char ** argv)
|
|||
{
|
||||
static struct sigaction sigact; /* SIGQUIT&SIGINT&SIGTERM signal handling */
|
||||
|
||||
uint8_t data = 0;
|
||||
uint8_t test_buff[BUFF_SIZE];
|
||||
uint8_t read_buff[BUFF_SIZE];
|
||||
uint32_t test_val, read_val;
|
||||
int cycle_number = 0;
|
||||
int i;
|
||||
uint16_t size;
|
||||
int i, x;
|
||||
|
||||
/* SPI interfaces */
|
||||
const char spidev_path_default[] = LINUXDEV_PATH_DEFAULT;
|
||||
const char * spidev_path = spidev_path_default;
|
||||
void *spi_target = NULL;
|
||||
/* COM interfaces */
|
||||
const char com_path_default[] = COM_PATH_DEFAULT;
|
||||
const char * com_path = com_path_default;
|
||||
lgw_com_type_t com_type = COM_TYPE_DEFAULT;
|
||||
|
||||
/* Parse command line options */
|
||||
while ((i = getopt(argc, argv, "hd:")) != -1) {
|
||||
while ((i = getopt(argc, argv, "hd:u")) != -1) {
|
||||
switch (i) {
|
||||
case 'h':
|
||||
usage();
|
||||
|
|
@ -91,10 +90,14 @@ int main(int argc, char ** argv)
|
|||
|
||||
case 'd':
|
||||
if (optarg != NULL) {
|
||||
spidev_path = optarg;
|
||||
com_path = optarg;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
com_type = LGW_COM_USB;
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("ERROR: argument parsing options, use -h option for help\n");
|
||||
usage();
|
||||
|
|
@ -110,74 +113,91 @@ int main(int argc, char ** argv)
|
|||
sigaction( SIGINT, &sigact, NULL );
|
||||
sigaction( SIGTERM, &sigact, NULL );
|
||||
|
||||
|
||||
/* Board reset */
|
||||
if (system("./reset_lgw.sh start") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
if (com_type == LGW_COM_SPI) {
|
||||
if (system("./reset_lgw.sh start") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
printf("Beginning of test for loragw_spi.c\n");
|
||||
i = lgw_spi_open(spidev_path, &spi_target);
|
||||
if (i != 0) {
|
||||
printf("ERROR: failed to open SPI device %s\n", spidev_path);
|
||||
return -1;
|
||||
/* Connect to the concentrator board */
|
||||
x = lgw_connect(com_type, com_path);
|
||||
if (x != LGW_REG_SUCCESS) {
|
||||
printf("ERROR: Failed to connect to the concentrator using COM %s\n", com_path);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* normal R/W test */
|
||||
/* TODO */
|
||||
/* Connect to the sx1261 radio */
|
||||
x = sx1261_connect(com_type, SX1261_PATH_DEFAULT);
|
||||
if (x != LGW_REG_SUCCESS) {
|
||||
printf("ERROR: Failed to connect to the sx1261 using COM %s\n", com_path);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* burst R/W test, small bursts << LGW_BURST_CHUNK */
|
||||
/* TODO */
|
||||
/* Set Radio in Standby mode */
|
||||
test_buff[0] = (uint8_t)SX1261_STDBY_RC;
|
||||
x = sx1261_reg_w(SX1261_SET_STANDBY, test_buff, 1);
|
||||
if (x != LGW_REG_SUCCESS) {
|
||||
printf("ERROR(%d): Failed to configure sx1261\n", __LINE__);
|
||||
exit_failure();
|
||||
}
|
||||
wait_ms(10);
|
||||
|
||||
/* burst R/W test, large bursts >> LGW_BURST_CHUNK */
|
||||
/* TODO */
|
||||
|
||||
lgw_spi_r(spi_target, LGW_SPI_MUX_TARGET_SX1302, SX1302_REG_COMMON + 6, &data);
|
||||
printf("SX1302 version: 0x%02X\n", data);
|
||||
|
||||
lgw_spi_r(spi_target, LGW_SPI_MUX_TARGET_SX1302, SX1302_REG_AGC_MCU + 0, &data);
|
||||
lgw_spi_w(spi_target, LGW_SPI_MUX_TARGET_SX1302, SX1302_REG_AGC_MCU + 0, 0x06); /* mcu_clear, host_prog */
|
||||
|
||||
srand(time(NULL));
|
||||
test_buff[0] = 0x00;
|
||||
x = sx1261_reg_r(SX1261_GET_STATUS, test_buff, 1);
|
||||
if (x != LGW_REG_SUCCESS) {
|
||||
printf("ERROR(%d): Failed to get sx1261 status\n", __LINE__);
|
||||
exit_failure();
|
||||
}
|
||||
printf("SX1261: get_status: 0x%02X\n", test_buff[0]);
|
||||
|
||||
/* databuffer R/W stress test */
|
||||
while ((quit_sig != 1) && (exit_sig != 1)) {
|
||||
size = rand() % BUFF_SIZE;
|
||||
for (i = 0; i < size; ++i) {
|
||||
test_buff[i] = rand() & 0xFF;
|
||||
}
|
||||
test_buff[0] = rand() & 0x7F;
|
||||
test_buff[1] = rand() & 0xFF;
|
||||
test_buff[2] = rand() & 0xFF;
|
||||
test_buff[3] = rand() & 0xFF;
|
||||
test_val = (test_buff[0] << 24) | (test_buff[1] << 16) | (test_buff[2] << 8) | (test_buff[3] << 0);
|
||||
sx1261_reg_w(SX1261_SET_RF_FREQUENCY, test_buff, 4);
|
||||
|
||||
read_buff[0] = 0x08;
|
||||
read_buff[1] = 0x8B;
|
||||
read_buff[2] = 0x00;
|
||||
read_buff[3] = 0x00;
|
||||
read_buff[4] = 0x00;
|
||||
read_buff[5] = 0x00;
|
||||
read_buff[6] = 0x00;
|
||||
sx1261_reg_r(SX1261_READ_REGISTER, read_buff, 7);
|
||||
read_val = (read_buff[3] << 24) | (read_buff[4] << 16) | (read_buff[5] << 8) | (read_buff[6] << 0);
|
||||
|
||||
printf("Cycle %i > ", cycle_number);
|
||||
lgw_spi_wb(spi_target, LGW_SPI_MUX_TARGET_SX1302, SX1302_AGC_MCU_MEM, test_buff, size);
|
||||
lgw_spi_rb(spi_target, LGW_SPI_MUX_TARGET_SX1302, SX1302_AGC_MCU_MEM, read_buff, size);
|
||||
for (i=0; ((i<size) && (test_buff[i] == read_buff[i])); ++i);
|
||||
if (i != size) {
|
||||
if (read_val != test_val) {
|
||||
printf("error during the buffer comparison\n");
|
||||
printf("Written values:\n");
|
||||
for (i=0; i<size; ++i) {
|
||||
printf(" %02X ", test_buff[i]);
|
||||
if (i%16 == 15) printf("\n");
|
||||
}
|
||||
printf("\n");
|
||||
printf("Read values:\n");
|
||||
for (i=0; i<size; ++i) {
|
||||
printf(" %02X ", read_buff[i]);
|
||||
if (i%16 == 15) printf("\n");
|
||||
}
|
||||
printf("\n");
|
||||
printf("Written value: %08X\n", test_val);
|
||||
printf("Read value: %08X\n", read_val);
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
printf("did a %i-byte R/W on a data buffer with no error\n", size);
|
||||
printf("did a %i-byte R/W on a register with no error\n", 4);
|
||||
++cycle_number;
|
||||
}
|
||||
}
|
||||
|
||||
lgw_spi_close(spi_target);
|
||||
printf("End of test for loragw_spi.c\n");
|
||||
/* Disconnect from the sx1261 radio */
|
||||
sx1261_disconnect();
|
||||
|
||||
/* Board reset */
|
||||
if (system("./reset_lgw.sh stop") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
/* Disconnect from the concentrator board */
|
||||
lgw_disconnect();
|
||||
|
||||
printf("End of test for loragw_spi_sx1261.c\n");
|
||||
|
||||
if (com_type == LGW_COM_SPI) {
|
||||
/* Board reset */
|
||||
if (system("./reset_lgw.sh stop") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -196,13 +216,25 @@ static void sig_handler(int sigio) {
|
|||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
static void exit_failure() {
|
||||
sx1261_disconnect();
|
||||
lgw_disconnect();
|
||||
|
||||
printf("End of test for loragw_spi_sx1261.c\n");
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
static void usage(void) {
|
||||
printf("~~~ Library version string~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
|
||||
printf(" %s\n", lgw_version_info());
|
||||
printf("~~~ Available options ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
|
||||
printf(" -h print this help\n");
|
||||
printf(" -d <path> use Linux SPI device driver\n");
|
||||
printf(" => default path: " LINUXDEV_PATH_DEFAULT "\n");
|
||||
printf(" -d <path> path to access the COM device\n");
|
||||
printf(" => default path: " COM_PATH_DEFAULT "\n");
|
||||
printf(" -u set COM type as USB (default is SPI)\n");
|
||||
}
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
||||
|
|
@ -38,7 +38,8 @@ License: Revised BSD License, see LICENSE.TXT file include in the project
|
|||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE MACROS ------------------------------------------------------- */
|
||||
|
||||
#define LINUXDEV_PATH_DEFAULT "/dev/spidev0.0"
|
||||
#define COM_TYPE_DEFAULT LGW_COM_SPI
|
||||
#define COM_PATH_DEFAULT "/dev/spidev0.0"
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
|
||||
#define RAND_RANGE(min, max) (rand() % (max + 1 - min) + min)
|
||||
|
|
@ -67,11 +68,14 @@ static void sig_handler(int sigio) {
|
|||
|
||||
void usage(void) {
|
||||
//printf("Library version information: %s\n", lgw_version_info());
|
||||
printf( "Available options:\n");
|
||||
printf( " -h print this help\n");
|
||||
printf( " -k <uint> Concentrator clock source (Radio A or Radio B) [0..1]\n");
|
||||
printf( " -r <uint> Radio type (1255, 1257, 1250)\n");
|
||||
printf( " -p Test PPS trig counter when set\n" );
|
||||
printf("Available options:\n");
|
||||
printf(" -h print this help\n");
|
||||
printf(" -u set COM type as USB (default is SPI)\n");
|
||||
printf(" -d <path> COM path to be used to connect the concentrator\n");
|
||||
printf(" => default path (SPI): " COM_PATH_DEFAULT "\n");
|
||||
printf(" -k <uint> Concentrator clock source (Radio A or Radio B) [0..1]\n");
|
||||
printf(" -r <uint> Radio type (1255, 1257, 1250)\n");
|
||||
printf(" -p Test PPS trig counter when set\n" );
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
|
@ -80,8 +84,9 @@ void usage(void) {
|
|||
int main(int argc, char **argv)
|
||||
{
|
||||
/* SPI interfaces */
|
||||
const char spidev_path_default[] = LINUXDEV_PATH_DEFAULT;
|
||||
const char * spidev_path = spidev_path_default;
|
||||
const char com_path_default[] = COM_PATH_DEFAULT;
|
||||
const char * com_path = com_path_default;
|
||||
lgw_com_type_t com_type = COM_TYPE_DEFAULT;
|
||||
|
||||
struct sigaction sigact; /* SIGQUIT&SIGINT&SIGTERM signal handling */
|
||||
|
||||
|
|
@ -90,7 +95,7 @@ int main(int argc, char **argv)
|
|||
uint32_t fb = DEFAULT_FREQ_HZ;
|
||||
unsigned int arg_u;
|
||||
uint8_t clocksource = 0;
|
||||
lgw_radio_type_t radio_type = LGW_RADIO_TYPE_NONE;
|
||||
lgw_radio_type_t radio_type = LGW_RADIO_TYPE_SX1250;
|
||||
|
||||
struct lgw_conf_board_s boardconf;
|
||||
struct lgw_conf_rxrf_s rfconf;
|
||||
|
|
@ -114,12 +119,17 @@ int main(int argc, char **argv)
|
|||
const uint8_t channel_rfchain[9] = { 1, 1, 1, 0, 0, 0, 0, 0, 1 };
|
||||
|
||||
/* parse command line options */
|
||||
while ((i = getopt (argc, argv, "hk:r:p")) != -1) {
|
||||
while ((i = getopt (argc, argv, "hk:r:pd:u")) != -1) {
|
||||
switch (i) {
|
||||
case 'h':
|
||||
usage();
|
||||
return -1;
|
||||
break;
|
||||
case 'd':
|
||||
if (optarg != NULL) {
|
||||
com_path = optarg;
|
||||
}
|
||||
break;
|
||||
case 'r': /* <uint> Radio type */
|
||||
i = sscanf(optarg, "%u", &arg_u);
|
||||
if ((i != 1) || ((arg_u != 1255) && (arg_u != 1257) && (arg_u != 1250))) {
|
||||
|
|
@ -151,6 +161,9 @@ int main(int argc, char **argv)
|
|||
case 'p':
|
||||
trig_cnt = true;
|
||||
break;
|
||||
case 'u':
|
||||
com_type = LGW_COM_USB;
|
||||
break;
|
||||
default:
|
||||
printf("ERROR: argument parsing\n");
|
||||
usage();
|
||||
|
|
@ -168,26 +181,29 @@ int main(int argc, char **argv)
|
|||
|
||||
printf("===== sx1302 counter test =====\n");
|
||||
|
||||
/* Board reset */
|
||||
if (system("./reset_lgw.sh start") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
if (com_type == LGW_COM_SPI) {
|
||||
/* Board reset */
|
||||
if (system("./reset_lgw.sh start") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Configure the gateway */
|
||||
memset( &boardconf, 0, sizeof boardconf);
|
||||
memset(&boardconf, 0, sizeof boardconf);
|
||||
boardconf.lorawan_public = true;
|
||||
boardconf.clksrc = clocksource;
|
||||
boardconf.full_duplex = false;
|
||||
strncpy(boardconf.spidev_path, spidev_path, sizeof boardconf.spidev_path);
|
||||
boardconf.spidev_path[sizeof boardconf.spidev_path - 1] = '\0'; /* ensure string termination */
|
||||
boardconf.com_type = com_type;
|
||||
strncpy(boardconf.com_path, com_path, sizeof boardconf.com_path);
|
||||
boardconf.com_path[sizeof boardconf.com_path - 1] = '\0'; /* ensure string termination */
|
||||
if (lgw_board_setconf(&boardconf) != LGW_HAL_SUCCESS) {
|
||||
printf("ERROR: failed to configure board\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* set configuration for RF chains */
|
||||
memset( &rfconf, 0, sizeof rfconf);
|
||||
memset(&rfconf, 0, sizeof rfconf);
|
||||
rfconf.enable = true;
|
||||
rfconf.freq_hz = fa;
|
||||
rfconf.type = radio_type;
|
||||
|
|
@ -198,7 +214,7 @@ int main(int argc, char **argv)
|
|||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
memset( &rfconf, 0, sizeof rfconf);
|
||||
memset(&rfconf, 0, sizeof rfconf);
|
||||
rfconf.enable = true;
|
||||
rfconf.freq_hz = fb;
|
||||
rfconf.type = radio_type;
|
||||
|
|
@ -247,10 +263,12 @@ int main(int argc, char **argv)
|
|||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* Board reset */
|
||||
if (system("./reset_lgw.sh stop") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
if (com_type == LGW_COM_SPI) {
|
||||
/* Board reset */
|
||||
if (system("./reset_lgw.sh stop") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
printf("=========== Test End ===========\n");
|
||||
|
|
|
|||
|
|
@ -43,7 +43,8 @@ License: Revised BSD License, see LICENSE.TXT file include in the project
|
|||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE CONSTANTS ---------------------------------------------------- */
|
||||
|
||||
#define LINUXDEV_PATH_DEFAULT "/dev/spidev0.0"
|
||||
#define COM_TYPE_DEFAULT LGW_COM_SPI
|
||||
#define COM_PATH_DEFAULT "/dev/spidev0.0"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE VARIABLES ---------------------------------------------------- */
|
||||
|
|
@ -65,10 +66,13 @@ static void gps_process_coords(void);
|
|||
|
||||
void usage(void) {
|
||||
//printf("Library version information: %s\n", lgw_version_info());
|
||||
printf( "Available options:\n");
|
||||
printf( " -h print this help\n");
|
||||
printf( " -k <uint> Concentrator clock source (Radio A or Radio B) [0..1]\n");
|
||||
printf( " -r <uint> Radio type (1255, 1257, 1250)\n");
|
||||
printf("Available options:\n");
|
||||
printf(" -h print this help\n");
|
||||
printf(" -u set COM type as USB (default is SPI)\n");
|
||||
printf(" -d <path> COM path to be used to connect the concentrator\n");
|
||||
printf(" => default path (SPI): " COM_PATH_DEFAULT "\n");
|
||||
printf(" -k <uint> Concentrator clock source (Radio A or Radio B) [0..1]\n");
|
||||
printf(" -r <uint> Radio type (1255, 1257, 1250)\n");
|
||||
}
|
||||
|
||||
static void sig_handler(int sigio) {
|
||||
|
|
@ -170,8 +174,9 @@ static void gps_process_coords(void) {
|
|||
int main(int argc, char **argv)
|
||||
{
|
||||
/* SPI interfaces */
|
||||
const char spidev_path_default[] = LINUXDEV_PATH_DEFAULT;
|
||||
const char * spidev_path = spidev_path_default;
|
||||
const char com_path_default[] = COM_PATH_DEFAULT;
|
||||
const char * com_path = com_path_default;
|
||||
lgw_com_type_t com_type = COM_TYPE_DEFAULT;
|
||||
|
||||
struct sigaction sigact; /* SIGQUIT&SIGINT&SIGTERM signal handling */
|
||||
|
||||
|
|
@ -180,7 +185,7 @@ int main(int argc, char **argv)
|
|||
|
||||
/* concentrator variables */
|
||||
uint8_t clocksource = 0;
|
||||
lgw_radio_type_t radio_type = LGW_RADIO_TYPE_NONE;
|
||||
lgw_radio_type_t radio_type = LGW_RADIO_TYPE_SX1250;
|
||||
struct lgw_conf_board_s boardconf;
|
||||
struct lgw_conf_rxrf_s rfconf;
|
||||
|
||||
|
|
@ -193,12 +198,20 @@ int main(int argc, char **argv)
|
|||
enum gps_msg latest_msg; /* keep track of latest NMEA/UBX message parsed */
|
||||
|
||||
/* parse command line options */
|
||||
while ((i = getopt (argc, argv, "hk:r:")) != -1) {
|
||||
while ((i = getopt (argc, argv, "hk:r:d:u")) != -1) {
|
||||
switch (i) {
|
||||
case 'h':
|
||||
usage();
|
||||
return -1;
|
||||
break;
|
||||
case 'd':
|
||||
if (optarg != NULL) {
|
||||
com_path = optarg;
|
||||
}
|
||||
break;
|
||||
case 'u':
|
||||
com_type = LGW_COM_USB;
|
||||
break;
|
||||
case 'r': /* <uint> Radio type */
|
||||
i = sscanf(optarg, "%u", &arg_u);
|
||||
if ((i != 1) || ((arg_u != 1255) && (arg_u != 1257) && (arg_u != 1250))) {
|
||||
|
|
@ -234,13 +247,6 @@ int main(int argc, char **argv)
|
|||
}
|
||||
}
|
||||
|
||||
/* Check arguments */
|
||||
if (radio_type == LGW_RADIO_TYPE_NONE) {
|
||||
printf("ERROR: radio type must be specified\n");
|
||||
usage();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* configure signal handling */
|
||||
sigemptyset(&sigact.sa_mask);
|
||||
sigact.sa_flags = 0;
|
||||
|
|
@ -253,10 +259,12 @@ int main(int argc, char **argv)
|
|||
printf("Beginning of test for loragw_gps.c\n");
|
||||
printf("*** Library version information ***\n%s\n***\n", lgw_version_info());
|
||||
|
||||
/* Board reset */
|
||||
if (system("./reset_lgw.sh start") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
if (com_type == LGW_COM_SPI) {
|
||||
/* Board reset */
|
||||
if (system("./reset_lgw.sh start") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Open and configure GPS */
|
||||
|
|
@ -272,8 +280,9 @@ int main(int argc, char **argv)
|
|||
boardconf.lorawan_public = true;
|
||||
boardconf.clksrc = clocksource;
|
||||
boardconf.full_duplex = false;
|
||||
strncpy(boardconf.spidev_path, spidev_path, sizeof boardconf.spidev_path);
|
||||
boardconf.spidev_path[sizeof boardconf.spidev_path - 1] = '\0'; /* ensure string termination */
|
||||
boardconf.com_type = com_type;
|
||||
strncpy(boardconf.com_path, com_path, sizeof boardconf.com_path);
|
||||
boardconf.com_path[sizeof boardconf.com_path - 1] = '\0'; /* ensure string termination */
|
||||
if (lgw_board_setconf(&boardconf) != LGW_HAL_SUCCESS) {
|
||||
printf("ERROR: failed to configure board\n");
|
||||
return EXIT_FAILURE;
|
||||
|
|
@ -405,10 +414,12 @@ int main(int argc, char **argv)
|
|||
lgw_stop();
|
||||
}
|
||||
|
||||
/* Board reset */
|
||||
if (system("./reset_lgw.sh stop") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
if (com_type == LGW_COM_SPI) {
|
||||
/* Board reset */
|
||||
if (system("./reset_lgw.sh stop") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
printf("\nEnd of test for loragw_gps.c\n");
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ License: Revised BSD License, see LICENSE.TXT file include in the project
|
|||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <math.h>
|
||||
#include <getopt.h>
|
||||
|
||||
#include "loragw_hal.h"
|
||||
#include "loragw_reg.h"
|
||||
|
|
@ -38,7 +39,8 @@ License: Revised BSD License, see LICENSE.TXT file include in the project
|
|||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE MACROS ------------------------------------------------------- */
|
||||
|
||||
#define LINUXDEV_PATH_DEFAULT "/dev/spidev0.0"
|
||||
#define COM_TYPE_DEFAULT LGW_COM_SPI
|
||||
#define COM_PATH_DEFAULT "/dev/spidev0.0"
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
|
||||
#define RAND_RANGE(min, max) (rand() % (max + 1 - min) + min)
|
||||
|
|
@ -66,9 +68,12 @@ static void sig_handler(int sigio) {
|
|||
}
|
||||
|
||||
void usage(void) {
|
||||
//printf("Library version information: %s\n", lgw_version_info());
|
||||
printf("Library version information: %s\n", lgw_version_info());
|
||||
printf("Available options:\n");
|
||||
printf(" -h print this help\n");
|
||||
printf(" -u set COM type as USB (default is SPI)\n");
|
||||
printf(" -d <path> COM path to be used to connect the concentrator\n");
|
||||
printf(" => default path: " COM_PATH_DEFAULT "\n");
|
||||
printf(" -k <uint> Concentrator clock source (Radio A or Radio B) [0..1]\n");
|
||||
printf(" -r <uint> Radio type (1255, 1257, 1250)\n");
|
||||
printf(" -a <float> Radio A RX frequency in MHz\n");
|
||||
|
|
@ -78,6 +83,8 @@ void usage(void) {
|
|||
printf(" -z <uint> Size of the RX packet array to be passed to lgw_receive()\n");
|
||||
printf(" -m <uint> Channel frequency plan mode [0:LoRaWAN-like, 1:Same frequency for all channels (-400000Hz on RF0)]\n");
|
||||
printf(" -j Set radio in single input mode (SX1250 only)\n");
|
||||
printf( "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" );
|
||||
printf(" --fdd Enable Full-Duplex mode (CN490 reference design)\n");
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
|
@ -86,8 +93,9 @@ void usage(void) {
|
|||
int main(int argc, char **argv)
|
||||
{
|
||||
/* SPI interfaces */
|
||||
const char spidev_path_default[] = LINUXDEV_PATH_DEFAULT;
|
||||
const char * spidev_path = spidev_path_default;
|
||||
const char com_path_default[] = COM_PATH_DEFAULT;
|
||||
const char * com_path = com_path_default;
|
||||
lgw_com_type_t com_type = COM_TYPE_DEFAULT;
|
||||
|
||||
struct sigaction sigact; /* SIGQUIT&SIGINT&SIGTERM signal handling */
|
||||
|
||||
|
|
@ -101,6 +109,7 @@ int main(int argc, char **argv)
|
|||
uint8_t max_rx_pkt = 16;
|
||||
bool single_input_mode = false;
|
||||
float rssi_offset = 0.0;
|
||||
bool full_duplex = false;
|
||||
|
||||
struct lgw_conf_board_s boardconf;
|
||||
struct lgw_conf_rxrf_s rfconf;
|
||||
|
|
@ -118,9 +127,9 @@ int main(int argc, char **argv)
|
|||
-400000,
|
||||
-200000,
|
||||
0,
|
||||
-400000,
|
||||
-200000,
|
||||
-400000 /* lora service */
|
||||
200000,
|
||||
400000,
|
||||
-200000 /* lora service */
|
||||
};
|
||||
|
||||
const int32_t channel_if_mode1[9] = {
|
||||
|
|
@ -139,13 +148,28 @@ int main(int argc, char **argv)
|
|||
|
||||
const uint8_t channel_rfchain_mode1[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
/* Parameter parsing */
|
||||
int option_index = 0;
|
||||
static struct option long_options[] = {
|
||||
{"fdd", no_argument, 0, 0},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
/* parse command line options */
|
||||
while ((i = getopt (argc, argv, "hja:b:k:r:n:z:m:o:")) != -1) {
|
||||
while ((i = getopt_long(argc, argv, "hja:b:k:r:n:z:m:o:d:u", long_options, &option_index)) != -1) {
|
||||
switch (i) {
|
||||
case 'h':
|
||||
usage();
|
||||
return -1;
|
||||
break;
|
||||
case 'd': /* <char> COM path */
|
||||
if (optarg != NULL) {
|
||||
com_path = optarg;
|
||||
}
|
||||
break;
|
||||
case 'u': /* Configure USB connection type */
|
||||
com_type = LGW_COM_USB;
|
||||
break;
|
||||
case 'r': /* <uint> Radio type */
|
||||
i = sscanf(optarg, "%u", &arg_u);
|
||||
if ((i != 1) || ((arg_u != 1255) && (arg_u != 1257) && (arg_u != 1250))) {
|
||||
|
|
@ -225,12 +249,20 @@ int main(int argc, char **argv)
|
|||
case 'o': /* <float> RSSI offset in dB */
|
||||
i = sscanf(optarg, "%lf", &arg_d);
|
||||
if (i != 1) {
|
||||
printf("ERROR: argument parsing of -f argument. Use -h to print help\n");
|
||||
printf("ERROR: argument parsing of -o argument. Use -h to print help\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
rssi_offset = (float)arg_d;
|
||||
}
|
||||
break;
|
||||
case 0:
|
||||
if (strcmp(long_options[option_index].name, "fdd") == 0) {
|
||||
full_duplex = true;
|
||||
} else {
|
||||
printf("ERROR: argument parsing options. Use -h to print help\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printf("ERROR: argument parsing\n");
|
||||
usage();
|
||||
|
|
@ -252,9 +284,10 @@ int main(int argc, char **argv)
|
|||
memset( &boardconf, 0, sizeof boardconf);
|
||||
boardconf.lorawan_public = true;
|
||||
boardconf.clksrc = clocksource;
|
||||
boardconf.full_duplex = false;
|
||||
strncpy(boardconf.spidev_path, spidev_path, sizeof boardconf.spidev_path);
|
||||
boardconf.spidev_path[sizeof boardconf.spidev_path - 1] = '\0'; /* ensure string termination */
|
||||
boardconf.full_duplex = full_duplex;
|
||||
boardconf.com_type = com_type;
|
||||
strncpy(boardconf.com_path, com_path, sizeof boardconf.com_path);
|
||||
boardconf.com_path[sizeof boardconf.com_path - 1] = '\0'; /* ensure string termination */
|
||||
if (lgw_board_setconf(&boardconf) != LGW_HAL_SUCCESS) {
|
||||
printf("ERROR: failed to configure board\n");
|
||||
return EXIT_FAILURE;
|
||||
|
|
@ -328,10 +361,12 @@ int main(int argc, char **argv)
|
|||
{
|
||||
cnt_loop += 1;
|
||||
|
||||
/* Board reset */
|
||||
if (system("./reset_lgw.sh start") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
if (com_type == LGW_COM_SPI) {
|
||||
/* Board reset */
|
||||
if (system("./reset_lgw.sh start") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
/* connect, configure and start the LoRa concentrator */
|
||||
|
|
@ -386,10 +421,12 @@ int main(int argc, char **argv)
|
|||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* Board reset */
|
||||
if (system("./reset_lgw.sh stop") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
if (com_type == LGW_COM_SPI) {
|
||||
/* Board reset */
|
||||
if (system("./reset_lgw.sh stop") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -44,7 +44,8 @@ License: Revised BSD License, see LICENSE.TXT file include in the project
|
|||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE CONSTANTS ---------------------------------------------------- */
|
||||
|
||||
#define LINUXDEV_PATH_DEFAULT "/dev/spidev0.0"
|
||||
#define COM_TYPE_DEFAULT LGW_COM_SPI
|
||||
#define COM_PATH_DEFAULT "/dev/spidev0.0"
|
||||
|
||||
#define DEFAULT_CLK_SRC 0
|
||||
#define DEFAULT_FREQ_HZ 868500000U
|
||||
|
|
@ -64,6 +65,9 @@ void usage(void) {
|
|||
//printf("Library version information: %s\n", lgw_version_info());
|
||||
printf("Available options:\n");
|
||||
printf(" -h print this help\n");
|
||||
printf(" -u Set COM type as USB (default is SPI)\n");
|
||||
printf(" -d <path> COM path to be used to connect the concentrator\n");
|
||||
printf(" => default path: " COM_PATH_DEFAULT "\n");
|
||||
printf(" -k <uint> Concentrator clock source (Radio A or Radio B) [0..1]\n");
|
||||
printf(" -c <uint> RF chain to be used for TX (Radio A or Radio B) [0..1]\n");
|
||||
printf(" -r <uint> Radio type (1255, 1257, 1250)\n");
|
||||
|
|
@ -73,8 +77,6 @@ void usage(void) {
|
|||
printf(" -s <uint> LoRa datarate 0:random, [5..12]\n");
|
||||
printf(" -b <uint> LoRa bandwidth in khz 0:random, [125, 250, 500]\n");
|
||||
printf(" -l <uint> FSK/LoRa preamble length, [6..65535]\n");
|
||||
printf(" -d <uint> FSK frequency deviation in kHz [1:250]\n");
|
||||
printf(" -q <float> FSK bitrate in kbps [0.5:250]\n");
|
||||
printf(" -n <uint> Number of packets to be sent\n");
|
||||
printf(" -z <uint> size of packets to be sent 0:random, [9..255]\n");
|
||||
printf(" -t <uint> TX mode timestamped with delay in ms. If delay is 0, TX mode GPS trigger\n");
|
||||
|
|
@ -82,6 +84,9 @@ void usage(void) {
|
|||
printf(" -i Send LoRa packet using inverted modulation polarity\n");
|
||||
printf(" -j Set radio in single input mode (SX1250 only)\n");
|
||||
printf( "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" );
|
||||
printf(" --fdev <uint> FSK frequency deviation in kHz [1:250]\n");
|
||||
printf(" --br <float> FSK bitrate in kbps [0.5:250]\n");
|
||||
printf( "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" );
|
||||
printf(" --pa <uint> PA gain SX125x:[0..3], SX1250:[0,1]\n");
|
||||
printf(" --dig <uint> sx1302 digital gain for sx125x [0..3]\n");
|
||||
printf(" --dac <uint> sx125x DAC gain [0..3]\n");
|
||||
|
|
@ -91,6 +96,8 @@ void usage(void) {
|
|||
printf(" --nhdr Send LoRa packet with implicit header\n");
|
||||
printf( "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" );
|
||||
printf(" --loop Number of loops for HAL start/stop (HAL unitary test)\n");
|
||||
printf( "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" );
|
||||
printf(" --fdd Enable Full-Duplex mode (CN490 reference design)\n");
|
||||
}
|
||||
|
||||
/* handle signals */
|
||||
|
|
@ -133,6 +140,7 @@ int main(int argc, char **argv)
|
|||
bool invert_pol = false;
|
||||
bool no_header = false;
|
||||
bool single_input_mode = false;
|
||||
bool full_duplex = false;
|
||||
|
||||
struct lgw_conf_board_s boardconf;
|
||||
struct lgw_conf_rxrf_s rfconf;
|
||||
|
|
@ -144,8 +152,9 @@ int main(int argc, char **argv)
|
|||
bool trig_delay = false;
|
||||
|
||||
/* SPI interfaces */
|
||||
const char spidev_path_default[] = LINUXDEV_PATH_DEFAULT;
|
||||
const char * spidev_path = spidev_path_default;
|
||||
const char com_path_default[] = COM_PATH_DEFAULT;
|
||||
const char * com_path = com_path_default;
|
||||
lgw_com_type_t com_type = COM_TYPE_DEFAULT;
|
||||
|
||||
static struct sigaction sigact; /* SIGQUIT&SIGINT&SIGTERM signal handling */
|
||||
|
||||
|
|
@ -156,6 +165,8 @@ int main(int argc, char **argv)
|
|||
/* Parameter parsing */
|
||||
int option_index = 0;
|
||||
static struct option long_options[] = {
|
||||
{"fdev", required_argument, 0, 0},
|
||||
{"br", required_argument, 0, 0},
|
||||
{"pa", required_argument, 0, 0},
|
||||
{"dac", required_argument, 0, 0},
|
||||
{"dig", required_argument, 0, 0},
|
||||
|
|
@ -163,16 +174,25 @@ int main(int argc, char **argv)
|
|||
{"pwid", required_argument, 0, 0},
|
||||
{"loop", required_argument, 0, 0},
|
||||
{"nhdr", no_argument, 0, 0},
|
||||
{"fdd", no_argument, 0, 0},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
/* parse command line options */
|
||||
while ((i = getopt_long (argc, argv, "hjif:s:b:n:z:p:k:r:c:l:t:m:o:q:d:", long_options, &option_index)) != -1) {
|
||||
while ((i = getopt_long (argc, argv, "hjif:s:b:n:z:p:k:r:c:l:t:m:o:ud:", long_options, &option_index)) != -1) {
|
||||
switch (i) {
|
||||
case 'h':
|
||||
usage();
|
||||
return -1;
|
||||
break;
|
||||
case 'u':
|
||||
com_type = LGW_COM_USB;
|
||||
break;
|
||||
case 'd': /* <char> COM path */
|
||||
if (optarg != NULL) {
|
||||
com_path = optarg;
|
||||
}
|
||||
break;
|
||||
case 'i': /* Send packet using inverted modulation polarity */
|
||||
invert_pol = true;
|
||||
break;
|
||||
|
|
@ -225,24 +245,6 @@ int main(int argc, char **argv)
|
|||
freq_offset = (int32_t)arg_i;
|
||||
}
|
||||
break;
|
||||
case 'd': /* <uint> FSK frequency deviation */
|
||||
i = sscanf(optarg, "%u", &arg_u);
|
||||
if ((i != 1) || (arg_u < 1) || (arg_u > 250)) {
|
||||
printf("ERROR: invalid FSK frequency deviation\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
fdev_khz = (uint8_t)arg_u;
|
||||
}
|
||||
break;
|
||||
case 'q': /* <float> FSK bitrate */
|
||||
i = sscanf(optarg, "%f", &xf);
|
||||
if ((i != 1) || (xf < 0.5) || (xf > 250)) {
|
||||
printf("ERROR: invalid FSK bitrate\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
br_kbps = xf;
|
||||
}
|
||||
break;
|
||||
case 't': /* <uint> Trigger delay in ms */
|
||||
i = sscanf(optarg, "%u", &arg_u);
|
||||
if (i != 1) {
|
||||
|
|
@ -328,7 +330,23 @@ int main(int argc, char **argv)
|
|||
}
|
||||
break;
|
||||
case 0:
|
||||
if (strcmp(long_options[option_index].name, "pa") == 0) {
|
||||
if (strcmp(long_options[option_index].name, "fdev") == 0) {
|
||||
i = sscanf(optarg, "%u", &arg_u);
|
||||
if ((i != 1) || (arg_u < 1) || (arg_u > 250)) {
|
||||
printf("ERROR: invalid FSK frequency deviation\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
fdev_khz = (uint8_t)arg_u;
|
||||
}
|
||||
} else if (strcmp(long_options[option_index].name, "br") == 0) {
|
||||
i = sscanf(optarg, "%f", &xf);
|
||||
if ((i != 1) || (xf < 0.5) || (xf > 250)) {
|
||||
printf("ERROR: invalid FSK bitrate\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
br_kbps = xf;
|
||||
}
|
||||
} else if (strcmp(long_options[option_index].name, "pa") == 0) {
|
||||
i = sscanf(optarg, "%u", &arg_u);
|
||||
if ((i != 1) || (arg_u > 3)) {
|
||||
printf("ERROR: argument parsing of --pa argument. Use -h to print help\n");
|
||||
|
|
@ -385,6 +403,8 @@ int main(int argc, char **argv)
|
|||
}
|
||||
} else if (strcmp(long_options[option_index].name, "nhdr") == 0) {
|
||||
no_header = true;
|
||||
} else if (strcmp(long_options[option_index].name, "fdd") == 0) {
|
||||
full_duplex = true;
|
||||
} else {
|
||||
printf("ERROR: argument parsing options. Use -h to print help\n");
|
||||
return EXIT_FAILURE;
|
||||
|
|
@ -419,9 +439,10 @@ int main(int argc, char **argv)
|
|||
memset( &boardconf, 0, sizeof boardconf);
|
||||
boardconf.lorawan_public = true;
|
||||
boardconf.clksrc = clocksource;
|
||||
boardconf.full_duplex = false;
|
||||
strncpy(boardconf.spidev_path, spidev_path, sizeof boardconf.spidev_path);
|
||||
boardconf.spidev_path[sizeof boardconf.spidev_path - 1] = '\0'; /* ensure string termination */
|
||||
boardconf.full_duplex = full_duplex;
|
||||
boardconf.com_type = com_type;
|
||||
strncpy(boardconf.com_path, com_path, sizeof boardconf.com_path);
|
||||
boardconf.com_path[sizeof boardconf.com_path - 1] = '\0'; /* ensure string termination */
|
||||
if (lgw_board_setconf(&boardconf) != LGW_HAL_SUCCESS) {
|
||||
printf("ERROR: failed to configure board\n");
|
||||
return EXIT_FAILURE;
|
||||
|
|
@ -457,10 +478,12 @@ int main(int argc, char **argv)
|
|||
}
|
||||
|
||||
for (cnt_loop = 0; cnt_loop < nb_loop; cnt_loop++) {
|
||||
if (com_type == LGW_COM_SPI) {
|
||||
/* Board reset */
|
||||
if (system("./reset_lgw.sh start") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
if (system("./reset_lgw.sh start") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
/* connect, configure and start the LoRa concentrator */
|
||||
|
|
@ -553,7 +576,7 @@ int main(int argc, char **argv)
|
|||
x = lgw_send(&pkt);
|
||||
if (x != 0) {
|
||||
printf("ERROR: failed to send packet\n");
|
||||
return EXIT_FAILURE;
|
||||
break;
|
||||
}
|
||||
/* wait for packet to finish sending */
|
||||
do {
|
||||
|
|
@ -573,13 +596,14 @@ int main(int argc, char **argv)
|
|||
x = lgw_stop();
|
||||
if (x != 0) {
|
||||
printf("ERROR: failed to stop the gateway\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* Board reset */
|
||||
if (system("./reset_lgw.sh stop") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
if (com_type == LGW_COM_SPI) {
|
||||
/* Board reset */
|
||||
if (system("./reset_lgw.sh stop") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ License: Revised BSD License, see LICENSE.TXT file include in the project
|
|||
#include <unistd.h> /* getopt, access */
|
||||
#include <math.h>
|
||||
|
||||
#include "loragw_com.h"
|
||||
#include "loragw_reg.h"
|
||||
#include "loragw_aux.h"
|
||||
#include "loragw_hal.h"
|
||||
|
|
@ -36,7 +37,8 @@ License: Revised BSD License, see LICENSE.TXT file include in the project
|
|||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE MACROS ------------------------------------------------------- */
|
||||
|
||||
#define LINUXDEV_PATH_DEFAULT "/dev/spidev0.0"
|
||||
#define COM_TYPE_DEFAULT LGW_COM_SPI
|
||||
#define COM_PATH_DEFAULT "/dev/spidev0.0"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE CONSTANTS ---------------------------------------------------- */
|
||||
|
|
@ -62,20 +64,25 @@ int main(int argc, char ** argv)
|
|||
uint8_t reg_max;
|
||||
|
||||
/* SPI interfaces */
|
||||
const char spidev_path_default[] = LINUXDEV_PATH_DEFAULT;
|
||||
const char * spidev_path = spidev_path_default;
|
||||
const char com_path_default[] = COM_PATH_DEFAULT;
|
||||
const char * com_path = com_path_default;
|
||||
lgw_com_type_t com_type = COM_TYPE_DEFAULT;
|
||||
|
||||
/* Parse command line options */
|
||||
while ((i = getopt(argc, argv, "hd:")) != -1) {
|
||||
while ((i = getopt(argc, argv, "hd:u")) != -1) {
|
||||
switch (i) {
|
||||
case 'h':
|
||||
usage();
|
||||
return EXIT_SUCCESS;
|
||||
break;
|
||||
|
||||
case 'u': /* Configure USB connection type */
|
||||
com_type = LGW_COM_USB;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
if (optarg != NULL) {
|
||||
spidev_path = optarg;
|
||||
com_path = optarg;
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
@ -86,13 +93,15 @@ int main(int argc, char ** argv)
|
|||
}
|
||||
}
|
||||
|
||||
/* Board reset */
|
||||
if (system("./reset_lgw.sh start") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
if (com_type == LGW_COM_SPI) {
|
||||
/* Board reset */
|
||||
if (system("./reset_lgw.sh start") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
x = lgw_connect(spidev_path);
|
||||
x = lgw_connect(com_type, com_path);
|
||||
if (x != LGW_REG_SUCCESS) {
|
||||
printf("ERROR: failed to connect\n");
|
||||
return -1;
|
||||
|
|
@ -179,10 +188,12 @@ int main(int argc, char ** argv)
|
|||
return -1;
|
||||
}
|
||||
|
||||
/* Board reset */
|
||||
if (system("./reset_lgw.sh stop") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
if (com_type == LGW_COM_SPI) {
|
||||
/* Board reset */
|
||||
if (system("./reset_lgw.sh stop") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -195,9 +206,10 @@ static void usage(void) {
|
|||
printf("~~~ Library version string~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
|
||||
printf(" %s\n", lgw_version_info());
|
||||
printf("~~~ Available options ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
|
||||
printf(" -h print this help\n");
|
||||
printf(" -d <path> use Linux SPI device driver\n");
|
||||
printf(" => default path: " LINUXDEV_PATH_DEFAULT "\n");
|
||||
printf(" -h print this help\n");
|
||||
printf(" -u set COM type as USB (default is SPI)\n");
|
||||
printf(" -d <path> COM path to be used to connect the concentrator\n");
|
||||
printf(" => default path: " COM_PATH_DEFAULT "\n");
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
361
libloragw/tst/test_loragw_sx1261_rssi.c
Normal file
361
libloragw/tst/test_loragw_sx1261_rssi.c
Normal file
|
|
@ -0,0 +1,361 @@
|
|||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2020 Semtech
|
||||
|
||||
Description:
|
||||
Set the sx1261 radio of the Corecell in RX continuous mode, and measure RSSI
|
||||
|
||||
License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*/
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- DEPENDANCIES --------------------------------------------------------- */
|
||||
|
||||
/* Fix an issue between POSIX and C99 */
|
||||
#if __STDC_VERSION__ >= 199901L
|
||||
#define _XOPEN_SOURCE 600
|
||||
#else
|
||||
#define _XOPEN_SOURCE 500
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <signal.h> /* sigaction */
|
||||
#include <unistd.h> /* getopt, access */
|
||||
|
||||
#include "loragw_aux.h"
|
||||
#include "loragw_hal.h"
|
||||
#include "loragw_reg.h"
|
||||
#include "loragw_com.h"
|
||||
#include "loragw_sx1261.h"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE MACROS ------------------------------------------------------- */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE CONSTANTS ---------------------------------------------------- */
|
||||
|
||||
#define BUFF_SIZE 16
|
||||
|
||||
#define COM_TYPE_DEFAULT LGW_COM_SPI
|
||||
#define COM_PATH_DEFAULT "/dev/spidev0.0"
|
||||
#define SX1261_PATH_DEFAULT "/dev/spidev0.1"
|
||||
|
||||
#define DEFAULT_FREQ_HZ 868500000U
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- GLOBAL VARIABLES ----------------------------------------------------- */
|
||||
|
||||
/* Signal handling variables */
|
||||
static int exit_sig = 0; /* 1 -> application terminates cleanly (shut down hardware, close open files, etc) */
|
||||
static int quit_sig = 0; /* 1 -> application terminates without shutting down the hardware */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- SUBFUNCTIONS DECLARATION --------------------------------------------- */
|
||||
|
||||
static void sig_handler(int sigio);
|
||||
static void usage(void);
|
||||
static void exit_failure();
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- MAIN FUNCTION -------------------------------------------------------- */
|
||||
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
static struct sigaction sigact; /* SIGQUIT&SIGINT&SIGTERM signal handling */
|
||||
|
||||
int i, x;
|
||||
double arg_d = 0.0;
|
||||
unsigned int arg_u;
|
||||
|
||||
uint8_t buff[BUFF_SIZE];
|
||||
uint32_t freq_hz = 0;
|
||||
float rssi_inst;
|
||||
uint32_t fa = DEFAULT_FREQ_HZ;
|
||||
uint32_t fb = DEFAULT_FREQ_HZ;
|
||||
uint8_t clocksource = 0;
|
||||
lgw_radio_type_t radio_type = LGW_RADIO_TYPE_SX1250;
|
||||
|
||||
/* COM interfaces */
|
||||
const char com_path_default[] = COM_PATH_DEFAULT;
|
||||
const char * com_path = com_path_default;
|
||||
lgw_com_type_t com_type = COM_TYPE_DEFAULT;
|
||||
const char sx1261_path_default[] = SX1261_PATH_DEFAULT;
|
||||
const char * sx1261_path = sx1261_path_default;
|
||||
|
||||
struct lgw_conf_board_s boardconf;
|
||||
struct lgw_conf_rxrf_s rfconf;
|
||||
|
||||
/* Parse command line options */
|
||||
while ((i = getopt(argc, argv, "hd:uf:D:k:r:a:b:")) != -1) {
|
||||
switch (i) {
|
||||
case 'h':
|
||||
usage();
|
||||
return EXIT_SUCCESS;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
if (optarg != NULL) {
|
||||
com_path = optarg;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
if (optarg != NULL) {
|
||||
sx1261_path = optarg;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
com_type = LGW_COM_USB;
|
||||
break;
|
||||
|
||||
case 'r': /* <uint> Radio type */
|
||||
i = sscanf(optarg, "%u", &arg_u);
|
||||
if ((i != 1) || ((arg_u != 1255) && (arg_u != 1257) && (arg_u != 1250))) {
|
||||
printf("ERROR: argument parsing of -r argument. Use -h to print help\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
switch (arg_u) {
|
||||
case 1255:
|
||||
radio_type = LGW_RADIO_TYPE_SX1255;
|
||||
break;
|
||||
case 1257:
|
||||
radio_type = LGW_RADIO_TYPE_SX1257;
|
||||
break;
|
||||
default: /* 1250 */
|
||||
radio_type = LGW_RADIO_TYPE_SX1250;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'k': /* <uint> Clock Source */
|
||||
i = sscanf(optarg, "%u", &arg_u);
|
||||
if ((i != 1) || (arg_u > 1)) {
|
||||
printf("ERROR: argument parsing of -k argument. Use -h to print help\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
clocksource = (uint8_t)arg_u;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'a': /* <float> Radio A RX frequency in MHz */
|
||||
i = sscanf(optarg, "%lf", &arg_d);
|
||||
if (i != 1) {
|
||||
printf("ERROR: argument parsing of -f argument. Use -h to print help\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
fa = (uint32_t)((arg_d*1e6) + 0.5); /* .5 Hz offset to get rounding instead of truncating */
|
||||
}
|
||||
break;
|
||||
|
||||
case 'b': /* <float> Radio B RX frequency in MHz */
|
||||
i = sscanf(optarg, "%lf", &arg_d);
|
||||
if (i != 1) {
|
||||
printf("ERROR: argument parsing of -f argument. Use -h to print help\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
fb = (uint32_t)((arg_d*1e6) + 0.5); /* .5 Hz offset to get rounding instead of truncating */
|
||||
}
|
||||
break;
|
||||
|
||||
case 'f': /* <float> SX1261 Radio RX frequency in MHz */
|
||||
i = sscanf(optarg, "%lf", &arg_d);
|
||||
if (i != 1) {
|
||||
printf("ERROR: argument parsing of -f argument. Use -h to print help\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
freq_hz = (uint32_t)((arg_d*1e6) + 0.5); /* .5 Hz offset to get rounding instead of truncating */
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("ERROR: argument parsing options, use -h option for help\n");
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check mandatory params */
|
||||
if (freq_hz == 0) {
|
||||
printf("ERROR: frequency must me set\n");
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* Configure signal handling */
|
||||
sigemptyset( &sigact.sa_mask );
|
||||
sigact.sa_flags = 0;
|
||||
sigact.sa_handler = sig_handler;
|
||||
sigaction( SIGQUIT, &sigact, NULL );
|
||||
sigaction( SIGINT, &sigact, NULL );
|
||||
sigaction( SIGTERM, &sigact, NULL );
|
||||
|
||||
/* Board reset */
|
||||
if (com_type == LGW_COM_SPI) {
|
||||
if (system("./reset_lgw.sh start") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Configure the gateway */
|
||||
memset( &boardconf, 0, sizeof boardconf);
|
||||
boardconf.lorawan_public = true;
|
||||
boardconf.clksrc = clocksource;
|
||||
boardconf.full_duplex = false;
|
||||
boardconf.com_type = com_type;
|
||||
strncpy(boardconf.com_path, com_path, sizeof boardconf.com_path);
|
||||
boardconf.com_path[sizeof boardconf.com_path - 1] = '\0'; /* ensure string termination */
|
||||
if (lgw_board_setconf(&boardconf) != LGW_HAL_SUCCESS) {
|
||||
printf("ERROR: failed to configure board\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* set configuration for RF chains */
|
||||
memset( &rfconf, 0, sizeof rfconf);
|
||||
rfconf.enable = true; /* must be enabled to proper RF matching */
|
||||
rfconf.freq_hz = fa;
|
||||
rfconf.type = radio_type;
|
||||
rfconf.rssi_offset = 0.0;
|
||||
rfconf.tx_enable = false;
|
||||
rfconf.single_input_mode = false;
|
||||
if (lgw_rxrf_setconf(0, &rfconf) != LGW_HAL_SUCCESS) {
|
||||
printf("ERROR: failed to configure rxrf 0\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
memset( &rfconf, 0, sizeof rfconf);
|
||||
rfconf.enable = true; /* must be enabled to proper RF matching */
|
||||
rfconf.freq_hz = fb;
|
||||
rfconf.type = radio_type;
|
||||
rfconf.rssi_offset = 0.0;
|
||||
rfconf.tx_enable = false;
|
||||
rfconf.single_input_mode = false;
|
||||
if (lgw_rxrf_setconf(1, &rfconf) != LGW_HAL_SUCCESS) {
|
||||
printf("ERROR: failed to configure rxrf 1\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* Connect to the concentrator board */
|
||||
x = lgw_start();
|
||||
if (x != LGW_REG_SUCCESS) {
|
||||
printf("ERROR: Failed to connect to the concentrator using COM %s\n", com_path);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* Connect to the sx1261 radio */
|
||||
x = sx1261_connect(com_type, sx1261_path);
|
||||
if (x != LGW_REG_SUCCESS) {
|
||||
printf("ERROR: Failed to connect to the sx1261 using COM %s\n", com_path);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
x = sx1261_calibrate(freq_hz);
|
||||
if (x != LGW_REG_SUCCESS) {
|
||||
printf("ERROR: Failed to calibrate the sx1261\n");
|
||||
exit_failure();
|
||||
}
|
||||
|
||||
x = sx1261_setup();
|
||||
if (x != LGW_REG_SUCCESS) {
|
||||
printf("ERROR: Failed to setup the sx1261\n");
|
||||
exit_failure();
|
||||
}
|
||||
|
||||
x = sx1261_set_rx_params(freq_hz, BW_125KHZ);
|
||||
if (x != LGW_REG_SUCCESS) {
|
||||
printf("ERROR: Failed to set RX params\n");
|
||||
exit_failure();
|
||||
}
|
||||
|
||||
/* databuffer R/W stress test */
|
||||
while ((quit_sig != 1) && (exit_sig != 1)) {
|
||||
buff[0] = 0x00;
|
||||
buff[1] = 0x00;
|
||||
sx1261_reg_r(SX1261_GET_RSSI_INST, buff, 2);
|
||||
|
||||
rssi_inst = -((float)buff[1] / 2);
|
||||
|
||||
printf("\rSX1261 RSSI at %uHz: %f dBm", freq_hz, rssi_inst);
|
||||
fflush(stdout);
|
||||
|
||||
wait_ms(100);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
/* Disconnect from the sx1261 radio */
|
||||
x = sx1261_disconnect();
|
||||
if (x != LGW_REG_SUCCESS) {
|
||||
printf("ERROR: Failed to disconnect from the SX1261 radio\n");
|
||||
}
|
||||
|
||||
/* Disconnect from the concentrator board */
|
||||
x = lgw_stop();
|
||||
if (x != LGW_REG_SUCCESS) {
|
||||
printf("ERROR: Failed to disconnect from the concentrator\n");
|
||||
}
|
||||
|
||||
printf("Disconnected\n");
|
||||
|
||||
if (com_type == LGW_COM_SPI) {
|
||||
/* Board reset */
|
||||
if (system("./reset_lgw.sh stop") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- SUBFUNCTIONS DEFINITION ---------------------------------------------- */
|
||||
|
||||
static void sig_handler(int sigio) {
|
||||
if (sigio == SIGQUIT) {
|
||||
quit_sig = 1;
|
||||
} else if((sigio == SIGINT) || (sigio == SIGTERM)) {
|
||||
exit_sig = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
static void exit_failure() {
|
||||
sx1261_disconnect();
|
||||
lgw_disconnect();
|
||||
|
||||
printf("End of test for loragw_spi_sx1261.c\n");
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
static void usage(void) {
|
||||
printf("~~~ Library version string~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
|
||||
printf(" %s\n", lgw_version_info());
|
||||
printf("~~~ Available options ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
|
||||
printf(" -h print this help\n");
|
||||
printf(" -u set COM type as USB (default is SPI)\n");
|
||||
printf(" -d <path> path to access the main COM device\n");
|
||||
printf(" => default path: " COM_PATH_DEFAULT "\n");
|
||||
printf(" -D [path] Path to the SX1261 SPI interface (not used for USB)\n");
|
||||
printf(" => default path: " SX1261_PATH_DEFAULT "\n");
|
||||
printf(" -k <uint> Concentrator clock source (Radio A or Radio B) [0..1]\n");
|
||||
printf(" -r <uint> Radio type (1255, 1257, 1250)\n");
|
||||
printf(" -a <float> Radio A RX frequency in MHz\n");
|
||||
printf(" -b <float> Radio B RX frequency in MHz\n");
|
||||
printf(" -f <float> SX1261 frequency for RSSI scanning, in MHz\n");
|
||||
}
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
||||
206
libloragw/tst/test_loragw_toa.c
Normal file
206
libloragw/tst/test_loragw_toa.c
Normal file
|
|
@ -0,0 +1,206 @@
|
|||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2020 Semtech
|
||||
|
||||
Description:
|
||||
Utility to compute Time on Air of a LoRa packet
|
||||
|
||||
License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*/
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- DEPENDANCIES --------------------------------------------------------- */
|
||||
|
||||
/* fix an issue between POSIX and C99 */
|
||||
#if __STDC_VERSION__ >= 199901L
|
||||
#define _XOPEN_SOURCE 600
|
||||
#else
|
||||
#define _XOPEN_SOURCE 500
|
||||
#endif
|
||||
|
||||
#include <stdint.h> /* C99 types */
|
||||
#include <stdbool.h> /* bool type */
|
||||
#include <stdio.h> /* printf fprintf */
|
||||
#include <stdlib.h> /* EXIT_FAILURE */
|
||||
#include <getopt.h> /* getopt_long */
|
||||
#include <string.h> /* strcmp */
|
||||
|
||||
#include "loragw_hal.h"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE MACROS ------------------------------------------------------- */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE CONSTANTS ---------------------------------------------------- */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE VARIABLES ---------------------------------------------------- */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE FUNCTIONS DECLARATION ---------------------------------------- */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE FUNCTIONS DEFINITION ----------------------------------------- */
|
||||
|
||||
/* describe command line options */
|
||||
void usage(void) {
|
||||
printf("Library version information: %s\n", lgw_version_info());
|
||||
printf("Available options:\n");
|
||||
printf(" -h print this help\n");
|
||||
printf(" -s <uint> LoRa datarate [5..12]\n");
|
||||
printf(" -b <uint> LoRa bandwidth in khz [125, 250, 500]\n");
|
||||
printf(" -l <uint> LoRa preamble length, [6..65535]\n");
|
||||
printf(" -c <uint> LoRa coding rate [1=4/5 2=4/6 3=4/7 4=4/8]\n");
|
||||
printf(" -z <uint> Payload length [0..255]\n");
|
||||
printf(" -i Implicit header (no header)\n");
|
||||
printf(" -r CRC enabled\n");
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- MAIN FUNCTION -------------------------------------------------------- */
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int i;
|
||||
unsigned int arg_u;
|
||||
|
||||
struct lgw_pkt_tx_s pkt;
|
||||
uint32_t toa_u;
|
||||
|
||||
/* mandatory params to be set by user */
|
||||
bool sf = false;
|
||||
bool bw = false;
|
||||
bool preamb = false;
|
||||
bool cr = false;
|
||||
bool sz = false;
|
||||
|
||||
/* Parameter parsing */
|
||||
int option_index = 0;
|
||||
static struct option long_options[] = {
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
memset(&pkt, 0, sizeof pkt);
|
||||
pkt.no_crc = true;
|
||||
pkt.modulation = MOD_LORA;
|
||||
|
||||
/* parse command line options */
|
||||
while ((i = getopt_long (argc, argv, "hirs:b:z:l:c:", long_options, &option_index)) != -1) {
|
||||
switch (i) {
|
||||
case 'h':
|
||||
usage();
|
||||
return -1;
|
||||
break;
|
||||
case 'i':
|
||||
pkt.no_header = true;
|
||||
break;
|
||||
case 'r':
|
||||
pkt.no_crc = false;
|
||||
break;
|
||||
case 'l':
|
||||
preamb = true; /* param set */
|
||||
i = sscanf(optarg, "%u", &arg_u);
|
||||
if ((i != 1) || (arg_u > 65535)) {
|
||||
printf("ERROR: argument parsing of -l argument. Use -h to print help\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
pkt.preamble = (uint16_t)arg_u;
|
||||
}
|
||||
break;
|
||||
case 's':
|
||||
sf = true; /* param set */
|
||||
i = sscanf(optarg, "%u", &arg_u);
|
||||
if ((i != 1) || (arg_u < 5) || (arg_u > 12)) {
|
||||
printf("ERROR: argument parsing of -s argument. Use -h to print help\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
pkt.datarate = arg_u;
|
||||
}
|
||||
break;
|
||||
case 'b':
|
||||
bw = true; /* param set */
|
||||
i = sscanf(optarg, "%u", &arg_u);
|
||||
if (i != 1) {
|
||||
printf("ERROR: argument parsing of -b argument. Use -h to print help\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
switch (arg_u) {
|
||||
case 125:
|
||||
pkt.bandwidth = BW_125KHZ;
|
||||
break;
|
||||
case 250:
|
||||
pkt.bandwidth = BW_250KHZ;
|
||||
break;
|
||||
case 500:
|
||||
pkt.bandwidth = BW_500KHZ;
|
||||
break;
|
||||
default:
|
||||
printf("ERROR: argument parsing of -b argument. Use -h to print help\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'c':
|
||||
cr = true; /* param set */
|
||||
i = sscanf(optarg, "%u", &arg_u);
|
||||
if (i != 1) {
|
||||
printf("ERROR: argument parsing of -b argument. Use -h to print help\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
switch (arg_u) {
|
||||
case 1:
|
||||
pkt.coderate = CR_LORA_4_5;
|
||||
break;
|
||||
case 2:
|
||||
pkt.coderate = CR_LORA_4_6;
|
||||
break;
|
||||
case 3:
|
||||
pkt.coderate = CR_LORA_4_7;
|
||||
break;
|
||||
case 4:
|
||||
pkt.coderate = CR_LORA_4_8;
|
||||
break;
|
||||
default:
|
||||
printf("ERROR: argument parsing of -b argument. Use -h to print help\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'z':
|
||||
sz = true; /* param set */
|
||||
i = sscanf(optarg, "%u", &arg_u);
|
||||
if ((i != 1) || (arg_u > 255)) {
|
||||
printf("ERROR: argument parsing of -z argument. Use -h to print help\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
pkt.size = (uint8_t)arg_u;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printf("ERROR: argument parsing\n");
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
printf("### LoRa - Time On Air Calculator ###\n");
|
||||
|
||||
if (sf == false ||
|
||||
bw == false ||
|
||||
preamb == false ||
|
||||
cr == false ||
|
||||
sz == false) {
|
||||
printf("ERROR: missing mandatory packet description parameter\n");
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
toa_u = lgw_time_on_air(&pkt);
|
||||
printf("=> %u ms\n", toa_u);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue