├── .gitignore ├── LICENSE ├── Makefile ├── VERSION ├── libloragw ├── Makefile ├── inc │ ├── loragw_aux.h │ ├── loragw_com.h │ ├── loragw_com_linux.h │ ├── loragw_hal.h │ ├── loragw_mcu.h │ ├── loragw_radio.h │ ├── loragw_reg.h │ └── loragw_sx125x.h ├── library.cfg ├── readme.md ├── src │ ├── agc_fw.var │ ├── arb_fw.var │ ├── cal_fw.var │ ├── cal_fw5-12.var │ ├── loragw_aux.c │ ├── loragw_com.c │ ├── loragw_com_linux.c │ ├── loragw_hal.c │ ├── loragw_mcu.c │ ├── loragw_radio.c │ └── loragw_reg.c └── tst │ ├── test_loragw_cal.c │ ├── test_loragw_hal.c │ └── test_loragw_reg.c ├── lora_indent.sh ├── readme.md ├── util_boot ├── Makefile ├── readme.md └── src │ └── util_boot.c ├── util_chip_id ├── Makefile ├── readme.md └── src │ └── util_chip_id.c ├── util_com_stress ├── Makefile ├── readme.md └── src │ └── util_com_stress.c ├── util_pkt_logger ├── Makefile ├── global_conf.json ├── inc │ └── parson.h ├── local_conf.json ├── readme.md └── src │ ├── parson.c │ └── util_pkt_logger.c ├── util_tx_continuous ├── Makefile ├── readme.md └── src │ └── util_tx_continuous.c └── util_tx_test ├── Makefile ├── readme.md └── src └── util_tx_test.c /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.swp 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013, SEMTECH S.A. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | * Redistributions of source code must retain the above copyright 7 | notice, this list of conditions and the following disclaimer. 8 | * Redistributions in binary form must reproduce the above copyright 9 | notice, this list of conditions and the following disclaimer in the 10 | documentation and/or other materials provided with the distribution. 11 | * Neither the name of the Semtech corporation nor the 12 | names of its contributors may be used to endorse or promote products 13 | derived from this software without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | DISCLAIMED. IN NO EVENT SHALL SEMTECH S.A. BE LIABLE FOR ANY 19 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | 26 | 27 | --- For the parson library used by the packet logger --- 28 | 29 | Parson ( http://kgabis.github.com/parson/ ) 30 | Copyright (c) 2012 Krzysztof Gabis 31 | 32 | Permission is hereby granted, free of charge, to any person obtaining a copy 33 | of this software and associated documentation files (the "Software"), to deal 34 | in the Software without restriction, including without limitation the rights 35 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 36 | copies of the Software, and to permit persons to whom the Software is 37 | furnished to do so, subject to the following conditions: 38 | 39 | The above copyright notice and this permission notice shall be included in 40 | all copies or substantial portions of the Software. 41 | 42 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 43 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 44 | ITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 45 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 46 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 47 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 48 | THE SOFTWARE. 49 | 50 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ### Environment constants 2 | 3 | ARCH ?= 4 | CROSS_COMPILE ?= 5 | export 6 | 7 | ### general build targets 8 | 9 | all: 10 | $(MAKE) all -e -C libloragw 11 | $(MAKE) all -e -C util_boot 12 | $(MAKE) all -e -C util_chip_id 13 | $(MAKE) all -e -C util_pkt_logger 14 | $(MAKE) all -e -C util_com_stress 15 | $(MAKE) all -e -C util_tx_test 16 | $(MAKE) all -e -C util_tx_continuous 17 | 18 | clean: 19 | $(MAKE) clean -e -C libloragw 20 | $(MAKE) clean -e -C util_boot 21 | $(MAKE) clean -e -C util_chip_id 22 | $(MAKE) clean -e -C util_pkt_logger 23 | $(MAKE) clean -e -C util_com_stress 24 | $(MAKE) clean -e -C util_tx_test 25 | $(MAKE) clean -e -C util_tx_continuous 26 | 27 | ### EOF 28 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | 0.2.3 2 | -------------------------------------------------------------------------------- /libloragw/Makefile: -------------------------------------------------------------------------------- 1 | ### get external defined data 2 | 3 | LIBLORAGW_VERSION := `cat ../VERSION` 4 | include library.cfg 5 | 6 | ### constant symbols 7 | 8 | ARCH ?= 9 | CROSS_COMPILE ?= 10 | CC := $(CROSS_COMPILE)gcc 11 | AR := $(CROSS_COMPILE)ar 12 | 13 | CFLAGS := -O2 -Wall -Wextra -std=c99 -Iinc -I. 14 | 15 | OBJDIR = obj 16 | INCLUDES = $(wildcard inc/*.h) 17 | 18 | ### linking options 19 | 20 | LIBS := -lloragw -lrt -lm 21 | 22 | ### general build targets 23 | 24 | all: libloragw.a test_loragw_reg test_loragw_hal test_loragw_cal 25 | 26 | clean: 27 | rm -f libloragw.a 28 | rm -f test_loragw_* 29 | rm -f $(OBJDIR)/*.o 30 | rm -f inc/config.h 31 | 32 | ### transpose library.cfg into a C header file : config.h 33 | 34 | inc/config.h: ../VERSION library.cfg 35 | @echo "*** Checking libloragw library configuration ***" 36 | @rm -f $@ 37 | #File initialization 38 | @echo "#ifndef _LORAGW_CONFIGURATION_H" >> $@ 39 | @echo "#define _LORAGW_CONFIGURATION_H" >> $@ 40 | # Release version 41 | @echo "Release version : $(LIBLORAGW_VERSION)" 42 | @echo " #define LIBLORAGW_VERSION "\"$(LIBLORAGW_VERSION)\""" >> $@ 43 | # Debug options 44 | @echo " #define DEBUG_AUX $(DEBUG_AUX)" >> $@ 45 | @echo " #define DEBUG_COM $(DEBUG_COM)" >> $@ 46 | @echo " #define DEBUG_REG $(DEBUG_REG)" >> $@ 47 | @echo " #define DEBUG_MCU $(DEBUG_MCU)" >> $@ 48 | @echo " #define DEBUG_HAL $(DEBUG_HAL)" >> $@ 49 | # end of file 50 | @echo "#endif" >> $@ 51 | @echo "*** Configuration seems ok ***" 52 | 53 | ### library module target 54 | 55 | $(OBJDIR): 56 | mkdir -p $(OBJDIR) 57 | 58 | $(OBJDIR)/%.o: src/%.c $(INCLUDES) inc/config.h | $(OBJDIR) 59 | $(CC) -c $(CFLAGS) $< -o $@ 60 | 61 | $(OBJDIR)/loragw_com_linux.o: src/loragw_com_linux.c $(INCLUDES) inc/config.h | $(OBJDIR) 62 | $(CC) -c $(CFLAGS) $< -o $@ 63 | 64 | $(OBJDIR)/loragw_com.o: src/loragw_com.c $(INCLUDES) inc/config.h | $(OBJDIR) 65 | $(CC) -c $(CFLAGS) $< -o $@ 66 | 67 | $(OBJDIR)/loragw_mcu.o: src/loragw_mcu.c $(INCLUDES) inc/config.h | $(OBJDIR) 68 | $(CC) -c $(CFLAGS) $< -o $@ 69 | 70 | $(OBJDIR)/loragw_hal.o: src/loragw_hal.c $(INCLUDES) src/arb_fw.var src/agc_fw.var src/cal_fw.var inc/config.h | $(OBJDIR) 71 | $(CC) -c $(CFLAGS) $< -o $@ 72 | 73 | ### static library 74 | 75 | libloragw.a: $(OBJDIR)/loragw_hal.o $(OBJDIR)/loragw_mcu.o $(OBJDIR)/loragw_reg.o $(OBJDIR)/loragw_com.o $(OBJDIR)/loragw_com_linux.o $(OBJDIR)/loragw_aux.o $(OBJDIR)/loragw_radio.o 76 | $(AR) rcs $@ $^ 77 | 78 | ### test programs 79 | 80 | test_loragw_com: tst/test_loragw_com.c libloragw.a 81 | $(CC) $(CFLAGS) -L. $< -o $@ $(LIBS) 82 | 83 | test_loragw_reg: tst/test_loragw_reg.c libloragw.a 84 | $(CC) $(CFLAGS) -L. $< -o $@ $(LIBS) 85 | 86 | test_loragw_hal: tst/test_loragw_hal.c libloragw.a 87 | $(CC) $(CFLAGS) -L. $< -o $@ $(LIBS) 88 | 89 | test_loragw_gps: tst/test_loragw_gps.c libloragw.a 90 | $(CC) $(CFLAGS) -L. $< -o $@ $(LIBS) 91 | 92 | test_loragw_cal: tst/test_loragw_cal.c libloragw.a src/cal_fw.var 93 | $(CC) $(CFLAGS) -L. $< -o $@ $(LIBS) 94 | 95 | ### EOF 96 | -------------------------------------------------------------------------------- /libloragw/inc/loragw_aux.h: -------------------------------------------------------------------------------- 1 | /* 2 | / _____) _ | | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 5 | _____) ) ____| | | || |_| ____( (___| | | | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 7 | (C)2017 Semtech-Cycleo 8 | 9 | Description: 10 | LoRa concentrator HAL common auxiliary functions 11 | 12 | License: Revised BSD License, see LICENSE.TXT file include in the project 13 | 14 | */ 15 | 16 | 17 | #ifndef _LORAGW_AUX_H 18 | #define _LORAGW_AUX_H 19 | 20 | /* -------------------------------------------------------------------------- */ 21 | /* --- DEPENDANCIES --------------------------------------------------------- */ 22 | 23 | #include "config.h" /* library configuration options (dynamically generated) */ 24 | 25 | /* -------------------------------------------------------------------------- */ 26 | /* --- PUBLIC MACROS -------------------------------------------------------- */ 27 | 28 | /** 29 | @brief Get a particular bit value from a byte 30 | @param b [in] Any byte from which we want a bit value 31 | @param p [in] Position of the bit in the byte [0..7] 32 | @param n [in] Number of bits we want to get 33 | @return The value corresponding the requested bits 34 | */ 35 | #define TAKE_N_BITS_FROM(b, p, n) (((b) >> (p)) & ((1 << (n)) - 1)) 36 | 37 | /* -------------------------------------------------------------------------- */ 38 | /* --- PUBLIC FUNCTIONS PROTOTYPES ------------------------------------------ */ 39 | 40 | /** 41 | @brief Wait for a certain time (millisecond accuracy) 42 | @param t number of milliseconds to wait. 43 | */ 44 | void wait_ms_linux(unsigned long t); 45 | void wait_ns_linux(unsigned long t); 46 | void wait_ms(unsigned long t); 47 | void wait_ns(unsigned long t); 48 | 49 | #endif 50 | 51 | /* --- EOF ------------------------------------------------------------------ */ 52 | -------------------------------------------------------------------------------- /libloragw/inc/loragw_com.h: -------------------------------------------------------------------------------- 1 | /* 2 | / _____) _ | | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 5 | _____) ) ____| | | || |_| ____( (___| | | | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 7 | (C)2017 Semtech-Cycleo 8 | 9 | Description: 10 | A communication bridge layer to abstract linux/windows OS or others. 11 | The current project support only linux os 12 | 13 | License: Revised BSD License, see LICENSE.TXT file include in the project 14 | 15 | */ 16 | 17 | #ifndef _LORAGW_COM_H 18 | #define _LORAGW_COM_H 19 | 20 | /* -------------------------------------------------------------------------- */ 21 | /* --- DEPENDANCIES --------------------------------------------------------- */ 22 | 23 | #include /* C99 types*/ 24 | 25 | #include "config.h" /* library configuration options (dynamically generated) */ 26 | 27 | /* -------------------------------------------------------------------------- */ 28 | /* --- PUBLIC CONSTANTS ----------------------------------------------------- */ 29 | 30 | #define LGW_COM_SUCCESS 0 31 | #define LGW_COM_ERROR -1 32 | #define LGW_BURST_CHUNK 1024 33 | #define LGW_COM_MUX_MODE0 0x0 /* No FPGA */ 34 | #define LGW_COM_MUX_TARGET_SX1301 0x0 35 | 36 | #define ATOMICTX 600 37 | #define ATOMICRX 900 38 | 39 | #define CMD_HEADER_TX_SIZE 4 /* id + len_msb + len_lsb + address */ 40 | #define CMD_HEADER_RX_SIZE 4 /* id + len_msb + len_lsb + status */ 41 | 42 | #define CMD_DATA_TX_SIZE ATOMICTX 43 | #define CMD_DATA_RX_SIZE (1024 + 16 * 44) /* MAX_FIFO + 16 * METADATA_SIZE_ALIGNED */ 44 | 45 | #define ACK_OK 1 46 | #define ACK_KO 0 47 | 48 | /* -------------------------------------------------------------------------- */ 49 | /* --- PUBLIC TYPES --------------------------------------------------------- */ 50 | 51 | /** 52 | @struct lgw_com_cmd_t 53 | @brief structure for host to mcu commands 54 | */ 55 | /********************************************************/ 56 | /* cmd name | description */ 57 | /*------------------------------------------------------*/ 58 | /* r |Read register */ 59 | /* s |Read long burst First packet */ 60 | /* t |Read long burst Middle packet */ 61 | /* u |Read long burst End packet */ 62 | /* p |Read atomic burst packet */ 63 | /* w |Write register */ 64 | /* x |Write long burst First packet */ 65 | /* y |Write long burst Middle packet */ 66 | /* z |Write long burst End packet */ 67 | /* a |Write atomic burst packet */ 68 | /*------------------------------------------------------*/ 69 | /* b |lgw_receive cmd */ 70 | /* c |lgw_rxrf_setconf cmd */ 71 | /* d |int lgw_rxif_setconf_cmd */ 72 | /* f |int lgw_send cmd */ 73 | /* h |lgw_txgain_setconf */ 74 | /* q |lgw_trigger */ 75 | /* i |lgw_board_setconf */ 76 | /* j |lgw_calibration_snapshot */ 77 | /* l |lgw_check_fw_version */ 78 | /* m |Reset STM32 */ 79 | /* n |Go to bootloader */ 80 | /********************************************************/ 81 | 82 | typedef struct { 83 | char id; /*!> command ID */ 84 | uint8_t len_msb; /*!> command length MSB */ 85 | uint8_t len_lsb; /*!> command length LSB */ 86 | uint8_t address; /*!> register address for register read/write commands */ 87 | uint8_t cmd_data[CMD_DATA_TX_SIZE]; /*!> raw data to be transfered */ 88 | } lgw_com_cmd_t; 89 | 90 | /** 91 | @struct lgw_com_ans_t 92 | @brief structure for mcu to host command answers 93 | */ 94 | typedef struct { 95 | char id; /*!> command ID */ 96 | uint8_t len_msb; /*!> command length MSB */ 97 | uint8_t len_lsb; /*!> command length LSB */ 98 | uint8_t status; /*!> command acknoledge */ 99 | uint8_t ans_data[CMD_DATA_RX_SIZE]; /*!> raw answer data */ 100 | } lgw_com_ans_t; 101 | 102 | /** 103 | @brief Generic file handle for communication bridge 104 | */ 105 | #ifdef _WIN32 106 | typedef HANDLE lgw_handle_t; 107 | #define LGW_GET_HANDLE(x) ((lgw_handle_t *)x) 108 | #elif __linux__ 109 | typedef int lgw_handle_t; 110 | #define LGW_GET_HANDLE(x) (*(lgw_handle_t *)x) 111 | #endif 112 | 113 | 114 | /* -------------------------------------------------------------------------- */ 115 | /* --- PUBLIC FUNCTIONS PROTOTYPES ------------------------------------------ */ 116 | 117 | /** 118 | @brief LoRa concentrator USB setup 119 | @param com_target_ptr pointer on a generic pointer to USB target 120 | @return status of register operation (LGW_COM_SUCCESS/LGW_COM_ERROR) 121 | */ 122 | 123 | int lgw_com_open(void **com_target_ptr, const char *com_path); 124 | 125 | /** 126 | @brief LoRa concentrator USB close 127 | @param com_target generic pointer to USB target 128 | @return status of register operation (LGW_COM_SUCCESS/LGW_COM_ERROR) 129 | */ 130 | 131 | int lgw_com_close(void *com_target); 132 | 133 | /** 134 | @brief LoRa usb bridge to spi sx1308 concentrator single-byte write 135 | @param com_target generic pointer to USB target 136 | @param address 7-bit register address 137 | @param data data byte to write 138 | @return status of register operation (LGW_COM_SUCCESS/LGW_COM_ERROR) 139 | */ 140 | int lgw_com_w(void *com_target, uint8_t com_mux_mode, uint8_t com_mux_target, uint8_t address, uint8_t data); 141 | 142 | /** 143 | @brief LoRa usb bridge to spi sx1308 concentrator single-byte read 144 | @param com_target generic pointer to USB target 145 | @param address 7-bit register address 146 | @param data data byte to write 147 | @return status of register operation (LGW_COM_SUCCESS/LGW_COM_ERROR) 148 | */ 149 | int lgw_com_r(void *com_target, uint8_t com_mux_mode, uint8_t com_mux_target, uint8_t address, uint8_t *data); 150 | 151 | /** 152 | @brief LoRa usb bridge to spi sx1308 concentrator burst (multiple-byte) write 153 | @param com_target generic pointer to USB target 154 | @param address 7-bit register address 155 | @param data pointer to byte array that will be sent to the LoRa concentrator 156 | @param size size of the transfer, in byte(s) 157 | @return status of register operation (LGW_COM_SUCCESS/LGW_COM_ERROR) 158 | */ 159 | int lgw_com_wb(void *com_target, uint8_t com_mux_mode, uint8_t com_mux_target, uint8_t address, uint8_t *data, uint16_t size); 160 | 161 | /** 162 | @brief LoRa usb bridge to spi sx1308 concentrator burst (multiple-byte) read 163 | @param com_target generic pointer to USB target 164 | @param address 7-bit register address 165 | @param data pointer to byte array that will be written from the LoRa concentrator 166 | @param size size of the transfer, in byte(s) 167 | @return status of register operation (LGW_COM_SUCCESS/LGW_COM_ERROR) 168 | */ 169 | int lgw_com_rb(void *com_target, uint8_t com_mux_mode, uint8_t com_mux_target, uint8_t address, uint8_t *data, uint16_t size); 170 | 171 | /** 172 | @brief Send command to concentrator through MCU, and wait for answer 173 | @param com_target generic pointer to USB target 174 | @param cmd command to be sent to the concentrator 175 | @param ans answer received from the concentrator 176 | @return status of operation (LGW_COM_SUCCESS/LGW_COM_ERROR) 177 | */ 178 | int lgw_com_send_command(void *com_target, lgw_com_cmd_t cmd, lgw_com_ans_t *ans); 179 | 180 | #endif 181 | 182 | /* --- EOF ------------------------------------------------------------------ */ 183 | -------------------------------------------------------------------------------- /libloragw/inc/loragw_com_linux.h: -------------------------------------------------------------------------------- 1 | /* 2 | / _____) _ | | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 5 | _____) ) ____| | | || |_| ____( (___| | | | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 7 | (C)2017 Semtech-Cycleo 8 | 9 | Description: 10 | this file contains the USB cmd to configure and communicate with 11 | the Sx1308 LoRA concentrator. 12 | An USB CDC drivers is required to establish the connection with the picogateway board. 13 | 14 | License: Revised BSD License, see LICENSE.TXT file include in the project 15 | */ 16 | 17 | 18 | #ifndef _LORAGW_com_linux_H 19 | #define _LORAGW_com_linux_H 20 | 21 | /* -------------------------------------------------------------------------- */ 22 | /* --- DEPENDANCIES --------------------------------------------------------- */ 23 | 24 | #include /* C99 types*/ 25 | 26 | #include "config.h" /* library configuration options _linux(dynamically generated) */ 27 | 28 | /* -------------------------------------------------------------------------- */ 29 | /* --- PUBLIC CONSTANTS ----------------------------------------------------- */ 30 | 31 | /* -------------------------------------------------------------------------- */ 32 | /* --- PUBLIC FUNCTIONS PROTOTYPES ------------------------------------------ */ 33 | 34 | /** 35 | @brief LoRa concentrator COM setup (configure I/O and peripherals) 36 | @param com_target_ptr pointer on a generic pointer to COM target 37 | @return status of register operation (LGW_COM_SUCCESS/LGW_COM_ERROR) 38 | */ 39 | 40 | int lgw_com_open_linux(void **com_target_ptr, const char *com_path); 41 | 42 | /** 43 | @brief LoRa concentrator COM close 44 | @param com_target generic pointer to COM target 45 | @return status of register operation (LGW_COM_SUCCESS/LGW_COM_ERROR) 46 | */ 47 | 48 | int lgw_com_close_linux(void *com_target); 49 | 50 | /** 51 | @brief LoRa concentrator COM single-byte write 52 | @param com_target generic pointer to COM target 53 | @param address 7-bit register address 54 | @param data data byte to write 55 | @return status of register operation (LGW_COM_SUCCESS/LGW_COM_ERROR) 56 | */ 57 | int lgw_com_w_linux(void *com_target, uint8_t com_mux_mode, uint8_t com_mux_target, uint8_t address, uint8_t data); 58 | 59 | /** 60 | @brief LoRa concentrator COM single-byte read 61 | @param com_target generic pointer to COM target 62 | @param address 7-bit register address 63 | @param data data byte to write 64 | @return status of register operation (LGW_COM_SUCCESS/LGW_COM_ERROR) 65 | */ 66 | int lgw_com_r_linux(void *com_target, uint8_t com_mux_mode, uint8_t com_mux_target, uint8_t address, uint8_t *data); 67 | 68 | /** 69 | @brief LoRa concentrator COM burst (multiple-byte) write 70 | @param com_target generic pointer to COM target 71 | @param address 7-bit register address 72 | @param data pointer to byte array that will be sent to the LoRa concentrator 73 | @param size size of the transfer, in byte(s) 74 | @return status of register operation (LGW_COM_SUCCESS/LGW_COM_ERROR) 75 | */ 76 | int lgw_com_wb_linux(void *com_target, uint8_t com_mux_mode, uint8_t com_mux_target, uint8_t address, uint8_t *data, uint16_t size); 77 | 78 | /** 79 | @brief LoRa concentrator COM burst (multiple-byte) read 80 | @param com_target generic pointer to COM target 81 | @param address 7-bit register address 82 | @param data pointer to byte array that will be written from the LoRa concentrator 83 | @param size size of the transfer, in byte(s) 84 | @return status of register operation (LGW_COM_SUCCESS/LGW_COM_ERROR) 85 | */ 86 | int lgw_com_rb_linux(void *com_target, uint8_t com_mux_mode, uint8_t com_mux_target, uint8_t address, uint8_t *data, uint16_t size); 87 | 88 | /** 89 | @brief Send command to LoRa concentrator through COM interface 90 | @param cmd command to be sent to the concentrator 91 | @param handle COM bridge handle 92 | @return status of operation (LGW_COM_SUCCESS/LGW_COM_ERROR) 93 | */ 94 | int lgw_com_send_cmd_linux(lgw_com_cmd_t cmd, lgw_handle_t handle); 95 | 96 | /** 97 | @brief Receive answer to the previously sent command from the LoRa concentrator through COM interface 98 | @param ans answer received from to the concentrator 99 | @param handle COM bridge handle 100 | @return status of operation (LGW_COM_SUCCESS/LGW_COM_ERROR) 101 | */ 102 | int lgw_com_receive_ans_linux(lgw_com_ans_t *ans, lgw_handle_t handle); 103 | 104 | #endif 105 | 106 | /* --- EOF ------------------------------------------------------------------ */ 107 | -------------------------------------------------------------------------------- /libloragw/inc/loragw_hal.h: -------------------------------------------------------------------------------- 1 | /* 2 | / _____) _ | | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 5 | _____) ) ____| | | || |_| ____( (___| | | | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 7 | (C)2017 Semtech-Cycleo 8 | 9 | Description: 10 | LoRa concentrator Hardware Abstraction Layer 11 | 12 | License: Revised BSD License, see LICENSE.TXT file include in the project 13 | 14 | */ 15 | 16 | 17 | #ifndef _LORAGW_HAL_H 18 | #define _LORAGW_HAL_H 19 | 20 | /* -------------------------------------------------------------------------- */ 21 | /* --- DEPENDANCIES --------------------------------------------------------- */ 22 | 23 | #include /* C99 types */ 24 | #include /* bool type */ 25 | 26 | #include "config.h" /* library configuration options (dynamically generated) */ 27 | 28 | /* -------------------------------------------------------------------------- */ 29 | /* --- PUBLIC MACROS -------------------------------------------------------- */ 30 | 31 | #define IS_LORA_BW(bw) ((bw == BW_125KHZ) || (bw == BW_250KHZ) || (bw == BW_500KHZ)) 32 | #define IS_LORA_STD_DR(dr) ((dr == DR_LORA_SF7) || (dr == DR_LORA_SF8) || (dr == DR_LORA_SF9) || (dr == DR_LORA_SF10) || (dr == DR_LORA_SF11) || (dr == DR_LORA_SF12)) 33 | #define IS_LORA_MULTI_DR(dr) ((dr & ~DR_LORA_MULTI) == 0) /* ones outside of DR_LORA_MULTI bitmask -> not a combination of LoRa datarates */ 34 | #define IS_LORA_CR(cr) ((cr == CR_LORA_4_5) || (cr == CR_LORA_4_6) || (cr == CR_LORA_4_7) || (cr == CR_LORA_4_8)) 35 | 36 | #define IS_FSK_BW(bw) ((bw >= 1) && (bw <= 7)) 37 | #define IS_FSK_DR(dr) ((dr >= DR_FSK_MIN) && (dr <= DR_FSK_MAX)) 38 | 39 | #define IS_TX_MODE(mode) ((mode == IMMEDIATE) || (mode == TIMESTAMPED) || (mode == ON_GPS)) 40 | 41 | /* -------------------------------------------------------------------------- */ 42 | /* --- PUBLIC CONSTANTS ----------------------------------------------------- */ 43 | 44 | /* return status code */ 45 | #define LGW_HAL_SUCCESS 0 46 | #define LGW_HAL_ERROR -1 47 | 48 | /* radio-specific parameters */ 49 | #define LGW_XTAL_FREQU 32000000 /* frequency of the RF reference oscillator */ 50 | #define LGW_RF_CHAIN_NB 2 /* number of RF chains */ 51 | #define LGW_RF_RX_BANDWIDTH {1000000, 1000000} /* bandwidth of the radios */ 52 | 53 | /* type of if_chain + modem */ 54 | #define IF_UNDEFINED 0 55 | #define IF_LORA_STD 0x10 /* if + standard single-SF LoRa modem */ 56 | #define IF_LORA_MULTI 0x11 /* if + LoRa receiver with multi-SF capability */ 57 | #define IF_FSK_STD 0x20 /* if + standard FSK modem */ 58 | 59 | /* concentrator chipset-specific parameters */ 60 | /* to use array parameters, declare a local const and use 'if_chain' as index */ 61 | #define LGW_IF_CHAIN_NB 10 /* number of IF+modem RX chains */ 62 | #define LGW_PKT_FIFO_SIZE 16 /* depth of the RX packet FIFO */ 63 | #define LGW_DATABUFF_SIZE 1024 /* size in bytes of the RX data buffer (contains payload & metadata) */ 64 | #define LGW_REF_BW 125000 /* typical bandwidth of data channel */ 65 | #define LGW_MULTI_NB 8 /* number of LoRa 'multi SF' chains */ 66 | #define LGW_IFMODEM_CONFIG {\ 67 | IF_LORA_MULTI, \ 68 | IF_LORA_MULTI, \ 69 | IF_LORA_MULTI, \ 70 | IF_LORA_MULTI, \ 71 | IF_LORA_MULTI, \ 72 | IF_LORA_MULTI, \ 73 | IF_LORA_MULTI, \ 74 | IF_LORA_MULTI, \ 75 | IF_LORA_STD, \ 76 | IF_FSK_STD } /* configuration of available IF chains and modems on the hardware */ 77 | 78 | /* values available for the 'modulation' parameters */ 79 | /* NOTE: arbitrary values */ 80 | #define MOD_UNDEFINED 0 81 | #define MOD_LORA 0x10 82 | #define MOD_FSK 0x20 83 | 84 | /* values available for the 'bandwidth' parameters (LoRa & FSK) */ 85 | /* NOTE: directly encode FSK RX bandwidth, do not change */ 86 | #define BW_UNDEFINED 0 87 | #define BW_500KHZ 0x01 88 | #define BW_250KHZ 0x02 89 | #define BW_125KHZ 0x03 90 | #define BW_62K5HZ 0x04 91 | #define BW_31K2HZ 0x05 92 | #define BW_15K6HZ 0x06 93 | #define BW_7K8HZ 0x07 94 | 95 | /* values available for the 'datarate' parameters */ 96 | /* NOTE: LoRa values used directly to code SF bitmask in 'multi' modem, do not change */ 97 | #define DR_UNDEFINED 0 98 | #define DR_LORA_SF7 0x02 99 | #define DR_LORA_SF8 0x04 100 | #define DR_LORA_SF9 0x08 101 | #define DR_LORA_SF10 0x10 102 | #define DR_LORA_SF11 0x20 103 | #define DR_LORA_SF12 0x40 104 | #define DR_LORA_MULTI 0x7E 105 | /* NOTE: for FSK directly use baudrate between 500 bauds and 250 kbauds */ 106 | #define DR_FSK_MIN 500 107 | #define DR_FSK_MAX 250000 108 | 109 | /* values available for the 'coderate' parameters (LoRa only) */ 110 | /* NOTE: arbitrary values */ 111 | #define CR_UNDEFINED 0 112 | #define CR_LORA_4_5 0x01 113 | #define CR_LORA_4_6 0x02 114 | #define CR_LORA_4_7 0x03 115 | #define CR_LORA_4_8 0x04 116 | 117 | /* values available for the 'status' parameter */ 118 | /* NOTE: values according to hardware specification */ 119 | #define STAT_UNDEFINED 0x00 120 | #define STAT_NO_CRC 0x01 121 | #define STAT_CRC_BAD 0x11 122 | #define STAT_CRC_OK 0x10 123 | 124 | /* values available for the 'tx_mode' parameter */ 125 | #define IMMEDIATE 0 126 | #define TIMESTAMPED 1 127 | #define ON_GPS 2 128 | //#define ON_EVENT 3 129 | //#define GPS_DELAYED 4 130 | //#define EVENT_DELAYED 5 131 | 132 | /* values available for 'select' in the status function */ 133 | #define TX_STATUS 1 134 | #define RX_STATUS 2 135 | 136 | /* status code for TX_STATUS */ 137 | /* NOTE: arbitrary values */ 138 | #define TX_STATUS_UNKNOWN 0 139 | #define TX_OFF 1 /* TX modem disabled, it will ignore commands */ 140 | #define TX_FREE 2 /* TX modem is free, ready to receive a command */ 141 | #define TX_SCHEDULED 3 /* TX modem is loaded, ready to send the packet after an event and/or delay */ 142 | #define TX_EMITTING 4 /* TX modem is emitting */ 143 | 144 | /* status code for RX_STATUS */ 145 | /* NOTE: arbitrary values */ 146 | #define RX_STATUS_UNKNOWN 0 147 | #define RX_OFF 1 /* RX modem is disabled, it will ignore commands */ 148 | #define RX_ON 2 /* RX modem is receiving */ 149 | #define RX_SUSPENDED 3 /* RX is suspended while a TX is ongoing */ 150 | 151 | /* Maximum size of Tx gain LUT */ 152 | #define TX_GAIN_LUT_SIZE_MAX 16 153 | 154 | /* -------------------------------------------------------------------------- */ 155 | /* --- PUBLIC TYPES --------------------------------------------------------- */ 156 | 157 | /** 158 | @enum lgw_radio_type_e 159 | @brief Radio types that can be found on the LoRa Gateway 160 | */ 161 | enum lgw_radio_type_e { 162 | LGW_RADIO_TYPE_NONE, 163 | LGW_RADIO_TYPE_SX1255, 164 | LGW_RADIO_TYPE_SX1257, 165 | LGW_RADIO_TYPE_SX1272, 166 | LGW_RADIO_TYPE_SX1276 167 | }; 168 | 169 | /** 170 | @struct lgw_conf_board_s 171 | @brief Configuration structure for board specificities 172 | */ 173 | struct lgw_conf_board_s { 174 | bool lorawan_public; /*!> Enable ONLY for *public* networks using the LoRa MAC protocol */ 175 | uint8_t clksrc; /*!> Index of RF chain which provides clock to concentrator */ 176 | }; 177 | 178 | /** 179 | @struct lgw_conf_rxrf_s 180 | @brief Configuration structure for a RF chain 181 | */ 182 | struct lgw_conf_rxrf_s { 183 | bool enable; /*!> enable or disable that RF chain */ 184 | uint32_t freq_hz; /*!> center frequency of the radio in Hz */ 185 | float rssi_offset; /*!> Board-specific RSSI correction factor */ 186 | enum lgw_radio_type_e type; /*!> Radio type for that RF chain (SX1255, SX1257....) */ 187 | bool tx_enable; /*!> enable or disable TX on that RF chain */ 188 | }; 189 | 190 | /** 191 | @struct lgw_conf_rxif_s 192 | @brief Configuration structure for an IF chain 193 | */ 194 | struct lgw_conf_rxif_s { 195 | bool enable; /*!> enable or disable that IF chain */ 196 | uint8_t rf_chain; /*!> to which RF chain is that IF chain associated */ 197 | int32_t freq_hz; /*!> center frequ of the IF chain, relative to RF chain frequency */ 198 | uint8_t bandwidth; /*!> RX bandwidth, 0 for default */ 199 | uint32_t datarate; /*!> RX datarate, 0 for default */ 200 | uint8_t sync_word_size; /*!> size of FSK sync word (number of bytes, 0 for default) */ 201 | uint64_t sync_word; /*!> FSK sync word (ALIGN RIGHT, eg. 0xC194C1) */ 202 | }; 203 | 204 | /** 205 | @struct lgw_pkt_rx_s 206 | @brief Structure containing the metadata of a packet that was received and a pointer to the payload 207 | */ 208 | struct lgw_pkt_rx_s { 209 | uint32_t freq_hz; /*!> central frequency of the IF chain */ 210 | uint8_t if_chain; /*!> by which IF chain was packet received */ 211 | uint8_t status; /*!> status of the received packet */ 212 | uint32_t count_us; /*!> internal concentrator counter for timestamping, 1 microsecond resolution */ 213 | uint8_t rf_chain; /*!> through which RF chain the packet was received */ 214 | uint8_t modulation; /*!> modulation used by the packet */ 215 | uint8_t bandwidth; /*!> modulation bandwidth (LoRa only) */ 216 | uint32_t datarate; /*!> RX datarate of the packet (SF for LoRa) */ 217 | uint8_t coderate; /*!> error-correcting code of the packet (LoRa only) */ 218 | float rssi; /*!> average packet RSSI in dB */ 219 | float snr; /*!> average packet SNR, in dB (LoRa only) */ 220 | float snr_min; /*!> minimum packet SNR, in dB (LoRa only) */ 221 | float snr_max; /*!> maximum packet SNR, in dB (LoRa only) */ 222 | uint16_t crc; /*!> CRC that was received in the payload */ 223 | uint16_t size; /*!> payload size in bytes */ 224 | uint8_t payload[256]; /*!> buffer containing the payload */ 225 | }; 226 | #define LGW_PKT_RX_METADATA_SIZE_ALIGNED 44 227 | /* ---------- WARNING ------------- 228 | This metadata size is used to convert the byte array received from the MCU to a 229 | lgw_pkt_rx_s structure. Structure members are 64-bits aligned in the byte array. 230 | Any modification of this structure has to be done with caution! 231 | --------------WARNING ------------- */ 232 | #define LGW_PKT_RX_STRUCT_SIZE_ALIGNED (256 + LGW_PKT_RX_METADATA_SIZE_ALIGNED) 233 | 234 | /** 235 | @struct lgw_pkt_tx_s 236 | @brief Structure containing the configuration of a packet to send and a pointer to the payload 237 | */ 238 | struct lgw_pkt_tx_s { 239 | uint32_t freq_hz; /*!> center frequency of TX */ 240 | uint8_t tx_mode; /*!> select on what event/time the TX is triggered */ 241 | uint32_t count_us; /*!> timestamp or delay in microseconds for TX trigger */ 242 | uint8_t rf_chain; /*!> through which RF chain will the packet be sent */ 243 | int8_t rf_power; /*!> TX power, in dBm */ 244 | uint8_t modulation; /*!> modulation to use for the packet */ 245 | uint8_t bandwidth; /*!> modulation bandwidth (LoRa only) */ 246 | uint32_t datarate; /*!> TX datarate (baudrate for FSK, SF for LoRa) */ 247 | uint8_t coderate; /*!> error-correcting code of the packet (LoRa only) */ 248 | bool invert_pol; /*!> invert signal polarity, for orthogonal downlinks (LoRa only) */ 249 | uint8_t f_dev; /*!> frequency deviation, in kHz (FSK only) */ 250 | uint16_t preamble; /*!> set the preamble length, 0 for default */ 251 | bool no_crc; /*!> if true, do not send a CRC in the packet */ 252 | bool no_header; /*!> if true, enable implicit header mode (LoRa), fixed length (FSK) */ 253 | uint16_t size; /*!> payload size in bytes */ 254 | uint8_t payload[256]; /*!> buffer containing the payload */ 255 | }; 256 | #define LGW_PKT_TX_METADATA_SIZE_ALIGNED 30 257 | /* ---------- WARNING ------------- 258 | This metadata size is used to convert a lgw_pkt_tx_s structure to the byte array 259 | sent to the MCU to. The structure members are 64-bits aligned in the byte array. 260 | Any modification of this structure has to be done with caution! 261 | --------------WARNING ------------- */ 262 | #define LGW_PKT_TX_STRUCT_SIZE_ALIGNED (256 + LGW_PKT_TX_METADATA_SIZE_ALIGNED) 263 | 264 | /** 265 | @struct lgw_tx_gain_s 266 | @brief Structure containing all gains of Tx chain 267 | */ 268 | struct lgw_tx_gain_s { 269 | uint8_t dig_gain; /*!> 2 bits, control of the digital gain of SX1301 */ 270 | uint8_t pa_gain; /*!> 2 bits, control of the external PA (SX1301 I/O) */ 271 | uint8_t dac_gain; /*!> 2 bits, control of the radio DAC */ 272 | uint8_t mix_gain; /*!> 4 bits, control of the radio mixer */ 273 | int8_t rf_power; /*!> measured TX power at the board connector, in dBm */ 274 | }; 275 | 276 | /** 277 | @struct lgw_tx_gain_lut_s 278 | @brief Structure defining the Tx gain LUT 279 | */ 280 | struct lgw_tx_gain_lut_s { 281 | struct lgw_tx_gain_s lut[TX_GAIN_LUT_SIZE_MAX]; /*!> Array of Tx gain struct */ 282 | uint8_t size; /*!> Number of LUT indexes */ 283 | }; 284 | 285 | /* -------------------------------------------------------------------------- */ 286 | /* --- PUBLIC FUNCTIONS PROTOTYPES ------------------------------------------ */ 287 | 288 | /** 289 | @brief Configure the gateway board 290 | @param conf structure containing the configuration parameters 291 | @return LGW_HAL_ERROR id the operation failed, LGW_HAL_SUCCESS else 292 | */ 293 | int lgw_board_setconf(struct lgw_conf_board_s conf); 294 | 295 | /** 296 | @brief Configure an RF chain (must configure before start) 297 | @param rf_chain number of the RF chain to configure [0, LGW_RF_CHAIN_NB - 1] 298 | @param conf structure containing the configuration parameters 299 | @return LGW_HAL_ERROR id the operation failed, LGW_HAL_SUCCESS else 300 | */ 301 | int lgw_rxrf_setconf(uint8_t rf_chain, struct lgw_conf_rxrf_s conf); 302 | 303 | /** 304 | @brief Configure an IF chain + modem (must configure before start) 305 | @param if_chain number of the IF chain + modem to configure [0, LGW_IF_CHAIN_NB - 1] 306 | @param conf structure containing the configuration parameters 307 | @return LGW_HAL_ERROR id the operation failed, LGW_HAL_SUCCESS else 308 | */ 309 | int lgw_rxif_setconf(uint8_t if_chain, struct lgw_conf_rxif_s conf); 310 | 311 | /** 312 | @brief Configure the Tx gain LUT 313 | @param pointer to structure defining the LUT 314 | @return LGW_HAL_ERROR id the operation failed, LGW_HAL_SUCCESS else 315 | */ 316 | int lgw_txgain_setconf(struct lgw_tx_gain_lut_s *conf); 317 | 318 | /** 319 | @brief Connect to the LoRa concentrator, reset it and configure it according to previously set parameters 320 | @return LGW_HAL_ERROR id the operation failed, LGW_HAL_SUCCESS else 321 | */ 322 | int lgw_start(void); 323 | 324 | /** 325 | @brief Stop the LoRa concentrator and disconnect it 326 | @return LGW_HAL_ERROR id the operation failed, LGW_HAL_SUCCESS else 327 | */ 328 | int lgw_stop(void); 329 | 330 | /** 331 | @brief A non-blocking function that will fetch up to 'max_pkt' packets from the LoRa concentrator FIFO and data buffer 332 | @param max_pkt maximum number of packet that must be retrieved (equal to the size of the array of struct) 333 | @param pkt_data pointer to an array of struct that will receive the packet metadata and payload pointers 334 | @return LGW_HAL_ERROR id the operation failed, else the number of packets retrieved 335 | */ 336 | int lgw_receive(uint8_t max_pkt, struct lgw_pkt_rx_s *pkt_data); 337 | 338 | /** 339 | @brief Schedule a packet to be send immediately or after a delay depending on tx_mode 340 | @param pkt_data structure containing the data and metadata for the packet to send 341 | @return LGW_HAL_ERROR id the operation failed, LGW_HAL_SUCCESS else 342 | 343 | /!\ When sending a packet, there is a 1.5 ms delay for the analog circuitry to start and be stable (TX_START_DELAY). 344 | In 'timestamp' mode, this is transparent: the modem is started 1.5ms before the user-set timestamp value is reached, the preamble of the packet start right when the internal timestamp counter reach target value. 345 | In 'immediate' mode, the packet is emitted as soon as possible: transferring the packet (and its parameters) from the host to the concentrator takes some time, then there is the TX_START_DELAY, then the packet is emitted. 346 | In 'triggered' mode (aka PPS/GPS mode), the packet, typically a beacon, is emitted 1.5ms after a rising edge of the trigger signal. Because there is no way to anticipate the triggering event and start the analog circuitry beforehand, that delay must be taken into account in the protocol. 347 | */ 348 | int lgw_send(struct lgw_pkt_tx_s pkt_data); 349 | 350 | /** 351 | @brief Give the the status of different part of the LoRa concentrator 352 | @param select is used to select what status we want to know 353 | @param code is used to return the status code 354 | @return LGW_HAL_ERROR id the operation failed, LGW_HAL_SUCCESS else 355 | */ 356 | int lgw_status(uint8_t select, uint8_t *code); 357 | 358 | /** 359 | @brief Abort a currently scheduled or ongoing TX 360 | @return LGW_HAL_ERROR id the operation failed, LGW_HAL_SUCCESS else 361 | */ 362 | int lgw_abort_tx(void); 363 | 364 | /** 365 | @brief Return value of internal counter when latest event (eg GPS pulse) was captured 366 | @param trig_cnt_us pointer to receive timestamp value 367 | @return LGW_HAL_ERROR id the operation failed, LGW_HAL_SUCCESS else 368 | */ 369 | int lgw_get_trigcnt(uint32_t* trig_cnt_us); 370 | 371 | /** 372 | @brief Allow user to check the version/options of the library once compiled 373 | @return pointer on a human-readable null terminated string 374 | */ 375 | const char* lgw_version_info(void); 376 | 377 | /** 378 | @brief Allow user to check the version of the concentrator MCU firmware 379 | @return An integer value representing the firmware version 380 | */ 381 | int lgw_mcu_version_info(void); 382 | 383 | /** 384 | @brief Return time on air of given packet, in milliseconds 385 | @param packet is a pointer to the packet structure 386 | @return the packet time on air in milliseconds 387 | */ 388 | uint32_t lgw_time_on_air(struct lgw_pkt_tx_s *packet); 389 | 390 | #endif 391 | 392 | /* --- EOF ------------------------------------------------------------------ */ 393 | -------------------------------------------------------------------------------- /libloragw/inc/loragw_mcu.h: -------------------------------------------------------------------------------- 1 | /* 2 | / _____) _ | | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 5 | _____) ) ____| | | || |_| ____( (___| | | | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 7 | (C)2017 Semtech-Cycleo 8 | 9 | Description: 10 | Wrapper to call MCU's HAL functions 11 | 12 | License: Revised BSD License, see LICENSE.TXT file include in the project 13 | */ 14 | 15 | #ifndef _LORAGW_MCU_H 16 | #define _LORAGW_MCU_H 17 | 18 | /* -------------------------------------------------------------------------- */ 19 | /* --- DEPENDANCIES --------------------------------------------------------- */ 20 | 21 | #include /* C99 types*/ 22 | 23 | #include "config.h" /* library configuration options (dynamically generated) */ 24 | 25 | #include "loragw_hal.h" 26 | 27 | /* -------------------------------------------------------------------------- */ 28 | /* --- PUBLIC CONSTANTS ----------------------------------------------------- */ 29 | 30 | #define LGW_MCU_SUCCESS 0 31 | #define LGW_MCU_ERROR -1 32 | 33 | #define STM32FWVERSION 0x010a0006 /* increment LSB for new version */ 34 | 35 | #define MCU_DELAY_COM_INIT 1000 36 | #define MCU_DELAY_RESET 200 37 | 38 | /* -------------------------------------------------------------------------- */ 39 | /* --- PUBLIC TYPES --------------------------------------------------------- */ 40 | 41 | /* -------------------------------------------------------------------------- */ 42 | /* --- PUBLIC FUNCTIONS PROTOTYPES ------------------------------------------ */ 43 | 44 | /** 45 | @brief Command to configure the board of the LoRa concentrator through MCU 46 | @param conf board configuration structure to be sent to MCU 47 | @return status of operation (LGW_MCU_SUCCESS/LGW_MCU_ERROR) 48 | */ 49 | int lgw_mcu_board_setconf(struct lgw_conf_board_s conf); 50 | 51 | /** 52 | @brief Command to configure an RF chain through MCU 53 | @param rfchain index of the RF chain to configure 54 | @param conf RF chain configuration structure to be sent to MCU 55 | @return status of operation (LGW_MCU_SUCCESS/LGW_MCU_ERROR) 56 | */ 57 | int lgw_mcu_rxrf_setconf(uint8_t rfchain, struct lgw_conf_rxrf_s conf); 58 | 59 | /** 60 | @brief Command to configure an IF chain through MCU 61 | @param ifchain index of the IF chain to configure 62 | @param conf IF chain configuration structure to be sent to MCU 63 | @return status of operation (LGW_MCU_SUCCESS/LGW_MCU_ERROR) 64 | */ 65 | int lgw_mcu_rxif_setconf(uint8_t ifchain, struct lgw_conf_rxif_s conf); 66 | 67 | /** 68 | @brief Command to configure the Tx gain LUT through MCU 69 | @param conf TX LUT gain table configuration structure to be sent to MCU 70 | @return status of operation (LGW_MCU_SUCCESS/LGW_MCU_ERROR) 71 | */ 72 | int lgw_mcu_txgain_setconf(struct lgw_tx_gain_lut_s *conf); 73 | 74 | /** 75 | @brief Command to receive packet from the concentrator through MCU 76 | @param max_pkt maximum number of received packets 77 | @param pkt_data array of packets received 78 | @return number of received packets 79 | */ 80 | int lgw_mcu_receive(uint8_t max_pkt, struct lgw_pkt_rx_s *pkt_data); 81 | 82 | /** 83 | @brief Command to send a packet to the concentrator through MCU 84 | @param pkt_data packet data to be sent to MCU 85 | @return status of operation (LGW_MCU_SUCCESS/LGW_MCU_ERROR) 86 | */ 87 | int lgw_mcu_send(struct lgw_pkt_tx_s pkt_data); 88 | 89 | /** 90 | @brief Command to get the value of the internal counter of the concentrator through MCU 91 | @param data pointer to byte array that will be read from the concentrator 92 | @return status of operation (LGW_MCU_SUCCESS/LGW_MCU_ERROR) 93 | */ 94 | int lgw_mcu_get_trigcnt(uint32_t *data); 95 | 96 | /** 97 | @brief Command to store radio calibration parameters to the concentrator through MCU 98 | @param idx_start start index in the MCU calibration offset table where to store the given offsets 99 | @param idx_nb the number of calibration offsets to be stored in the MCU table 100 | @return status of operation (LGW_MCU_SUCCESS/LGW_MCU_ERROR) 101 | */ 102 | int lgw_mcu_commit_radio_calibration(uint8_t idx_start, uint8_t idx_nb); 103 | 104 | /** 105 | @brief Command to reset the MCU 106 | @return status of operation (LGW_MCU_SUCCESS/LGW_MCU_ERROR) 107 | */ 108 | int lgw_mcu_reset(void); 109 | 110 | /** 111 | @brief Command to get the MCU's unique ID 112 | @return status of operation (LGW_MCU_SUCCESS/LGW_MCU_ERROR) 113 | */ 114 | int lgw_mcu_get_unique_id(uint8_t *uid); 115 | 116 | #endif 117 | 118 | /* --- EOF ------------------------------------------------------------------ */ 119 | -------------------------------------------------------------------------------- /libloragw/inc/loragw_radio.h: -------------------------------------------------------------------------------- 1 | /* 2 | / _____) _ | | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 5 | _____) ) ____| | | || |_| ____( (___| | | | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 7 | (C)2017 Semtech-Cycleo 8 | 9 | Description: 10 | Functions used to handle LoRa concentrator radios. 11 | 12 | License: Revised BSD License, see LICENSE.TXT file include in the project 13 | 14 | */ 15 | 16 | #ifndef _LORAGW_RADIO_H 17 | #define _LORAGW_RADIO_H 18 | 19 | /* -------------------------------------------------------------------------- */ 20 | /* --- DEPENDANCIES --------------------------------------------------------- */ 21 | 22 | #include /* C99 types */ 23 | #include /* bool type */ 24 | 25 | /* -------------------------------------------------------------------------- */ 26 | /* --- PUBLIC CONSTANTS ----------------------------------------------------- */ 27 | 28 | #define LGW_REG_SUCCESS 0 29 | #define LGW_REG_ERROR -1 30 | 31 | #define SX125x_32MHz_FRAC 15625 /* irreductible fraction for PLL register caculation */ 32 | 33 | /* -------------------------------------------------------------------------- */ 34 | /* --- PUBLIC CONSTANTS ----------------------------------------------------- */ 35 | 36 | /* -------------------------------------------------------------------------- */ 37 | /* --- PUBLIC FUNCTIONS PROTOTYPES ------------------------------------------ */ 38 | 39 | int lgw_setup_sx125x(uint8_t rf_chain, uint8_t rf_clkout, bool rf_enable, uint8_t rf_radio_type, uint32_t freq_hz); 40 | 41 | #endif 42 | /* --- EOF ------------------------------------------------------------------ */ 43 | -------------------------------------------------------------------------------- /libloragw/inc/loragw_reg.h: -------------------------------------------------------------------------------- 1 | /* 2 | / _____) _ | | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 5 | _____) ) ____| | | || |_| ____( (___| | | | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 7 | (C)2017 Semtech-Cycleo 8 | 9 | Description: 10 | Functions used to handle a single LoRa concentrator. 11 | Registers are addressed by name. 12 | Multi-bytes registers are handled automatically. 13 | Read-modify-write is handled automatically. 14 | 15 | License: Revised BSD License, see LICENSE.TXT file include in the project 16 | 17 | */ 18 | 19 | #ifndef _LORAGW_REG_H 20 | #define _LORAGW_REG_H 21 | 22 | /* -------------------------------------------------------------------------- */ 23 | /* --- DEPENDANCIES --------------------------------------------------------- */ 24 | 25 | #include /* C99 types */ 26 | #include /* bool type */ 27 | 28 | #include "config.h" /* library configuration options (dynamically generated) */ 29 | 30 | /* -------------------------------------------------------------------------- */ 31 | /* --- INTERNAL SHARED TYPES ------------------------------------------------ */ 32 | 33 | struct lgw_reg_s { 34 | int8_t page; /*!< page containing the register (-1 for all pages) */ 35 | uint8_t addr; /*!< base address of the register (7 bit) */ 36 | uint8_t offs; /*!< position of the register LSB (between 0 to 7) */ 37 | bool sign; /*!< 1 indicates the register is signed (2 complem.) */ 38 | uint8_t leng; /*!< number of bits in the register */ 39 | bool rdon; /*!< 1 indicates a read-only register */ 40 | int32_t dflt; /*!< register default value */ 41 | }; 42 | 43 | /* -------------------------------------------------------------------------- */ 44 | /* --- INTERNAL SHARED FUNCTIONS -------------------------------------------- */ 45 | 46 | int reg_w_align32(void *com_target, uint8_t com_mux_mode, uint8_t com_mux_target, struct lgw_reg_s r, int32_t reg_value); 47 | int reg_r_align32(void *com_target, uint8_t com_mux_mode, uint8_t com_mux_target, struct lgw_reg_s r, int32_t *reg_value); 48 | 49 | /* -------------------------------------------------------------------------- */ 50 | /* --- PUBLIC CONSTANTS ----------------------------------------------------- */ 51 | 52 | #define LGW_REG_SUCCESS 0 53 | #define LGW_REG_ERROR -1 54 | 55 | /* 56 | auto generated register mapping for C code : 11-Jul-2013 13:20:40 57 | this file contains autogenerated C struct used to access the LORA registers 58 | this file is autogenerated from registers description 59 | 293 registers are defined 60 | */ 61 | 62 | #define LGW_PAGE_REG 0 63 | #define LGW_SOFT_RESET 1 64 | #define LGW_VERSION 2 65 | #define LGW_RX_DATA_BUF_ADDR 3 66 | #define LGW_RX_DATA_BUF_DATA 4 67 | #define LGW_TX_DATA_BUF_ADDR 5 68 | #define LGW_TX_DATA_BUF_DATA 6 69 | #define LGW_CAPTURE_RAM_ADDR 7 70 | #define LGW_CAPTURE_RAM_DATA 8 71 | #define LGW_MCU_PROM_ADDR 9 72 | #define LGW_MCU_PROM_DATA 10 73 | #define LGW_RX_PACKET_DATA_FIFO_NUM_STORED 11 74 | #define LGW_RX_PACKET_DATA_FIFO_ADDR_POINTER 12 75 | #define LGW_RX_PACKET_DATA_FIFO_STATUS 13 76 | #define LGW_RX_PACKET_DATA_FIFO_PAYLOAD_SIZE 14 77 | #define LGW_MBWSSF_MODEM_ENABLE 15 78 | #define LGW_CONCENTRATOR_MODEM_ENABLE 16 79 | #define LGW_FSK_MODEM_ENABLE 17 80 | #define LGW_GLOBAL_EN 18 81 | #define LGW_CLK32M_EN 19 82 | #define LGW_CLKHS_EN 20 83 | #define LGW_START_BIST0 21 84 | #define LGW_START_BIST1 22 85 | #define LGW_CLEAR_BIST0 23 86 | #define LGW_CLEAR_BIST1 24 87 | #define LGW_BIST0_FINISHED 25 88 | #define LGW_BIST1_FINISHED 26 89 | #define LGW_MCU_AGC_PROG_RAM_BIST_STATUS 27 90 | #define LGW_MCU_ARB_PROG_RAM_BIST_STATUS 28 91 | #define LGW_CAPTURE_RAM_BIST_STATUS 29 92 | #define LGW_CHAN_FIR_RAM0_BIST_STATUS 30 93 | #define LGW_CHAN_FIR_RAM1_BIST_STATUS 31 94 | #define LGW_CORR0_RAM_BIST_STATUS 32 95 | #define LGW_CORR1_RAM_BIST_STATUS 33 96 | #define LGW_CORR2_RAM_BIST_STATUS 34 97 | #define LGW_CORR3_RAM_BIST_STATUS 35 98 | #define LGW_CORR4_RAM_BIST_STATUS 36 99 | #define LGW_CORR5_RAM_BIST_STATUS 37 100 | #define LGW_CORR6_RAM_BIST_STATUS 38 101 | #define LGW_CORR7_RAM_BIST_STATUS 39 102 | #define LGW_MODEM0_RAM0_BIST_STATUS 40 103 | #define LGW_MODEM1_RAM0_BIST_STATUS 41 104 | #define LGW_MODEM2_RAM0_BIST_STATUS 42 105 | #define LGW_MODEM3_RAM0_BIST_STATUS 43 106 | #define LGW_MODEM4_RAM0_BIST_STATUS 44 107 | #define LGW_MODEM5_RAM0_BIST_STATUS 45 108 | #define LGW_MODEM6_RAM0_BIST_STATUS 46 109 | #define LGW_MODEM7_RAM0_BIST_STATUS 47 110 | #define LGW_MODEM0_RAM1_BIST_STATUS 48 111 | #define LGW_MODEM1_RAM1_BIST_STATUS 49 112 | #define LGW_MODEM2_RAM1_BIST_STATUS 50 113 | #define LGW_MODEM3_RAM1_BIST_STATUS 51 114 | #define LGW_MODEM4_RAM1_BIST_STATUS 52 115 | #define LGW_MODEM5_RAM1_BIST_STATUS 53 116 | #define LGW_MODEM6_RAM1_BIST_STATUS 54 117 | #define LGW_MODEM7_RAM1_BIST_STATUS 55 118 | #define LGW_MODEM0_RAM2_BIST_STATUS 56 119 | #define LGW_MODEM1_RAM2_BIST_STATUS 57 120 | #define LGW_MODEM2_RAM2_BIST_STATUS 58 121 | #define LGW_MODEM3_RAM2_BIST_STATUS 59 122 | #define LGW_MODEM4_RAM2_BIST_STATUS 60 123 | #define LGW_MODEM5_RAM2_BIST_STATUS 61 124 | #define LGW_MODEM6_RAM2_BIST_STATUS 62 125 | #define LGW_MODEM7_RAM2_BIST_STATUS 63 126 | #define LGW_MODEM_MBWSSF_RAM0_BIST_STATUS 64 127 | #define LGW_MODEM_MBWSSF_RAM1_BIST_STATUS 65 128 | #define LGW_MODEM_MBWSSF_RAM2_BIST_STATUS 66 129 | #define LGW_MCU_AGC_DATA_RAM_BIST0_STATUS 67 130 | #define LGW_MCU_AGC_DATA_RAM_BIST1_STATUS 68 131 | #define LGW_MCU_ARB_DATA_RAM_BIST0_STATUS 69 132 | #define LGW_MCU_ARB_DATA_RAM_BIST1_STATUS 70 133 | #define LGW_TX_TOP_RAM_BIST0_STATUS 71 134 | #define LGW_TX_TOP_RAM_BIST1_STATUS 72 135 | #define LGW_DATA_MNGT_RAM_BIST0_STATUS 73 136 | #define LGW_DATA_MNGT_RAM_BIST1_STATUS 74 137 | #define LGW_GPIO_SELECT_INPUT 75 138 | #define LGW_GPIO_SELECT_OUTPUT 76 139 | #define LGW_GPIO_MODE 77 140 | #define LGW_GPIO_PIN_REG_IN 78 141 | #define LGW_GPIO_PIN_REG_OUT 79 142 | #define LGW_MCU_AGC_STATUS 80 143 | #define LGW_MCU_ARB_STATUS 81 144 | #define LGW_CHIP_ID 82 145 | #define LGW_EMERGENCY_FORCE_HOST_CTRL 83 146 | #define LGW_RX_INVERT_IQ 84 147 | #define LGW_MODEM_INVERT_IQ 85 148 | #define LGW_MBWSSF_MODEM_INVERT_IQ 86 149 | #define LGW_RX_EDGE_SELECT 87 150 | #define LGW_MISC_RADIO_EN 88 151 | #define LGW_FSK_MODEM_INVERT_IQ 89 152 | #define LGW_FILTER_GAIN 90 153 | #define LGW_RADIO_SELECT 91 154 | #define LGW_IF_FREQ_0 92 155 | #define LGW_IF_FREQ_1 93 156 | #define LGW_IF_FREQ_2 94 157 | #define LGW_IF_FREQ_3 95 158 | #define LGW_IF_FREQ_4 96 159 | #define LGW_IF_FREQ_5 97 160 | #define LGW_IF_FREQ_6 98 161 | #define LGW_IF_FREQ_7 99 162 | #define LGW_IF_FREQ_8 100 163 | #define LGW_IF_FREQ_9 101 164 | #define LGW_CHANN_OVERRIDE_AGC_GAIN 102 165 | #define LGW_CHANN_AGC_GAIN 103 166 | #define LGW_CORR0_DETECT_EN 104 167 | #define LGW_CORR1_DETECT_EN 105 168 | #define LGW_CORR2_DETECT_EN 106 169 | #define LGW_CORR3_DETECT_EN 107 170 | #define LGW_CORR4_DETECT_EN 108 171 | #define LGW_CORR5_DETECT_EN 109 172 | #define LGW_CORR6_DETECT_EN 110 173 | #define LGW_CORR7_DETECT_EN 111 174 | #define LGW_CORR_SAME_PEAKS_OPTION_SF6 112 175 | #define LGW_CORR_SAME_PEAKS_OPTION_SF7 113 176 | #define LGW_CORR_SAME_PEAKS_OPTION_SF8 114 177 | #define LGW_CORR_SAME_PEAKS_OPTION_SF9 115 178 | #define LGW_CORR_SAME_PEAKS_OPTION_SF10 116 179 | #define LGW_CORR_SAME_PEAKS_OPTION_SF11 117 180 | #define LGW_CORR_SAME_PEAKS_OPTION_SF12 118 181 | #define LGW_CORR_SIG_NOISE_RATIO_SF6 119 182 | #define LGW_CORR_SIG_NOISE_RATIO_SF7 120 183 | #define LGW_CORR_SIG_NOISE_RATIO_SF8 121 184 | #define LGW_CORR_SIG_NOISE_RATIO_SF9 122 185 | #define LGW_CORR_SIG_NOISE_RATIO_SF10 123 186 | #define LGW_CORR_SIG_NOISE_RATIO_SF11 124 187 | #define LGW_CORR_SIG_NOISE_RATIO_SF12 125 188 | #define LGW_CORR_NUM_SAME_PEAK 126 189 | #define LGW_CORR_MAC_GAIN 127 190 | #define LGW_ADJUST_MODEM_START_OFFSET_RDX4 128 191 | #define LGW_ADJUST_MODEM_START_OFFSET_SF12_RDX4 129 192 | #define LGW_DBG_CORR_SELECT_SF 130 193 | #define LGW_DBG_CORR_SELECT_CHANNEL 131 194 | #define LGW_DBG_DETECT_CPT 132 195 | #define LGW_DBG_SYMB_CPT 133 196 | #define LGW_CHIRP_INVERT_RX 134 197 | #define LGW_DC_NOTCH_EN 135 198 | #define LGW_IMPLICIT_CRC_EN 136 199 | #define LGW_IMPLICIT_CODING_RATE 137 200 | #define LGW_IMPLICIT_PAYLOAD_LENGHT 138 201 | #define LGW_FREQ_TO_TIME_INVERT 139 202 | #define LGW_FREQ_TO_TIME_DRIFT 140 203 | #define LGW_PAYLOAD_FINE_TIMING_GAIN 141 204 | #define LGW_PREAMBLE_FINE_TIMING_GAIN 142 205 | #define LGW_TRACKING_INTEGRAL 143 206 | #define LGW_FRAME_SYNCH_PEAK1_POS 144 207 | #define LGW_FRAME_SYNCH_PEAK2_POS 145 208 | #define LGW_PREAMBLE_SYMB1_NB 146 209 | #define LGW_FRAME_SYNCH_GAIN 147 210 | #define LGW_SYNCH_DETECT_TH 148 211 | #define LGW_LLR_SCALE 149 212 | #define LGW_SNR_AVG_CST 150 213 | #define LGW_PPM_OFFSET 151 214 | #define LGW_MAX_PAYLOAD_LEN 152 215 | #define LGW_ONLY_CRC_EN 153 216 | #define LGW_ZERO_PAD 154 217 | #define LGW_DEC_GAIN_OFFSET 155 218 | #define LGW_CHAN_GAIN_OFFSET 156 219 | #define LGW_FORCE_HOST_RADIO_CTRL 157 220 | #define LGW_FORCE_HOST_FE_CTRL 158 221 | #define LGW_FORCE_DEC_FILTER_GAIN 159 222 | #define LGW_MCU_RST_0 160 223 | #define LGW_MCU_RST_1 161 224 | #define LGW_MCU_SELECT_MUX_0 162 225 | #define LGW_MCU_SELECT_MUX_1 163 226 | #define LGW_MCU_CORRUPTION_DETECTED_0 164 227 | #define LGW_MCU_CORRUPTION_DETECTED_1 165 228 | #define LGW_MCU_SELECT_EDGE_0 166 229 | #define LGW_MCU_SELECT_EDGE_1 167 230 | #define LGW_CHANN_SELECT_RSSI 168 231 | #define LGW_RSSI_BB_DEFAULT_VALUE 169 232 | #define LGW_RSSI_DEC_DEFAULT_VALUE 170 233 | #define LGW_RSSI_CHANN_DEFAULT_VALUE 171 234 | #define LGW_RSSI_BB_FILTER_ALPHA 172 235 | #define LGW_RSSI_DEC_FILTER_ALPHA 173 236 | #define LGW_RSSI_CHANN_FILTER_ALPHA 174 237 | #define LGW_IQ_MISMATCH_A_AMP_COEFF 175 238 | #define LGW_IQ_MISMATCH_A_PHI_COEFF 176 239 | #define LGW_IQ_MISMATCH_B_AMP_COEFF 177 240 | #define LGW_IQ_MISMATCH_B_SEL_I 178 241 | #define LGW_IQ_MISMATCH_B_PHI_COEFF 179 242 | #define LGW_TX_TRIG_IMMEDIATE 180 243 | #define LGW_TX_TRIG_DELAYED 181 244 | #define LGW_TX_TRIG_GPS 182 245 | #define LGW_TX_START_DELAY 183 246 | #define LGW_TX_FRAME_SYNCH_PEAK1_POS 184 247 | #define LGW_TX_FRAME_SYNCH_PEAK2_POS 185 248 | #define LGW_TX_RAMP_DURATION 186 249 | #define LGW_TX_OFFSET_I 187 250 | #define LGW_TX_OFFSET_Q 188 251 | #define LGW_TX_MODE 189 252 | #define LGW_TX_ZERO_PAD 190 253 | #define LGW_TX_EDGE_SELECT 191 254 | #define LGW_TX_EDGE_SELECT_TOP 192 255 | #define LGW_TX_GAIN 193 256 | #define LGW_TX_CHIRP_LOW_PASS 194 257 | #define LGW_TX_FCC_WIDEBAND 195 258 | #define LGW_TX_SWAP_IQ 196 259 | #define LGW_MBWSSF_IMPLICIT_HEADER 197 260 | #define LGW_MBWSSF_IMPLICIT_CRC_EN 198 261 | #define LGW_MBWSSF_IMPLICIT_CODING_RATE 199 262 | #define LGW_MBWSSF_IMPLICIT_PAYLOAD_LENGHT 200 263 | #define LGW_MBWSSF_AGC_FREEZE_ON_DETECT 201 264 | #define LGW_MBWSSF_FRAME_SYNCH_PEAK1_POS 202 265 | #define LGW_MBWSSF_FRAME_SYNCH_PEAK2_POS 203 266 | #define LGW_MBWSSF_PREAMBLE_SYMB1_NB 204 267 | #define LGW_MBWSSF_FRAME_SYNCH_GAIN 205 268 | #define LGW_MBWSSF_SYNCH_DETECT_TH 206 269 | #define LGW_MBWSSF_DETECT_MIN_SINGLE_PEAK 207 270 | #define LGW_MBWSSF_DETECT_TRIG_SAME_PEAK_NB 208 271 | #define LGW_MBWSSF_FREQ_TO_TIME_INVERT 209 272 | #define LGW_MBWSSF_FREQ_TO_TIME_DRIFT 210 273 | #define LGW_MBWSSF_PPM_CORRECTION 211 274 | #define LGW_MBWSSF_PAYLOAD_FINE_TIMING_GAIN 212 275 | #define LGW_MBWSSF_PREAMBLE_FINE_TIMING_GAIN 213 276 | #define LGW_MBWSSF_TRACKING_INTEGRAL 214 277 | #define LGW_MBWSSF_ZERO_PAD 215 278 | #define LGW_MBWSSF_MODEM_BW 216 279 | #define LGW_MBWSSF_RADIO_SELECT 217 280 | #define LGW_MBWSSF_RX_CHIRP_INVERT 218 281 | #define LGW_MBWSSF_LLR_SCALE 219 282 | #define LGW_MBWSSF_SNR_AVG_CST 220 283 | #define LGW_MBWSSF_PPM_OFFSET 221 284 | #define LGW_MBWSSF_RATE_SF 222 285 | #define LGW_MBWSSF_ONLY_CRC_EN 223 286 | #define LGW_MBWSSF_MAX_PAYLOAD_LEN 224 287 | #define LGW_TX_STATUS 225 288 | #define LGW_FSK_CH_BW_EXPO 226 289 | #define LGW_FSK_RSSI_LENGTH 227 290 | #define LGW_FSK_RX_INVERT 228 291 | #define LGW_FSK_PKT_MODE 229 292 | #define LGW_FSK_PSIZE 230 293 | #define LGW_FSK_CRC_EN 231 294 | #define LGW_FSK_DCFREE_ENC 232 295 | #define LGW_FSK_CRC_IBM 233 296 | #define LGW_FSK_ERROR_OSR_TOL 234 297 | #define LGW_FSK_RADIO_SELECT 235 298 | #define LGW_FSK_BR_RATIO 236 299 | #define LGW_FSK_REF_PATTERN_LSB 237 300 | #define LGW_FSK_REF_PATTERN_MSB 238 301 | #define LGW_FSK_PKT_LENGTH 239 302 | #define LGW_FSK_TX_GAUSSIAN_EN 240 303 | #define LGW_FSK_TX_GAUSSIAN_SELECT_BT 241 304 | #define LGW_FSK_TX_PATTERN_EN 242 305 | #define LGW_FSK_TX_PREAMBLE_SEQ 243 306 | #define LGW_FSK_TX_PSIZE 244 307 | #define LGW_FSK_NODE_ADRS 245 308 | #define LGW_FSK_BROADCAST 246 309 | #define LGW_FSK_AUTO_AFC_ON 247 310 | #define LGW_FSK_PATTERN_TIMEOUT_CFG 248 311 | #define LGW_SPI_RADIO_A__DATA 249 312 | #define LGW_SPI_RADIO_A__DATA_READBACK 250 313 | #define LGW_SPI_RADIO_A__ADDR 251 314 | #define LGW_SPI_RADIO_A__CS 252 315 | #define LGW_SPI_RADIO_B__DATA 253 316 | #define LGW_SPI_RADIO_B__DATA_READBACK 254 317 | #define LGW_SPI_RADIO_B__ADDR 255 318 | #define LGW_SPI_RADIO_B__CS 256 319 | #define LGW_RADIO_A_EN 257 320 | #define LGW_RADIO_B_EN 258 321 | #define LGW_RADIO_RST 259 322 | #define LGW_LNA_A_EN 260 323 | #define LGW_PA_A_EN 261 324 | #define LGW_LNA_B_EN 262 325 | #define LGW_PA_B_EN 263 326 | #define LGW_PA_GAIN 264 327 | #define LGW_LNA_A_CTRL_LUT 265 328 | #define LGW_PA_A_CTRL_LUT 266 329 | #define LGW_LNA_B_CTRL_LUT 267 330 | #define LGW_PA_B_CTRL_LUT 268 331 | #define LGW_CAPTURE_SOURCE 269 332 | #define LGW_CAPTURE_START 270 333 | #define LGW_CAPTURE_FORCE_TRIGGER 271 334 | #define LGW_CAPTURE_WRAP 272 335 | #define LGW_CAPTURE_PERIOD 273 336 | #define LGW_MODEM_STATUS 274 337 | #define LGW_VALID_HEADER_COUNTER_0 275 338 | #define LGW_VALID_PACKET_COUNTER_0 276 339 | #define LGW_VALID_HEADER_COUNTER_MBWSSF 277 340 | #define LGW_VALID_HEADER_COUNTER_FSK 278 341 | #define LGW_VALID_PACKET_COUNTER_MBWSSF 279 342 | #define LGW_VALID_PACKET_COUNTER_FSK 280 343 | #define LGW_CHANN_RSSI 281 344 | #define LGW_BB_RSSI 282 345 | #define LGW_DEC_RSSI 283 346 | #define LGW_DBG_MCU_DATA 284 347 | #define LGW_DBG_ARB_MCU_RAM_DATA 285 348 | #define LGW_DBG_AGC_MCU_RAM_DATA 286 349 | #define LGW_NEXT_PACKET_CNT 287 350 | #define LGW_ADDR_CAPTURE_COUNT 288 351 | #define LGW_TIMESTAMP 289 352 | #define LGW_DBG_CHANN0_GAIN 290 353 | #define LGW_DBG_CHANN1_GAIN 291 354 | #define LGW_DBG_CHANN2_GAIN 292 355 | #define LGW_DBG_CHANN3_GAIN 293 356 | #define LGW_DBG_CHANN4_GAIN 294 357 | #define LGW_DBG_CHANN5_GAIN 295 358 | #define LGW_DBG_CHANN6_GAIN 296 359 | #define LGW_DBG_CHANN7_GAIN 297 360 | #define LGW_DBG_DEC_FILT_GAIN 298 361 | #define LGW_SPI_DATA_FIFO_PTR 299 362 | #define LGW_PACKET_DATA_FIFO_PTR 300 363 | #define LGW_DBG_ARB_MCU_RAM_ADDR 301 364 | #define LGW_DBG_AGC_MCU_RAM_ADDR 302 365 | #define LGW_SPI_MASTER_CHIP_SELECT_POLARITY 303 366 | #define LGW_SPI_MASTER_CPOL 304 367 | #define LGW_SPI_MASTER_CPHA 305 368 | #define LGW_SIG_GEN_ANALYSER_MUX_SEL 306 369 | #define LGW_SIG_GEN_EN 307 370 | #define LGW_SIG_ANALYSER_EN 308 371 | #define LGW_SIG_ANALYSER_AVG_LEN 309 372 | #define LGW_SIG_ANALYSER_PRECISION 310 373 | #define LGW_SIG_ANALYSER_VALID_OUT 311 374 | #define LGW_SIG_GEN_FREQ 312 375 | #define LGW_SIG_ANALYSER_FREQ 313 376 | #define LGW_SIG_ANALYSER_I_OUT 314 377 | #define LGW_SIG_ANALYSER_Q_OUT 315 378 | #define LGW_GPS_EN 316 379 | #define LGW_GPS_POL 317 380 | #define LGW_SW_TEST_REG1 318 381 | #define LGW_SW_TEST_REG2 319 382 | #define LGW_SW_TEST_REG3 320 383 | #define LGW_DATA_MNGT_STATUS 321 384 | #define LGW_DATA_MNGT_CPT_FRAME_ALLOCATED 322 385 | #define LGW_DATA_MNGT_CPT_FRAME_FINISHED 323 386 | #define LGW_DATA_MNGT_CPT_FRAME_READEN 324 387 | #define LGW_TX_TRIG_ALL 325 388 | 389 | #define LGW_TOTALREGS 326 390 | 391 | /* -------------------------------------------------------------------------- */ 392 | /* --- PUBLIC FUNCTIONS PROTOTYPES ------------------------------------------ */ 393 | 394 | /** 395 | @brief Connect LoRa concentrator by opening communication link 396 | @return status of register operation (LGW_REG_SUCCESS/LGW_REG_ERROR) 397 | */ 398 | int lgw_connect(const char *com_path); 399 | 400 | /** 401 | @brief Disconnect LoRa concentrator by closing SPI link 402 | @return status of register operation (LGW_REG_SUCCESS/LGW_REG_ERROR) 403 | */ 404 | int lgw_disconnect(void); 405 | 406 | /** 407 | @brief Use the soft-reset register to put the concentrator in initial state 408 | @return status of register operation (LGW_REG_SUCCESS/LGW_REG_ERROR) 409 | */ 410 | int lgw_soft_reset(void); 411 | 412 | /** 413 | @brief Check if the registers are ok, send diagnostics to stdio/stderr/file 414 | @param f file descriptor to to which the check result will be written 415 | @return status of register operation (LGW_REG_SUCCESS/LGW_REG_ERROR) 416 | */ 417 | int lgw_reg_check(FILE *f); 418 | 419 | /** 420 | @brief LoRa concentrator register write 421 | @param register_id register number in the data structure describing registers 422 | @param reg_value signed value to write to the register (for u32, use cast) 423 | @return status of register operation (LGW_REG_SUCCESS/LGW_REG_ERROR) 424 | */ 425 | int lgw_reg_w(uint16_t register_id, int32_t reg_value); 426 | 427 | /** 428 | @brief LoRa concentrator register read 429 | @param register_id register number in the data structure describing registers 430 | @param reg_value pointer to a variable where to write register read value 431 | @return status of register operation (LGW_REG_SUCCESS/LGW_REG_ERROR) 432 | */ 433 | int lgw_reg_r(uint16_t register_id, int32_t *reg_value); 434 | 435 | /** 436 | @brief LoRa concentrator register burst write 437 | @param register_id register number in the data structure describing registers 438 | @param data pointer to byte array that will be sent to the LoRa concentrator 439 | @param size size of the transfer, in byte(s) 440 | @return status of register operation (LGW_REG_SUCCESS/LGW_REG_ERROR) 441 | */ 442 | int lgw_reg_wb(uint16_t register_id, uint8_t *data, uint16_t size); 443 | 444 | /** 445 | @brief LoRa concentrator register burst read 446 | @param register_id register number in the data structure describing registers 447 | @param data pointer to byte array that will be written from the LoRa concentrator 448 | @param size size of the transfer, in byte(s) 449 | @return status of register operation (LGW_REG_SUCCESS/LGW_REG_ERROR) 450 | */ 451 | int lgw_reg_rb(uint16_t register_id, uint8_t *data, uint16_t size); 452 | 453 | #endif 454 | 455 | /* --- EOF ------------------------------------------------------------------ */ 456 | -------------------------------------------------------------------------------- /libloragw/inc/loragw_sx125x.h: -------------------------------------------------------------------------------- 1 | /* 2 | / _____) _ | | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 5 | _____) ) ____| | | || |_| ____( (___| | | | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 7 | (C)2017 Semtech 8 | 9 | Description: SX125x radio registers and constant definitions 10 | 11 | License: Revised BSD License, see LICENSE.TXT file include in the project 12 | 13 | 14 | */ 15 | #ifndef __SX125X_REGS_H__ 16 | #define __SX125X_REGS_H__ 17 | 18 | /* 19 | SX1257 frequency setting : 20 | F_register(24bit) = F_rf (Hz) / F_step(Hz) 21 | = F_rf (Hz) * 2^19 / F_xtal(Hz) 22 | = F_rf (Hz) * 2^19 / 32e6 23 | = F_rf (Hz) * 256/15625 24 | 25 | SX1255 frequency setting : 26 | F_register(24bit) = F_rf (Hz) / F_step(Hz) 27 | = F_rf (Hz) * 2^20 / F_xtal(Hz) 28 | = F_rf (Hz) * 2^20 / 32e6 29 | = F_rf (Hz) * 512/15625 30 | */ 31 | 32 | #define SX125x_TX_DAC_CLK_SEL 1 /* 0:int, 1:ext */ 33 | #define SX125x_TX_DAC_GAIN 2 /* 3:0, 2:-3, 1:-6, 0:-9 dBFS (default 2) */ 34 | #define SX125x_TX_MIX_GAIN 14 /* -38 + 2*TxMixGain dB (default 14) */ 35 | #define SX125x_TX_PLL_BW 1 /* 0:75, 1:150, 2:225, 3:300 kHz (default 3) */ 36 | #define SX125x_TX_ANA_BW 0 /* 17.5 / 2*(41-TxAnaBw) MHz (default 0) */ 37 | #define SX125x_TX_DAC_BW 5 /* 24 + 8*TxDacBw Nb FIR taps (default 2) */ 38 | #define SX125x_RX_LNA_GAIN 1 /* 1 to 6, 1 highest gain */ 39 | #define SX125x_RX_BB_GAIN 12 /* 0 to 15 , 15 highest gain */ 40 | #define SX125x_LNA_ZIN 1 /* 0:50, 1:200 Ohms (default 1) */ 41 | #define SX125x_RX_ADC_BW 7 /* 0 to 7, 2:100 root configuration file 192 | * libloragw/libloragw.a -> static library, to be linked with a program 193 | * libloragw/readme.md -> required for license compliance 194 | * libloragw/inc/config.h -> C configuration flags, derived from library.cfg 195 | * libloragw/inc/loragw_*.h -> take only the ones you need (eg. _hal and _gps) 196 | 197 | After statically linking the library to your application, only the license 198 | is required to be kept or copied inside your program documentation. 199 | 200 | 4. Hardware dependencies 201 | ------------------------ 202 | 203 | ### 4.1. Hardware revision ### 204 | 205 | The loragw_reg and loragw_hal are written for a specific version on the Semtech 206 | hardware (IP and/or silicon revision). 207 | 208 | This code has been written for: 209 | 210 | * Semtech SX1301 chip 211 | * Semtech SX1257 or SX1255 I/Q transceivers 212 | 213 | The library will not work if there is a mismatch between the hardware version 214 | and the library version. You can use the test program test_loragw_reg to check 215 | if the hardware registers match their software declaration. 216 | 217 | ### 4.2. USB/UART communication ### 218 | 219 | loragw_com contains 4 functions (read, write, burst read, burst write) that are 220 | platform-dependant. 221 | The functions must be rewritten depending on the communication bridge you use: 222 | 223 | * USB/UART over linux tty port (provided) 224 | 225 | You can use the test program test_loragw_com to check that the USB communication 226 | is working. 227 | 228 | 229 | 5. Usage 230 | -------- 231 | 232 | ### 5.1. Setting the software environment ### 233 | 234 | For a typical application you need to: 235 | 236 | * include loragw_hal.h in your program source 237 | * link to the libloragw.a static library during compilation 238 | * link to the librt library due to loragw_aux dependencies (timing functions) 239 | 240 | For an application that will also access the concentrator configuration 241 | registers directly (eg. for advanced configuration) you also need to: 242 | 243 | * include loragw_reg.h in your program source 244 | 245 | ### 5.2. Using the software API ### 246 | 247 | To use the HAL in your application, you must follow some basic rules: 248 | 249 | * configure the radios path and IF+modem path before starting the radio 250 | * the configuration is only transferred to hardware when you call the *start* 251 | function 252 | * you cannot receive packets until one (or +) radio is enabled AND one (or +) 253 | IF+modem part is enabled AND the concentrator is started 254 | * you cannot send packets until one (or +) radio is enabled AND the concentrator 255 | is started 256 | * you must stop the concentrator before changing the configuration 257 | 258 | A typical application flow for using the HAL is the following: 259 | 260 | 261 | 262 | loop { 263 | 264 | 265 | 266 | } 267 | 268 | 269 | **/!\ Warning** The lgw_send function is non-blocking and returns while the 270 | LoRa concentrator is still sending the packet, or even before the packet has 271 | started to be transmitted if the packet is triggered on a future event. 272 | While a packet is emitted, no packet can be received (limitation intrinsic to 273 | most radio frequency systems). 274 | 275 | Your application *must* take into account the time it takes to send a packet or 276 | check the status (using lgw_status) before attempting to send another packet. 277 | 278 | Trying to send a packet while the previous packet has not finished being send 279 | will result in the previous packet not being sent or being sent only partially 280 | (resulting in a CRC error in the receiver). 281 | 282 | ### 5.3. Debugging mode ### 283 | 284 | To debug your application, it might help to compile the loragw_hal function 285 | with the debug messages activated (set DEBUG_HAL=1 in library.cfg). 286 | It then send a lot of details, including detailed error messages to *stderr*. 287 | 288 | 6. License 289 | ----------- 290 | 291 | Copyright (c) 2013, SEMTECH S.A. 292 | All rights reserved. 293 | 294 | Redistribution and use in source and binary forms, with or without 295 | modification, are permitted provided that the following conditions are met: 296 | 297 | * Redistributions of source code must retain the above copyright 298 | notice, this list of conditions and the following disclaimer. 299 | * Redistributions in binary form must reproduce the above copyright 300 | notice, this list of conditions and the following disclaimer in the 301 | documentation and/or other materials provided with the distribution. 302 | * Neither the name of the Semtech corporation nor the 303 | names of its contributors may be used to endorse or promote products 304 | derived from this software without specific prior written permission. 305 | 306 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 307 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 308 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 309 | DISCLAIMED. IN NO EVENT SHALL SEMTECH S.A. BE LIABLE FOR ANY 310 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 311 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 312 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 313 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 314 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 315 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 316 | 317 | *EOF* 318 | -------------------------------------------------------------------------------- /libloragw/src/loragw_aux.c: -------------------------------------------------------------------------------- 1 | /* 2 | / _____) _ | | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 5 | _____) ) ____| | | || |_| ____( (___| | | | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 7 | (C)2017 Semtech-Cycleo 8 | 9 | Description: 10 | LoRa concentrator HAL auxiliary functions 11 | 12 | License: Revised BSD License, see LICENSE.TXT file include in the project 13 | 14 | */ 15 | 16 | 17 | /* -------------------------------------------------------------------------- */ 18 | /* --- DEPENDANCIES --------------------------------------------------------- */ 19 | 20 | /* fix an issue between POSIX and C99 */ 21 | #if __STDC_VERSION__ >= 199901L 22 | #define _XOPEN_SOURCE 600 23 | #else 24 | #define _XOPEN_SOURCE 500 25 | #endif 26 | 27 | #include /* printf fprintf */ 28 | #include /* clock_nanosleep */ 29 | 30 | /* -------------------------------------------------------------------------- */ 31 | /* --- PRIVATE MACROS ------------------------------------------------------- */ 32 | 33 | #if DEBUG_AUX == 1 34 | #define DEBUG_MSG(str) fprintf(stderr, str) 35 | #define DEBUG_PRINTF(fmt, args...) fprintf(stderr,"%s:%d: "fmt, __FUNCTION__, __LINE__, args) 36 | #else 37 | #define DEBUG_MSG(str) 38 | #define DEBUG_PRINTF(fmt, args...) 39 | #endif 40 | 41 | /* -------------------------------------------------------------------------- */ 42 | /* --- PUBLIC FUNCTIONS DEFINITION ------------------------------------------ */ 43 | 44 | /* This implementation is POSIX-pecific and require a fix to be compatible with C99 */ 45 | 46 | 47 | void wait_ms_linux(unsigned long a) { 48 | struct timespec dly; 49 | struct timespec rem; 50 | 51 | dly.tv_sec = a / 1000; 52 | dly.tv_nsec = ((long)a % 1000) * 1000000; 53 | 54 | DEBUG_PRINTF("NOTE dly: %ld sec %ld ns\n", dly.tv_sec, dly.tv_nsec); 55 | 56 | if((dly.tv_sec > 0) || ((dly.tv_sec == 0) && (dly.tv_nsec > 100000))) { 57 | clock_nanosleep(CLOCK_MONOTONIC, 0, &dly, &rem); 58 | DEBUG_PRINTF("NOTE remain: %ld sec %ld ns\n", rem.tv_sec, rem.tv_nsec); 59 | } 60 | return; 61 | } 62 | 63 | void wait_ns_linux(unsigned long a) { 64 | struct timespec dly; 65 | struct timespec rem; 66 | 67 | dly.tv_sec = 0; 68 | dly.tv_nsec = a; 69 | 70 | DEBUG_PRINTF("NOTE dly: %ld sec %ld ns\n", dly.tv_sec, dly.tv_nsec); 71 | 72 | if((dly.tv_sec > 0) || ((dly.tv_sec == 0) && (dly.tv_nsec > 1))) { 73 | clock_nanosleep(CLOCK_MONOTONIC, 0, &dly, &rem); 74 | DEBUG_PRINTF("NOTE remain: %ld sec %ld ns\n", rem.tv_sec, rem.tv_nsec); 75 | } 76 | return; 77 | } 78 | 79 | void wait_ms(unsigned long a) { 80 | #ifdef _WIN32 81 | return wait_ms_win(a) ; 82 | #elif __linux__ 83 | return wait_ms_linux(a) ; 84 | #elif __APPLE__ 85 | DEBUG_PRINTF("System is not recognized."); 86 | #elif __unix__ 87 | DEBUG_PRINTF("System is not recognized."); 88 | #elif __posix__ 89 | DEBUG_PRINTF("System is not recognized."); 90 | #else 91 | DEBUG_PRINTF("System is not recognized."); 92 | #endif 93 | } 94 | void wait_ns(unsigned long a) { 95 | #ifdef _WIN32 96 | return wait_ns_win(a) ; 97 | #elif __linux__ 98 | return wait_ns_linux(a) ; 99 | #elif __APPLE__ 100 | DEBUG_PRINTF("System is not recognized."); 101 | #elif __unix__ 102 | DEBUG_PRINTF("System is not recognized."); 103 | #elif __posix__ 104 | DEBUG_PRINTF("System is not recognized."); 105 | #else 106 | DEBUG_PRINTF("System is not recognized."); 107 | #endif 108 | } 109 | 110 | /* --- EOF ------------------------------------------------------------------ */ 111 | -------------------------------------------------------------------------------- /libloragw/src/loragw_com.c: -------------------------------------------------------------------------------- 1 | /* 2 | / _____) _ | | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 5 | _____) ) ____| | | || |_| ____( (___| | | | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 7 | (C)2017 Semtech-Cycleo 8 | 9 | Description: 10 | A communication bridge layer to abstract linux/windows OS or others. 11 | The current project support only linux os 12 | 13 | License: Revised BSD License, see LICENSE.TXT file include in the project 14 | */ 15 | 16 | 17 | /* -------------------------------------------------------------------------- */ 18 | /* --- DEPENDANCIES --------------------------------------------------------- */ 19 | 20 | #include /* C99 types */ 21 | #include /* printf fprintf */ 22 | #include /* malloc free */ 23 | #include /* lseek, close */ 24 | #include /* open */ 25 | #include /* memset */ 26 | #include /* Error number definitions */ 27 | #include /* POSIX terminal control definitions */ 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include "loragw_aux.h" 34 | #include "loragw_reg.h" 35 | #include "loragw_com.h" 36 | #include "loragw_com_linux.h" 37 | 38 | /* -------------------------------------------------------------------------- */ 39 | /* --- PRIVATE MACROS ------------------------------------------------------- */ 40 | 41 | #if DEBUG_COM == 1 42 | #define DEBUG_MSG(str) fprintf(stderr, str) 43 | #define DEBUG_PRINTF(fmt, args...) fprintf(stderr,"%s:%d: "fmt, __FUNCTION__, __LINE__, args) 44 | #define CHECK_NULL(a) if(a==NULL){fprintf(stderr,"%s:%d: ERROR: NULL POINTER AS ARGUMENT\n", __FUNCTION__, __LINE__);return LGW_COM_ERROR;} 45 | #else 46 | #define DEBUG_MSG(str) 47 | #define DEBUG_PRINTF(fmt, args...) 48 | #define CHECK_NULL(a) if(a==NULL){return LGW_COM_ERROR;} 49 | #endif 50 | 51 | /* -------------------------------------------------------------------------- */ 52 | /* --- PRIVATE SHARED VARIABLES (GLOBAL) ------------------------------------ */ 53 | 54 | extern void *lgw_com_target; /*! generic pointer to the COM device */ 55 | 56 | pthread_mutex_t mx_usbbridgesync = PTHREAD_MUTEX_INITIALIZER; /* control access to usbbridge sync offsets */ 57 | 58 | /* -------------------------------------------------------------------------- */ 59 | /* --- PRIVATE CONSTANTS ---------------------------------------------------- */ 60 | 61 | /* -------------------------------------------------------------------------- */ 62 | /* --- PRIVATE FUNCTIONS DEFINITION ----------------------------------------- */ 63 | 64 | int lgw_com_send_cmd(lgw_com_cmd_t cmd, lgw_handle_t handle) { 65 | #ifdef _WIN32 66 | return lgw_com_send_cmd_win(cmd, handle); 67 | #elif __linux__ 68 | return lgw_com_send_cmd_linux(cmd, handle); 69 | #elif __APPLE__ 70 | DEBUG_PRINTF("System is not recognized."); 71 | #elif __unix__ 72 | DEBUG_PRINTF("System is not recognized."); 73 | #elif __posix__ 74 | DEBUG_PRINTF("System is not recognized."); 75 | #else 76 | DEBUG_PRINTF("System is not recognized."); 77 | #endif 78 | } 79 | 80 | /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 81 | 82 | int lgw_com_receive_ans(lgw_com_ans_t *ans, lgw_handle_t handle) { 83 | #ifdef _WIN32 84 | return lgw_com_receive_ans_win(ans, handle); 85 | #elif __linux__ 86 | return lgw_com_receive_ans_linux(ans, handle); 87 | #elif __APPLE__ 88 | DEBUG_PRINTF("System is not recognized."); 89 | #elif __unix__ 90 | DEBUG_PRINTF("System is not recognized."); 91 | #elif __posix__ 92 | DEBUG_PRINTF("System is not recognized."); 93 | #else 94 | DEBUG_PRINTF("System is not recognized."); 95 | #endif 96 | } 97 | 98 | /* -------------------------------------------------------------------------- */ 99 | /* --- PUBLIC FUNCTIONS DEFINITION ------------------------------------------ */ 100 | 101 | int lgw_com_open(void **com_target_ptr, const char *com_path) { 102 | #ifdef _WIN32 103 | return lgw_com_open_win(com_target_ptr); 104 | #elif __linux__ 105 | return lgw_com_open_linux(com_target_ptr, com_path); 106 | #elif __APPLE__ 107 | DEBUG_PRINTF("System is not recognized."); 108 | #elif __unix__ 109 | DEBUG_PRINTF("System is not recognized."); 110 | #elif __posix__ 111 | DEBUG_PRINTF("System is not recognized."); 112 | #else 113 | DEBUG_PRINTF("System is not recognized."); 114 | #endif 115 | } 116 | 117 | /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 118 | 119 | int lgw_com_close(void *com_target) { 120 | #ifdef _WIN32 121 | return lgw_com_close_win(com_target); 122 | #elif __linux__ 123 | return lgw_com_close_linux(com_target); 124 | #elif __APPLE__ 125 | DEBUG_PRINTF("System is not recognized."); 126 | #elif __unix__ 127 | DEBUG_PRINTF("System is not recognized."); 128 | #elif __posix__ 129 | DEBUG_PRINTF("System is not recognized."); 130 | #else 131 | DEBUG_PRINTF("System is not recognized."); 132 | #endif 133 | } 134 | 135 | /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 136 | 137 | int lgw_com_w(void *com_target, uint8_t com_mux_mode, uint8_t com_mux_target, uint8_t address, uint8_t data) { 138 | #ifdef _WIN32 139 | return lgw_com_w_win(com_target, com_mux_mode, com_mux_target, address, data); 140 | #elif __linux__ 141 | return lgw_com_w_linux(com_target, com_mux_mode, com_mux_target, address, data); 142 | #elif __APPLE__ 143 | DEBUG_PRINTF("System is not recognized."); 144 | #elif __unix__ 145 | DEBUG_PRINTF("System is not recognized."); 146 | #elif __posix__ 147 | DEBUG_PRINTF("System is not recognized."); 148 | #else 149 | DEBUG_PRINTF("System is not recognized."); 150 | #endif 151 | } 152 | 153 | /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 154 | 155 | int lgw_com_r(void *com_target, uint8_t com_mux_mode, uint8_t com_mux_target, uint8_t address, uint8_t *data) { 156 | #ifdef _WIN32 157 | return lgw_com_r_win(com_target, com_mux_mode, com_mux_target, address, data); 158 | #elif __linux__ 159 | return lgw_com_r_linux(com_target, com_mux_mode, com_mux_target, address, data); 160 | #elif __APPLE__ 161 | DEBUG_PRINTF("System is not recognized."); 162 | #elif __unix__ 163 | DEBUG_PRINTF("System is not recognized."); 164 | #elif __posix__ 165 | DEBUG_PRINTF("System is not recognized."); 166 | #else 167 | DEBUG_PRINTF("System is not recognized."); 168 | #endif 169 | } 170 | 171 | /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 172 | 173 | int lgw_com_wb(void *com_target, uint8_t com_mux_mode, uint8_t com_mux_target, uint8_t address, uint8_t *data, uint16_t size) { 174 | #ifdef _WIN32 175 | return lgw_com_wb_win(com_target, com_mux_mode, com_mux_target, address, data, size); 176 | #elif __linux__ 177 | return lgw_com_wb_linux(com_target, com_mux_mode, com_mux_target, address, data, size); 178 | #elif __APPLE__ 179 | DEBUG_PRINTF("System is not recognized."); 180 | #elif __unix__ 181 | DEBUG_PRINTF("System is not recognized."); 182 | #elif __posix__ 183 | DEBUG_PRINTF("System is not recognized."); 184 | #else 185 | DEBUG_PRINTF("System is not recognized."); 186 | #endif 187 | } 188 | 189 | /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 190 | 191 | int lgw_com_rb(void *com_target, uint8_t com_mux_mode, uint8_t com_mux_target, uint8_t address, uint8_t *data, uint16_t size) { 192 | #ifdef _WIN32 193 | return lgw_com_rb_win(com_target, com_mux_mode, com_mux_target, address, data, size); 194 | #elif __linux__ 195 | return lgw_com_rb_linux(com_target, com_mux_mode, com_mux_target, address, data, size); 196 | #elif __APPLE__ 197 | DEBUG_PRINTF("System is not recognized."); 198 | #elif __unix__ 199 | DEBUG_PRINTF("System is not recognized."); 200 | #elif __posix__ 201 | DEBUG_PRINTF("System is not recognized."); 202 | #else 203 | DEBUG_PRINTF("System is not recognized."); 204 | #endif 205 | } 206 | 207 | /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 208 | 209 | int lgw_com_send_command(void *com_target, lgw_com_cmd_t cmd, lgw_com_ans_t *ans) { 210 | lgw_handle_t handle; 211 | 212 | CHECK_NULL(com_target); 213 | CHECK_NULL(ans); 214 | 215 | handle = LGW_GET_HANDLE(com_target); 216 | 217 | pthread_mutex_lock(&mx_usbbridgesync); 218 | 219 | if (lgw_com_send_cmd(cmd, handle) == LGW_COM_ERROR) { 220 | pthread_mutex_unlock(&mx_usbbridgesync); 221 | return LGW_COM_ERROR; 222 | } 223 | if (lgw_com_receive_ans(ans, handle) == LGW_COM_ERROR) { 224 | pthread_mutex_unlock(&mx_usbbridgesync); 225 | return LGW_COM_ERROR; 226 | } 227 | 228 | pthread_mutex_unlock(&mx_usbbridgesync); 229 | 230 | return LGW_COM_SUCCESS; 231 | } 232 | 233 | /* --- EOF ------------------------------------------------------------------ */ 234 | -------------------------------------------------------------------------------- /libloragw/src/loragw_radio.c: -------------------------------------------------------------------------------- 1 | /* 2 | / _____) _ | | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 5 | _____) ) ____| | | || |_| ____( (___| | | | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 7 | (C)2017 Semtech-Cycleo 8 | 9 | Description: 10 | Functions used to handle LoRa concentrator radios. 11 | 12 | License: Revised BSD License, see LICENSE.TXT file include in the project 13 | 14 | */ 15 | 16 | /* -------------------------------------------------------------------------- */ 17 | /* --- DEPENDANCIES --------------------------------------------------------- */ 18 | 19 | #include /* C99 types */ 20 | #include /* bool type */ 21 | #include /* printf fprintf */ 22 | 23 | #include "loragw_sx125x.h" 24 | #include "loragw_com.h" 25 | #include "loragw_aux.h" 26 | #include "loragw_reg.h" 27 | #include "loragw_hal.h" 28 | #include "loragw_radio.h" 29 | 30 | /* -------------------------------------------------------------------------- */ 31 | /* --- PRIVATE MACROS ------------------------------------------------------- */ 32 | 33 | #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) 34 | #if DEBUG_REG == 1 35 | #define DEBUG_MSG(str) fprintf(stderr, str) 36 | #define DEBUG_PRINTF(fmt, args...) fprintf(stderr,"%s:%d: "fmt, __FUNCTION__, __LINE__, args) 37 | #define CHECK_NULL(a) if(a==NULL){fprintf(stderr,"%s:%d: ERROR: NULL POINTER AS ARGUMENT\n", __FUNCTION__, __LINE__);return LGW_REG_ERROR;} 38 | #else 39 | #define DEBUG_MSG(str) 40 | #define DEBUG_PRINTF(fmt, args...) 41 | #define CHECK_NULL(a) if(a==NULL){return LGW_REG_ERROR;} 42 | #endif 43 | 44 | /* -------------------------------------------------------------------------- */ 45 | /* --- PRIVATE TYPES -------------------------------------------------------- */ 46 | 47 | /** 48 | @struct lgw_radio_type_version_s 49 | @brief Associate a radio type with its corresponding expected version value 50 | read in the radio version register. 51 | */ 52 | struct lgw_radio_type_version_s { 53 | enum lgw_radio_type_e type; 54 | uint8_t reg_version; 55 | }; 56 | 57 | /* -------------------------------------------------------------------------- */ 58 | /* --- PRIVATE CONSTANTS ---------------------------------------------------- */ 59 | 60 | #define PLL_LOCK_MAX_ATTEMPTS 5 61 | 62 | /* -------------------------------------------------------------------------- */ 63 | /* --- PRIVATE VARIABLES ---------------------------------------------------- */ 64 | 65 | /* -------------------------------------------------------------------------- */ 66 | /* --- PRIVATE FUNCTIONS ---------------------------------------------------- */ 67 | 68 | void sx125x_write(uint8_t channel, uint8_t addr, uint8_t data); 69 | uint8_t sx125x_read(uint8_t channel, uint8_t addr); 70 | 71 | /* -------------------------------------------------------------------------- */ 72 | /* --- PRIVATE FUNCTIONS DEFINITION ----------------------------------------- */ 73 | 74 | void sx125x_write(uint8_t channel, uint8_t addr, uint8_t data) { 75 | int reg_add, reg_dat, reg_cs; 76 | 77 | /* checking input parameters */ 78 | if (channel >= LGW_RF_CHAIN_NB) { 79 | DEBUG_MSG("ERROR: INVALID RF_CHAIN\n"); 80 | return; 81 | } 82 | if (addr >= 0x7F) { 83 | DEBUG_MSG("ERROR: ADDRESS OUT OF RANGE\n"); 84 | return; 85 | } 86 | 87 | /* selecting the target radio */ 88 | switch (channel) { 89 | case 0: 90 | reg_add = LGW_SPI_RADIO_A__ADDR; 91 | reg_dat = LGW_SPI_RADIO_A__DATA; 92 | reg_cs = LGW_SPI_RADIO_A__CS; 93 | break; 94 | 95 | case 1: 96 | reg_add = LGW_SPI_RADIO_B__ADDR; 97 | reg_dat = LGW_SPI_RADIO_B__DATA; 98 | reg_cs = LGW_SPI_RADIO_B__CS; 99 | break; 100 | 101 | default: 102 | DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", channel); 103 | return; 104 | } 105 | 106 | /* SPI master data write procedure */ 107 | lgw_reg_w(reg_cs, 0); 108 | lgw_reg_w(reg_add, 0x80 | addr); /* MSB at 1 for write operation */ 109 | lgw_reg_w(reg_dat, data); 110 | lgw_reg_w(reg_cs, 1); 111 | lgw_reg_w(reg_cs, 0); 112 | 113 | return; 114 | } 115 | 116 | /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 117 | 118 | uint8_t sx125x_read(uint8_t channel, uint8_t addr) { 119 | int reg_add, reg_dat, reg_cs, reg_rb; 120 | int32_t read_value; 121 | 122 | /* checking input parameters */ 123 | if (channel >= LGW_RF_CHAIN_NB) { 124 | DEBUG_MSG("ERROR: INVALID RF_CHAIN\n"); 125 | return 0; 126 | } 127 | if (addr >= 0x7F) { 128 | DEBUG_MSG("ERROR: ADDRESS OUT OF RANGE\n"); 129 | return 0; 130 | } 131 | 132 | /* selecting the target radio */ 133 | switch (channel) { 134 | case 0: 135 | reg_add = LGW_SPI_RADIO_A__ADDR; 136 | reg_dat = LGW_SPI_RADIO_A__DATA; 137 | reg_cs = LGW_SPI_RADIO_A__CS; 138 | reg_rb = LGW_SPI_RADIO_A__DATA_READBACK; 139 | break; 140 | 141 | case 1: 142 | reg_add = LGW_SPI_RADIO_B__ADDR; 143 | reg_dat = LGW_SPI_RADIO_B__DATA; 144 | reg_cs = LGW_SPI_RADIO_B__CS; 145 | reg_rb = LGW_SPI_RADIO_B__DATA_READBACK; 146 | break; 147 | 148 | default: 149 | DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", channel); 150 | return 0; 151 | } 152 | 153 | /* SPI master data read procedure */ 154 | lgw_reg_w(reg_cs, 0); 155 | lgw_reg_w(reg_add, addr); /* MSB at 0 for read operation */ 156 | lgw_reg_w(reg_dat, 0); 157 | lgw_reg_w(reg_cs, 1); 158 | lgw_reg_w(reg_cs, 0); 159 | lgw_reg_r(reg_rb, &read_value); 160 | 161 | return (uint8_t)read_value; 162 | } 163 | 164 | /* -------------------------------------------------------------------------- */ 165 | /* --- PUBLIC FUNCTIONS DEFINITION ------------------------------------------ */ 166 | 167 | int lgw_setup_sx125x(uint8_t rf_chain, uint8_t rf_clkout, bool rf_enable, uint8_t rf_radio_type, uint32_t freq_hz) { 168 | uint32_t part_int = 0; 169 | uint32_t part_frac = 0; 170 | int cpt_attempts = 0; 171 | 172 | if (rf_chain >= LGW_RF_CHAIN_NB) { 173 | DEBUG_MSG("ERROR: INVALID RF_CHAIN\n"); 174 | return -1; 175 | } 176 | 177 | /* Get version to identify SX1255/57 silicon revision */ 178 | DEBUG_PRINTF("Note: SX125x #%d version register returned 0x%02x\n", rf_chain, sx125x_read(rf_chain, 0x07)); 179 | 180 | /* General radio setup */ 181 | if (rf_clkout == rf_chain) { 182 | sx125x_write(rf_chain, 0x10, SX125x_TX_DAC_CLK_SEL + 2); 183 | DEBUG_PRINTF("Note: SX125x #%d clock output enabled\n", rf_chain); 184 | } else { 185 | sx125x_write(rf_chain, 0x10, SX125x_TX_DAC_CLK_SEL); 186 | DEBUG_PRINTF("Note: SX125x #%d clock output disabled\n", rf_chain); 187 | } 188 | 189 | switch (rf_radio_type) { 190 | case LGW_RADIO_TYPE_SX1255: 191 | sx125x_write(rf_chain, 0x28, SX125x_XOSC_GM_STARTUP + SX125x_XOSC_DISABLE * 16); 192 | break; 193 | case LGW_RADIO_TYPE_SX1257: 194 | sx125x_write(rf_chain, 0x26, SX125x_XOSC_GM_STARTUP + SX125x_XOSC_DISABLE * 16); 195 | break; 196 | default: 197 | DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d FOR RADIO TYPE\n", rf_radio_type); 198 | break; 199 | } 200 | 201 | if (rf_enable == true) { 202 | /* Tx gain and trim */ 203 | sx125x_write(rf_chain, 0x08, SX125x_TX_MIX_GAIN + SX125x_TX_DAC_GAIN * 16); 204 | sx125x_write(rf_chain, 0x0A, SX125x_TX_ANA_BW + SX125x_TX_PLL_BW * 32); 205 | sx125x_write(rf_chain, 0x0B, SX125x_TX_DAC_BW); 206 | 207 | /* Rx gain and trim */ 208 | sx125x_write(rf_chain, 0x0C, SX125x_LNA_ZIN + SX125x_RX_BB_GAIN * 2 + SX125x_RX_LNA_GAIN * 32); 209 | sx125x_write(rf_chain, 0x0D, SX125x_RX_BB_BW + SX125x_RX_ADC_TRIM * 4 + SX125x_RX_ADC_BW * 32); 210 | sx125x_write(rf_chain, 0x0E, SX125x_ADC_TEMP + SX125x_RX_PLL_BW * 2); 211 | 212 | /* set RX PLL frequency */ 213 | switch (rf_radio_type) { 214 | case LGW_RADIO_TYPE_SX1255: 215 | part_int = freq_hz / (SX125x_32MHz_FRAC << 7); /* integer part, gives the MSB */ 216 | part_frac = ((freq_hz % (SX125x_32MHz_FRAC << 7)) << 9) / SX125x_32MHz_FRAC; /* fractional part, gives middle part and LSB */ 217 | break; 218 | case LGW_RADIO_TYPE_SX1257: 219 | part_int = freq_hz / (SX125x_32MHz_FRAC << 8); /* integer part, gives the MSB */ 220 | part_frac = ((freq_hz % (SX125x_32MHz_FRAC << 8)) << 8) / SX125x_32MHz_FRAC; /* fractional part, gives middle part and LSB */ 221 | break; 222 | default: 223 | DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d FOR RADIO TYPE\n", rf_radio_type); 224 | break; 225 | } 226 | 227 | sx125x_write(rf_chain, 0x01, 0xFF & part_int); /* Most Significant Byte */ 228 | sx125x_write(rf_chain, 0x02, 0xFF & (part_frac >> 8)); /* middle byte */ 229 | sx125x_write(rf_chain, 0x03, 0xFF & part_frac); /* Least Significant Byte */ 230 | 231 | /* start and PLL lock */ 232 | do { 233 | if (cpt_attempts >= PLL_LOCK_MAX_ATTEMPTS) { 234 | DEBUG_MSG("ERROR: FAIL TO LOCK PLL\n"); 235 | return -1; 236 | } 237 | sx125x_write(rf_chain, 0x00, 1); /* enable Xtal oscillator */ 238 | sx125x_write(rf_chain, 0x00, 3); /* Enable RX (PLL+FE) */ 239 | ++cpt_attempts; 240 | DEBUG_PRINTF("Note: SX125x #%d PLL start (attempt %d)\n", rf_chain, cpt_attempts); 241 | wait_ms(1); 242 | } while((sx125x_read(rf_chain, 0x11) & 0x02) == 0); 243 | } else { 244 | DEBUG_PRINTF("Note: SX125x #%d kept in standby mode\n", rf_chain); 245 | } 246 | 247 | return 0; 248 | } 249 | 250 | /* --- EOF ------------------------------------------------------------------ */ 251 | -------------------------------------------------------------------------------- /libloragw/tst/test_loragw_hal.c: -------------------------------------------------------------------------------- 1 | /* 2 | / _____) _ | | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 5 | _____) ) ____| | | || |_| ____( (___| | | | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 7 | (C)2017 Semtech-Cycleo 8 | 9 | Description: 10 | Minimum test program for the loragw_hal 'library' 11 | 12 | License: Revised BSD License, see LICENSE.TXT file include in the project 13 | 14 | */ 15 | 16 | 17 | /* -------------------------------------------------------------------------- */ 18 | /* --- DEPENDANCIES --------------------------------------------------------- */ 19 | 20 | /* fix an issue between POSIX and C99 */ 21 | #if __STDC_VERSION__ >= 199901L 22 | #define _XOPEN_SOURCE 600 23 | #else 24 | #define _XOPEN_SOURCE 500 25 | #endif 26 | 27 | #include /* C99 types */ 28 | #include /* bool type */ 29 | #include /* printf */ 30 | #include /* memset */ 31 | #include /* sigaction */ 32 | #include /* getopt access */ 33 | 34 | #include "loragw_hal.h" 35 | #include "loragw_reg.h" 36 | #include "loragw_aux.h" 37 | 38 | /* -------------------------------------------------------------------------- */ 39 | /* --- PRIVATE MACROS ------------------------------------------------------- */ 40 | 41 | #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) 42 | 43 | /* -------------------------------------------------------------------------- */ 44 | /* --- PRIVATE CONSTANTS ---------------------------------------------------- */ 45 | 46 | #define COM_PATH_DEFAULT "/dev/ttyACM0" 47 | #define DEFAULT_RSSI_OFFSET 0.0 48 | 49 | /* -------------------------------------------------------------------------- */ 50 | /* --- PRIVATE VARIABLES ---------------------------------------------------- */ 51 | 52 | static int exit_sig = 0; /* 1 -> application terminates cleanly (shut down hardware, close open files, etc) */ 53 | static int quit_sig = 0; /* 1 -> application terminates without shutting down the hardware */ 54 | 55 | /* -------------------------------------------------------------------------- */ 56 | /* --- PRIVATE FUNCTIONS DECLARATION ---------------------------------------- */ 57 | 58 | static void sig_handler(int sigio); 59 | 60 | /* -------------------------------------------------------------------------- */ 61 | /* --- PRIVATE FUNCTIONS DEFINITION ----------------------------------------- */ 62 | 63 | static void sig_handler(int sigio) { 64 | if (sigio == SIGQUIT) { 65 | quit_sig = 1;; 66 | } else if ((sigio == SIGINT) || (sigio == SIGTERM)) { 67 | exit_sig = 1; 68 | } 69 | } 70 | 71 | /* describe command line options */ 72 | void usage(void) { 73 | printf("Library version information: %s\n", lgw_version_info()); 74 | printf("Available options:\n"); 75 | printf(" -h print this help\n"); 76 | printf(" -d COM device to be used to access the concentrator board\n"); 77 | printf(" => default path: " COM_PATH_DEFAULT "\n"); 78 | printf(" -a Radio A RX frequency in MHz\n"); 79 | printf(" -b Radio B RX frequency in MHz\n"); 80 | printf(" -t Radio TX frequency in MHz\n"); 81 | printf(" -r Radio type (SX1255:1255, SX1257:1257)\n"); 82 | printf(" -k Concentrator clock source (0: radio_A, 1: radio_B(default))\n"); 83 | } 84 | 85 | /* -------------------------------------------------------------------------- */ 86 | /* --- MAIN FUNCTION -------------------------------------------------------- */ 87 | 88 | int main(int argc, char **argv) { 89 | struct sigaction sigact; /* SIGQUIT&SIGINT&SIGTERM signal handling */ 90 | 91 | struct lgw_conf_board_s boardconf; 92 | struct lgw_conf_rxrf_s rfconf; 93 | struct lgw_conf_rxif_s ifconf; 94 | 95 | struct lgw_pkt_rx_s rxpkt[4]; /* array containing up to 4 inbound packets metadata */ 96 | struct lgw_pkt_tx_s txpkt; /* configuration and metadata for an outbound packet */ 97 | struct lgw_pkt_rx_s *p; /* pointer on a RX packet */ 98 | 99 | int i, j; 100 | int nb_pkt; 101 | uint32_t fa = 0, fb = 0, ft = 0; 102 | enum lgw_radio_type_e radio_type = LGW_RADIO_TYPE_NONE; 103 | uint8_t clocksource = 1; /* Radio B is source by default */ 104 | 105 | uint32_t tx_cnt = 0; 106 | unsigned long loop_cnt = 0; 107 | uint8_t status_var = 0; 108 | double xd = 0.0; 109 | int xi = 0; 110 | 111 | /* COM interfaces */ 112 | const char com_path_default[] = COM_PATH_DEFAULT; 113 | const char *com_path = com_path_default; 114 | 115 | /* parse command line options */ 116 | while ((i = getopt (argc, argv, "ha:b:t:r:k:d:")) != -1) { 117 | switch (i) { 118 | case 'h': 119 | usage(); 120 | return -1; 121 | break; 122 | case 'd': 123 | if (optarg != NULL) { 124 | com_path = optarg; 125 | } 126 | break; 127 | case 'a': /* Radio A RX frequency in MHz */ 128 | sscanf(optarg, "%lf", &xd); 129 | fa = (uint32_t)((xd * 1e6) + 0.5); /* .5 Hz offset to get rounding instead of truncating */ 130 | break; 131 | case 'b': /* Radio B RX frequency in MHz */ 132 | sscanf(optarg, "%lf", &xd); 133 | fb = (uint32_t)((xd * 1e6) + 0.5); /* .5 Hz offset to get rounding instead of truncating */ 134 | break; 135 | case 't': /* Radio TX frequency in MHz */ 136 | sscanf(optarg, "%lf", &xd); 137 | ft = (uint32_t)((xd * 1e6) + 0.5); /* .5 Hz offset to get rounding instead of truncating */ 138 | break; 139 | case 'r': /* Radio type (1255, 1257) */ 140 | sscanf(optarg, "%i", &xi); 141 | switch (xi) { 142 | case 1255: 143 | radio_type = LGW_RADIO_TYPE_SX1255; 144 | break; 145 | case 1257: 146 | radio_type = LGW_RADIO_TYPE_SX1257; 147 | break; 148 | default: 149 | printf("ERROR: invalid radio type\n"); 150 | usage(); 151 | return -1; 152 | } 153 | break; 154 | case 'k': /* Concentrator clock source (Radio A or Radio B) */ 155 | sscanf(optarg, "%i", &xi); 156 | clocksource = (uint8_t)xi; 157 | break; 158 | default: 159 | printf("ERROR: argument parsing\n"); 160 | usage(); 161 | return -1; 162 | } 163 | } 164 | 165 | /* check input parameters */ 166 | if ((fa == 0) || (fb == 0) || (ft == 0)) { 167 | printf("ERROR: missing frequency input parameter:\n"); 168 | printf(" Radio A RX: %u\n", fa); 169 | printf(" Radio B RX: %u\n", fb); 170 | printf(" Radio TX: %u\n", ft); 171 | usage(); 172 | return -1; 173 | } 174 | 175 | if (radio_type == LGW_RADIO_TYPE_NONE) { 176 | printf("ERROR: missing radio type parameter:\n"); 177 | usage(); 178 | return -1; 179 | } 180 | 181 | /* configure signal handling */ 182 | sigemptyset(&sigact.sa_mask); 183 | sigact.sa_flags = 0; 184 | sigact.sa_handler = sig_handler; 185 | sigaction(SIGQUIT, &sigact, NULL); 186 | sigaction(SIGINT, &sigact, NULL); 187 | sigaction(SIGTERM, &sigact, NULL); 188 | 189 | /* beginning of LoRa concentrator-specific code */ 190 | printf("Beginning of test for loragw_hal.c\n"); 191 | 192 | printf("*** Library version information ***\n%s\n\n", lgw_version_info()); 193 | 194 | /* Open communication bridge */ 195 | i = lgw_connect(com_path); 196 | if (i == -1) { 197 | printf("ERROR: FAIL TO CONNECT BOARD ON %s\n", com_path); 198 | return -1; 199 | } 200 | 201 | /* set configuration for board */ 202 | memset(&boardconf, 0, sizeof(boardconf)); 203 | 204 | boardconf.lorawan_public = true; 205 | boardconf.clksrc = clocksource; 206 | lgw_board_setconf(boardconf); 207 | 208 | /* set configuration for RF chains */ 209 | memset(&rfconf, 0, sizeof(rfconf)); 210 | 211 | rfconf.enable = true; 212 | rfconf.freq_hz = fa; 213 | rfconf.rssi_offset = DEFAULT_RSSI_OFFSET; 214 | rfconf.type = radio_type; 215 | rfconf.tx_enable = true; 216 | lgw_rxrf_setconf(0, rfconf); /* radio A, f0 */ 217 | 218 | rfconf.enable = true; 219 | rfconf.freq_hz = fb; 220 | rfconf.rssi_offset = DEFAULT_RSSI_OFFSET; 221 | rfconf.type = radio_type; 222 | rfconf.tx_enable = false; 223 | lgw_rxrf_setconf(1, rfconf); /* radio B, f1 */ 224 | 225 | /* set configuration for LoRa multi-SF channels (bandwidth cannot be set) */ 226 | memset(&ifconf, 0, sizeof(ifconf)); 227 | 228 | ifconf.enable = true; 229 | ifconf.rf_chain = 1; 230 | ifconf.freq_hz = -400000; 231 | ifconf.datarate = DR_LORA_MULTI; 232 | lgw_rxif_setconf(0, ifconf); /* chain 0: LoRa 125kHz, all SF, on f1 - 0.4 MHz */ 233 | 234 | ifconf.enable = true; 235 | ifconf.rf_chain = 1; 236 | ifconf.freq_hz = -200000; 237 | ifconf.datarate = DR_LORA_MULTI; 238 | lgw_rxif_setconf(1, ifconf); /* chain 1: LoRa 125kHz, all SF, on f1 - 0.2 MHz */ 239 | 240 | ifconf.enable = true; 241 | ifconf.rf_chain = 1; 242 | ifconf.freq_hz = 0; 243 | ifconf.datarate = DR_LORA_MULTI; 244 | lgw_rxif_setconf(2, ifconf); /* chain 2: LoRa 125kHz, all SF, on f1 - 0.0 MHz */ 245 | 246 | ifconf.enable = true; 247 | ifconf.rf_chain = 0; 248 | ifconf.freq_hz = -400000; 249 | ifconf.datarate = DR_LORA_MULTI; 250 | lgw_rxif_setconf(3, ifconf); /* chain 3: LoRa 125kHz, all SF, on f0 - 0.4 MHz */ 251 | 252 | ifconf.enable = true; 253 | ifconf.rf_chain = 0; 254 | ifconf.freq_hz = -200000; 255 | ifconf.datarate = DR_LORA_MULTI; 256 | lgw_rxif_setconf(4, ifconf); /* chain 4: LoRa 125kHz, all SF, on f0 - 0.2 MHz */ 257 | 258 | ifconf.enable = true; 259 | ifconf.rf_chain = 0; 260 | ifconf.freq_hz = 0; 261 | ifconf.datarate = DR_LORA_MULTI; 262 | lgw_rxif_setconf(5, ifconf); /* chain 5: LoRa 125kHz, all SF, on f0 + 0.0 MHz */ 263 | 264 | ifconf.enable = true; 265 | ifconf.rf_chain = 0; 266 | ifconf.freq_hz = 200000; 267 | ifconf.datarate = DR_LORA_MULTI; 268 | lgw_rxif_setconf(6, ifconf); /* chain 6: LoRa 125kHz, all SF, on f0 + 0.2 MHz */ 269 | 270 | ifconf.enable = true; 271 | ifconf.rf_chain = 0; 272 | ifconf.freq_hz = 400000; 273 | ifconf.datarate = DR_LORA_MULTI; 274 | lgw_rxif_setconf(7, ifconf); /* chain 7: LoRa 125kHz, all SF, on f0 + 0.4 MHz */ 275 | 276 | /* set configuration for LoRa 'stand alone' channel */ 277 | memset(&ifconf, 0, sizeof(ifconf)); 278 | ifconf.enable = true; 279 | ifconf.rf_chain = 0; 280 | ifconf.freq_hz = 0; 281 | ifconf.bandwidth = BW_250KHZ; 282 | ifconf.datarate = DR_LORA_SF10; 283 | lgw_rxif_setconf(8, ifconf); /* chain 8: LoRa 250kHz, SF10, on f0 MHz */ 284 | 285 | /* set configuration for FSK channel */ 286 | memset(&ifconf, 0, sizeof(ifconf)); 287 | ifconf.enable = true; 288 | ifconf.rf_chain = 1; 289 | ifconf.freq_hz = 0; 290 | ifconf.bandwidth = BW_250KHZ; 291 | ifconf.datarate = 64000; 292 | lgw_rxif_setconf(9, ifconf); /* chain 9: FSK 64kbps, on f1 MHz */ 293 | 294 | /* set configuration for TX packet */ 295 | memset(&txpkt, 0, sizeof(txpkt)); 296 | txpkt.freq_hz = ft; 297 | txpkt.tx_mode = IMMEDIATE; 298 | txpkt.rf_power = 10; 299 | txpkt.modulation = MOD_LORA; 300 | txpkt.bandwidth = BW_125KHZ; 301 | txpkt.datarate = DR_LORA_SF9; 302 | txpkt.coderate = CR_LORA_4_5; 303 | strcpy((char *)txpkt.payload, "TX.TEST.LORA.GW.????" ); 304 | txpkt.size = 20; 305 | txpkt.preamble = 6; 306 | txpkt.rf_chain = 0; 307 | /* 308 | memset(&txpkt, 0, sizeof(txpkt)); 309 | txpkt.freq_hz = F_TX; 310 | txpkt.tx_mode = IMMEDIATE; 311 | txpkt.rf_power = 10; 312 | txpkt.modulation = MOD_FSK; 313 | txpkt.f_dev = 50; 314 | txpkt.datarate = 64000; 315 | strcpy((char *)txpkt.payload, "TX.TEST.LORA.GW.????" ); 316 | txpkt.size = 20; 317 | txpkt.preamble = 4; 318 | txpkt.rf_chain = 0; 319 | */ 320 | 321 | /* connect, configure and start the LoRa concentrator */ 322 | i = lgw_start(); 323 | if (i == LGW_HAL_SUCCESS) { 324 | printf("*** Concentrator started ***\n"); 325 | } else { 326 | printf("*** Impossible to start concentrator ***\n"); 327 | return -1; 328 | } 329 | 330 | /* once configured, dump content of registers to a file, for reference */ 331 | // FILE * reg_dump = NULL; 332 | // reg_dump = fopen("reg_dump.log", "w"); 333 | // if (reg_dump != NULL) { 334 | // lgw_reg_check(reg_dump); 335 | // fclose(reg_dump); 336 | // } 337 | 338 | while ((quit_sig != 1) && (exit_sig != 1)) { 339 | loop_cnt++; 340 | 341 | /* fetch N packets */ 342 | nb_pkt = lgw_receive(ARRAY_SIZE(rxpkt), rxpkt); 343 | 344 | if (nb_pkt == 0) { 345 | wait_ms(300); 346 | } else { 347 | /* display received packets */ 348 | for(i = 0; i < nb_pkt; ++i) { 349 | p = &rxpkt[i]; 350 | printf("---\nRcv pkt #%d >>", i + 1); 351 | if (p->status == STAT_CRC_OK) { 352 | printf(" if_chain:%2d", p->if_chain); 353 | printf(" tstamp:%010u", p->count_us); 354 | printf(" size:%3u", p->size); 355 | switch (p-> modulation) { 356 | case MOD_LORA: 357 | printf(" LoRa"); 358 | break; 359 | case MOD_FSK: 360 | printf(" FSK"); 361 | break; 362 | default: 363 | printf(" modulation?"); 364 | } 365 | switch (p->datarate) { 366 | case DR_LORA_SF7: 367 | printf(" SF7"); 368 | break; 369 | case DR_LORA_SF8: 370 | printf(" SF8"); 371 | break; 372 | case DR_LORA_SF9: 373 | printf(" SF9"); 374 | break; 375 | case DR_LORA_SF10: 376 | printf(" SF10"); 377 | break; 378 | case DR_LORA_SF11: 379 | printf(" SF11"); 380 | break; 381 | case DR_LORA_SF12: 382 | printf(" SF12"); 383 | break; 384 | default: 385 | printf(" datarate?"); 386 | } 387 | switch (p->coderate) { 388 | case CR_LORA_4_5: 389 | printf(" CR1(4/5)"); 390 | break; 391 | case CR_LORA_4_6: 392 | printf(" CR2(2/3)"); 393 | break; 394 | case CR_LORA_4_7: 395 | printf(" CR3(4/7)"); 396 | break; 397 | case CR_LORA_4_8: 398 | printf(" CR4(1/2)"); 399 | break; 400 | default: 401 | printf(" coderate?"); 402 | } 403 | printf("\n"); 404 | printf(" RSSI:%+6.1f SNR:%+5.1f (min:%+5.1f, max:%+5.1f) payload:\n", p->rssi, p->snr, p->snr_min, p->snr_max); 405 | 406 | for (j = 0; j < p->size; ++j) { 407 | printf(" %02X", p->payload[j]); 408 | } 409 | printf(" #\n"); 410 | } else if (p->status == STAT_CRC_BAD) { 411 | printf(" if_chain:%2d", p->if_chain); 412 | printf(" tstamp:%010u", p->count_us); 413 | printf(" size:%3u\n", p->size); 414 | printf(" CRC error, damaged packet\n\n"); 415 | } else if (p->status == STAT_NO_CRC) { 416 | printf(" if_chain:%2d", p->if_chain); 417 | printf(" tstamp:%010u", p->count_us); 418 | printf(" size:%3u\n", p->size); 419 | printf(" no CRC\n\n"); 420 | } else { 421 | printf(" if_chain:%2d", p->if_chain); 422 | printf(" tstamp:%010u", p->count_us); 423 | printf(" size:%3u\n", p->size); 424 | printf(" invalid status ?!?\n\n"); 425 | } 426 | } 427 | } 428 | 429 | /* send a packet every X loop */ 430 | if (loop_cnt % 16 == 0) { 431 | /* 32b counter in the payload, big endian */ 432 | txpkt.payload[16] = 0xff & (tx_cnt >> 24); 433 | txpkt.payload[17] = 0xff & (tx_cnt >> 16); 434 | txpkt.payload[18] = 0xff & (tx_cnt >> 8); 435 | txpkt.payload[19] = 0xff & tx_cnt; 436 | i = lgw_send(txpkt); /* non-blocking scheduling of TX packet */ 437 | j = 0; 438 | printf("+++\nSending packet #%u, rf path %d, return %d\nstatus -> ", tx_cnt, txpkt.rf_chain, i); 439 | do { 440 | ++j; 441 | wait_ms(100); 442 | lgw_status(TX_STATUS, &status_var); /* get TX status */ 443 | printf("%d:", status_var); 444 | } while ((status_var != TX_FREE) && (j < 100)); 445 | ++tx_cnt; 446 | printf("\nTX finished\n"); 447 | } 448 | } 449 | 450 | if (exit_sig == 1) { 451 | /* clean up before leaving */ 452 | lgw_stop(); 453 | } 454 | 455 | printf("\nEnd of test for loragw_hal.c\n"); 456 | return 0; 457 | } 458 | 459 | /* --- EOF ------------------------------------------------------------------ */ 460 | -------------------------------------------------------------------------------- /libloragw/tst/test_loragw_reg.c: -------------------------------------------------------------------------------- 1 | /* 2 | / _____) _ | | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 5 | _____) ) ____| | | || |_| ____( (___| | | | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 7 | (C)2017 Semtech-Cycleo 8 | 9 | Description: 10 | Minimum test program for the loragw_reg 'library' 11 | 12 | License: Revised BSD License, see LICENSE.TXT file include in the project 13 | */ 14 | 15 | /* -------------------------------------------------------------------------- */ 16 | /* --- DEPENDANCIES --------------------------------------------------------- */ 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | #include "loragw_reg.h" 23 | 24 | /* -------------------------------------------------------------------------- */ 25 | /* --- PRIVATE CONSTANTS ---------------------------------------------------- */ 26 | 27 | #define COM_PATH_DEFAULT "/dev/ttyACM0" 28 | #define BURST_TEST_LENGTH 8192 29 | 30 | /* -------------------------------------------------------------------------- */ 31 | /* --- PRIVATE FUNCTIONS DEFINITION ----------------------------------------- */ 32 | 33 | /* describe command line options */ 34 | void usage(void) { 35 | printf("Available options:\n"); 36 | printf(" -h print this help\n"); 37 | printf(" -d COM device to be used to access the concentrator board\n"); 38 | printf(" => default path: " COM_PATH_DEFAULT "\n"); 39 | } 40 | 41 | /* -------------------------------------------------------------------------- */ 42 | /* --- MAIN FUNCTION -------------------------------------------------------- */ 43 | 44 | int main(int argc, char **argv) { 45 | int32_t read_value, test_value; 46 | uint16_t lfsr; 47 | uint8_t burst_buffout[BURST_TEST_LENGTH]; 48 | uint8_t burst_buffin[BURST_TEST_LENGTH]; 49 | int i; 50 | /* COM interfaces */ 51 | const char com_path_default[] = COM_PATH_DEFAULT; 52 | const char *com_path = com_path_default; 53 | 54 | /* parse command line options */ 55 | while ((i = getopt (argc, argv, "hd:")) != -1) { 56 | switch (i) { 57 | case 'h': 58 | usage(); 59 | return -1; 60 | break; 61 | case 'd': 62 | if (optarg != NULL) { 63 | com_path = optarg; 64 | } 65 | break; 66 | default: 67 | printf("ERROR: argument parsing\n"); 68 | usage(); 69 | return -1; 70 | } 71 | } 72 | 73 | printf("Beginning of test for loragw_reg.c\n"); 74 | 75 | i = lgw_connect(com_path); 76 | if (i == -1) { 77 | printf("ERROR: FAIL TO CONNECT BOARD ON %s\n", com_path); 78 | return -1; 79 | } 80 | 81 | /* 2 SPI transactions: 82 | -> 0x80 0x00 <- 0x00 0x00 forcing page 0 83 | -> 0x01 0x00 <- 0x00 0x64 checking version 84 | */ 85 | 86 | /* --- READ TEST --- */ 87 | 88 | lgw_reg_w(LGW_SOFT_RESET, 1); 89 | lgw_reg_check(stdout); 90 | 91 | /* --- READ/WRITE COHERENCY TEST --- */ 92 | 93 | /* 8b unsigned */ 94 | test_value = 197; /* 11000101b */ 95 | lgw_reg_w(LGW_IMPLICIT_PAYLOAD_LENGHT, test_value); 96 | lgw_reg_r(LGW_IMPLICIT_PAYLOAD_LENGHT, &read_value); 97 | printf("IMPLICIT_PAYLOAD_LENGHT = %d (should be %d)\n", read_value, test_value); 98 | 99 | /* 8b signed */ 100 | /* NO SUCH REG AVAILABLE */ 101 | // /* RADIO_SELECT is normally unsigned, modify it manually in loragw_reg.c */ 102 | // test_value = -59; /* 11000101b */ 103 | // lgw_reg_w(LGW_RADIO_SELECT, test_value); 104 | // lgw_reg_r(LGW_RADIO_SELECT, &read_value); 105 | // printf("RADIO_SELECT = %d (should be %d)\n", read_value, test_value); 106 | 107 | /* less than 8b, with offset, unsigned */ 108 | test_value = 11; /* 1011b */ 109 | lgw_reg_w(LGW_FRAME_SYNCH_PEAK2_POS, test_value); 110 | lgw_reg_r(LGW_FRAME_SYNCH_PEAK2_POS, &read_value); 111 | printf("FRAME_SYNCH_PEAK2_POS = %d (should be %d)\n", read_value, test_value); 112 | 113 | /* less than 8b, with offset, signed */ 114 | /* NO SUCH REG AVAILABLE */ 115 | // /* MBWSSF_FRAME_SYNCH_PEAK2_POS is normally unsigned, modify it manually in loragw_reg.c */ 116 | // test_value = -5; /* 1011b */ 117 | // lgw_reg_w(LGW_MBWSSF_FRAME_SYNCH_PEAK2_POS, test_value); 118 | // lgw_reg_r(LGW_MBWSSF_FRAME_SYNCH_PEAK2_POS, &read_value); 119 | // printf("MBWSSF_FRAME_SYNCH_PEAK2_POS = %d (should be %d)\n", read_value, test_value); 120 | 121 | /* 16b unsigned */ 122 | test_value = 49253; /* 11000000 01100101b */ 123 | lgw_reg_w(LGW_PREAMBLE_SYMB1_NB, test_value); 124 | lgw_reg_r(LGW_PREAMBLE_SYMB1_NB, &read_value); 125 | printf("PREAMBLE_SYMB1_NB = %d (should be %d)\n", read_value, test_value); 126 | 127 | /* 16b signed */ 128 | /* NO SUCH REG AVAILABLE */ 129 | // /* CAPTURE_PERIOD is normally unsigned, modify it manually in loragw_reg.c */ 130 | // test_value = -16283; /* 11000000 01100101b */ 131 | // lgw_reg_w(LGW_CAPTURE_PERIOD, test_value); 132 | // lgw_reg_r(LGW_CAPTURE_PERIOD, &read_value); 133 | // printf("CAPTURE_PERIOD = %d (should be %d)\n", read_value, test_value); 134 | 135 | /* between 8b and 16b, unsigned */ 136 | test_value = 3173; /* 1100 01100101b */ 137 | lgw_reg_w(LGW_ADJUST_MODEM_START_OFFSET_SF12_RDX4, test_value); 138 | lgw_reg_r(LGW_ADJUST_MODEM_START_OFFSET_SF12_RDX4, &read_value); 139 | printf("ADJUST_MODEM_START_OFFSET_SF12_RDX4 = %d (should be %d)\n", read_value, test_value); 140 | 141 | /* between 8b and 16b, signed */ 142 | test_value = -1947; /* 11000 01100101b */ 143 | lgw_reg_w(LGW_IF_FREQ_1, test_value); 144 | lgw_reg_r(LGW_IF_FREQ_1, &read_value); 145 | printf("IF_FREQ_1 = %d (should be %d)\n", read_value, test_value); 146 | 147 | /* --- BURST WRITE AND READ TEST --- */ 148 | 149 | /* initialize data for SPI test */ 150 | lfsr = 0xFFFF; 151 | for(i = 0; i < BURST_TEST_LENGTH; ++i) { 152 | burst_buffout[i] = (uint8_t)(lfsr ^ (lfsr >> 4)); 153 | /* printf("%05d # 0x%04x 0x%02x\n", i, lfsr, burst_buffout[i]); */ 154 | lfsr = (lfsr & 1) ? ((lfsr >> 1) ^ 0x8679) : (lfsr >> 1); 155 | } 156 | 157 | lgw_reg_wb(LGW_TX_DATA_BUF_DATA, burst_buffout, 256); 158 | lgw_reg_rb(LGW_RX_DATA_BUF_DATA, burst_buffin, 256); 159 | 160 | /* impossible to check in software, 161 | RX_DATA_BUF_DATA is read-only, 162 | TX_DATA_BUF_DATA is write only, 163 | use a logic analyser */ 164 | 165 | /* --- END OF TEST --- */ 166 | 167 | lgw_disconnect(); 168 | /* no SPI transaction */ 169 | 170 | printf("End of test for loragw_reg.c\n"); 171 | return 0; 172 | } 173 | 174 | /* --- EOF ------------------------------------------------------------------ */ 175 | -------------------------------------------------------------------------------- /lora_indent.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Convert file encoding type from dos 2 unix 4 | find . -regex '.*\.\(cpp\|h\|c\)' -exec dos2unix {} \; 5 | 6 | # Remove trailing spaces from source files 7 | find . -regex '.*\.\(cpp\|h\|c\)' -exec sed -i 's/[ \t]*$//g' {} \; 8 | 9 | # Replace tabs with 4-spaces in all source files 10 | find . -regex '.*\.\(cpp\|h\|c\)' -exec sed -i 's/\t/ /g' {} \; 11 | 12 | # indent code 13 | find . -regex '.*\.\(cpp\|h\|c\)' -exec astyle --indent-switches --indent-cases --pad-oper --pad-comma --add-brackets --indent=spaces=4 -A2 --mode=c {} \; 14 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | / _____) _ | | 2 | ( (____ _____ ____ _| |_ _____ ____| |__ 3 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 4 | _____) ) ____| | | || |_| ____( (___| | | | 5 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 6 | (C)2013 Semtech-Cycleo 7 | 8 | LoRa Gateway project 9 | ===================== 10 | 11 | ## 1. Core library: libloragw 12 | ----------------------------- 13 | 14 | This directory contains the sources of the library to build a LoRa Picocell 15 | Gateway based on a Semtech LoRa multi-channel RF receiver (a.k.a. concentrator). 16 | Once compiled all the code is contained in the libloragw.a file that will be 17 | statically linked (ie. integrated in the final executable). 18 | The library implements the communication with the concentrator embedded MCU 19 | through a serial port. 20 | 21 | The library also comes with a bunch of basic tests programs that are used to 22 | test the different sub-modules of the library. 23 | 24 | ## 2. Helper programs 25 | --------------------- 26 | 27 | Those programs are included in the project to provide examples on how to use 28 | the HAL library, and to help the system builder test different parts of it. 29 | 30 | ### 2.1. util_pkt_logger ### 31 | 32 | This software is used to set up a LoRa concentrator using a JSON configuration 33 | file and then record all the packets received in a log file, indefinitely, until 34 | the user stops the application. 35 | 36 | ### 2.2. util_com_stress ### 37 | 38 | This software is used to check the reliability of the link between the host 39 | platform (on which the program is run) and the LoRa concentrator register file 40 | that is the interface through which all interaction with the LoRa concentrator 41 | happens. 42 | 43 | ### 2.3. util_tx_test ### 44 | 45 | This software is used to send test packets with a LoRa concentrator. The packets 46 | contain little information, on no protocol (ie. MAC address) information but 47 | can be used to assess the functionality of a gateway downlink using other 48 | gateways as receivers. 49 | 50 | ### 2.4. util_tx_continuous ### 51 | 52 | This software is used to set LoRa concentrator in Tx continuous mode, 53 | for spectral measurement. 54 | 55 | ### 2.5. util_boot ### 56 | 57 | This software is used to jump to the PicoCell Gateway bootloader for programming 58 | the MCU with a new firmware. 59 | Please refer to the readme of picoGW_mcu repository for more information about 60 | MCU flash programming. 61 | 62 | ### 2.6. util_chip_id ### 63 | 64 | This software is used to obtain the unique id of the PicoCell gateway (the 65 | 64 bits unique id extracted from the STM32 unique id registers). 66 | 67 | ## 4. User Guide 68 | ---------------- 69 | 70 | [A detailed PicoCell GW user guide is available here](https://github.com/Lora-net/picoGW_hal/wiki/Instructions-&-User-guide) 71 | 72 | ## 5. Changelog 73 | --------------- 74 | 75 | ### v0.2.3 ### 76 | 77 | * HAL: fixed an issue in the lgw_reg_r()/lgw_reg_w()/lgw_reg_rb()/lgw_reg_wb() 78 | functions to write the register page before reading/writing any register to 79 | avoid conflicting with MCU register page setting. 80 | 81 | ### v0.2.2 ### 82 | 83 | * HAL: updated MCU firmware version to match with picoGW_mcu V0.2.1 release. 84 | 85 | ### v0.2.1 ### 86 | 87 | * HAL: Fixed bug in lgw_mcu_receive() which was preventing from fetching more 88 | than 2 packets simultaneously. 89 | 90 | ### v0.2.0 ### 91 | 92 | * HAL: reverted AGC FW to version 4, as v5 was necessary to fix a HW bug which 93 | has been fixed since rev V02A of the picoCell reference design. 94 | * HAL: fixed a bug lgw_com_send_command() function to prevent from hanging when 95 | writing on the COM link was not possible. 96 | * HAL: fixed memory alignment on FSK syncword configuration. 97 | 98 | ### v0.1.2 ### 99 | 100 | * HAL: fixed a wrong copy size and position of MCU unique ID in lgw_mcu_get_unique_id(). 101 | * HAL: disabled some logs. 102 | 103 | ### v0.1.1 ### 104 | 105 | * HAL: fixed MCU command wrong size in lgw_mcu_commit_radio_calibration(). 106 | * HAL: fixed MCU reset sequence to wait for MCU to complete reset and reinit 107 | the communication bridge before exiting. This is to avoid issues when restarting 108 | the concentrator after exit. 109 | 110 | ### v0.1.0 ### 111 | 112 | * HAL: code clean-up/refactoring 113 | * HAL: serial port configuration to handle both USB or UART communication with 114 | mcu. 115 | * util_boot: only used to jump to the MCU bootloader. 116 | * util_chip_id: no more command line parameter, just print the PicoCell GW 117 | unique ID on the console. 118 | * HAL/util_*: added a parameter to lgw_connect() function to specify the COM 119 | device path to be used to communicate with the concentrator board (tty...). 120 | 121 | ### v0.0.1 ### 122 | 123 | * Initial release 124 | 125 | 126 | ## 6. Legal notice 127 | ------------------ 128 | 129 | The information presented in this project documentation does not form part of 130 | any quotation or contract, is believed to be accurate and reliable and may be 131 | changed without notice. No liability will be accepted by the publisher for any 132 | consequence of its use. Publication thereof does not convey nor imply any 133 | license under patent or other industrial or intellectual property rights. 134 | Semtech assumes no responsibility or liability whatsoever for any failure or 135 | unexpected operation resulting from misuse, neglect improper installation, 136 | repair or improper handling or unusual physical or electrical stress 137 | including, but not limited to, exposure to parameters beyond the specified 138 | maximum ratings or operation outside the specified range. 139 | 140 | SEMTECH PRODUCTS ARE NOT DESIGNED, INTENDED, AUTHORIZED OR WARRANTED TO BE 141 | SUITABLE FOR USE IN LIFE-SUPPORT APPLICATIONS, DEVICES OR SYSTEMS OR OTHER 142 | CRITICAL APPLICATIONS. INCLUSION OF SEMTECH PRODUCTS IN SUCH APPLICATIONS IS 143 | UNDERSTOOD TO BE UNDERTAKEN SOLELY AT THE CUSTOMER'S OWN RISK. Should a 144 | customer purchase or use Semtech products for any such unauthorized 145 | application, the customer shall indemnify and hold Semtech and its officers, 146 | employees, subsidiaries, affiliates, and distributors harmless against all 147 | claims, costs damages and attorney fees which could arise. 148 | 149 | *EOF* 150 | -------------------------------------------------------------------------------- /util_boot/Makefile: -------------------------------------------------------------------------------- 1 | ### Application-specific constants 2 | 3 | APP_NAME := util_boot 4 | 5 | ### Environment constants 6 | 7 | LGW_PATH ?= ../libloragw 8 | ARCH ?= 9 | CROSS_COMPILE ?= 10 | 11 | ### External constant definitions 12 | # must get library build option to know if mpsse must be linked or not 13 | 14 | include $(LGW_PATH)/library.cfg 15 | 16 | ### Constant symbols 17 | 18 | CC := $(CROSS_COMPILE)gcc 19 | AR := $(CROSS_COMPILE)ar 20 | 21 | CFLAGS=-O2 -Wall -Wextra -std=c99 -Iinc -I. 22 | 23 | OBJDIR = obj 24 | 25 | ### Constants for LoRa concentrator HAL library 26 | # List the library sub-modules that are used by the application 27 | 28 | LGW_INC = $(LGW_PATH)/inc/config.h 29 | LGW_INC += $(LGW_PATH)/inc/loragw_reg.h 30 | 31 | ### Linking options 32 | 33 | LIBS := -lloragw -lrt -lm 34 | 35 | ### General build targets 36 | 37 | all: $(APP_NAME) 38 | 39 | clean: 40 | rm -f $(OBJDIR)/*.o 41 | rm -f $(APP_NAME) 42 | 43 | ### HAL library (do no force multiple library rebuild even with 'make -B') 44 | 45 | $(LGW_PATH)/inc/config.h: 46 | @if test ! -f $@; then \ 47 | $(MAKE) all -C $(LGW_PATH); \ 48 | fi 49 | 50 | $(LGW_PATH)/libloragw.a: $(LGW_INC) 51 | @if test ! -f $@; then \ 52 | $(MAKE) all -C $(LGW_PATH); \ 53 | fi 54 | 55 | ### Main program compilation and assembly 56 | 57 | $(OBJDIR): 58 | mkdir -p $(OBJDIR) 59 | 60 | $(OBJDIR)/$(APP_NAME).o: src/$(APP_NAME).c $(LGW_INC) | $(OBJDIR) 61 | $(CC) -c $(CFLAGS) -I$(LGW_PATH)/inc $< -o $@ 62 | 63 | $(APP_NAME): $(OBJDIR)/$(APP_NAME).o $(LGW_PATH)/libloragw.a 64 | $(CC) -L$(LGW_PATH) $< -o $@ $(LIBS) 65 | 66 | ### EOF 67 | -------------------------------------------------------------------------------- /util_boot/readme.md: -------------------------------------------------------------------------------- 1 | ______ _ 2 | / _____) _ | | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 5 | _____) ) ____| | | || |_| ____( (___| | | | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 7 | (C)2014 Semtech-Cycleo 8 | 9 | util_boot program for LoRa concentrator 10 | =========================================== 11 | 12 | 13 | 1. Introduction 14 | ---------------- 15 | 16 | This software is used to jump to the PicoCell Gateway bootloader in order to 17 | program the MCU flash with a new firmware. 18 | 19 | 20 | 2. Usage 21 | -------- 22 | 23 | See command line help to get the list of all available options: 24 | ./util_boot -h 25 | 26 | 4. License 27 | ----------- 28 | 29 | Copyright (c) 2013, SEMTECH S.A. 30 | All rights reserved. 31 | 32 | Redistribution and use in source and binary forms, with or without 33 | modification, are permitted provided that the following conditions are met: 34 | 35 | * Redistributions of source code must retain the above copyright 36 | notice, this list of conditions and the following disclaimer. 37 | * Redistributions in binary form must reproduce the above copyright 38 | notice, this list of conditions and the following disclaimer in the 39 | documentation and/or other materials provided with the distribution. 40 | * Neither the name of the Semtech corporation nor the 41 | names of its contributors may be used to endorse or promote products 42 | derived from this software without specific prior written permission. 43 | 44 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 45 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 46 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 47 | DISCLAIMED. IN NO EVENT SHALL SEMTECH S.A. BE LIABLE FOR ANY 48 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 49 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 50 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 51 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 52 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 53 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 54 | 55 | *EOF* 56 | -------------------------------------------------------------------------------- /util_boot/src/util_boot.c: -------------------------------------------------------------------------------- 1 | /* 2 | / _____) _ | | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 5 | _____) ) ____| | | || |_| ____( (___| | | | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 7 | (C)2017 Semtech-Cycleo 8 | 9 | Description: 10 | Utility to jump to the PicoCell MCU bootloader 11 | 12 | License: Revised BSD License, see LICENSE.TXT file include in the project 13 | */ 14 | 15 | 16 | /* -------------------------------------------------------------------------- */ 17 | /* --- DEPENDANCIES --------------------------------------------------------- */ 18 | 19 | /* fix an issue between POSIX and C99 */ 20 | #if __STDC_VERSION__ >= 199901L 21 | #define _XOPEN_SOURCE 600 22 | #else 23 | #define _XOPEN_SOURCE 500 24 | #endif 25 | 26 | #include /* C99 types */ 27 | #include /* printf fprintf sprintf fopen fputs */ 28 | #include /* getopt access */ 29 | #include /* EXIT_FAILURE */ 30 | 31 | #include "loragw_com.h" 32 | 33 | /* -------------------------------------------------------------------------- */ 34 | /* --- PRIVATE MACROS ------------------------------------------------------- */ 35 | 36 | #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) 37 | #define MSG(args...) fprintf(stderr, args) /* message that is destined to the user */ 38 | 39 | /* -------------------------------------------------------------------------- */ 40 | /* --- PRIVATE CONSTANTS ---------------------------------------------------- */ 41 | 42 | #define COM_PATH_DEFAULT "/dev/ttyACM0" 43 | 44 | /* -------------------------------------------------------------------------- */ 45 | /* --- PRIVATE VARIABLES (GLOBAL) ------------------------------------------- */ 46 | 47 | void *lgw_com_target = NULL; /*! generic pointer to the COM device */ 48 | 49 | /* -------------------------------------------------------------------------- */ 50 | /* --- PRIVATE FUNCTIONS DECLARATION ---------------------------------------- */ 51 | 52 | void usage (void); 53 | 54 | /* -------------------------------------------------------------------------- */ 55 | /* --- PRIVATE FUNCTIONS DEFINITION ----------------------------------------- */ 56 | 57 | /* describe command line options */ 58 | void usage(void) { 59 | MSG("Available options:\n"); 60 | MSG(" -h print this help\n"); 61 | MSG(" -d COM device to be used to access the concentrator board\n"); 62 | MSG(" => default path: " COM_PATH_DEFAULT "\n"); 63 | } 64 | 65 | /* -------------------------------------------------------------------------- */ 66 | /* --- MAIN FUNCTION -------------------------------------------------------- */ 67 | 68 | int main(int argc, char **argv) { 69 | int i, x; 70 | lgw_com_cmd_t cmd; 71 | lgw_com_ans_t ans; 72 | /* COM interfaces */ 73 | const char com_path_default[] = COM_PATH_DEFAULT; 74 | const char *com_path = com_path_default; 75 | 76 | while ((i = getopt (argc, argv, "hd:")) != -1) { 77 | switch (i) { 78 | case 'h': 79 | usage(); 80 | return EXIT_FAILURE; 81 | break; 82 | 83 | case 'd': 84 | if (optarg != NULL) { 85 | com_path = optarg; 86 | } 87 | break; 88 | 89 | default: 90 | MSG("ERROR: argument parsing use -h option for help\n"); 91 | usage(); 92 | return EXIT_FAILURE; 93 | } 94 | } 95 | 96 | /* Open communication bridge */ 97 | x = lgw_com_open(&lgw_com_target, com_path); 98 | if (x == LGW_COM_ERROR) { 99 | printf("ERROR: FAIL TO CONNECT BOARD ON %s\n", com_path); 100 | return -1; 101 | } 102 | 103 | /* prepare command to jump to bootloader */ 104 | cmd.id = 'n'; 105 | cmd.len_msb = 0; 106 | cmd.len_lsb = 0; 107 | cmd.address = 0; 108 | /* send command to MCU */ 109 | x = lgw_com_send_command(lgw_com_target, cmd, &ans); 110 | if (x == LGW_COM_ERROR) { 111 | printf("ERROR: FAIL TO SEND COMMAND\n"); 112 | return -1; 113 | } 114 | 115 | /* Close communication bridge */ 116 | x = lgw_com_close(lgw_com_target); 117 | if (x == LGW_COM_ERROR) { 118 | printf("ERROR: FAIL TO DISCONNECT BOARD\n"); 119 | return -1; 120 | } 121 | 122 | return EXIT_SUCCESS; 123 | } 124 | 125 | /* --- EOF ------------------------------------------------------------------ */ 126 | 127 | 128 | -------------------------------------------------------------------------------- /util_chip_id/Makefile: -------------------------------------------------------------------------------- 1 | ### Application-specific constants 2 | 3 | APP_NAME := util_chip_id 4 | 5 | ### Environment constants 6 | 7 | LGW_PATH ?= ../libloragw 8 | ARCH ?= 9 | CROSS_COMPILE ?= 10 | 11 | ### External constant definitions 12 | # must get library build option to know if mpsse must be linked or not 13 | 14 | include $(LGW_PATH)/library.cfg 15 | 16 | ### Constant symbols 17 | 18 | CC := $(CROSS_COMPILE)gcc 19 | AR := $(CROSS_COMPILE)ar 20 | 21 | CFLAGS=-O2 -Wall -Wextra -std=c99 -Iinc -I. 22 | 23 | OBJDIR = obj 24 | 25 | ### Constants for LoRa concentrator HAL library 26 | # List the library sub-modules that are used by the application 27 | 28 | LGW_INC = $(LGW_PATH)/inc/config.h 29 | LGW_INC += $(LGW_PATH)/inc/loragw_reg.h 30 | 31 | ### Linking options 32 | 33 | LIBS := -lloragw -lrt -lm 34 | 35 | ### General build targets 36 | 37 | all: $(APP_NAME) 38 | 39 | clean: 40 | rm -f $(OBJDIR)/*.o 41 | rm -f $(APP_NAME) 42 | 43 | ### HAL library (do no force multiple library rebuild even with 'make -B') 44 | 45 | $(LGW_PATH)/inc/config.h: 46 | @if test ! -f $@; then \ 47 | $(MAKE) all -C $(LGW_PATH); \ 48 | fi 49 | 50 | $(LGW_PATH)/libloragw.a: $(LGW_INC) 51 | @if test ! -f $@; then \ 52 | $(MAKE) all -C $(LGW_PATH); \ 53 | fi 54 | 55 | ### Main program compilation and assembly 56 | 57 | $(OBJDIR): 58 | mkdir -p $(OBJDIR) 59 | 60 | $(OBJDIR)/$(APP_NAME).o: src/$(APP_NAME).c $(LGW_INC) | $(OBJDIR) 61 | $(CC) -c $(CFLAGS) -I$(LGW_PATH)/inc $< -o $@ 62 | 63 | $(APP_NAME): $(OBJDIR)/$(APP_NAME).o $(LGW_PATH)/libloragw.a 64 | $(CC) -L$(LGW_PATH) $< -o $@ $(LIBS) 65 | 66 | ### EOF 67 | -------------------------------------------------------------------------------- /util_chip_id/readme.md: -------------------------------------------------------------------------------- 1 | ______ _ 2 | / _____) _ | | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 5 | _____) ) ____| | | || |_| ____( (___| | | | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 7 | (C)2014 Semtech-Cycleo 8 | 9 | util_chip_id program for LoRa concentrator 10 | =========================================== 11 | 12 | 13 | 1. Introduction 14 | ---------------- 15 | 16 | This software is used to obtain the unique id of the PicoCell gateway. 17 | 64 bits unique id extracts from the STM32 uinque id registers. 18 | 19 | 20 | 2. Usage 21 | -------- 22 | 23 | See command line help to get the list of all available options: 24 | ./util_chip_id -h 25 | 26 | example 27 | ./util_chip_id -l 28 | 29 | 4. License 30 | ----------- 31 | 32 | Copyright (c) 2013, SEMTECH S.A. 33 | All rights reserved. 34 | 35 | Redistribution and use in source and binary forms, with or without 36 | modification, are permitted provided that the following conditions are met: 37 | 38 | * Redistributions of source code must retain the above copyright 39 | notice, this list of conditions and the following disclaimer. 40 | * Redistributions in binary form must reproduce the above copyright 41 | notice, this list of conditions and the following disclaimer in the 42 | documentation and/or other materials provided with the distribution. 43 | * Neither the name of the Semtech corporation nor the 44 | names of its contributors may be used to endorse or promote products 45 | derived from this software without specific prior written permission. 46 | 47 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 48 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 49 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 50 | DISCLAIMED. IN NO EVENT SHALL SEMTECH S.A. BE LIABLE FOR ANY 51 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 52 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 53 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 54 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 55 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 56 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 57 | 58 | *EOF* 59 | -------------------------------------------------------------------------------- /util_chip_id/src/util_chip_id.c: -------------------------------------------------------------------------------- 1 | /* 2 | / _____) _ | | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 5 | _____) ) ____| | | || |_| ____( (___| | | | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 7 | (C)2013 Semtech-Cycleo 8 | 9 | Description: 10 | Get unique ID of the PicoCell gateway board 11 | 12 | License: Revised BSD License, see LICENSE.TXT file include in the project 13 | */ 14 | 15 | 16 | /* -------------------------------------------------------------------------- */ 17 | /* --- DEPENDANCIES --------------------------------------------------------- */ 18 | 19 | /* fix an issue between POSIX and C99 */ 20 | #if __STDC_VERSION__ >= 199901L 21 | #define _XOPEN_SOURCE 600 22 | #else 23 | #define _XOPEN_SOURCE 500 24 | #endif 25 | 26 | #include /* C99 types */ 27 | #include /* bool type */ 28 | #include /* printf fprintf sprintf fopen fputs */ 29 | 30 | #include /* sigaction */ 31 | #include /* getopt access */ 32 | #include /* rand */ 33 | 34 | #include "loragw_reg.h" 35 | #include "loragw_mcu.h" 36 | 37 | /* -------------------------------------------------------------------------- */ 38 | /* --- PRIVATE MACROS ------------------------------------------------------- */ 39 | 40 | #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) 41 | #define MSG(args...) fprintf(stderr, args) /* message that is destined to the user */ 42 | 43 | /* -------------------------------------------------------------------------- */ 44 | /* --- PRIVATE CONSTANTS ---------------------------------------------------- */ 45 | 46 | #define COM_PATH_DEFAULT "/dev/ttyACM0" 47 | 48 | /* -------------------------------------------------------------------------- */ 49 | /* --- PRIVATE VARIABLES (GLOBAL) ------------------------------------------- */ 50 | 51 | /* -------------------------------------------------------------------------- */ 52 | /* --- PRIVATE FUNCTIONS DECLARATION ---------------------------------------- */ 53 | 54 | void usage (void); 55 | 56 | /* -------------------------------------------------------------------------- */ 57 | /* --- PRIVATE FUNCTIONS DEFINITION ----------------------------------------- */ 58 | 59 | /* describe command line options */ 60 | void usage(void) { 61 | MSG("Available options:\n"); 62 | MSG(" -h print this help\n"); 63 | MSG(" -d COM device to be used to access the concentrator board\n"); 64 | MSG(" => default path: " COM_PATH_DEFAULT "\n"); 65 | MSG(" -l generate a new guid.json file\n"); 66 | MSG(" -p print the ID of the PicoCell gateway\n"); 67 | } 68 | 69 | /* -------------------------------------------------------------------------- */ 70 | /* --- MAIN FUNCTION -------------------------------------------------------- */ 71 | 72 | int main(int argc, char **argv) { 73 | int i, x; 74 | uint8_t uid[8]; 75 | /* COM interfaces */ 76 | const char com_path_default[] = COM_PATH_DEFAULT; 77 | const char *com_path = com_path_default; 78 | 79 | while ((i = getopt (argc, argv, "hd:")) != -1) { 80 | switch (i) { 81 | case 'h': 82 | usage(); 83 | return EXIT_FAILURE; 84 | break; 85 | 86 | case 'd': 87 | if (optarg != NULL) { 88 | com_path = optarg; 89 | } 90 | break; 91 | 92 | default: 93 | MSG("ERROR: argument parsing use -h option for help\n"); 94 | usage(); 95 | return EXIT_FAILURE; 96 | } 97 | } 98 | 99 | x = lgw_connect(com_path); 100 | if (x == -1) { 101 | printf("ERROR: FAIL TO CONNECT BOARD ON %s\n", com_path); 102 | return -1; 103 | } 104 | 105 | lgw_mcu_get_unique_id(&uid[0]); 106 | printf("%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x\n", uid[0], uid[1], uid[2], uid[3], uid[4], uid[5], uid[6], uid[7]); 107 | 108 | x = lgw_disconnect(); 109 | if (x == -1) { 110 | printf("ERROR: FAIL TO DISCONNECT BOARD\n"); 111 | return -1; 112 | } 113 | 114 | return EXIT_SUCCESS; 115 | } 116 | 117 | /* --- EOF ------------------------------------------------------------------ */ 118 | 119 | 120 | -------------------------------------------------------------------------------- /util_com_stress/Makefile: -------------------------------------------------------------------------------- 1 | ### Application-specific constants 2 | 3 | APP_NAME := util_com_stress 4 | 5 | ### Environment constants 6 | 7 | LGW_PATH ?= ../libloragw 8 | ARCH ?= 9 | CROSS_COMPILE ?= 10 | 11 | ### External constant definitions 12 | # must get library build option to know if mpsse must be linked or not 13 | 14 | include $(LGW_PATH)/library.cfg 15 | 16 | ### Constant symbols 17 | 18 | CC := $(CROSS_COMPILE)gcc 19 | AR := $(CROSS_COMPILE)ar 20 | 21 | CFLAGS=-O2 -Wall -Wextra -std=c99 -Iinc -I. 22 | 23 | OBJDIR = obj 24 | 25 | ### Constants for LoRa concentrator HAL library 26 | # List the library sub-modules that are used by the application 27 | 28 | LGW_INC = $(LGW_PATH)/inc/config.h 29 | LGW_INC += $(LGW_PATH)/inc/loragw_reg.h 30 | 31 | ### Linking options 32 | 33 | LIBS := -lloragw -lrt -lm 34 | 35 | ### General build targets 36 | 37 | all: $(APP_NAME) 38 | 39 | clean: 40 | rm -f $(OBJDIR)/*.o 41 | rm -f $(APP_NAME) 42 | 43 | ### HAL library (do no force multiple library rebuild even with 'make -B') 44 | 45 | $(LGW_PATH)/inc/config.h: 46 | @if test ! -f $@; then \ 47 | $(MAKE) all -C $(LGW_PATH); \ 48 | fi 49 | 50 | $(LGW_PATH)/libloragw.a: $(LGW_INC) 51 | @if test ! -f $@; then \ 52 | $(MAKE) all -C $(LGW_PATH); \ 53 | fi 54 | 55 | ### Main program compilation and assembly 56 | 57 | $(OBJDIR): 58 | mkdir -p $(OBJDIR) 59 | 60 | $(OBJDIR)/$(APP_NAME).o: src/$(APP_NAME).c $(LGW_INC) | $(OBJDIR) 61 | $(CC) -c $(CFLAGS) -I$(LGW_PATH)/inc $< -o $@ 62 | 63 | $(APP_NAME): $(OBJDIR)/$(APP_NAME).o $(LGW_PATH)/libloragw.a 64 | $(CC) -L$(LGW_PATH) $< -o $@ $(LIBS) 65 | 66 | ### EOF 67 | -------------------------------------------------------------------------------- /util_com_stress/readme.md: -------------------------------------------------------------------------------- 1 | / _____) _ | | 2 | ( (____ _____ ____ _| |_ _____ ____| |__ 3 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 4 | _____) ) ____| | | || |_| ____( (___| | | | 5 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 6 | (C)2013 Semtech-Cycleo 7 | 8 | LoRa concentrator SPI stress test 9 | ================================== 10 | 11 | 1. Introduction 12 | ---------------- 13 | 14 | This software is used to check the reliability of the link between the host 15 | platform (on which the program is run) and the LoRa concentrator register file 16 | that is the interface through which all interaction with the LoRa concentrator 17 | happens. 18 | 19 | 2. Dependencies 20 | ---------------- 21 | 22 | This program only access the LoRa concentrator HAL library through its 23 | loragw_reg "named registers" access sub-module. 24 | 25 | 26 | 27 | The registers used are: 28 | * LGW_VERSION 29 | * LGW_IMPLICIT_PAYLOAD_LENGHT 30 | * LGW_FSK_REF_PATTERN_LSB 31 | * LGW_RX_DATA_BUF_ADDR 32 | * LGW_RX_DATA_BUF_DATA 33 | 34 | A data buffer accessible through the 2 registers above must be implemented. 35 | 36 | 3. Usage 37 | --------- 38 | 39 | The tests run forever or until an error is detected. 40 | Press Ctrl+C to stop the application. 41 | 42 | When an error is detected, diagnosis information are displayed. Please refer to 43 | the source code for more details on what is displayed for diagnosis. 44 | 45 | All tests use pseudo-random data generated by the rand() function. The random 46 | generator is not seeded, and the same sequence of data will be use each time the 47 | program is launched. 48 | 49 | Basically, some random data is written, read back and then compared to the 50 | initial written data. Some "useless" read on others registers might be inserted 51 | to be sure that the data read back is coming from the hardware, and not from the 52 | internal buffer(s) of the software driver(s). 53 | 54 | Test 1 > R/W on a simple 8-bit register 55 | 56 | Test 2 > R/W on a simple 8-bit register with interstitial reads on VERSION 57 | 58 | Test 3 > R/W on a 32-bit register 59 | 60 | Test 4 > data buffer R/W 61 | 62 | 4. License 63 | ----------- 64 | 65 | Copyright (c) 2013, SEMTECH S.A. 66 | All rights reserved. 67 | 68 | Redistribution and use in source and binary forms, with or without 69 | modification, are permitted provided that the following conditions are met: 70 | 71 | * Redistributions of source code must retain the above copyright 72 | notice, this list of conditions and the following disclaimer. 73 | * Redistributions in binary form must reproduce the above copyright 74 | notice, this list of conditions and the following disclaimer in the 75 | documentation and/or other materials provided with the distribution. 76 | * Neither the name of the Semtech corporation nor the 77 | names of its contributors may be used to endorse or promote products 78 | derived from this software without specific prior written permission. 79 | 80 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 81 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 82 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 83 | DISCLAIMED. IN NO EVENT SHALL SEMTECH S.A. BE LIABLE FOR ANY 84 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 85 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 86 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 87 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 88 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 89 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 90 | 91 | *EOF* -------------------------------------------------------------------------------- /util_com_stress/src/util_com_stress.c: -------------------------------------------------------------------------------- 1 | /* 2 | / _____) _ | | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 5 | _____) ) ____| | | || |_| ____( (___| | | | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 7 | (C)2017 Semtech-Cycleo 8 | 9 | Description: 10 | USB stress test 11 | 12 | License: Revised BSD License, see LICENSE.TXT file include in the project 13 | */ 14 | 15 | 16 | /* -------------------------------------------------------------------------- */ 17 | /* --- DEPENDANCIES --------------------------------------------------------- */ 18 | 19 | /* fix an issue between POSIX and C99 */ 20 | #if __STDC_VERSION__ >= 199901L 21 | #define _XOPEN_SOURCE 600 22 | #else 23 | #define _XOPEN_SOURCE 500 24 | #endif 25 | 26 | #include /* C99 types */ 27 | #include /* bool type */ 28 | #include /* printf fprintf sprintf fopen fputs */ 29 | 30 | #include /* sigaction */ 31 | #include /* getopt access */ 32 | #include /* rand */ 33 | 34 | #include "loragw_reg.h" 35 | 36 | /* -------------------------------------------------------------------------- */ 37 | /* --- PRIVATE MACROS ------------------------------------------------------- */ 38 | 39 | #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) 40 | #define MSG(args...) fprintf(stderr, args) /* message that is destined to the user */ 41 | 42 | /* -------------------------------------------------------------------------- */ 43 | /* --- PRIVATE CONSTANTS ---------------------------------------------------- */ 44 | 45 | #define COM_PATH_DEFAULT "/dev/ttyACM0" 46 | #define VERS 103 47 | #define READS_WHEN_ERROR 16 /* number of times a read is repeated if there is a read error */ 48 | #define BUFF_SIZE 1024 /* maximum number of bytes that we can write in sx1301 RX data buffer */ 49 | 50 | /* -------------------------------------------------------------------------- */ 51 | /* --- PRIVATE VARIABLES (GLOBAL) ------------------------------------------- */ 52 | 53 | /* signal handling variables */ 54 | struct sigaction sigact; /* SIGQUIT&SIGINT&SIGTERM signal handling */ 55 | static int exit_sig = 0; /* 1 -> application terminates cleanly (shut down hardware, close open files, etc) */ 56 | static int quit_sig = 0; /* 1 -> application terminates without shutting down the hardware */ 57 | 58 | /* -------------------------------------------------------------------------- */ 59 | /* --- PRIVATE FUNCTIONS DECLARATION ---------------------------------------- */ 60 | 61 | static void sig_handler(int sigio); 62 | 63 | void usage (void); 64 | 65 | /* -------------------------------------------------------------------------- */ 66 | /* --- PRIVATE FUNCTIONS DEFINITION ----------------------------------------- */ 67 | 68 | static void sig_handler(int sigio) { 69 | if (sigio == SIGQUIT) { 70 | quit_sig = 1;; 71 | } else if ((sigio == SIGINT) || (sigio == SIGTERM)) { 72 | exit_sig = 1; 73 | } 74 | } 75 | 76 | /* describe command line options */ 77 | void usage(void) { 78 | MSG("Available options:\n"); 79 | MSG(" -d COM device to be used to access the concentrator board\n"); 80 | MSG(" => default path: " COM_PATH_DEFAULT "\n"); 81 | MSG(" -h print this help\n"); 82 | MSG(" -t specify which test you want to run (1-4)\n"); 83 | } 84 | 85 | /* -------------------------------------------------------------------------- */ 86 | /* --- MAIN FUNCTION -------------------------------------------------------- */ 87 | 88 | int main(int argc, char **argv) { 89 | int i; 90 | int xi = 0; 91 | 92 | /* application option */ 93 | int test_number = 1; 94 | int cycle_number = 0; 95 | int repeats_per_cycle = 1000; 96 | bool error = false; 97 | 98 | /* in/out variables */ 99 | int32_t test_value; 100 | int32_t read_value; 101 | int32_t rb1, rb2, rb3; /* interstitial readbacks, to flush buffers if needed */ 102 | 103 | /* data buffer */ 104 | int32_t test_addr; 105 | uint8_t test_buff[BUFF_SIZE]; 106 | uint8_t read_buff[BUFF_SIZE]; 107 | 108 | /* COM interfaces */ 109 | const char com_path_default[] = COM_PATH_DEFAULT; 110 | const char *com_path = com_path_default; 111 | 112 | /* parse command line options */ 113 | while ((i = getopt (argc, argv, "ht:d:")) != -1) { 114 | switch (i) { 115 | case 'h': 116 | usage(); 117 | return EXIT_FAILURE; 118 | break; 119 | 120 | case 'd': 121 | if (optarg != NULL) { 122 | com_path = optarg; 123 | } 124 | break; 125 | 126 | case 't': 127 | i = sscanf(optarg, "%i", &xi); 128 | if ((i != 1) || (xi < 1) || (xi > 4)) { 129 | MSG("ERROR: invalid test number\n"); 130 | return EXIT_FAILURE; 131 | } else { 132 | test_number = xi; 133 | } 134 | break; 135 | 136 | default: 137 | MSG("ERROR: argument parsing use -h option for help\n"); 138 | usage(); 139 | return EXIT_FAILURE; 140 | } 141 | } 142 | MSG("INFO: Starting LoRa concentrator SPI stress-test number %i\n", test_number); 143 | 144 | /* configure signal handling */ 145 | sigemptyset(&sigact.sa_mask); 146 | sigact.sa_flags = 0; 147 | sigact.sa_handler = sig_handler; 148 | sigaction(SIGQUIT, &sigact, NULL); 149 | sigaction(SIGINT, &sigact, NULL); 150 | sigaction(SIGTERM, &sigact, NULL); 151 | 152 | /* start SPI link */ 153 | i = lgw_connect(com_path); 154 | if (i != LGW_REG_SUCCESS) { 155 | MSG("ERROR: lgw_connect() did not return SUCCESS ON %s\n", com_path); 156 | return EXIT_FAILURE; 157 | } 158 | 159 | if (test_number == 1) { 160 | /* single 8b register R/W stress test */ 161 | while ((quit_sig != 1) && (exit_sig != 1)) { 162 | printf("Cycle %i > ", cycle_number); 163 | for (i = 0; i < repeats_per_cycle; ++i) { 164 | test_value = (rand() % 256); 165 | lgw_reg_w(LGW_IMPLICIT_PAYLOAD_LENGHT, test_value); 166 | lgw_reg_r(LGW_IMPLICIT_PAYLOAD_LENGHT, &read_value); 167 | if (read_value != test_value) { 168 | error = true; 169 | break; 170 | } 171 | } 172 | if (error) { 173 | printf("error during the %ith iteration: write 0x%02X, read 0x%02X\n", i + 1, test_value, read_value); 174 | printf("Repeat read of target register:"); 175 | for (i = 0; i < READS_WHEN_ERROR; ++i) { 176 | lgw_reg_r(LGW_IMPLICIT_PAYLOAD_LENGHT, &read_value); 177 | printf(" 0x%02X", read_value); 178 | } 179 | printf("\n"); 180 | return EXIT_FAILURE; 181 | } else { 182 | printf("did %i R/W on an 8 bits reg with no error\n", repeats_per_cycle); 183 | ++cycle_number; 184 | } 185 | } 186 | } else if (test_number == 2) { 187 | /* single 8b register R/W with interstitial VERSION check stress test */ 188 | while ((quit_sig != 1) && (exit_sig != 1)) { 189 | printf("Cycle %i > ", cycle_number); 190 | for (i = 0; i < repeats_per_cycle; ++i) { 191 | test_value = (rand() % 256); 192 | lgw_reg_r(LGW_VERSION, &rb1); 193 | lgw_reg_w(LGW_IMPLICIT_PAYLOAD_LENGHT, test_value); 194 | lgw_reg_r(LGW_VERSION, &rb2); 195 | lgw_reg_r(LGW_IMPLICIT_PAYLOAD_LENGHT, &read_value); 196 | lgw_reg_r(LGW_VERSION, &rb3); 197 | if ((rb1 != VERS) || (rb2 != VERS) || (rb3 != VERS) || (read_value != test_value)) { 198 | error = true; 199 | break; 200 | } 201 | } 202 | if (error) { 203 | printf("error during the %ith iteration: write %02X, read %02X, version (%i, %i, %i)\n", i + 1, test_value, read_value, rb1, rb2, rb3); 204 | printf("Repeat read of target register:"); 205 | for (i = 0; i < READS_WHEN_ERROR; ++i) { 206 | lgw_reg_r(LGW_IMPLICIT_PAYLOAD_LENGHT, &read_value); 207 | printf(" 0x%02X", read_value); 208 | } 209 | printf("\n"); 210 | return EXIT_FAILURE; 211 | } else { 212 | printf("did %i R/W on an 8 bits reg with no error\n", repeats_per_cycle); 213 | ++cycle_number; 214 | } 215 | } 216 | } else if (test_number == 3) { 217 | /* 32b register R/W stress test */ 218 | while ((quit_sig != 1) && (exit_sig != 1)) { 219 | printf("Cycle %i > ", cycle_number); 220 | for (i = 0; i < repeats_per_cycle; ++i) { 221 | test_value = (rand() & 0x0000FFFF); 222 | test_value += (int32_t)(rand() & 0x0000FFFF) << 16; 223 | lgw_reg_w(LGW_FSK_REF_PATTERN_LSB, test_value); 224 | lgw_reg_r(LGW_FSK_REF_PATTERN_LSB, &read_value); 225 | if (read_value != test_value) { 226 | error = true; 227 | break; 228 | } 229 | } 230 | if (error) { 231 | printf("error during the %ith iteration: write 0x%08X, read 0x%08X\n", i + 1, test_value, read_value); 232 | printf("Repeat read of target register:"); 233 | for (i = 0; i < READS_WHEN_ERROR; ++i) { 234 | lgw_reg_r(LGW_FSK_REF_PATTERN_LSB, &read_value); 235 | printf(" 0x%08X", read_value); 236 | } 237 | printf("\n"); 238 | return EXIT_FAILURE; 239 | } else { 240 | printf("did %i R/W on a 32 bits reg with no error\n", repeats_per_cycle); 241 | ++cycle_number; 242 | } 243 | } 244 | } else if (test_number == 4) { 245 | /* databuffer R/W stress test */ 246 | int bufftest = 5; 247 | while ((quit_sig != 1) && (exit_sig != 1)) { 248 | if(bufftest < BUFF_SIZE) { 249 | bufftest++; 250 | } else { 251 | bufftest = 5; 252 | } 253 | 254 | for (i = 0; i < bufftest; ++i) { 255 | test_buff[i] = rand() & 0xFF; 256 | } 257 | printf("Cycle %i > ", cycle_number); 258 | test_addr = rand() & 0x0000FFFF; 259 | lgw_reg_w(LGW_RX_DATA_BUF_ADDR, test_addr); /* write at random offset in memory */ 260 | lgw_reg_wb(LGW_RX_DATA_BUF_DATA, test_buff, bufftest); 261 | 262 | lgw_reg_w(LGW_RX_DATA_BUF_ADDR, test_addr); /* go back to start of segment */ 263 | lgw_reg_rb(LGW_RX_DATA_BUF_DATA, read_buff, bufftest); 264 | for (i = 0; ((i < bufftest) && (test_buff[i] == read_buff[i])); ++i); 265 | if (i != bufftest) { 266 | printf("error during the buffer comparison\n"); 267 | printf("Written values:\n"); 268 | for (i = 0; i < bufftest; ++i) { 269 | printf(" %02X ", test_buff[i]); 270 | if (i % 16 == 15) { 271 | printf("\n"); 272 | } 273 | } 274 | printf("\n"); 275 | printf("Read values:\n"); 276 | for (i = 0; i < bufftest; ++i) { 277 | printf(" %02X ", (uint8_t)(test_buff[i] - read_buff[i])); 278 | if (i % 16 == 15) { 279 | printf("\n"); 280 | } 281 | } 282 | printf("\n"); 283 | lgw_reg_w(LGW_RX_DATA_BUF_ADDR, test_addr); /* go back to start of segment */ 284 | lgw_reg_rb(LGW_RX_DATA_BUF_DATA, read_buff, bufftest); 285 | printf("Re-read values:\n"); 286 | for (i = 0; i < bufftest; ++i) { 287 | printf(" %02X ", (uint8_t)(test_buff[i] - read_buff[i])); 288 | if (i % 16 == 15) { 289 | printf("\n"); 290 | } 291 | } 292 | printf("\n"); 293 | i = lgw_disconnect(); 294 | return EXIT_FAILURE; 295 | } else { 296 | printf("did a %i-bytes R/W on a data buffer with no error\n", bufftest); 297 | ++cycle_number; 298 | } 299 | } 300 | } else { 301 | MSG("ERROR: invalid test number\n"); 302 | usage(); 303 | } 304 | 305 | /* close SPI link */ 306 | i = lgw_disconnect(); 307 | if (i != LGW_REG_SUCCESS) { 308 | MSG("ERROR: lgw_disconnect() did not return SUCCESS\n"); 309 | return EXIT_FAILURE; 310 | } 311 | 312 | MSG("INFO: Exiting LoRa concentrator SPI stress-test program\n"); 313 | return EXIT_SUCCESS; 314 | } 315 | 316 | /* --- EOF ------------------------------------------------------------------ */ 317 | 318 | -------------------------------------------------------------------------------- /util_pkt_logger/Makefile: -------------------------------------------------------------------------------- 1 | ### Application-specific constants 2 | 3 | APP_NAME := util_pkt_logger 4 | 5 | ### Environment constants 6 | 7 | LGW_PATH ?= ../libloragw 8 | ARCH ?= 9 | CROSS_COMPILE ?= 10 | 11 | ### External constant definitions 12 | 13 | include $(LGW_PATH)/library.cfg 14 | 15 | ### Constant symbols 16 | 17 | CC := $(CROSS_COMPILE)gcc 18 | AR := $(CROSS_COMPILE)ar 19 | 20 | CFLAGS=-O2 -Wall -Wextra -std=c99 -Iinc -I. 21 | 22 | OBJDIR = obj 23 | 24 | ### Constants for LoRa concentrator HAL library 25 | # List the library sub-modules that are used by the application 26 | 27 | LGW_INC = $(LGW_PATH)/inc/config.h 28 | LGW_INC += $(LGW_PATH)/inc/loragw_hal.h 29 | 30 | ### Linking options 31 | 32 | LIBS := -lloragw -lrt -lm 33 | 34 | ### General build targets 35 | 36 | all: $(APP_NAME) 37 | 38 | clean: 39 | rm -f $(OBJDIR)/*.o 40 | rm -f $(APP_NAME) 41 | 42 | ### HAL library (do no force multiple library rebuild even with 'make -B') 43 | 44 | $(LGW_PATH)/inc/config.h: 45 | @if test ! -f $@; then \ 46 | $(MAKE) all -C $(LGW_PATH); \ 47 | fi 48 | 49 | $(LGW_PATH)/libloragw.a: $(LGW_INC) 50 | @if test ! -f $@; then \ 51 | $(MAKE) all -C $(LGW_PATH); \ 52 | fi 53 | 54 | ### Sub-modules compilation 55 | 56 | $(OBJDIR): 57 | mkdir -p $(OBJDIR) 58 | 59 | $(OBJDIR)/parson.o: src/parson.c inc/parson.h | $(OBJDIR) 60 | $(CC) -c $(CFLAGS) $< -o $@ 61 | 62 | ### Main program compilation and assembly 63 | 64 | $(OBJDIR)/$(APP_NAME).o: src/$(APP_NAME).c $(LGW_INC) inc/parson.h | $(OBJDIR) 65 | $(CC) -c $(CFLAGS) -I$(LGW_PATH)/inc $< -o $@ 66 | 67 | $(APP_NAME): $(OBJDIR)/$(APP_NAME).o $(LGW_PATH)/libloragw.a $(OBJDIR)/parson.o 68 | $(CC) -L$(LGW_PATH) $< $(OBJDIR)/parson.o -o $@ $(LIBS) 69 | 70 | ### EOF 71 | -------------------------------------------------------------------------------- /util_pkt_logger/global_conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "SX1301_conf": { 3 | "lorawan_public": true, 4 | "clksrc": 1, /* radio_1 provides clock to concentrator */ 5 | "radio_0": { 6 | "enable": true, 7 | "type": "SX1257", 8 | "freq": 867500000, 9 | "rssi_offset": -166.0, 10 | "tx_enable": false 11 | }, 12 | "radio_1": { 13 | "enable": true, 14 | "type": "SX1257", 15 | "freq": 868500000, 16 | "rssi_offset": -166.0, 17 | "tx_enable": false 18 | }, 19 | "chan_multiSF_0": { 20 | /* Lora MAC channel, 125kHz, all SF, 868.1 MHz */ 21 | "enable": true, 22 | "radio": 1, 23 | "if": -400000 24 | }, 25 | "chan_multiSF_1": { 26 | /* Lora MAC channel, 125kHz, all SF, 868.3 MHz */ 27 | "enable": true, 28 | "radio": 1, 29 | "if": -200000 30 | }, 31 | "chan_multiSF_2": { 32 | /* Lora MAC channel, 125kHz, all SF, 868.5 MHz */ 33 | "enable": true, 34 | "radio": 1, 35 | "if": 0 36 | }, 37 | "chan_multiSF_3": { 38 | /* Lora MAC channel, 125kHz, all SF, 867.1 MHz */ 39 | "enable": true, 40 | "radio": 0, 41 | "if": -400000 42 | }, 43 | "chan_multiSF_4": { 44 | /* Lora MAC channel, 125kHz, all SF, 867.3 MHz */ 45 | "enable": true, 46 | "radio": 0, 47 | "if": -200000 48 | }, 49 | "chan_multiSF_5": { 50 | /* Lora MAC channel, 125kHz, all SF, 867.5 MHz */ 51 | "enable": true, 52 | "radio": 0, 53 | "if": 0 54 | }, 55 | "chan_multiSF_6": { 56 | /* Lora MAC channel, 125kHz, all SF, 867.7 MHz */ 57 | "enable": true, 58 | "radio": 0, 59 | "if": 200000 60 | }, 61 | "chan_multiSF_7": { 62 | /* Lora MAC channel, 125kHz, all SF, 867.9 MHz */ 63 | "enable": true, 64 | "radio": 0, 65 | "if": 400000 66 | }, 67 | "chan_Lora_std": { 68 | /* Lora MAC channel, 250kHz, SF7, 868.3 MHz */ 69 | "enable": true, 70 | "radio": 1, 71 | "if": -200000, 72 | "bandwidth": 250000, 73 | "spread_factor": 7 74 | }, 75 | "chan_FSK": { 76 | /* FSK 50kbps channel, 868.8 MHz */ 77 | "enable": true, 78 | "radio": 1, 79 | "if": 300000, 80 | "bandwidth": 125000, 81 | "datarate": 50000 82 | } 83 | }, 84 | "gateway_conf": { 85 | "gateway_ID": "AA555A0000000000" 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /util_pkt_logger/inc/parson.h: -------------------------------------------------------------------------------- 1 | /* 2 | Parson ( http://kgabis.github.com/parson/ ) 3 | Copyright (c) 2012 - 2016 Krzysztof Gabis 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | */ 23 | 24 | #ifndef parson_parson_h 25 | #define parson_parson_h 26 | 27 | #ifdef __cplusplus 28 | extern "C" 29 | { 30 | #endif 31 | 32 | #include /* size_t */ 33 | 34 | /* Types and enums */ 35 | typedef struct json_object_t JSON_Object; 36 | typedef struct json_array_t JSON_Array; 37 | typedef struct json_value_t JSON_Value; 38 | 39 | enum json_value_type { 40 | JSONError = -1, 41 | JSONNull = 1, 42 | JSONString = 2, 43 | JSONNumber = 3, 44 | JSONObject = 4, 45 | JSONArray = 5, 46 | JSONBoolean = 6 47 | }; 48 | typedef int JSON_Value_Type; 49 | 50 | enum json_result_t { 51 | JSONSuccess = 0, 52 | JSONFailure = -1 53 | }; 54 | typedef int JSON_Status; 55 | 56 | typedef void * (*JSON_Malloc_Function)(size_t); 57 | typedef void (*JSON_Free_Function)(void *); 58 | 59 | /* Call only once, before calling any other function from parson API. If not called, malloc and free 60 | from stdlib will be used for all allocations */ 61 | void json_set_allocation_functions(JSON_Malloc_Function malloc_fun, JSON_Free_Function free_fun); 62 | 63 | /* Parses first JSON value in a file, returns NULL in case of error */ 64 | JSON_Value * json_parse_file(const char *filename); 65 | 66 | /* Parses first JSON value in a file and ignores comments (/ * * / and //), 67 | returns NULL in case of error */ 68 | JSON_Value * json_parse_file_with_comments(const char *filename); 69 | 70 | /* Parses first JSON value in a string, returns NULL in case of error */ 71 | JSON_Value * json_parse_string(const char *string); 72 | 73 | /* Parses first JSON value in a string and ignores comments (/ * * / and //), 74 | returns NULL in case of error */ 75 | JSON_Value * json_parse_string_with_comments(const char *string); 76 | 77 | /* Serialization */ 78 | size_t json_serialization_size(const JSON_Value *value); /* returns 0 on fail */ 79 | JSON_Status json_serialize_to_buffer(const JSON_Value *value, char *buf, size_t buf_size_in_bytes); 80 | JSON_Status json_serialize_to_file(const JSON_Value *value, const char *filename); 81 | char * json_serialize_to_string(const JSON_Value *value); 82 | 83 | /* Pretty serialization */ 84 | size_t json_serialization_size_pretty(const JSON_Value *value); /* returns 0 on fail */ 85 | JSON_Status json_serialize_to_buffer_pretty(const JSON_Value *value, char *buf, size_t buf_size_in_bytes); 86 | JSON_Status json_serialize_to_file_pretty(const JSON_Value *value, const char *filename); 87 | char * json_serialize_to_string_pretty(const JSON_Value *value); 88 | 89 | void json_free_serialized_string(char *string); /* frees string from json_serialize_to_string and json_serialize_to_string_pretty */ 90 | 91 | /* Comparing */ 92 | int json_value_equals(const JSON_Value *a, const JSON_Value *b); 93 | 94 | /* Validation 95 | This is *NOT* JSON Schema. It validates json by checking if object have identically 96 | named fields with matching types. 97 | For example schema {"name":"", "age":0} will validate 98 | {"name":"Joe", "age":25} and {"name":"Joe", "age":25, "gender":"m"}, 99 | but not {"name":"Joe"} or {"name":"Joe", "age":"Cucumber"}. 100 | In case of arrays, only first value in schema is checked against all values in tested array. 101 | Empty objects ({}) validate all objects, empty arrays ([]) validate all arrays, 102 | null validates values of every type. 103 | */ 104 | JSON_Status json_validate(const JSON_Value *schema, const JSON_Value *value); 105 | 106 | /* 107 | * JSON Object 108 | */ 109 | JSON_Value * json_object_get_value (const JSON_Object *object, const char *name); 110 | const char * json_object_get_string (const JSON_Object *object, const char *name); 111 | JSON_Object * json_object_get_object (const JSON_Object *object, const char *name); 112 | JSON_Array * json_object_get_array (const JSON_Object *object, const char *name); 113 | double json_object_get_number (const JSON_Object *object, const char *name); /* returns 0 on fail */ 114 | int json_object_get_boolean(const JSON_Object *object, const char *name); /* returns -1 on fail */ 115 | 116 | /* dotget functions enable addressing values with dot notation in nested objects, 117 | just like in structs or c++/java/c# objects (e.g. objectA.objectB.value). 118 | Because valid names in JSON can contain dots, some values may be inaccessible 119 | this way. */ 120 | JSON_Value * json_object_dotget_value (const JSON_Object *object, const char *name); 121 | const char * json_object_dotget_string (const JSON_Object *object, const char *name); 122 | JSON_Object * json_object_dotget_object (const JSON_Object *object, const char *name); 123 | JSON_Array * json_object_dotget_array (const JSON_Object *object, const char *name); 124 | double json_object_dotget_number (const JSON_Object *object, const char *name); /* returns 0 on fail */ 125 | int json_object_dotget_boolean(const JSON_Object *object, const char *name); /* returns -1 on fail */ 126 | 127 | /* Functions to get available names */ 128 | size_t json_object_get_count(const JSON_Object *object); 129 | const char * json_object_get_name (const JSON_Object *object, size_t index); 130 | 131 | /* Creates new name-value pair or frees and replaces old value with a new one. 132 | * json_object_set_value does not copy passed value so it shouldn't be freed afterwards. */ 133 | JSON_Status json_object_set_value(JSON_Object *object, const char *name, JSON_Value *value); 134 | JSON_Status json_object_set_string(JSON_Object *object, const char *name, const char *string); 135 | JSON_Status json_object_set_number(JSON_Object *object, const char *name, double number); 136 | JSON_Status json_object_set_boolean(JSON_Object *object, const char *name, int boolean); 137 | JSON_Status json_object_set_null(JSON_Object *object, const char *name); 138 | 139 | /* Works like dotget functions, but creates whole hierarchy if necessary. 140 | * json_object_dotset_value does not copy passed value so it shouldn't be freed afterwards. */ 141 | JSON_Status json_object_dotset_value(JSON_Object *object, const char *name, JSON_Value *value); 142 | JSON_Status json_object_dotset_string(JSON_Object *object, const char *name, const char *string); 143 | JSON_Status json_object_dotset_number(JSON_Object *object, const char *name, double number); 144 | JSON_Status json_object_dotset_boolean(JSON_Object *object, const char *name, int boolean); 145 | JSON_Status json_object_dotset_null(JSON_Object *object, const char *name); 146 | 147 | /* Frees and removes name-value pair */ 148 | JSON_Status json_object_remove(JSON_Object *object, const char *name); 149 | 150 | /* Works like dotget function, but removes name-value pair only on exact match. */ 151 | JSON_Status json_object_dotremove(JSON_Object *object, const char *key); 152 | 153 | /* Removes all name-value pairs in object */ 154 | JSON_Status json_object_clear(JSON_Object *object); 155 | 156 | /* 157 | *JSON Array 158 | */ 159 | JSON_Value * json_array_get_value (const JSON_Array *array, size_t index); 160 | const char * json_array_get_string (const JSON_Array *array, size_t index); 161 | JSON_Object * json_array_get_object (const JSON_Array *array, size_t index); 162 | JSON_Array * json_array_get_array (const JSON_Array *array, size_t index); 163 | double json_array_get_number (const JSON_Array *array, size_t index); /* returns 0 on fail */ 164 | int json_array_get_boolean(const JSON_Array *array, size_t index); /* returns -1 on fail */ 165 | size_t json_array_get_count (const JSON_Array *array); 166 | 167 | /* Frees and removes value at given index, does nothing and returns JSONFailure if index doesn't exist. 168 | * Order of values in array may change during execution. */ 169 | JSON_Status json_array_remove(JSON_Array *array, size_t i); 170 | 171 | /* Frees and removes from array value at given index and replaces it with given one. 172 | * Does nothing and returns JSONFailure if index doesn't exist. 173 | * json_array_replace_value does not copy passed value so it shouldn't be freed afterwards. */ 174 | JSON_Status json_array_replace_value(JSON_Array *array, size_t i, JSON_Value *value); 175 | JSON_Status json_array_replace_string(JSON_Array *array, size_t i, const char* string); 176 | JSON_Status json_array_replace_number(JSON_Array *array, size_t i, double number); 177 | JSON_Status json_array_replace_boolean(JSON_Array *array, size_t i, int boolean); 178 | JSON_Status json_array_replace_null(JSON_Array *array, size_t i); 179 | 180 | /* Frees and removes all values from array */ 181 | JSON_Status json_array_clear(JSON_Array *array); 182 | 183 | /* Appends new value at the end of array. 184 | * json_array_append_value does not copy passed value so it shouldn't be freed afterwards. */ 185 | JSON_Status json_array_append_value(JSON_Array *array, JSON_Value *value); 186 | JSON_Status json_array_append_string(JSON_Array *array, const char *string); 187 | JSON_Status json_array_append_number(JSON_Array *array, double number); 188 | JSON_Status json_array_append_boolean(JSON_Array *array, int boolean); 189 | JSON_Status json_array_append_null(JSON_Array *array); 190 | 191 | /* 192 | *JSON Value 193 | */ 194 | JSON_Value * json_value_init_object (void); 195 | JSON_Value * json_value_init_array (void); 196 | JSON_Value * json_value_init_string (const char *string); /* copies passed string */ 197 | JSON_Value * json_value_init_number (double number); 198 | JSON_Value * json_value_init_boolean(int boolean); 199 | JSON_Value * json_value_init_null (void); 200 | JSON_Value * json_value_deep_copy (const JSON_Value *value); 201 | void json_value_free (JSON_Value *value); 202 | 203 | JSON_Value_Type json_value_get_type (const JSON_Value *value); 204 | JSON_Object * json_value_get_object (const JSON_Value *value); 205 | JSON_Array * json_value_get_array (const JSON_Value *value); 206 | const char * json_value_get_string (const JSON_Value *value); 207 | double json_value_get_number (const JSON_Value *value); 208 | int json_value_get_boolean(const JSON_Value *value); 209 | 210 | /* Same as above, but shorter */ 211 | JSON_Value_Type json_type (const JSON_Value *value); 212 | JSON_Object * json_object (const JSON_Value *value); 213 | JSON_Array * json_array (const JSON_Value *value); 214 | const char * json_string (const JSON_Value *value); 215 | double json_number (const JSON_Value *value); 216 | int json_boolean(const JSON_Value *value); 217 | 218 | #ifdef __cplusplus 219 | } 220 | #endif 221 | 222 | #endif 223 | -------------------------------------------------------------------------------- /util_pkt_logger/local_conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "gateway_conf": { 3 | "gateway_ID": "AA555A0000000101" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /util_pkt_logger/readme.md: -------------------------------------------------------------------------------- 1 | / _____) _ | | 2 | ( (____ _____ ____ _| |_ _____ ____| |__ 3 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 4 | _____) ) ____| | | || |_| ____( (___| | | | 5 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 6 | (C)2013 Semtech-Cycleo 7 | 8 | LoRa packet logger 9 | =================== 10 | 11 | 1. Introduction 12 | ---------------- 13 | 14 | This software is used to set up a LoRa concentrator using a JSON configuration 15 | file and then record all the packets received in a log file, indefinitely, until 16 | the user stops the application. 17 | No filtering is done and all packets that are LoRa packets with the correct RF 18 | parameters (frequency, datarate, bandwidth) should appear in the log. 19 | 20 | 2. Dependencies 21 | ---------------- 22 | 23 | This program uses the Parson library (http://kgabis.github.com/parson/) by 24 | Krzysztof Gabis for JSON parsing. 25 | Many thanks to him for that very practical and well written library. 26 | 27 | This program is a typical example of LoRa concentrator HAL usage for receiving 28 | packets. 29 | 30 | Only high-level functions are used (the ones contained in loragw_hal) so there 31 | is no hardware dependencies assuming the HAL is matched with the proper version 32 | of the hardware. 33 | Data structures of the received packets are accessed by name (ie. not at a 34 | binary level) so new functionalities can be added to the API without affecting 35 | that program at all. 36 | 37 | It was tested with v1.3.0 of the libloragw library, and should be compatible 38 | with any later version of the library assuming the API is downward-compatible. 39 | 40 | 3. Usage 41 | --------- 42 | 43 | To stop the application, press Ctrl+C. 44 | 45 | The only optional parameter when launching the application is the log rotation 46 | time (in seconds). 47 | 48 | The way the program takes configuration files into account is the following: 49 | * if there is a debug_conf.json parse it, others are ignored 50 | * if there is a global_conf.json parse it and look for the next file 51 | * if there is a local_conf.json parse it 52 | If some parameters are defined in both global and local configuration files, the 53 | local definition overwrites the global definition. 54 | 55 | The global configuration file should be exactly the same throughout your 56 | network, contain all global parameters (parameters for "sensor" radio channels) 57 | and preferably default "safe" values for parameters that are specific for each 58 | gateway (eg. specify a default MAC address). 59 | 60 | If you have build the libloragw library for a specific radio band (eg. ETSI 61 | 868 MHz band) a ready-to-use global_conf.json file is generated by the Makefile 62 | with a set of channels typical for a 'LoRa MAC' network application. 63 | If you don't specify a radio band, an empty global_conf.json is generated and 64 | must be filled with the settings you need. 65 | 66 | The local configuration file should contain parameters that are specific to each 67 | gateway (eg. MAC address, frequency for backhaul radio channels). 68 | 69 | In each configuration file, the program looks for a JSON object named 70 | "SX1301_conf" that should contain the parameters for the LoRa concentrator board 71 | (RF channels definition, modem parameters, etc) and another JSON object called 72 | "gateway_conf" that should contain the gateway parameters (gateway MAC address, 73 | IP address of the LoRa MAC controller, network authentication parameters, etc). 74 | 75 | To learn more about the JSON configuration format, read the provided JSON files 76 | and the API documentation. A dedicated document will be available later on. 77 | 78 | The received packets are put in a CSV file whose name include the MAC address of 79 | the gateway in hexadecimal format and a UTC timestamp of log starting time in 80 | ISO 8601 recommended compact format: 81 | yyyymmddThhmmssZ (eg. 20131009T172345Z for October 9th, 2013 at 5:23:45PM UTC) 82 | 83 | To able continuous monitoring, the current log file is closed is closed and a 84 | new one is opened every hour (by default, rotation interval is settable by the 85 | user using -r command line option). 86 | No packet is lost during that rotation of log file. 87 | Every log file but the current one can then be modified, uploaded and/or deleted 88 | without any consequence for the program execution. 89 | 90 | 4. License 91 | ----------- 92 | 93 | Copyright (c) 2013, SEMTECH S.A. 94 | All rights reserved. 95 | 96 | Redistribution and use in source and binary forms, with or without 97 | modification, are permitted provided that the following conditions are met: 98 | 99 | * Redistributions of source code must retain the above copyright 100 | notice, this list of conditions and the following disclaimer. 101 | * Redistributions in binary form must reproduce the above copyright 102 | notice, this list of conditions and the following disclaimer in the 103 | documentation and/or other materials provided with the distribution. 104 | * Neither the name of the Semtech corporation nor the 105 | names of its contributors may be used to endorse or promote products 106 | derived from this software without specific prior written permission. 107 | 108 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 109 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 110 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 111 | DISCLAIMED. IN NO EVENT SHALL SEMTECH S.A. BE LIABLE FOR ANY 112 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 113 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 114 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 115 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 116 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 117 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 118 | 119 | 5. License for Parson library 120 | ------------------------------ 121 | 122 | Parson ( http://kgabis.github.com/parson/ ) 123 | Copyright (c) 2012 Krzysztof Gabis 124 | 125 | Permission is hereby granted, free of charge, to any person obtaining a copy 126 | of this software and associated documentation files (the "Software"), to deal 127 | in the Software without restriction, including without limitation the rights 128 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 129 | copies of the Software, and to permit persons to whom the Software is 130 | furnished to do so, subject to the following conditions: 131 | 132 | The above copyright notice and this permission notice shall be included in 133 | all copies or substantial portions of the Software. 134 | 135 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 136 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 137 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 138 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 139 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 140 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 141 | THE SOFTWARE. 142 | 143 | *EOF* -------------------------------------------------------------------------------- /util_tx_continuous/Makefile: -------------------------------------------------------------------------------- 1 | ### Application-specific constants 2 | 3 | APP_NAME := util_tx_continuous 4 | 5 | ### Environment constants 6 | 7 | LGW_PATH ?= ../libloragw 8 | ARCH ?= 9 | CROSS_COMPILE ?= 10 | 11 | ### External constant definitions 12 | # must get library build option to know if mpsse must be linked or not 13 | 14 | include $(LGW_PATH)/library.cfg 15 | 16 | ### Constant symbols 17 | 18 | CC := $(CROSS_COMPILE)gcc 19 | AR := $(CROSS_COMPILE)ar 20 | 21 | CFLAGS=-O2 -Wall -Wextra -std=c99 -Iinc -I. 22 | 23 | OBJDIR = obj 24 | 25 | ### Constants for LoRa concentrator HAL library 26 | # List the library sub-modules that are used by the application 27 | 28 | LGW_INC = $(LGW_PATH)/inc/config.h 29 | LGW_INC += $(LGW_PATH)/inc/loragw_hal.h 30 | LGW_INC += $(LGW_PATH)/inc/loragw_reg.h 31 | LGW_INC += $(LGW_PATH)/inc/loragw_aux.h 32 | 33 | ### Linking options 34 | 35 | LIBS := -lloragw -lrt -lm 36 | 37 | ### General build targets 38 | 39 | all: $(APP_NAME) 40 | 41 | clean: 42 | rm -f $(OBJDIR)/*.o 43 | rm -f $(APP_NAME) 44 | 45 | ### HAL library (do no force multiple library rebuild even with 'make -B') 46 | 47 | $(LGW_PATH)/inc/config.h: 48 | @if test ! -f $@; then \ 49 | $(MAKE) all -C $(LGW_PATH); \ 50 | fi 51 | 52 | $(LGW_PATH)/libloragw.a: $(LGW_INC) 53 | @if test ! -f $@; then \ 54 | $(MAKE) all -C $(LGW_PATH); \ 55 | fi 56 | 57 | ### Main program compilation and assembly 58 | 59 | $(OBJDIR): 60 | mkdir -p $(OBJDIR) 61 | 62 | $(OBJDIR)/$(APP_NAME).o: src/$(APP_NAME).c $(LGW_INC) | $(OBJDIR) 63 | $(CC) -c $(CFLAGS) -I$(LGW_PATH)/inc $< -o $@ 64 | 65 | $(APP_NAME): $(OBJDIR)/$(APP_NAME).o $(LGW_PATH)/libloragw.a 66 | $(CC) -L$(LGW_PATH) $< -o $@ $(LIBS) 67 | 68 | ### EOF 69 | -------------------------------------------------------------------------------- /util_tx_continuous/readme.md: -------------------------------------------------------------------------------- 1 | ______ _ 2 | / _____) _ | | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 5 | _____) ) ____| | | || |_| ____( (___| | | | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 7 | (C)2014 Semtech-Cycleo 8 | 9 | Tx continuous program for LoRa concentrator 10 | =========================================== 11 | 12 | 13 | 1. Introduction 14 | ---------------- 15 | 16 | This software is used to set LoRa concentrator in Tx continuous mode, for 17 | spectral measurement. 18 | The user can set the modulation type, the modulation parameters, and the 19 | multiple gains of the Tx chain. 20 | The program runs indefinitely, until the user stops the application. 21 | 22 | 23 | 2. Usage 24 | -------- 25 | 26 | See command line help to get the list of all available options: 27 | ./util_tx_continuous -h 28 | 29 | Example: 30 | ./util_tx_continuous -f 868 -r 1257 --dig 0 --mix 14 --pa 3 --mod "LORA" --sf 7 --bw 125 31 | 32 | 33 | 4. License 34 | ----------- 35 | 36 | Copyright (c) 2013, SEMTECH S.A. 37 | All rights reserved. 38 | 39 | Redistribution and use in source and binary forms, with or without 40 | modification, are permitted provided that the following conditions are met: 41 | 42 | * Redistributions of source code must retain the above copyright 43 | notice, this list of conditions and the following disclaimer. 44 | * Redistributions in binary form must reproduce the above copyright 45 | notice, this list of conditions and the following disclaimer in the 46 | documentation and/or other materials provided with the distribution. 47 | * Neither the name of the Semtech corporation nor the 48 | names of its contributors may be used to endorse or promote products 49 | derived from this software without specific prior written permission. 50 | 51 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 52 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 53 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 54 | DISCLAIMED. IN NO EVENT SHALL SEMTECH S.A. BE LIABLE FOR ANY 55 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 56 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 57 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 58 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 59 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 60 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 61 | 62 | *EOF* 63 | -------------------------------------------------------------------------------- /util_tx_continuous/src/util_tx_continuous.c: -------------------------------------------------------------------------------- 1 | /* 2 | ______ _ 3 | / _____) _ | | 4 | ( (____ _____ ____ _| |_ _____ ____| |__ 5 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 6 | _____) ) ____| | | || |_| ____( (___| | | | 7 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 8 | (C)2014 Semtech-Cycleo 9 | 10 | Description: 11 | SX1301 tx continuous utility 12 | 13 | License: Revised BSD License, see LICENSE.TXT file include in the project 14 | */ 15 | 16 | 17 | /* -------------------------------------------------------------------------- */ 18 | /* --- DEPENDENCIES --------------------------------------------------------- */ 19 | 20 | /* Fix an issue between POSIX and C99 */ 21 | #if __STDC_VERSION__ >= 199901L 22 | #define _XOPEN_SOURCE 600 23 | #else 24 | #define _XOPEN_SOURCE 500 25 | #endif 26 | 27 | #include /* C99 types */ 28 | #include /* bool type */ 29 | #include /* printf fprintf sprintf fopen fputs */ 30 | #include /* memset */ 31 | #include /* sigaction */ 32 | #include /* getopt access */ 33 | #include /* exit codes */ 34 | #include /* getopt_long */ 35 | 36 | #include "loragw_hal.h" 37 | #include "loragw_reg.h" 38 | #include "loragw_aux.h" 39 | 40 | /* -------------------------------------------------------------------------- */ 41 | /* --- MACROS & CONSTANTS --------------------------------------------------- */ 42 | 43 | #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) 44 | #define MSG(args...) fprintf(stderr, args) /* message that is destined to the user */ 45 | 46 | #define TX_RF_CHAIN 0 /* TX only supported on radio A */ 47 | #define DEFAULT_RSSI_OFFSET 0.0 48 | 49 | #define DEFAULT_FREQ_HZ 868e6 50 | #define DEFAULT_DIGITAL_GAIN 0 51 | #define DEFAULT_DAC_GAIN 3 52 | #define DEFAULT_MIXER_GAIN 14 53 | #define DEFAULT_PA_GAIN 3 54 | #define DEFAULT_MODULATION "LORA" 55 | #define DEFAULT_SF 7 56 | #define DEFAULT_BW_KHZ 125 57 | #define DEFAULT_BR_KBPS 50 58 | #define DEFAULT_FDEV_KHZ 25 59 | #define DEFAULT_BT 2 60 | 61 | #define COM_PATH_DEFAULT "/dev/ttyACM0" 62 | 63 | /* -------------------------------------------------------------------------- */ 64 | /* --- GLOBAL VARIABLES ----------------------------------------------------- */ 65 | 66 | /* Signal handling variables */ 67 | static int exit_sig = 0; /* 1 -> application terminates cleanly (shut down hardware, close open files, etc) */ 68 | static int quit_sig = 0; /* 1 -> application terminates without shutting down the hardware */ 69 | 70 | /* -------------------------------------------------------------------------- */ 71 | /* --- SUBFUNCTIONS DECLARATION --------------------------------------------- */ 72 | 73 | static void exit_cleanup(void); 74 | static void sig_handler(int sigio); 75 | 76 | /* -------------------------------------------------------------------------- */ 77 | /* --- MAIN FUNCTION -------------------------------------------------------- */ 78 | 79 | int main(int argc, char **argv) { 80 | static struct sigaction sigact; /* SIGQUIT&SIGINT&SIGTERM signal handling */ 81 | 82 | int i; /* loop and temporary variables */ 83 | 84 | /* Parameter parsing */ 85 | int option_index = 0; 86 | static struct option long_options[] = { 87 | {"dig", 1, 0, 0}, 88 | {"dac", 1, 0, 0}, 89 | {"mix", 1, 0, 0}, 90 | {"pa", 1, 0, 0}, 91 | {"mod", 1, 0, 0}, 92 | {"sf", 1, 0, 0}, 93 | {"bw", 1, 0, 0}, 94 | {"br", 1, 0, 0}, 95 | {"fdev", 1, 0, 0}, 96 | {"bt", 1, 0, 0}, 97 | {0, 0, 0, 0} 98 | }; 99 | unsigned int arg_u; 100 | float arg_f; 101 | char arg_s[64]; 102 | 103 | /* Application parameters */ 104 | uint32_t freq_hz = DEFAULT_FREQ_HZ; 105 | uint8_t g_dig = DEFAULT_DIGITAL_GAIN; 106 | uint8_t g_dac = DEFAULT_DAC_GAIN; 107 | uint8_t g_mix = DEFAULT_MIXER_GAIN; 108 | uint8_t g_pa = DEFAULT_PA_GAIN; 109 | char mod[64] = DEFAULT_MODULATION; 110 | uint8_t sf = DEFAULT_SF; 111 | unsigned int bw_khz = DEFAULT_BW_KHZ; 112 | float br_kbps = DEFAULT_BR_KBPS; 113 | uint8_t fdev_khz = DEFAULT_FDEV_KHZ; 114 | uint8_t bt = DEFAULT_BT; 115 | 116 | int32_t offset_i, offset_q; 117 | 118 | /* RF configuration (TX fail if RF chain is not enabled) */ 119 | enum lgw_radio_type_e radio_type = LGW_RADIO_TYPE_SX1257; 120 | struct lgw_conf_board_s boardconf; 121 | struct lgw_conf_rxrf_s rfconf; 122 | struct lgw_tx_gain_lut_s txlut; 123 | struct lgw_pkt_tx_s txpkt; 124 | 125 | /* COM interfaces */ 126 | const char com_path_default[] = COM_PATH_DEFAULT; 127 | const char *com_path = com_path_default; 128 | 129 | /* Parse command line options */ 130 | while ((i = getopt_long (argc, argv, "hf:r:d:", long_options, &option_index)) != -1) { 131 | switch (i) { 132 | case 'h': 133 | printf("~~~ Library version string~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"); 134 | printf(" %s\n", lgw_version_info()); 135 | printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"); 136 | printf(" -d COM device to be used to access the concentrator board\n"); 137 | printf(" => default path: " COM_PATH_DEFAULT "\n"); 138 | printf(" -f Tx RF frequency in MHz [800:1000]\n"); 139 | printf(" -r Radio type (SX1255:1255, SX1257:1257)\n"); 140 | printf(" --dig Digital gain trim, [0:3]\n"); 141 | printf(" 0:1, 1:7/8, 2:3/4, 3:1/2\n"); 142 | printf(" --mix Radio Tx mixer gain trim, [0:15]\n"); 143 | printf(" 15 corresponds to maximum gain, 1 LSB corresponds to 2dB step\n"); 144 | printf(" --pa PA gain trim, [0:3]\n"); 145 | printf(" --mod Modulation type ['LORA','FSK','CW']\n"); 146 | printf(" --sf LoRa Spreading Factor, [7:12]\n"); 147 | printf(" --bw LoRa bandwidth in kHz, [125,250,500]\n"); 148 | printf(" --br FSK bitrate in kbps, [0.5:250]\n"); 149 | printf(" --fdev FSK frequency deviation in kHz, [1:250]\n"); 150 | printf(" --bt FSK gaussian filter BT trim, [0:3]\n"); 151 | printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"); 152 | return EXIT_SUCCESS; 153 | break; 154 | 155 | case 0: 156 | if (strcmp(long_options[option_index].name, "dig") == 0) { 157 | i = sscanf(optarg, "%u", &arg_u); 158 | if ((i != 1) || (arg_u > 3)) { 159 | printf("ERROR: argument parsing of --dig argument. Use -h to print help\n"); 160 | return EXIT_FAILURE; 161 | } else { 162 | g_dig = (uint8_t)arg_u; 163 | } 164 | } else if (strcmp(long_options[option_index].name, "dac") == 0) { 165 | i = sscanf(optarg, "%u", &arg_u); 166 | if ((i != 1) || (arg_u > 3)) { 167 | printf("ERROR: argument parsing of --dac argument. Use -h to print help\n"); 168 | return EXIT_FAILURE; 169 | } else { 170 | g_dac = (uint8_t)arg_u; 171 | } 172 | } else if (strcmp(long_options[option_index].name, "mix") == 0) { 173 | i = sscanf(optarg, "%u", &arg_u); 174 | if ((i != 1) || (arg_u > 15)) { 175 | printf("ERROR: argument parsing of --mix argument. Use -h to print help\n"); 176 | return EXIT_FAILURE; 177 | } else { 178 | g_mix = (uint8_t)arg_u; 179 | } 180 | } else if (strcmp(long_options[option_index].name, "pa") == 0) { 181 | i = sscanf(optarg, "%u", &arg_u); 182 | if ((i != 1) || (arg_u > 3)) { 183 | printf("ERROR: argument parsing of --pa argument. Use -h to print help\n"); 184 | return EXIT_FAILURE; 185 | } else { 186 | g_pa = arg_u; 187 | } 188 | } else if (strcmp(long_options[option_index].name, "mod") == 0) { 189 | i = sscanf(optarg, "%63s", arg_s); 190 | if ((i != 1) || ((strcmp(arg_s, "LORA") != 0) && (strcmp(arg_s, "FSK") != 0) && (strcmp(arg_s, "CW") != 0))) { 191 | printf("ERROR: argument parsing of --mod argument. Use -h to print help\n"); 192 | return EXIT_FAILURE; 193 | } else { 194 | sprintf(mod, "%s", arg_s); 195 | } 196 | } else if (strcmp(long_options[option_index].name, "sf") == 0) { 197 | i = sscanf(optarg, "%u", &arg_u); 198 | if ((i != 1) || (arg_u < 7) || (arg_u > 12)) { 199 | printf("ERROR: argument parsing of --sf argument. Use -h to print help\n"); 200 | return EXIT_FAILURE; 201 | } else { 202 | sf = (uint8_t)arg_u; 203 | } 204 | } else if (strcmp(long_options[option_index].name, "bw") == 0) { 205 | i = sscanf(optarg, "%u", &arg_u); 206 | if ((i != 1) || ((arg_u != 125) && (arg_u != 250) && (arg_u != 500))) { 207 | printf("ERROR: argument parsing of --bw argument. Use -h to print help\n"); 208 | return EXIT_FAILURE; 209 | } else { 210 | bw_khz = arg_u; 211 | } 212 | } else if (strcmp(long_options[option_index].name, "br") == 0) { 213 | i = sscanf(optarg, "%f", &arg_f); 214 | if ((i != 1) || (arg_f < 0.5) || (arg_f > 250)) { 215 | printf("ERROR: argument parsing of --br argument. Use -h to print help\n"); 216 | return EXIT_FAILURE; 217 | } else { 218 | br_kbps = arg_f; 219 | } 220 | } else if (strcmp(long_options[option_index].name, "fdev") == 0) { 221 | i = sscanf(optarg, "%u", &arg_u); 222 | if ((i != 1) || (arg_u < 1) || (arg_u > 250)) { 223 | printf("ERROR: argument parsing of --fdev argument. Use -h to print help\n"); 224 | return EXIT_FAILURE; 225 | } else { 226 | fdev_khz = (uint8_t)arg_u; 227 | } 228 | } else if (strcmp(long_options[option_index].name, "bt") == 0) { 229 | i = sscanf(optarg, "%u", &arg_u); 230 | if ((i != 1) || (arg_u > 3)) { 231 | printf("ERROR: argument parsing of --bt argument. Use -h to print help\n"); 232 | return EXIT_FAILURE; 233 | } else { 234 | bt = (uint8_t)arg_u; 235 | } 236 | } else { 237 | printf("ERROR: argument parsing options. Use -h to print help\n"); 238 | return EXIT_FAILURE; 239 | } 240 | break; 241 | 242 | case 'f': 243 | i = sscanf(optarg, "%f", &arg_f); 244 | if ((i != 1) || (arg_f < 1)) { 245 | printf("ERROR: argument parsing of -f argument. Use -h to print help\n"); 246 | return EXIT_FAILURE; 247 | } else { 248 | freq_hz = (uint32_t)((arg_f * 1e6) + 0.5); 249 | } 250 | break; 251 | 252 | case 'r': 253 | i = sscanf(optarg, "%u", &arg_u); 254 | switch (arg_u) { 255 | case 1255: 256 | radio_type = LGW_RADIO_TYPE_SX1255; 257 | break; 258 | case 1257: 259 | radio_type = LGW_RADIO_TYPE_SX1257; 260 | break; 261 | default: 262 | printf("ERROR: argument parsing of -r argument. Use -h to print help\n"); 263 | return EXIT_FAILURE; 264 | } 265 | break; 266 | 267 | case 'd': 268 | if (optarg != NULL) { 269 | com_path = optarg; 270 | } 271 | break; 272 | 273 | default: 274 | printf("ERROR: argument parsing options. Use -h to print help\n"); 275 | return EXIT_FAILURE; 276 | } 277 | } 278 | 279 | /* register function to be called for exit cleanups */ 280 | atexit(exit_cleanup); 281 | 282 | /* Configure signal handling */ 283 | sigemptyset( &sigact.sa_mask ); 284 | sigact.sa_flags = 0; 285 | sigact.sa_handler = sig_handler; 286 | sigaction( SIGQUIT, &sigact, NULL ); 287 | sigaction( SIGINT, &sigact, NULL ); 288 | sigaction( SIGTERM, &sigact, NULL ); 289 | 290 | /* Open communication bridge */ 291 | i = lgw_connect(com_path); 292 | if (i == -1) { 293 | printf("ERROR: FAIL TO CONNECT BOARD ON %s\n", com_path); 294 | exit(EXIT_FAILURE); 295 | } 296 | 297 | /* Board config */ 298 | memset(&boardconf, 0, sizeof(boardconf)); 299 | boardconf.lorawan_public = true; 300 | boardconf.clksrc = 1; /* Radio B is source by default */ 301 | lgw_board_setconf(boardconf); 302 | 303 | /* RF config */ 304 | memset(&rfconf, 0, sizeof(rfconf)); 305 | rfconf.enable = true; 306 | rfconf.freq_hz = freq_hz; 307 | rfconf.rssi_offset = DEFAULT_RSSI_OFFSET; 308 | rfconf.type = radio_type; 309 | rfconf.tx_enable = true; 310 | lgw_rxrf_setconf(TX_RF_CHAIN, rfconf); 311 | 312 | /* Tx gain LUT */ 313 | memset(&txlut, 0, sizeof txlut); 314 | txlut.size = 16; 315 | int kk; 316 | for (kk = 0; kk < 16; kk++) { 317 | txlut.lut[kk].dig_gain = g_dig; 318 | txlut.lut[kk].pa_gain = g_pa; 319 | txlut.lut[kk].dac_gain = g_dac; 320 | txlut.lut[kk].mix_gain = g_mix; 321 | txlut.lut[kk].rf_power = 0; 322 | } 323 | lgw_txgain_setconf(&txlut); 324 | 325 | /* Start the concentrator */ 326 | i = lgw_start(); 327 | if (i == LGW_HAL_SUCCESS) { 328 | MSG("INFO: concentrator started, packet can be sent\n"); 329 | } else { 330 | MSG("ERROR: failed to start the concentrator\n"); 331 | exit(EXIT_FAILURE); 332 | } 333 | 334 | /* fill-up payload and parameters */ 335 | memset(&txpkt, 0, sizeof(txpkt)); 336 | txpkt.freq_hz = freq_hz; 337 | txpkt.tx_mode = IMMEDIATE; 338 | txpkt.rf_chain = TX_RF_CHAIN; 339 | txpkt.rf_power = 0; 340 | if (strcmp(mod, "FSK") == 0) { 341 | txpkt.modulation = MOD_FSK; 342 | txpkt.datarate = br_kbps * 1e3; 343 | } else { 344 | txpkt.modulation = MOD_LORA; 345 | switch (bw_khz) { 346 | case 125: 347 | txpkt.bandwidth = BW_125KHZ; 348 | break; 349 | case 250: 350 | txpkt.bandwidth = BW_250KHZ; 351 | break; 352 | case 500: 353 | txpkt.bandwidth = BW_500KHZ; 354 | break; 355 | default: 356 | MSG("ERROR: invalid 'bw' variable\n"); 357 | exit(EXIT_FAILURE); 358 | } 359 | switch (sf) { 360 | case 7: 361 | txpkt.datarate = DR_LORA_SF7; 362 | break; 363 | case 8: 364 | txpkt.datarate = DR_LORA_SF8; 365 | break; 366 | case 9: 367 | txpkt.datarate = DR_LORA_SF9; 368 | break; 369 | case 10: 370 | txpkt.datarate = DR_LORA_SF10; 371 | break; 372 | case 11: 373 | txpkt.datarate = DR_LORA_SF11; 374 | break; 375 | case 12: 376 | txpkt.datarate = DR_LORA_SF12; 377 | break; 378 | default: 379 | MSG("ERROR: invalid 'sf' variable\n"); 380 | exit(EXIT_FAILURE); 381 | } 382 | } 383 | txpkt.coderate = CR_LORA_4_5; 384 | txpkt.f_dev = fdev_khz; 385 | txpkt.preamble = 65535; 386 | txpkt.invert_pol = false; 387 | txpkt.no_crc = true; 388 | txpkt.no_header = true; 389 | txpkt.size = 1; 390 | txpkt.payload[0] = 0; 391 | 392 | /* Overwrite settings */ 393 | lgw_reg_w(LGW_TX_MODE, 1); /* Tx continuous */ 394 | lgw_reg_w(LGW_FSK_TX_GAUSSIAN_SELECT_BT, bt); 395 | if (strcmp(mod, "CW") == 0) { 396 | /* Enable signal generator with DC */ 397 | lgw_reg_w(LGW_SIG_GEN_FREQ, 0); 398 | lgw_reg_w(LGW_SIG_GEN_EN, 1); 399 | lgw_reg_w(LGW_TX_OFFSET_I, 0); 400 | lgw_reg_w(LGW_TX_OFFSET_Q, 0); 401 | } 402 | 403 | /* Send packet */ 404 | i = lgw_send(txpkt); 405 | if (i == -1) { 406 | printf("ERROR: FAIL TO START TX...\n"); 407 | exit(EXIT_FAILURE); 408 | } 409 | 410 | /* Recap all settings */ 411 | printf("SX1301 library version: %s\n", lgw_version_info()); 412 | if (strcmp(mod, "LORA") == 0) { 413 | printf("Modulation: LORA SF:%u BW:%u kHz\n", sf, bw_khz); 414 | } else if (strcmp(mod, "FSK") == 0) { 415 | printf("Modulation: FSK BR:%3.3f kbps FDEV:%d kHz BT:%d\n", br_kbps, fdev_khz, bt); 416 | } else if (strcmp(mod, "CW") == 0) { 417 | printf("Modulation: CW\n"); 418 | } 419 | switch(rfconf.type) { 420 | case LGW_RADIO_TYPE_SX1255: 421 | printf("Radio Type: SX1255\n"); 422 | break; 423 | case LGW_RADIO_TYPE_SX1257: 424 | printf("Radio Type: SX1257\n"); 425 | break; 426 | default: 427 | printf("ERROR: undefined radio type\n"); 428 | break; 429 | } 430 | printf("Frequency: %4.3f MHz\n", freq_hz / 1e6); 431 | printf("TX Gains: Digital:%d DAC:%d Mixer:%d PA:%d\n", g_dig, g_dac, g_mix, g_pa); 432 | if (strcmp(mod, "CW") != 0) { 433 | lgw_reg_r(LGW_TX_OFFSET_I, &offset_i); 434 | lgw_reg_r(LGW_TX_OFFSET_Q, &offset_q); 435 | printf("Calibrated DC offsets: I:%d Q:%d\n", offset_i, offset_q); 436 | } 437 | 438 | /* waiting for user input */ 439 | while ((quit_sig != 1) && (exit_sig != 1)) { 440 | wait_ms(100); 441 | } 442 | 443 | exit(EXIT_SUCCESS); 444 | } 445 | 446 | /* -------------------------------------------------------------------------- */ 447 | /* --- SUBFUNCTIONS DEFINITION ---------------------------------------------- */ 448 | 449 | static void exit_cleanup(void) { 450 | printf("Stopping concentrator.\n"); 451 | lgw_stop(); 452 | } 453 | 454 | static void sig_handler(int sigio) { 455 | if (sigio == SIGQUIT) { 456 | quit_sig = 1; 457 | } else if((sigio == SIGINT) || (sigio == SIGTERM)) { 458 | exit_sig = 1; 459 | } 460 | } 461 | 462 | /* --- EOF ------------------------------------------------------------------ */ 463 | -------------------------------------------------------------------------------- /util_tx_test/Makefile: -------------------------------------------------------------------------------- 1 | ### Application-specific constants 2 | 3 | APP_NAME := util_tx_test 4 | 5 | ### Environment constants 6 | 7 | LGW_PATH ?= ../libloragw 8 | ARCH ?= 9 | CROSS_COMPILE ?= 10 | 11 | ### External constant definitions 12 | # must get library build option to know if mpsse must be linked or not 13 | 14 | include $(LGW_PATH)/library.cfg 15 | 16 | ### Constant symbols 17 | 18 | CC := $(CROSS_COMPILE)gcc 19 | AR := $(CROSS_COMPILE)ar 20 | 21 | CFLAGS=-O2 -Wall -Wextra -std=c99 -Iinc -I. 22 | 23 | OBJDIR = obj 24 | 25 | ### Constants for LoRa concentrator HAL library 26 | # List the library sub-modules that are used by the application 27 | 28 | LGW_INC = $(LGW_PATH)/inc/config.h 29 | LGW_INC += $(LGW_PATH)/inc/loragw_hal.h 30 | LGW_INC += $(LGW_PATH)/inc/loragw_aux.h 31 | 32 | ### Linking options 33 | 34 | LIBS := -lloragw -lrt -lm 35 | 36 | ### General build targets 37 | 38 | all: $(APP_NAME) 39 | 40 | clean: 41 | rm -f $(OBJDIR)/*.o 42 | rm -f $(APP_NAME) 43 | 44 | ### HAL library (do no force multiple library rebuild even with 'make -B') 45 | 46 | $(LGW_PATH)/inc/config.h: 47 | @if test ! -f $@; then \ 48 | $(MAKE) all -C $(LGW_PATH); \ 49 | fi 50 | 51 | $(LGW_PATH)/libloragw.a: $(LGW_INC) 52 | @if test ! -f $@; then \ 53 | $(MAKE) all -C $(LGW_PATH); \ 54 | fi 55 | 56 | ### Main program compilation and assembly 57 | 58 | $(OBJDIR): 59 | mkdir -p $(OBJDIR) 60 | 61 | $(OBJDIR)/$(APP_NAME).o: src/$(APP_NAME).c $(LGW_INC) | $(OBJDIR) 62 | $(CC) -c $(CFLAGS) -I$(LGW_PATH)/inc $< -o $@ 63 | 64 | $(APP_NAME): $(OBJDIR)/$(APP_NAME).o $(LGW_PATH)/libloragw.a 65 | $(CC) -L$(LGW_PATH) $< -o $@ $(LIBS) 66 | 67 | ### EOF 68 | -------------------------------------------------------------------------------- /util_tx_test/readme.md: -------------------------------------------------------------------------------- 1 | / _____) _ | | 2 | ( (____ _____ ____ _| |_ _____ ____| |__ 3 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 4 | _____) ) ____| | | || |_| ____( (___| | | | 5 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 6 | (C)2013 Semtech-Cycleo 7 | 8 | LoRa concentrator packet sender 9 | ================================ 10 | 11 | 1. Introduction 12 | ---------------- 13 | 14 | This software is used to send test packets with a LoRa concentrator. The packets 15 | contain little information, on no protocol (ie. MAC address) information but 16 | can be used to assess the functionality of a gateway downlink using other 17 | gateways as receivers. 18 | 19 | 2. Dependencies 20 | ---------------- 21 | 22 | This program is a typical example of LoRa concentrator HAL usage for sending 23 | packets. 24 | 25 | Only high-level functions are used (the ones contained in loragw_hal) so there 26 | is no hardware dependencies assuming the HAL is matched with the proper version 27 | of the hardware. 28 | Data structures of the sent packets are accessed by name (ie. not at a 29 | binary level) so new functionalities can be added to the API without affecting 30 | that program at all. 31 | 32 | 3. Usage 33 | --------- 34 | 35 | The application runs until the specified number of packets have been sent. 36 | Press Ctrl+C to stop the application before that. 37 | 38 | Use the -h to get help and details about available options. 39 | 40 | The payload content is: 41 | [T][E][S][T][packet counter MSB][packet counter LSB] followed by ASCII padding. 42 | 43 | All LoRa data is scrambled and whitened, so the padding has no influence 44 | whatsoever on the packet error rate. 45 | 46 | 4. License 47 | ----------- 48 | 49 | Copyright (c) 2013, SEMTECH S.A. 50 | All rights reserved. 51 | 52 | Redistribution and use in source and binary forms, with or without 53 | modification, are permitted provided that the following conditions are met: 54 | 55 | * Redistributions of source code must retain the above copyright 56 | notice, this list of conditions and the following disclaimer. 57 | * Redistributions in binary form must reproduce the above copyright 58 | notice, this list of conditions and the following disclaimer in the 59 | documentation and/or other materials provided with the distribution. 60 | * Neither the name of the Semtech corporation nor the 61 | names of its contributors may be used to endorse or promote products 62 | derived from this software without specific prior written permission. 63 | 64 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 65 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 66 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 67 | DISCLAIMED. IN NO EVENT SHALL SEMTECH S.A. BE LIABLE FOR ANY 68 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 69 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 70 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 71 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 72 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 73 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 74 | 75 | *EOF* 76 | --------------------------------------------------------------------------------