summaryrefslogtreecommitdiff
path: root/loragw_tx_test
diff options
context:
space:
mode:
Diffstat (limited to 'loragw_tx_test')
-rw-r--r--loragw_tx_test/LICENSE.TXT8
-rw-r--r--loragw_tx_test/Makefile34
-rw-r--r--loragw_tx_test/README.TXT65
-rw-r--r--loragw_tx_test/obj/.gitkeep0
-rw-r--r--loragw_tx_test/src/loragw_tx_test.c290
5 files changed, 397 insertions, 0 deletions
diff --git a/loragw_tx_test/LICENSE.TXT b/loragw_tx_test/LICENSE.TXT
new file mode 100644
index 0000000..e406dcb
--- /dev/null
+++ b/loragw_tx_test/LICENSE.TXT
@@ -0,0 +1,8 @@
+Copyright (C) 2013 SEMTECH S.A.
+
+ THE FOLLOWING SOFTWARE IS PROVIDED: (1) "AS IS" WITH NO WARRANTY; AND
+(2)TO ENABLE ACCESS TO CODING INFORMATION TO GUIDE AND FACILITATE CUSTOMER.
+CONSEQUENTLY, SEMTECH SHALL NOT BE HELD LIABLE FOR ANY DIRECT, INDIRECT OR
+CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT
+OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION
+CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
diff --git a/loragw_tx_test/Makefile b/loragw_tx_test/Makefile
new file mode 100644
index 0000000..5d07c6d
--- /dev/null
+++ b/loragw_tx_test/Makefile
@@ -0,0 +1,34 @@
+### Application-specific constants
+
+APP_NAME=loragw_tx_test
+
+### constant symbols
+
+CC=gcc
+CFLAGS=-O2 -Wall -Wextra -Iinc
+C99FLAGS=-O2 -Wall -Wextra -std=c99 -Iinc
+FLAG_AUX=
+
+### constants for Lora Gateway HAL library
+
+LGW_PATH=../loragw_hal
+LGW_INC=-I$(LGW_PATH)/inc
+#LGW_LNK=-lloragw -lrt
+LGW_LNK=-lloragw -lrt -lmpsse
+# add libmpsse or not, depending on what option you compiled the libloragw with
+
+### general build targets
+
+all: $(APP_NAME)
+
+clean:
+ rm -f obj/*.o
+ rm -f $(APP_NAME)
+
+### main program compilation and assembly
+
+obj/$(APP_NAME).o: src/$(APP_NAME).c
+ $(CC) -c $(C99FLAGS) -o obj/$(APP_NAME).o $(LGW_INC) src/$(APP_NAME).c $(FLAG_AUX)
+
+$(APP_NAME): $(LGW_PATH)/libloragw.a obj/$(APP_NAME).o
+ $(CC) -o $(APP_NAME) obj/$(APP_NAME).o -L$(LGW_PATH) $(LGW_LNK)
diff --git a/loragw_tx_test/README.TXT b/loragw_tx_test/README.TXT
new file mode 100644
index 0000000..2f95735
--- /dev/null
+++ b/loragw_tx_test/README.TXT
@@ -0,0 +1,65 @@
+ / _____) _ | |
+ ( (____ _____ ____ _| |_ _____ ____| |__
+ \____ \| ___ | (_ _) ___ |/ ___) _ \
+ _____) ) ____| | | || |_| ____( (___| | | |
+ (______/|_____)_|_|_| \__)_____)\____)_| |_|
+ ©2013 Semtech-Cycleo
+
+Lora Gateway packet sender
+===========================
+
+1. Introduction
+----------------
+
+This software is used to send test packets with a Lora concentrator. The packets
+contain little information, on no protocol (ie. MAC address) information but
+can be used to assess the functionality of a gateway downlink using other
+gateways as receivers.
+
+2. Dependencies
+----------------
+
+This program is a typical example of Lora Gateway HAL usage for sending packets.
+
+Only high-level functions are used (the ones contained in loragw_hal) so there
+is no hardware dependencies assuming the HAL is matched with the proper version
+of the hardware.
+Data structures of the sent packets are accessed by name (ie. not at a
+binary level) so new functionalities can be added to the API without affecting
+that program at all.
+
+It was tested with beta8 of the libloragw library, and should be compatible
+with any later version of the library assuming the API is downward-compatible.
+
+3. Usage
+---------
+
+The application runs until the specified number of packets have been send.
+Press Ctrl+C to stop the application before that.
+
+Use the -f option followed by a real number (decimal point and scientific
+'E notation' are OK) to specify the modulation central frequency.
+Use the -s option to specify the Spreading Factor of Lora modulation (values 7
+to 12 are valid).
+Use the -b option to set Lora modulation bandwidth in kHz (accepted values: 125,
+250 or 500).
+Use the -p option to set the concentrator TX power in dBm. Not all values are
+supported by hardware (typically 14 et 20 dBm are supported, other values might
+not give expected power). Check with a RF power meter before connecting any
+sensitive equipment.
+Use the -t option to specify the number of milliseconds of pause between
+packets. Using zero will result in a quasi-continuous emission.
+Use the -x to specify how many packets should be sent.
+
+The packets are 20 bytes long, and protected by the smallest supported ECC.
+
+The payload content is:
+[T][E][S][T][packet counter MSB][packet counter MSB] followed by ASCII padding.
+All Lora data is whitened, so the padding has no influence whatsoever on the
+packet error rate.
+
+4. Changelog
+-------------
+
+2013-10-18, beta 1
+Initial version.
diff --git a/loragw_tx_test/obj/.gitkeep b/loragw_tx_test/obj/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/loragw_tx_test/obj/.gitkeep
diff --git a/loragw_tx_test/src/loragw_tx_test.c b/loragw_tx_test/src/loragw_tx_test.c
new file mode 100644
index 0000000..bb8fe2c
--- /dev/null
+++ b/loragw_tx_test/src/loragw_tx_test.c
@@ -0,0 +1,290 @@
+/*
+ / _____) _ | |
+( (____ _____ ____ _| |_ _____ ____| |__
+ \____ \| ___ | (_ _) ___ |/ ___) _ \
+ _____) ) ____| | | || |_| ____( (___| | | |
+(______/|_____)_|_|_| \__)_____)\____)_| |_|
+ ©2013 Semtech-Cycleo
+
+Description:
+ Send a bunch of packets on a settable frequency
+*/
+
+
+/* -------------------------------------------------------------------------- */
+/* --- 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 sprintf fopen fputs */
+
+#include <string.h> /* memset */
+#include <signal.h> /* sigaction */
+#include <unistd.h> /* getopt access */
+#include <stdlib.h> /* exit codes */
+
+#include "loragw_hal.h"
+#include "loragw_aux.h"
+
+/* -------------------------------------------------------------------------- */
+/* --- PRIVATE MACROS ------------------------------------------------------- */
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+#define MSG(args...) fprintf(stderr, args) /* message that is destined to the user */
+
+/* -------------------------------------------------------------------------- */
+/* --- PRIVATE CONSTANTS ---------------------------------------------------- */
+
+#define RF_CHAIN 0 /* we'll use radio A only */
+
+const uint32_t lowfreq[LGW_RF_CHAIN_NB] = LGW_RF_TX_LOWFREQ;
+const uint32_t upfreq[LGW_RF_CHAIN_NB] = LGW_RF_TX_UPFREQ;
+
+/* -------------------------------------------------------------------------- */
+/* --- PRIVATE VARIABLES (GLOBAL) ------------------------------------------- */
+
+/* signal handling variables */
+struct sigaction sigact; /* SIGQUIT&SIGINT&SIGTERM signal handling */
+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 */
+
+/* -------------------------------------------------------------------------- */
+/* --- PRIVATE FUNCTIONS DECLARATION ---------------------------------------- */
+
+static void sig_handler(int sigio);
+
+void usage (void);
+
+/* -------------------------------------------------------------------------- */
+/* --- PRIVATE FUNCTIONS DEFINITION ----------------------------------------- */
+
+static void sig_handler(int sigio) {
+ if (sigio == SIGQUIT) {
+ quit_sig = 1;;
+ } else if ((sigio == SIGINT) || (sigio == SIGTERM)) {
+ exit_sig = 1;
+ }
+}
+
+/* describe command line options */
+void usage(void) {
+ MSG( "Available options:\n");
+ MSG( " -h print this help\n");
+ MSG( " -f <float> target frequency in MHz\n");
+ MSG( " -s <int> Spreading Factor\n");
+ MSG( " -b <int> Modulation bandwidth in kHz\n");
+ MSG( " -p <int> RF power (dBm)\n");
+ MSG( " -t <int> pause between packets (ms)\n");
+ MSG( " -x <int> numbers of times the sequence is repeated\n");
+ MSG( " -i send packet using inverted modulation polarity \n");
+}
+
+/* -------------------------------------------------------------------------- */
+/* --- MAIN FUNCTION -------------------------------------------------------- */
+
+int main(int argc, char **argv)
+{
+ int i;
+ uint8_t status_var;
+
+ /* user entry parameters */
+ int xi = 0;
+ double xd = 0.0;
+ uint32_t f_min;
+ uint32_t f_max;
+
+ /* application parameters */
+ uint32_t f_target = lowfreq[RF_CHAIN]/2 + upfreq[RF_CHAIN]/2; /* target frequency */
+ int sf = 10; /* SF10 by default */
+ int bw = 125; /* 125kHz bandwidth by default */
+ int pow = 14; /* 14 dBm by default */
+ int delay = 1000; /* 1 second between packets by default */
+ int repeat = 1; /* sweep only once by default */
+ bool invert = false;
+
+ /* RF configuration (TX fail if RF chain is not enabled) */
+ const struct lgw_conf_rxrf_s rfconf = {true, lowfreq[RF_CHAIN]};
+
+ /* allocate memory for packet sending */
+ struct lgw_pkt_tx_s txpkt; /* array containing 1 outbound packet + metadata */
+
+ /* loop variables (also use as counters in the packet payload) */
+ uint16_t cycle_count = 0;
+
+ /* parse command line options */
+ while ((i = getopt (argc, argv, "hf:s:b:p:t:x:i")) != -1) {
+ switch (i) {
+ case 'h':
+ usage();
+ return EXIT_FAILURE;
+ break;
+
+ case 'f': /* -f <float> target frequency in MHz */
+ i = sscanf(optarg, "%lf", &xd);
+ if ((i != 1) || (xd < 30.0) || (xd > 3000.0)) {
+ MSG("ERROR: invalid TX frequency\n");
+ return EXIT_FAILURE;
+ } else {
+ f_target = (uint32_t)((xd*1e6) + 0.5); /* .5 Hz offset to get rounding instead of truncating */
+ }
+ break;
+
+ case 's': /* -s <int> Spreading Factor */
+ i = sscanf(optarg, "%i", &xi);
+ if ((i != 1) || (xi < 7) || (xi > 12)) {
+ MSG("ERROR: invalid spreading factor\n");
+ return EXIT_FAILURE;
+ } else {
+ sf = xi;
+ }
+ break;
+
+ case 'b': /* -b <int> Modulation bandwidth in kHz */
+ i = sscanf(optarg, "%i", &xi);
+ if ((i != 1) || ((xi != 125)&&(xi != 250)&&(xi != 500))) {
+ MSG("ERROR: invalid Lora bandwidth\n");
+ return EXIT_FAILURE;
+ } else {
+ bw = xi;
+ }
+ break;
+
+ case 'p': /* -p <int> RF power */
+ i = sscanf(optarg, "%i", &xi);
+ if ((i != 1) || (xi < 0) || (xi > 20)) {
+ MSG("ERROR: invalid RF power\n");
+ return EXIT_FAILURE;
+ } else {
+ pow = xi;
+ }
+ break;
+
+ case 't': /* -t <int> pause between packets (ms) */
+ i = sscanf(optarg, "%i", &xi);
+ if ((i != 1) || (xi < 0)) {
+ MSG("ERROR: invalid time between packets\n");
+ return EXIT_FAILURE;
+ } else {
+ delay = xi;
+ }
+ break;
+
+ case 'x': /* -x <int> numbers of times the sequence is repeated */
+ i = sscanf(optarg, "%i", &xi);
+ if ((i != 1) || (xi < 1)) {
+ MSG("ERROR: invalid number of repeats\n");
+ return EXIT_FAILURE;
+ } else {
+ repeat = xi;
+ }
+ break;
+
+ case 'i': /* -i send packet using inverted modulation polarity */
+ invert = true;
+ break;
+
+ default:
+ MSG("ERROR: argument parsing use -h option for help\n");
+ usage();
+ return EXIT_FAILURE;
+ }
+ }
+
+ /* check parameter sanity */
+ f_min = lowfreq[RF_CHAIN] + (500 * bw);
+ f_max = upfreq[RF_CHAIN] - (500 * bw);
+ if ((f_target < f_min) || (f_target > f_max)) {
+ MSG("ERROR: frequency out of authorized band (accounting for modulation bandwidth)\n");
+ return EXIT_FAILURE;
+ }
+ printf("Sending %u packets on %u Hz (BW %u kHz, SF %u, 20 bytes payload) at %i dBm, with %u ms between each\n", repeat, f_target, bw, sf, pow, delay);
+
+ /* 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);
+
+ /* starting the concentrator */
+ lgw_rxrf_setconf(RF_CHAIN, rfconf);
+ 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 = f_target;
+ txpkt.tx_mode = IMMEDIATE;
+ txpkt.rf_chain = RF_CHAIN;
+ txpkt.rf_power = pow;
+ txpkt.modulation = MOD_LORA;
+ switch (bw) {
+ 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.invert_pol = invert;
+ txpkt.preamble = 8;
+ txpkt.size = 20; /* should be close to typical payload length */
+ strcpy((char *)txpkt.payload, "TEST**abcdefghijklmn" ); /* abc.. is for padding */
+
+ /* main loop */
+ for (cycle_count = 0; cycle_count < repeat; ++cycle_count) {
+ /* refresh counters in payload (big endian, for readability) */
+ txpkt.payload[4] = (uint8_t)(cycle_count >> 8); /* MSB */
+ txpkt.payload[5] = (uint8_t)(cycle_count & 0x00FF); /* LSB */
+
+ /* send packet */
+ printf("Sending packet number %u ...", cycle_count);
+ i = lgw_send(txpkt); /* non-blocking scheduling of TX packet */
+ do {
+ wait_ms(5);
+ lgw_status(TX_STATUS, &status_var); /* get TX status */
+ } while (status_var != TX_FREE);
+ printf("OK\n");
+
+ /* wait inter-packet delay */
+ wait_ms(delay);
+
+ /* exit loop on user signals */
+ if ((quit_sig == 1) || (exit_sig == 1)) {
+ break;
+ }
+ }
+
+ /* clean up before leaving */
+ lgw_stop();
+
+ printf("Exiting Lora concentrator TX test program\n");
+ return EXIT_SUCCESS;
+}
+
+/* --- EOF ------------------------------------------------------------------ */