From 7c383be1542368f2601015d9fc2a417197677677 Mon Sep 17 00:00:00 2001 From: Harsh Sharma <92harshsharma@gmail.com> Date: Wed, 13 Jun 2018 13:24:54 -0500 Subject: Initial Commit --- util_tx_continuous/Makefile | 68 +++++ util_tx_continuous/readme.md | 62 ++++ util_tx_continuous/src/util_tx_continuous.c | 454 ++++++++++++++++++++++++++++ 3 files changed, 584 insertions(+) create mode 100644 util_tx_continuous/Makefile create mode 100644 util_tx_continuous/readme.md create mode 100644 util_tx_continuous/src/util_tx_continuous.c (limited to 'util_tx_continuous') diff --git a/util_tx_continuous/Makefile b/util_tx_continuous/Makefile new file mode 100644 index 0000000..b07419b --- /dev/null +++ b/util_tx_continuous/Makefile @@ -0,0 +1,68 @@ +### Application-specific constants + +APP_NAME := util_tx_continuous + +### Environment constants + +LGW_PATH ?= ../libloragw +ARCH ?= +CROSS_COMPILE ?= + +### External constant definitions +# must get library build option to know if mpsse must be linked or not + +include $(LGW_PATH)/library.cfg + +### Constant symbols + +CC := $(CROSS_COMPILE)gcc +AR := $(CROSS_COMPILE)ar + +CFLAGS=-O2 -Wall -Wextra -std=c99 -Iinc -I. + +OBJDIR = obj + +### Constants for LoRa concentrator HAL library +# List the library sub-modules that are used by the application + +LGW_INC = $(LGW_PATH)/inc/config.h +LGW_INC += $(LGW_PATH)/inc/loragw_hal.h +LGW_INC += $(LGW_PATH)/inc/loragw_reg.h +LGW_INC += $(LGW_PATH)/inc/loragw_aux.h + +### Linking options + +LIBS := -lloragw -lrt -lm + +### General build targets + +all: $(APP_NAME) + +clean: + rm -f $(OBJDIR)/*.o + rm -f $(APP_NAME) + +### HAL library (do no force multiple library rebuild even with 'make -B') + +$(LGW_PATH)/inc/config.h: + @if test ! -f $@; then \ + $(MAKE) all -C $(LGW_PATH); \ + fi + +$(LGW_PATH)/libloragw.a: $(LGW_INC) + @if test ! -f $@; then \ + $(MAKE) all -C $(LGW_PATH); \ + fi + +### Main program compilation and assembly + +$(OBJDIR): + mkdir -p $(OBJDIR) + +$(OBJDIR)/$(APP_NAME).o: src/$(APP_NAME).c $(LGW_INC) | $(OBJDIR) + $(CC) -c $(CFLAGS) -I$(LGW_PATH)/inc $< -o $@ + +$(APP_NAME): $(OBJDIR)/$(APP_NAME).o $(LGW_PATH)/libloragw.a + $(CC) -L$(LGW_PATH) $< -o $@ $(LIBS) + +### EOF diff --git a/util_tx_continuous/readme.md b/util_tx_continuous/readme.md new file mode 100644 index 0000000..70a75ba --- /dev/null +++ b/util_tx_continuous/readme.md @@ -0,0 +1,62 @@ + ______ _ + / _____) _ | | + ( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | + (______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2014 Semtech-Cycleo + +Tx continuous program for LoRa concentrator +=========================================== + + +1. Introduction +---------------- + +This software is used to set LoRa concentrator in Tx continuous mode, for +spectral measurement. +The user can set the modulation type, the modulation parameters, and the +multiple gains of the Tx chain. +The program runs indefinitely, until the user stops the application. + + +2. Usage +-------- + +See command line help to get the list of all available options: +./util_tx_continuous -h + +Example: +./util_tx_continuous -f 868 -r 1257 --dig 0 --mix 14 --pa 3 --mod "LORA" --sf 7 --bw 125 + + +4. License +----------- + +Copyright (c) 2013, SEMTECH S.A. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +* Neither the name of the Semtech corporation nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL SEMTECH S.A. BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*EOF* diff --git a/util_tx_continuous/src/util_tx_continuous.c b/util_tx_continuous/src/util_tx_continuous.c new file mode 100644 index 0000000..b081cce --- /dev/null +++ b/util_tx_continuous/src/util_tx_continuous.c @@ -0,0 +1,454 @@ +/* + ______ _ + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2014 Semtech-Cycleo + +Description: + SX1301 tx continuous utility + +License: Revised BSD License, see LICENSE.TXT file include in the project +Maintainer: Matthieu Leurent +*/ + + +/* -------------------------------------------------------------------------- */ +/* --- DEPENDENCIES --------------------------------------------------------- */ + +/* Fix an issue between POSIX and C99 */ +#if __STDC_VERSION__ >= 199901L + #define _XOPEN_SOURCE 600 +#else + #define _XOPEN_SOURCE 500 +#endif + +#include /* C99 types */ +#include /* bool type */ +#include /* printf fprintf sprintf fopen fputs */ +#include /* memset */ +#include /* sigaction */ +#include /* getopt access */ +#include /* exit codes */ +#include /* getopt_long */ + +#include "loragw_hal.h" +#include "loragw_reg.h" +#include "loragw_aux.h" + +/* -------------------------------------------------------------------------- */ +/* --- MACROS & CONSTANTS --------------------------------------------------- */ + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) +#define MSG(args...) fprintf(stderr, args) /* message that is destined to the user */ + +#define TX_RF_CHAIN 0 /* TX only supported on radio A */ +#define DEFAULT_RSSI_OFFSET 0.0 + +#define DEFAULT_FREQ_HZ 868e6 +#define DEFAULT_DIGITAL_GAIN 0 +#define DEFAULT_DAC_GAIN 3 +#define DEFAULT_MIXER_GAIN 14 +#define DEFAULT_PA_GAIN 3 +#define DEFAULT_MODULATION "LORA" +#define DEFAULT_SF 7 +#define DEFAULT_BW_KHZ 125 +#define DEFAULT_BR_KBPS 50 +#define DEFAULT_FDEV_KHZ 25 +#define DEFAULT_BT 2 +#define DEFAULT_NOTCH_FREQ 129000U + +/* -------------------------------------------------------------------------- */ +/* --- 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); + +/* -------------------------------------------------------------------------- */ +/* --- MAIN FUNCTION -------------------------------------------------------- */ + +int main(int argc, char **argv) +{ + static struct sigaction sigact; /* SIGQUIT&SIGINT&SIGTERM signal handling */ + + int i; /* loop and temporary variables */ + + /* Parameter parsing */ + int option_index = 0; + static struct option long_options[] = { + {"dig", 1, 0, 0}, + {"dac", 1, 0, 0}, + {"mix", 1, 0, 0}, + {"pa", 1, 0, 0}, + {"mod", 1, 0, 0}, + {"sf", 1, 0, 0}, + {"bw", 1, 0, 0}, + {"br", 1, 0, 0}, + {"fdev", 1, 0, 0}, + {"bt", 1, 0, 0}, + {"notch", 1, 0, 0}, + {0, 0, 0, 0} + }; + unsigned int arg_u; + float arg_f; + char arg_s[64]; + + /* Application parameters */ + uint32_t freq_hz = DEFAULT_FREQ_HZ; + uint8_t g_dig = DEFAULT_DIGITAL_GAIN; + uint8_t g_dac = DEFAULT_DAC_GAIN; + uint8_t g_mix = DEFAULT_MIXER_GAIN; + uint8_t g_pa = DEFAULT_PA_GAIN; + char mod[64] = DEFAULT_MODULATION; + uint8_t sf = DEFAULT_SF; + unsigned int bw_khz = DEFAULT_BW_KHZ; + float br_kbps = DEFAULT_BR_KBPS; + uint8_t fdev_khz = DEFAULT_FDEV_KHZ; + uint8_t bt = DEFAULT_BT; + uint32_t tx_notch_freq = DEFAULT_NOTCH_FREQ; + + int32_t offset_i, offset_q; + + /* RF configuration (TX fail if RF chain is not enabled) */ + enum lgw_radio_type_e radio_type = LGW_RADIO_TYPE_SX1257; + struct lgw_conf_board_s boardconf; + struct lgw_conf_rxrf_s rfconf; + struct lgw_tx_gain_lut_s txlut; + struct lgw_pkt_tx_s txpkt; + + + /* Parse command line options */ + while ((i = getopt_long (argc, argv, "hud::f:r:", long_options, &option_index)) != -1) { + switch (i) { + case 'h': + printf("~~~ Library version string~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"); + printf(" %s\n", lgw_version_info()); + printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"); + printf(" -f Tx RF frequency in MHz [800:1000]\n"); + printf(" -r Radio type (SX1255:1255, SX1257:1257)\n"); + printf(" --notch Tx notch filter frequency in KhZ [126..250]\n"); + printf(" --dig Digital gain trim, [0:3]\n"); + printf(" 0:1, 1:7/8, 2:3/4, 3:1/2\n"); + printf(" --mix Radio Tx mixer gain trim, [0:15]\n"); + printf(" 15 corresponds to maximum gain, 1 LSB corresponds to 2dB step\n"); + printf(" --pa PA gain trim, [0:3]\n"); + printf(" --mod Modulation type ['LORA','FSK','CW']\n"); + printf(" --sf LoRa Spreading Factor, [7:12]\n"); + printf(" --bw LoRa bandwidth in kHz, [125,250,500]\n"); + printf(" --br FSK bitrate in kbps, [0.5:250]\n"); + printf(" --fdev FSK frequency deviation in kHz, [1:250]\n"); + printf(" --bt FSK gaussian filter BT trim, [0:3]\n"); + printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"); + return EXIT_SUCCESS; + break; + + case 0: + if (strcmp(long_options[option_index].name,"dig") == 0) { + i = sscanf(optarg, "%u", &arg_u); + if ((i != 1) || (arg_u > 3)) { + printf("ERROR: argument parsing of --dig argument. Use -h to print help\n"); + return EXIT_FAILURE; + } + else + { + g_dig = (uint8_t)arg_u; + } + } + else if (strcmp(long_options[option_index].name,"dac") == 0) { + i = sscanf(optarg, "%u", &arg_u); + if ((i != 1) || (arg_u > 3)) { + printf("ERROR: argument parsing of --dac argument. Use -h to print help\n"); + return EXIT_FAILURE; + } + else { + g_dac = (uint8_t)arg_u; + } + } + else if (strcmp(long_options[option_index].name,"mix") == 0) { + i = sscanf(optarg, "%u", &arg_u); + if ((i != 1) || (arg_u > 15)) { + printf("ERROR: argument parsing of --mix argument. Use -h to print help\n"); + return EXIT_FAILURE; + } + else { + g_mix = (uint8_t)arg_u; + } + } + 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"); + return EXIT_FAILURE; + } + else { + g_pa = arg_u; + } + } + else if (strcmp(long_options[option_index].name,"mod") == 0) { + i = sscanf(optarg, "%s", arg_s); + if ((i != 1) || ((strcmp(arg_s,"LORA") != 0) && (strcmp(arg_s,"FSK") != 0) && (strcmp(arg_s,"CW") != 0))) { + printf("ERROR: argument parsing of --mod argument. Use -h to print help\n"); + return EXIT_FAILURE; + } + else { + sprintf(mod, "%s", arg_s); + } + } + else if (strcmp(long_options[option_index].name,"sf") == 0) { + i = sscanf(optarg, "%u", &arg_u); + if ((i != 1) || (arg_u < 7) || (arg_u > 12)) { + printf("ERROR: argument parsing of --sf argument. Use -h to print help\n"); + return EXIT_FAILURE; + } + else { + sf = (uint8_t)arg_u; + } + } + else if (strcmp(long_options[option_index].name,"bw") == 0) { + i = sscanf(optarg, "%u", &arg_u); + if ((i != 1) || ((arg_u != 125) && (arg_u != 250) && (arg_u != 500))) { + printf("ERROR: argument parsing of --bw argument. Use -h to print help\n"); + return EXIT_FAILURE; + } + else { + bw_khz = arg_u; + } + } + else if (strcmp(long_options[option_index].name,"br") == 0) { + i = sscanf(optarg, "%f", &arg_f); + if ((i != 1) || (arg_f < 0.5) || (arg_f > 250)) { + printf("ERROR: argument parsing of --br argument. Use -h to print help\n"); + return EXIT_FAILURE; + } + else { + br_kbps = arg_f; + } + } + else 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: argument parsing of --fdev argument. Use -h to print help\n"); + return EXIT_FAILURE; + } + else { + fdev_khz = (uint8_t)arg_u; + } + } + else if (strcmp(long_options[option_index].name,"bt") == 0) { + i = sscanf(optarg, "%u", &arg_u); + if ((i != 1) || (arg_u > 3)) { + printf("ERROR: argument parsing of --bt argument. Use -h to print help\n"); + return EXIT_FAILURE; + } + else { + bt = (uint8_t)arg_u; + } + } + else if (strcmp(long_options[option_index].name,"notch") == 0) { + i = sscanf(optarg, "%u", &arg_u); + if ((i != 1) || ((arg_u < 126) || (arg_u > 250))) { + printf("ERROR: argument parsing of --notch argument. Use -h to print help\n"); + return EXIT_FAILURE; + } + else { + tx_notch_freq = (uint32_t)arg_u * 1000U; + } + } + else { + printf("ERROR: argument parsing options. Use -h to print help\n"); + return EXIT_FAILURE; + } + break; + + case 'f': + i = sscanf(optarg, "%f", &arg_f); + if ((i != 1) || (arg_f < 1)) { + printf("ERROR: argument parsing of -f argument. Use -h to print help\n"); + return EXIT_FAILURE; + } + else { + freq_hz = (uint32_t)((arg_f * 1e6) + 0.5); + } + break; + + case 'r': + i = sscanf(optarg, "%u", &arg_u); + switch (arg_u) { + case 1255: + radio_type = LGW_RADIO_TYPE_SX1255; + break; + case 1257: + radio_type = LGW_RADIO_TYPE_SX1257; + break; + default: + printf("ERROR: argument parsing of -r argument. Use -h to print help\n"); + return EXIT_FAILURE; + } + break; + + default: + printf("ERROR: argument parsing options. Use -h to print help\n"); + 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 config */ + memset(&boardconf, 0, sizeof(boardconf)); + boardconf.lorawan_public = true; + boardconf.clksrc = 1; /* Radio B is source by default */ + lgw_board_setconf(boardconf); + + /* RF config */ + memset(&rfconf, 0, sizeof(rfconf)); + rfconf.enable = true; + rfconf.freq_hz = freq_hz; + rfconf.rssi_offset = DEFAULT_RSSI_OFFSET; + rfconf.type = radio_type; + rfconf.tx_enable = true; + rfconf.tx_notch_freq = tx_notch_freq; + lgw_rxrf_setconf(TX_RF_CHAIN, rfconf); + + /* Tx gain LUT */ + memset(&txlut, 0, sizeof txlut); + txlut.size = 1; + txlut.lut[0].dig_gain = g_dig; + txlut.lut[0].pa_gain = g_pa; + txlut.lut[0].dac_gain = g_dac; + txlut.lut[0].mix_gain = g_mix; + txlut.lut[0].rf_power = 0; + lgw_txgain_setconf(&txlut); + + /* Start the concentrator */ + i = lgw_start(); + if (i == LGW_HAL_SUCCESS) { + MSG("INFO: concentrator started, packet can be sent\n"); + } else { + MSG("ERROR: failed to start the concentrator\n"); + return EXIT_FAILURE; + } + + /* fill-up payload and parameters */ + memset(&txpkt, 0, sizeof(txpkt)); + txpkt.freq_hz = freq_hz; + txpkt.tx_mode = IMMEDIATE; + txpkt.rf_chain = TX_RF_CHAIN; + txpkt.rf_power = 0; + if (strcmp(mod, "FSK") == 0) { + txpkt.modulation = MOD_FSK; + txpkt.datarate = br_kbps * 1e3; + } else { + txpkt.modulation = MOD_LORA; + switch (bw_khz) { + case 125: txpkt.bandwidth = BW_125KHZ; break; + case 250: txpkt.bandwidth = BW_250KHZ; break; + case 500: txpkt.bandwidth = BW_500KHZ; break; + default: + MSG("ERROR: invalid 'bw' variable\n"); + return EXIT_FAILURE; + } + switch (sf) { + case 7: txpkt.datarate = DR_LORA_SF7; break; + case 8: txpkt.datarate = DR_LORA_SF8; break; + case 9: txpkt.datarate = DR_LORA_SF9; break; + case 10: txpkt.datarate = DR_LORA_SF10; break; + case 11: txpkt.datarate = DR_LORA_SF11; break; + case 12: txpkt.datarate = DR_LORA_SF12; break; + default: + MSG("ERROR: invalid 'sf' variable\n"); + return EXIT_FAILURE; + } + } + txpkt.coderate = CR_LORA_4_5; + txpkt.f_dev = fdev_khz; + txpkt.preamble = 65535; + txpkt.invert_pol = false; + txpkt.no_crc = true; + txpkt.no_header = true; + txpkt.size = 1; + txpkt.payload[0] = 0; + + /* Overwrite settings */ + lgw_reg_w(LGW_TX_MODE, 1); /* Tx continuous */ + lgw_reg_w(LGW_FSK_TX_GAUSSIAN_SELECT_BT, bt); + if (strcmp(mod, "CW") == 0) { + /* Enable signal generator with DC */ + lgw_reg_w(LGW_SIG_GEN_FREQ, 0); + lgw_reg_w(LGW_SIG_GEN_EN, 1); + lgw_reg_w(LGW_TX_OFFSET_I, 0); + lgw_reg_w(LGW_TX_OFFSET_Q, 0); + } + + /* Send packet */ + i = lgw_send(txpkt); + + /* Recap all settings */ + printf("SX1301 library version: %s\n", lgw_version_info()); + if (strcmp(mod, "LORA") == 0) { + printf("Modulation: LORA SF:%d BW:%d kHz\n", sf, bw_khz); + } + else if (strcmp(mod, "FSK") == 0) { + printf("Modulation: FSK BR:%3.3f kbps FDEV:%d kHz BT:%d\n", br_kbps, fdev_khz, bt); + } + else if (strcmp(mod, "CW") == 0) { + printf("Modulation: CW\n"); + } + switch(rfconf.type) { + case LGW_RADIO_TYPE_SX1255: + printf("Radio Type: SX1255\n"); + break; + case LGW_RADIO_TYPE_SX1257: + printf("Radio Type: SX1257\n"); + break; + default: + printf("ERROR: undefined radio type\n"); + break; + } + printf("Frequency: %4.3f MHz\n", freq_hz/1e6); + printf("TX Gains: Digital:%d DAC:%d Mixer:%d PA:%d\n", g_dig, g_dac, g_mix, g_pa); + if (strcmp(mod, "CW") != 0) { + lgw_reg_r(LGW_TX_OFFSET_I, &offset_i); + lgw_reg_r(LGW_TX_OFFSET_Q, &offset_q); + printf("Calibrated DC offsets: I:%d Q:%d\n", offset_i, offset_q); + } + + /* waiting for user input */ + while ((quit_sig != 1) && (exit_sig != 1)) { + wait_ms(100); + } + + /* clean up before leaving */ + lgw_stop(); + + 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; + } +} + +/* --- EOF ------------------------------------------------------------------ */ -- cgit v1.2.3