diff options
| -rw-r--r-- | libloragw/Makefile (renamed from loragw_hal/Makefile) | 37 | ||||
| -rw-r--r-- | libloragw/README.TXT | 30 | ||||
| -rw-r--r-- | libloragw/VERSION | 20 | ||||
| -rw-r--r-- | libloragw/doc/99-libftdi.rules (renamed from loragw_hal/99-libftdi.rules) | 0 | ||||
| -rw-r--r-- | libloragw/doc/CHANGELOG.TXT | 35 | ||||
| -rw-r--r-- | libloragw/doc/INSTALL_FTDI.TXT (renamed from loragw_hal/INSTALL_FTDI.TXT) | 0 | ||||
| -rw-r--r-- | libloragw/doc/LICENSE.TXT | 8 | ||||
| -rw-r--r-- | libloragw/doc/MANUAL.TXT (renamed from loragw_hal/README.txt) | 67 | ||||
| -rw-r--r-- | libloragw/inc/loragw_aux.h (renamed from loragw_hal/inc/loragw_aux.h) | 0 | ||||
| -rw-r--r-- | libloragw/inc/loragw_hal.h (renamed from loragw_hal/inc/loragw_hal.h) | 101 | ||||
| -rw-r--r-- | libloragw/inc/loragw_reg.h (renamed from loragw_hal/inc/loragw_reg.h) | 0 | ||||
| -rw-r--r-- | libloragw/inc/loragw_spi.h (renamed from loragw_hal/inc/loragw_spi.h) | 0 | ||||
| -rw-r--r-- | libloragw/library.cfg (renamed from loragw_hal/library.cfg) | 0 | ||||
| -rw-r--r-- | libloragw/obj/.gitkeep (renamed from loragw_hal/obj/.gitkeep) | 0 | ||||
| -rw-r--r-- | libloragw/src/agc_fw.var (renamed from loragw_hal/src/agc_fw.var) | 0 | ||||
| -rw-r--r-- | libloragw/src/arb_fw.var (renamed from loragw_hal/src/arb_fw.var) | 0 | ||||
| -rw-r--r-- | libloragw/src/loragw_aux.c (renamed from loragw_hal/src/loragw_aux.c) | 0 | ||||
| -rw-r--r-- | libloragw/src/loragw_hal.c (renamed from loragw_hal/src/loragw_hal.c) | 278 | ||||
| -rw-r--r-- | libloragw/src/loragw_reg.c (renamed from loragw_hal/src/loragw_reg.c) | 14 | ||||
| -rw-r--r-- | libloragw/src/loragw_spi.ftdi.c (renamed from loragw_hal/src/loragw_spi.ftdi.c) | 0 | ||||
| -rw-r--r-- | libloragw/src/loragw_spi.native.c (renamed from loragw_hal/src/loragw_spi.native.c) | 0 | ||||
| -rw-r--r-- | libloragw/tst/test_loragw_hal.c (renamed from loragw_hal/test/test_loragw_hal.c) | 90 | ||||
| -rw-r--r-- | libloragw/tst/test_loragw_reg.c (renamed from loragw_hal/test/test_loragw_reg.c) | 0 | ||||
| -rw-r--r-- | libloragw/tst/test_loragw_spi.c (renamed from loragw_hal/test/test_loragw_spi.c) | 0 | 
24 files changed, 462 insertions, 218 deletions
| diff --git a/loragw_hal/Makefile b/libloragw/Makefile index 872952a..38d2fae 100644 --- a/loragw_hal/Makefile +++ b/libloragw/Makefile @@ -3,8 +3,8 @@ include library.cfg  # constant symbols  CC=gcc -CFLAGS=-O2 -Iinc -C99FLAGS=-O2 -std=c99 -Iinc +CFLAGS=-O2 -Iinc -I. +C99FLAGS=-O2 -std=c99 -Iinc -I.  # configuration-dependant symbols  ifeq ($(LGW_PHY),native) @@ -14,12 +14,12 @@ ifeq ($(LGW_PHY),ftdi)  LDFLAGS=-lrt -lmpsse  endif -  # general build targets -all: test_loragw_spi test_loragw_reg test_loragw_hal +all: libloragw.a test_loragw_spi test_loragw_reg test_loragw_hal  clean: +	rm -f *.a  	rm -f test_*  	rm -f obj/*.o  	rm -f .conf_ok @@ -37,8 +37,13 @@ else  endif  endif  	@echo "*** Config seems ok ***" +	@echo ""  	@touch .conf_ok +# static library + +libloragw.a: obj/loragw_hal.o obj/loragw_reg.o obj/loragw_spi.o obj/loragw_aux.o +	ar rcs libloragw.a obj/loragw_hal.o obj/loragw_reg.o obj/loragw_spi.o obj/loragw_aux.o  # library module target @@ -57,26 +62,16 @@ obj/loragw_reg.o: .conf_ok src/loragw_reg.c inc/loragw_reg.h inc/loragw_spi.h  	$(CC) -c $(C99FLAGS) src/loragw_reg.c -o obj/loragw_reg.o $(FLAG_REG)  obj/loragw_hal.o: .conf_ok src/loragw_hal.c src/arb_fw.var src/agc_fw.var inc/loragw_hal.h inc/loragw_reg.h inc/loragw_spi.h inc/loragw_aux.h -	$(CC) -c $(C99FLAGS) src/loragw_hal.c -o obj/loragw_hal.o $(FLAG_HAL) - +	$(CC) -c $(C99FLAGS) src/loragw_hal.c -o obj/loragw_hal.o -D LGW_PHY="\"$(LGW_PHY)\"" $(FLAG_HAL)  # test programs -obj/test_loragw_spi.o: test/test_loragw_spi.c inc/loragw_spi.h -	$(CC) -c $(C99FLAGS) -Iinc test/test_loragw_spi.c -o obj/test_loragw_spi.o - -obj/test_loragw_reg.o: test/test_loragw_reg.c inc/loragw_reg.h -	$(CC) -c $(C99FLAGS) -Iinc test/test_loragw_reg.c -o obj/test_loragw_reg.o - -obj/test_loragw_hal.o: test/test_loragw_hal.c inc/loragw_hal.h inc/loragw_aux.h -	$(CC) -c $(C99FLAGS) test/test_loragw_hal.c -o obj/test_loragw_hal.o - -test_loragw_spi: .conf_ok obj/test_loragw_spi.o obj/loragw_spi.o -	$(CC) obj/test_loragw_spi.o obj/loragw_spi.o -o test_loragw_spi $(LDFLAGS) +test_loragw_spi: tst/test_loragw_spi.c obj/loragw_spi.o +	$(CC) $(C99FLAGS) tst/test_loragw_spi.c obj/loragw_spi.o -o test_loragw_spi $(LDFLAGS) -test_loragw_reg: .conf_ok obj/test_loragw_reg.o obj/loragw_reg.o obj/loragw_spi.o -	$(CC) obj/test_loragw_reg.o obj/loragw_reg.o obj/loragw_spi.o -o test_loragw_reg $(LDFLAGS) +test_loragw_reg: tst/test_loragw_reg.c obj/loragw_reg.o obj/loragw_spi.o +	$(CC) $(C99FLAGS) tst/test_loragw_reg.c obj/loragw_reg.o obj/loragw_spi.o -o test_loragw_reg $(LDFLAGS) -test_loragw_hal: .conf_ok obj/test_loragw_hal.o obj/loragw_hal.o obj/loragw_reg.o obj/loragw_spi.o obj/loragw_aux.o -	$(CC) obj/test_loragw_hal.o obj/loragw_hal.o obj/loragw_reg.o obj/loragw_spi.o obj/loragw_aux.o -o test_loragw_hal $(LDFLAGS) +test_loragw_hal: tst/test_loragw_hal.c obj/loragw_hal.o obj/loragw_reg.o obj/loragw_spi.o obj/loragw_aux.o +	$(CC) $(C99FLAGS) tst/test_loragw_hal.c obj/loragw_hal.o obj/loragw_reg.o obj/loragw_spi.o obj/loragw_aux.o -o test_loragw_hal $(LDFLAGS) diff --git a/libloragw/README.TXT b/libloragw/README.TXT new file mode 100644 index 0000000..9d13a4a --- /dev/null +++ b/libloragw/README.TXT @@ -0,0 +1,30 @@ +Lora Gateway HAL library - Content of subdirectories +==================================================== + +## 1. doc ## + +Contains the user manual, licensing informations, udev rules, etc. + +## 2. inc ## + +Contain C header files for the different sub-modules of the library. + +You *MUST* include loragw_hal.h in your application. +You *MAY* include loragw_reg.h in your application if you need direct registers  +access. + +## 3. obj ## + +Contained the compiled intermediary objects. + +## 4. src ## + +Contain library C sources. + +## 5. tst ## + +Contain the C sources for test programs to validate SPI link, register access  +and hardware functionality. + + +*EOF*
\ No newline at end of file diff --git a/libloragw/VERSION b/libloragw/VERSION new file mode 100644 index 0000000..87b0704 --- /dev/null +++ b/libloragw/VERSION @@ -0,0 +1,20 @@ +/* Software library version: */ +#define VERSION_LIBRARY			"beta7" + +/* API version */ +#define VERSION_API				"beta" + +/* Accepted value of CHIP_ID (SPI registers) must match reg default value in loragw_reg.c */ +#define ACCEPT_CHIP_ID			"1" + +/* Accepted value of VERSION (SPI registers) must match reg default value in loragw_reg.c */ +#define	ACCEPT_VERSION_REG		"103" + +/* Accepted radio components */ +#define	INFO_RADIO_CHIP			"dual SX1257" + +/* Radio constants defined for the following bands */ +#define	INFO_RF_PARAM			"863-870 MHz TX&RX" + +/* Library validated on the following concentrator boards */ +#define	INFO_REF_HARDWARE		"Semtech Nano Concentrator v1 and v2" diff --git a/loragw_hal/99-libftdi.rules b/libloragw/doc/99-libftdi.rules index 8487413..8487413 100644 --- a/loragw_hal/99-libftdi.rules +++ b/libloragw/doc/99-libftdi.rules diff --git a/libloragw/doc/CHANGELOG.TXT b/libloragw/doc/CHANGELOG.TXT new file mode 100644 index 0000000..4ec6bd7 --- /dev/null +++ b/libloragw/doc/CHANGELOG.TXT @@ -0,0 +1,35 @@ +Lora Gateway HAL changelog +========================== + + Beta 7 (from beta 5) +--------------------- + + * Reduced number of SPI transactions to fetch a packet (improved number a packets par second that can be downloaded from gateway) + * Streamlined build process, main target is now a static library: libloragw.a + * Change memory allocation for payload: they are now part of the struct for TX/RX, no need to malloc/free + * All RX chains can use any of the two radios now + * FSK is available and working in TX and RX (variable length mode) + * Calibrated RSSI for FSK + * lgw_connect now check the CHIP_ID + * Added a license file and a changelog + * Added a function returning a version string to allow identification of the version/options once compiled + + Beta 6 +------- + +Not a mainline release, not taken into account in that changelog. + + Beta 5 (from beta 4) +--------------------- + + * Updated registers, firmware and configuration to align with r986 bitstream revision + * Calibrated RSSI for Lora "multi" and Lora "stand alone" modems + * Renamed some confusing TX status code + * Preliminary FSK support + + Beta 4 (from beta 3) +--------------------- + + * Unified build environment with selectable SPI layer (Linux native or FTDI SPI-over-USB bridge) + * Remove the 500 kHz limit on radio bandwith, back to the nominal 800 kHz + * Renamed debug flags diff --git a/loragw_hal/INSTALL_FTDI.TXT b/libloragw/doc/INSTALL_FTDI.TXT index d26ad4b..d26ad4b 100644 --- a/loragw_hal/INSTALL_FTDI.TXT +++ b/libloragw/doc/INSTALL_FTDI.TXT diff --git a/libloragw/doc/LICENSE.TXT b/libloragw/doc/LICENSE.TXT new file mode 100644 index 0000000..eab9548 --- /dev/null +++ b/libloragw/doc/LICENSE.TXT @@ -0,0 +1,8 @@ +THE FOLLOWING SOFTWARE IS PROVIDED: (1) "AS IS" WITH NO WARRANTY; AND  +(2)TO ENABLE ACCESS TO CODING INFORMATION TO GUIDE AND FACILITATE CUSTOMER. +CONSEQUENTLY, SEMTECH SHALL NOT BE HELD LIABLE FOR ANY DIRECT, INDIRECT OR +CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT +OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION +CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + +Copyright (C) SEMTECH S.A. diff --git a/loragw_hal/README.txt b/libloragw/doc/MANUAL.TXT index 58e7fbe..1659f03 100644 --- a/loragw_hal/README.txt +++ b/libloragw/doc/MANUAL.TXT @@ -1,14 +1,12 @@ -+===============================================+ -|  / _____)             _              | |      | -| ( (____  _____ ____ _| |_ _____  ____| |__    | -|  \____ \| ___ |    (_   _) ___ |/ ___)  _ \   | -|  _____) ) ____| | | || |_| ____( (___| | | |  | -| (______/|_____)_|_|_| \__)_____)\____)_| |_|  | -|     ©2013 Semtech-Cycleo                      | -|                                               | -| Description:                                  | -|     Lora Gateway HAL documentation            | -+===============================================+ +	 / _____)             _              | |     +	( (____  _____ ____ _| |_ _____  ____| |__   +	 \____ \| ___ |    (_   _) ___ |/ ___)  _ \  +	 _____) ) ____| | | || |_| ____( (___| | | | +	(______/|_____)_|_|_| \__)_____)\____)_| |_| +		©2013 Semtech-Cycleo + +Lora Gateway HAL user manual +============================  1. Introduction  --------------- @@ -18,8 +16,7 @@ use a Semtech Lora gateway hardware through a reduced number of high level C  functions to configure the hardware, send and receive packets.  The Semtech Lora gateway is a digital multi-channel multi-standard packet radio -used to send and receive packets wirelessly using Lora, FSK or GFSK -modulations. +used to send and receive packets wirelessly using Lora or FSK modulations.  2. Components of the library @@ -145,12 +142,17 @@ instructions.  4. Hardware dependencies  ------------------------ +### 4.1. Hardware revision ### +  The loragw_reg and loragw_hal are written for a specific version on the Semtech -hardware. -The library will not work if there is a mismatch between the hardware version -and the library version. -You can use the test program test_loragw_reg to check if the hardware registers -match their software declaration. +hardware (IP and/or silicon revision). +All relevant details are contained in the VERSION.TXT file. + +The library will not work if there is a mismatch between the hardware version  +and the library version. You can use the test program test_loragw_reg to check  +if the hardware registers match their software declaration. + +### 4.2. SPI communication ###  loragw_spi contains 4 SPI functions (read, write, burst read, burst write) that  are platform-dependant. @@ -169,6 +171,22 @@ that the SPI communication is working  5. Usage  -------- +### 5.1. Setting the software environment ### + +For a typical application you need to: + +* include loragw_hal.h in your program source +* link to the libloragw.a static library during compilation +* link to the librt library due to loragw_aux dependencies (timing functions) +* link to the libmpsse library if you use a FTDI SPI-over-USB bridge + +For an application that will also access the concentrator configuration  +registers directly (eg. for advanced configuration) you also need to: + +* include loragw_reg.h in your program source + +### 5.2. Using the software API ### +  To use the HAL in your application, you must follow some basic rules:  * configure the radios path and IF+modem path before starting the radio @@ -191,11 +209,6 @@ loop {  }  <stop the gateway> -To debug your application, it might help to compile the loragw_hal function -with the debug messages activated (set DEBUG_HAL=1 in library.cfg). -It then send a lot of details, including detailed error messages to *stderr*. - -  **/!\ Warning** The lgw_send function is non-blocking and returns while the  Lora gateway is still sending the packet, or even before the packet has started  to be transmitted if the packet is triggered on a future event. @@ -209,11 +222,11 @@ Trying to send a packet while the previous packet has not finished being send  will result in the previous packet not being sent or being sent only partially  (resulting in a CRC error in the receiver). +### 5.3. Debugging mode ### -6. License ----------- - -To Be Defined. +To debug your application, it might help to compile the loragw_hal function +with the debug messages activated (set DEBUG_HAL=1 in library.cfg). +It then send a lot of details, including detailed error messages to *stderr*.  *EOF*
\ No newline at end of file diff --git a/loragw_hal/inc/loragw_aux.h b/libloragw/inc/loragw_aux.h index 09f543f..09f543f 100644 --- a/loragw_hal/inc/loragw_aux.h +++ b/libloragw/inc/loragw_aux.h diff --git a/loragw_hal/inc/loragw_hal.h b/libloragw/inc/loragw_hal.h index d5daafd..08aa945 100644 --- a/loragw_hal/inc/loragw_hal.h +++ b/libloragw/inc/loragw_hal.h @@ -27,6 +27,10 @@ Description:  #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))  #define IS_LORA_MULTI_DR(dr)	((dr & ~DR_LORA_MULTI) == 0) /* ones outside of DR_LORA_MULTI bitmask -> not a combination of Lora datarates */  #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)) + +#define IS_FSK_BW(bw)			((bw >= 1) && (bw <= 7)) +#define IS_FSK_DR(dr)			((dr >= DR_FSK_MIN) && (dr <= DR_FSK_MAX)) +  #define	IS_TX_MODE(mode)		((mode == IMMEDIATE) || (mode == TIMESTAMPED) || (mode == ON_GPS))  /* -------------------------------------------------------------------------- */ @@ -41,25 +45,17 @@ Description:  #define LGW_IF_CHAIN_NB		10	/* number of IF+modem RX chains */  #define LGW_MULTI_NB		4	/* number of Lora 'multi SF' chains */ -#define LGW_PKT_FIFO_SIZE	8 -#define LGW_DATABUFF_SIZE	1024 -#define LGW_REF_BW			125000	/* typical bandwidth of data channel */ - -/* -SX1275 frequency setting : -F_register(24bit) = F_rf (Hz) / F_step(Hz) -                  = F_rf (Hz) * 2^19 / F_xtal(Hz) -                  = F_rf (Hz) * 256/15625 -*/ -#define LGW_XTAL_FREQU	32000000 -#define LGW_SX1257_DENOMINATOR	15625 /* pll settings denominator when the numerator is 2^8 */ +#define LGW_PKT_FIFO_SIZE	8			/* depth of the RX packet FIFO */ +#define LGW_DATABUFF_SIZE	1024		/* size in bytes of the RX data buffer (contains payload & metadata) */ +#define LGW_REF_BW			125000		/* typical bandwidth of data channel */ +#define LGW_XTAL_FREQU		32000000	/* frequency of the RF reference oscillator */  /* to use those parameters, declare a local constant, and use 'rf_chain' as index */ -#define LGW_RF_RX_LOWFREQ	{863000000, 863000000} -#define LGW_RF_RX_UPFREQ	{870000000, 870000000} -#define LGW_RF_RX_BANDWIDTH	{800000, 	800000}	/* bandwidth of the radios */ -#define LGW_RF_TX_LOWFREQ	{863000000, 863000000} -#define LGW_RF_TX_UPFREQ	{870000000, 870000000} +#define LGW_RF_RX_LOWFREQ	{863000000, 863000000}	/* lower limit of the usable band in RX for each radio */ +#define LGW_RF_RX_UPFREQ	{870000000, 870000000}	/* upper limit of the usable band in RX for each radio */ +#define LGW_RF_RX_BANDWIDTH	{800000, 	800000}		/* bandwidth of the radios */ +#define LGW_RF_TX_LOWFREQ	{863000000, 863000000}	/* lower limit of the usable band in TX for each radio */ +#define LGW_RF_TX_UPFREQ	{870000000, 870000000}	/* upper limit of the usable band in TX for each radio */  /* type of if_chain + modem */  #define IF_UNDEFINED		0 @@ -82,37 +78,46 @@ F_register(24bit) = F_rf (Hz) / F_step(Hz)  	IF_FSK_STD }  /* values available for the 'modulation' parameters */ +/* NOTE: arbitrary values */  #define MOD_UNDEFINED	0  #define MOD_LORA		0x10  #define MOD_FSK			0x20 -#define MOD_GFSK		0x21 -/* values available for the 'bandwidth' parameters */ +/* values available for the 'bandwidth' parameters (Lora & FSK) */ +/* NOTE: directly encode FSK RX bandwidth, do not change */  #define BW_UNDEFINED	0 -#define BW_500KHZ		0x04 -#define BW_250KHZ		0x08 -#define BW_125KHZ		0x0C -// TODO: add all the supported FSK bandwidth +#define BW_500KHZ		0x01 +#define BW_250KHZ		0x02 +#define BW_125KHZ		0x03 +#define BW_62K5HZ		0x04 +#define BW_31K2HZ		0x05 +#define BW_15K6HZ		0x06 +#define BW_7K8HZ		0x07  /* values available for the 'datarate' parameters */ +/* NOTE: Lora values used directly to code SF bitmask in 'multi' modem, do not change */  #define DR_UNDEFINED	0 -#define DR_LORA_SF7		0x1002 -#define DR_LORA_SF8		0x1004 -#define DR_LORA_SF9		0x1008 -#define DR_LORA_SF10	0x1010 -#define DR_LORA_SF11	0x1020 -#define DR_LORA_SF12	0x1040 -#define DR_LORA_MULTI	0x107E -// TODO: add FSK data rates - -/* values available for the 'coderate' parameters */ +#define DR_LORA_SF7		0x02 +#define DR_LORA_SF8		0x04 +#define DR_LORA_SF9		0x08 +#define DR_LORA_SF10	0x10 +#define DR_LORA_SF11	0x20 +#define DR_LORA_SF12	0x40 +#define DR_LORA_MULTI	0x7E +/* NOTE: for FSK directly use baudrate between 300 bauds and 250 kbauds */ +#define DR_FSK_MIN		300 +#define DR_FSK_MAX		250000 + +/* values available for the 'coderate' parameters (Lora only) */ +/* NOTE: arbitrary values */  #define CR_UNDEFINED	0 -#define CR_LORA_4_5		0x11 -#define CR_LORA_4_6		0x12 -#define CR_LORA_4_7		0x13 -#define CR_LORA_4_8		0x14 +#define CR_LORA_4_5		0x01 +#define CR_LORA_4_6		0x02 +#define CR_LORA_4_7		0x03 +#define CR_LORA_4_8		0x04  /* values available for the 'status' parameter */ +/* NOTE: values according to hardware specification */  #define STAT_UNDEFINED	0x00  #define STAT_NO_CRC		0x01  #define STAT_CRC_BAD	0x11 @@ -131,6 +136,7 @@ F_register(24bit) = F_rf (Hz) / F_step(Hz)  #define	RX_STATUS		2  /* status code for TX_STATUS */ +/* NOTE: arbitrary values */  #define TX_STATUS_UNKNOWN	0  #define	TX_OFF				1	/* TX modem disabled, it will ignore commands */  #define TX_FREE				2	/* TX modem is free, ready to receive a command */ @@ -138,6 +144,7 @@ F_register(24bit) = F_rf (Hz) / F_step(Hz)  #define TX_EMITTING			4	/* TX modem is emitting */  /* status code for RX_STATUS */ +/* NOTE: arbitrary values */  #define RX_STATUS_UNKNOWN	0  #define RX_OFF				1	/* RX modem is disabled, it will ignore commands  */  #define RX_ON				2	/* RX modem is receiving */ @@ -164,7 +171,7 @@ struct lgw_conf_rxif_s {  	uint8_t		rf_chain;	/*!> to which RF chain is that IF chain associated */  	int32_t		freq_hz;	/*!> center frequ of the IF chain, relative to RF chain frequency */  	uint8_t		bandwidth;	/*!> RX bandwidth, 0 for default */ -	uint16_t	datarate;	/*!> RX datarate, 0 for default */ +	uint32_t	datarate;	/*!> RX datarate, 0 for default */  };  /** @@ -185,7 +192,7 @@ struct lgw_pkt_rx_s {  	float		snr_max;	/*!> maximum packet SNR, in dB (Lora only) */  	uint16_t	crc;		/*!> CRC that was received in the payload */  	uint16_t	size;		/*!> payload size in bytes */ -	uint8_t		*payload;	/*!> pointer to the payload */ +	uint8_t		payload[256]; /*!> buffer containing the payload */  };  /** @@ -201,14 +208,14 @@ struct lgw_pkt_tx_s {  	uint8_t		modulation; /*!> modulation to use for the packet */  	uint8_t		bandwidth;	/*!> modulation bandwidth (Lora only) */  	bool		invert_pol;	/*!> invert signal polarity, for orthogonal downlinks (Lora only) */ -	uint16_t	f_dev;		/*!> frequency deviation (FSK only) */ -	uint16_t	datarate;	/*!> TX datarate */ -	uint8_t		coderate;	/*!> error-correcting code of the packet */ +	uint8_t		f_dev;		/*!> frequency deviation, in kHz (FSK only) */ +	uint16_t	datarate;	/*!> TX datarate (baudrate for FSK) */ +	uint8_t		coderate;	/*!> error-correcting code of the packet (Lora only) */  	uint16_t	preamble;	/*!> set the preamble length, 0 for default */  	bool		no_crc;		/*!> if true, do not send a CRC in the packet */ -	bool		no_header;	/*!> if true, enable implicit header mode */ +	bool		no_header;	/*!> if true, enable implicit header mode (Lora), fixed length (FSK) */  	uint16_t	size;		/*!> payload size in bytes */ -	uint8_t		*payload;	/*!> pointer to the payload */ +	uint8_t		payload[256]; /*!> buffer containing the payload */  };  /* -------------------------------------------------------------------------- */ @@ -265,6 +272,12 @@ int lgw_send(struct lgw_pkt_tx_s pkt_data);  */  int lgw_status(uint8_t select, uint8_t *code); +/** +@brief Allow user to check the version/options of the library once compiled +@return pointer on a human-readable null terminated string +*/ +const char* lgw_version_info(void); +  #endif  /* --- EOF ------------------------------------------------------------------ */ diff --git a/loragw_hal/inc/loragw_reg.h b/libloragw/inc/loragw_reg.h index 870780f..870780f 100644 --- a/loragw_hal/inc/loragw_reg.h +++ b/libloragw/inc/loragw_reg.h diff --git a/loragw_hal/inc/loragw_spi.h b/libloragw/inc/loragw_spi.h index 68d8bcf..68d8bcf 100644 --- a/loragw_hal/inc/loragw_spi.h +++ b/libloragw/inc/loragw_spi.h diff --git a/loragw_hal/library.cfg b/libloragw/library.cfg index ac24416..ac24416 100644 --- a/loragw_hal/library.cfg +++ b/libloragw/library.cfg diff --git a/loragw_hal/obj/.gitkeep b/libloragw/obj/.gitkeep index e69de29..e69de29 100644 --- a/loragw_hal/obj/.gitkeep +++ b/libloragw/obj/.gitkeep diff --git a/loragw_hal/src/agc_fw.var b/libloragw/src/agc_fw.var index 7d30fb9..7d30fb9 100644 --- a/loragw_hal/src/agc_fw.var +++ b/libloragw/src/agc_fw.var diff --git a/loragw_hal/src/arb_fw.var b/libloragw/src/arb_fw.var index 014a8e5..014a8e5 100644 --- a/loragw_hal/src/arb_fw.var +++ b/libloragw/src/arb_fw.var diff --git a/loragw_hal/src/loragw_aux.c b/libloragw/src/loragw_aux.c index 1c7e354..1c7e354 100644 --- a/loragw_hal/src/loragw_aux.c +++ b/libloragw/src/loragw_aux.c diff --git a/loragw_hal/src/loragw_hal.c b/libloragw/src/loragw_hal.c index 5b261f2..a57d9f1 100644 --- a/loragw_hal/src/loragw_hal.c +++ b/libloragw/src/loragw_hal.c @@ -15,7 +15,6 @@ Description:  /* --- DEPENDANCIES --------------------------------------------------------- */  #include <stdint.h>		/* C99 types */ -#include <stdlib.h>		/* malloc & free */  #include <stdbool.h>	/* bool type */  #include <stdio.h>		/* printf fprintf */  #include <math.h>		/* NaN */ @@ -61,6 +60,14 @@ const uint32_t rf_tx_upfreq[LGW_RF_CHAIN_NB] = LGW_RF_TX_UPFREQ;  #define		MCU_ARB_FW_BYTE		8192 /* size of the firmware IN BYTES (= twice the number of 14b words) */  #define		MCU_AGC_FW_BYTE		8192 /* size of the firmware IN BYTES (= twice the number of 14b words) */ +/* +SX1275 frequency setting : +F_register(24bit) = F_rf (Hz) / F_step(Hz) +                  = F_rf (Hz) * 2^19 / F_xtal(Hz) +                  = F_rf (Hz) * 256/15625 +*/ +#define 	SX1257_DENOM	15625	/* pll settings denominator when the numerator is 2^8 */ +  #define		SX1257_CLK_OUT			1	  #define		SX1257_TX_DAC_CLK_SEL	1	/* 0:int, 1:ext */  #define		SX1257_TX_DAC_GAIN		2	/* 3:0, 2:-3, 1:-6, 0:-9 dBFS (default 2) */ @@ -74,14 +81,16 @@ const uint32_t rf_tx_upfreq[LGW_RF_CHAIN_NB] = LGW_RF_TX_UPFREQ;  #define		SX1257_RX_ADC_TRIM		6	/* 0 to 7, 6 for 32MHz ref, 5 for 36MHz ref */  #define		SX1257_RXBB_BW			2 -#define		RSSI_OFFSET_LORA_MULTI	-130.0	/* calibrated value */ -#define		RSSI_OFFSET_LORA_STD	-168.0	/* calibrated for all bandwidth */ -#define		RSSI_OFFSET_FSK			0.0	/* TODO */ +#define		RSSI_OFFSET_LORA_MULTI	-128.0	/* calibrated value */ +#define		RSSI_OFFSET_LORA_STD	-167.0	/* calibrated for all bandwidth */ +#define		RSSI_OFFSET_FSK			-146.5	/* calibrated value */ +#define		RSSI_SLOPE_FSK			1.2		/* calibrated value */  #define		TX_METADATA_NB		16  #define		RX_METADATA_NB		16  #define		MIN_LORA_PREAMBLE		4 +#define		MIN_FSK_PREAMBLE		3  #define		PLL_LOCK_MAX_ATTEMPTS	6  /* -------------------------------------------------------------------------- */ @@ -90,6 +99,10 @@ const uint32_t rf_tx_upfreq[LGW_RF_CHAIN_NB] = LGW_RF_TX_UPFREQ;  #include "arb_fw.var" /* external definition of the variable */  #include "agc_fw.var" /* external definition of the variable */ +/* Version string, used to identify the library version/options once compiled */ +#include "VERSION" +const char lgw_version_string[] = "Library: " VERSION_LIBRARY "; API: " VERSION_API "; SPI layer: " LGW_PHY "; Chip id: " ACCEPT_CHIP_ID "; SPI reg: " ACCEPT_VERSION_REG "; Radio(s): " INFO_RADIO_CHIP "; Usable band: " INFO_RF_PARAM "; Reference plateform: " INFO_REF_HARDWARE ";"; +  /*  The following static variables are the configuration set that the user can  modify using rxrf_setconf and rxif_setconf functions. @@ -104,16 +117,18 @@ static bool lgw_is_started = false;  static bool rf_enable[LGW_RF_CHAIN_NB] = {0, 0};  static uint32_t rf_rx_freq[LGW_IF_CHAIN_NB] = {0, 0}; /* absolute, in Hz */ -static uint8_t if_rf_switch = 0x00; /* each IF from 0 to 7 has 1 bit associated to it, 0 -> radio A, 1 -> radio B */ -/* IF 8 and 9 are on radio A */ -  static bool if_enable[LGW_IF_CHAIN_NB] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static bool if_rf_chain[LGW_IF_CHAIN_NB] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* for each IF, 0 -> radio A, 1 -> radio B */  static int32_t if_freq[LGW_IF_CHAIN_NB] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* relative to radio frequency, +/- in Hz */  static uint8_t lora_multi_sfmask[LGW_MULTI_NB] = {0, 0, 0, 0}; /* enables SF for Lora 'multi' modems */ -static uint8_t lora_rx_bw = 0; /* for the Lora standalone modem(s) */ -static uint16_t lora_rx_sf = 0; /* for the Lora standalone modem(s) */ -static uint8_t lora_rx_ppm_offset = 0;  /* for the Lora standalone modem(s) */ + +static uint8_t lora_rx_bw = 0; /* bandwidth setting for Lora standalone modem */ +static uint8_t lora_rx_sf = 0; /* spreading factor setting for Lora standalone modem */ +static bool lora_rx_ppm_offset = 0; + +static uint8_t fsk_rx_bw = 0; /* bandwidth setting of FSK modem */ +static uint32_t fsk_rx_dr = 0; /* FSK modem datarate in bauds */  /* -------------------------------------------------------------------------- */  /* --- PRIVATE FUNCTIONS DECLARATION ---------------------------------------- */ @@ -291,8 +306,8 @@ int setup_sx1257(uint8_t rf_chain, uint32_t freq_hz) {  	sx125x_write(rf_chain, 0x0D, SX1257_RXBB_BW + SX1257_RX_ADC_TRIM*4 + SX1257_RX_ADC_BW*32);  	/* set RX PLL frequency */ -	part_int = freq_hz / LGW_SX1257_DENOMINATOR; /* integer part, gives the MSB and the middle byte */ -	part_frac = ((freq_hz % LGW_SX1257_DENOMINATOR) << 8) / LGW_SX1257_DENOMINATOR; /* fractional part, gives LSB */ +	part_int = freq_hz / SX1257_DENOM; /* integer part, gives the MSB and the middle byte */ +	part_frac = ((freq_hz % SX1257_DENOM) << 8) / SX1257_DENOM; /* fractional part, gives LSB */  	sx125x_write(rf_chain, 0x01,0xFF & (part_int >> 8)); /* Most Significant Byte */  	sx125x_write(rf_chain, 0x02,0xFF & part_int); /* middle byte */  	sx125x_write(rf_chain, 0x03,0xFF & part_frac); /* Least Significant Byte */ @@ -352,7 +367,7 @@ void lgw_constant_adjust(void) {  	// lgw_reg_w(LGW_CORR_SIG_NOISE_RATIO_SF11,4); /* default 4 */  	// lgw_reg_w(LGW_CORR_SIG_NOISE_RATIO_SF12,4); /* default 4 */ -	/* Lora 'multi' modems setup */ +	/* Lora 'multi' demodulators setup */  	lgw_reg_w(LGW_PREAMBLE_SYMB1_NB,4); /* default 10 */  	// lgw_reg_w(LGW_FREQ_TO_TIME_DRIFT,9); /* default 9 */  	// lgw_reg_w(LGW_FREQ_TO_TIME_INVERT,29); /* default 29 */ @@ -370,7 +385,7 @@ void lgw_constant_adjust(void) {  	// lgw_reg_w(LGW_ADJUST_MODEM_START_OFFSET_SF12_RDX4,4092); /* default 4092 */  	// lgw_reg_w(LGW_MAX_PAYLOAD_LEN,255); /* default 255 */ -	/* MBWSSF Modem */ +	/* Lora standalone 'MBWSSF' demodulator setup */  	// lgw_reg_w(LGW_MBWSSF_MODEM_ENABLE,1); /* default 0 */  	// lgw_reg_w(LGW_MBWSSF_PREAMBLE_SYMB1_NB,10); /* default 10 */  	// lgw_reg_w(LGW_MBWSSF_FREQ_TO_TIME_DRIFT,36); /* default 36 */ @@ -386,37 +401,41 @@ void lgw_constant_adjust(void) {  	// lgw_reg_w(LGW_MBWSSF_TRACKING_INTEGRAL,0); /* default 0 */  	// lgw_reg_w(LGW_MBWSSF_AGC_FREEZE_ON_DETECT,1); /* default 1 */ -	/* FSK datapath */ +	/* FSK datapath setup */  	lgw_reg_w(LGW_FSK_RX_INVERT,1); /* default 0 */  	lgw_reg_w(LGW_FSK_MODEM_INVERT_IQ,1); /* default 0 */ -	/* FSK demod */ -	// lgw_reg_w(LGW_FSK_AUTO_AFC_ON,0); /* default 0 */ -	// lgw_reg_w(LGW_FSK_BROADCAST,0); /* default 0 */ +	/* FSK demodulator setup */ +	lgw_reg_w(LGW_FSK_RSSI_LENGTH,4); /* default 0 */ +	lgw_reg_w(LGW_FSK_PKT_MODE,1); /* variable length, default 0 */ +	lgw_reg_w(LGW_FSK_PSIZE,3); /* ???, default 0 */  	lgw_reg_w(LGW_FSK_CRC_EN,1); /* default 0 */ -	// lgw_reg_w(LGW_FSK_CRC_IBM,0); /* default 0 */  	// lgw_reg_w(LGW_FSK_DCFREE_ENC,0); /* default 0 */ +	// lgw_reg_w(LGW_FSK_CRC_IBM,0); /* default 0 */  	lgw_reg_w(LGW_FSK_ERROR_OSR_TOL,10); /* default 0 */ -	lgw_reg_w(LGW_FSK_MODEM_INVERT_IQ,1); /* default 0 */ +	lgw_reg_w(LGW_FSK_REF_PATTERN_LSB,0x01010101); /* default 0 */ +	lgw_reg_w(LGW_FSK_REF_PATTERN_MSB,0x01010101); /* default 0 */ +	lgw_reg_w(LGW_FSK_PKT_LENGTH,255); /* max packet length in variable length mode */ +	  	// lgw_reg_w(LGW_FSK_NODE_ADRS,0); /* default 0 */ -	lgw_reg_w(LGW_FSK_PATTERN_TIMEOUT_CFG,64); /* default 0 */ -	lgw_reg_w(LGW_FSK_PKT_LENGTH,64); /* default 0 */ -	lgw_reg_w(LGW_FSK_PKT_MODE,1); /* default 0 */ -	lgw_reg_w(LGW_FSK_PSIZE,3); /* default 0 */ -	lgw_reg_w(LGW_FSK_REF_PATTERN_LSB,0x55); /* default 0 */ -	lgw_reg_w(LGW_FSK_REF_PATTERN_MSB,0x55); /* default 0 */ -	lgw_reg_w(LGW_FSK_RSSI_LENGTH,4); /* default 0 */ -	lgw_reg_w(LGW_FSK_CH_BW_EXPO,2); /* 125kHz (default 0, 500kHz) */ +	// lgw_reg_w(LGW_FSK_BROADCAST,0); /* default 0 */ +	// lgw_reg_w(LGW_FSK_AUTO_AFC_ON,0); /* default 0 */ +	lgw_reg_w(LGW_FSK_PATTERN_TIMEOUT_CFG,128); /* sync timeout (allow 8 bytes preamble + 8 bytes sync word, default 0 */ -	/* FSK mod */ -	lgw_reg_w(LGW_FSK_TX_PSIZE,3); /* default 0 */ -	lgw_reg_w(LGW_FSK_TX_GAUSSIAN_SELECT_BT,1); /* default 0 */ +	/* TX general parameters */ +	lgw_reg_w(LGW_TX_START_DELAY,1000); /* default 0 */ -	/* TX */ +	/* TX Lora */  	// lgw_reg_w(LGW_TX_MODE,0); /* default 0 */ -	lgw_reg_w(LGW_TX_START_DELAY,1000); /* default 0 */  	lgw_reg_w(LGW_TX_SWAP_IQ,1); /* "normal" polarity; default 0 */ +	/* TX FSK */ +	// lgw_reg_w(LGW_FSK_TX_GAUSSIAN_EN,1); /* default 1 */ +	lgw_reg_w(LGW_FSK_TX_GAUSSIAN_SELECT_BT,1); /* Gaussian filter always on TX, default 0 */ +	lgw_reg_w(LGW_FSK_TX_PSIZE,3); /* default 0 */ +	// lgw_reg_w(LGW_FSK_TX_PATTERN_EN, 1); /* default 1 */ +	// lgw_reg_w(LGW_FSK_TX_PREAMBLE_SEQ,0); /* default 0 */ +	  	return;  } @@ -494,10 +513,10 @@ int lgw_rxif_setconf(uint8_t if_chain, struct lgw_conf_rxif_s conf) {  	switch (ifmod_config[if_chain]) {  		case IF_LORA_STD:  			/* fill default parameters if needed */ -			if (conf.bandwidth == 0) { +			if (conf.bandwidth == BW_UNDEFINED) {  				conf.bandwidth = BW_250KHZ;  			} -			if (conf.datarate == 0) { +			if (conf.datarate == DR_UNDEFINED) {  				conf.datarate = DR_LORA_SF9;  			}  			/* check BW & DR */ @@ -511,9 +530,10 @@ int lgw_rxif_setconf(uint8_t if_chain, struct lgw_conf_rxif_s conf) {  			}  			/* set internal configuration  */  			if_enable[if_chain] = conf.enable; +			if_rf_chain[if_chain] = conf.rf_chain;  			if_freq[if_chain] = conf.freq_hz;  			lora_rx_bw = conf.bandwidth; -			lora_rx_sf = conf.datarate; +			lora_rx_sf = (uint8_t)(DR_LORA_MULTI & conf.datarate); /* filter SF out of the 7-12 range */  			if (SET_PPM_ON(conf.bandwidth, conf.datarate)) {  				lora_rx_ppm_offset = 1;  			} else { @@ -525,11 +545,14 @@ int lgw_rxif_setconf(uint8_t if_chain, struct lgw_conf_rxif_s conf) {  		case IF_LORA_MULTI:  			/* fill default parameters if needed */ -			if (conf.datarate == 0) { +			if (conf.bandwidth == BW_UNDEFINED) { +				conf.bandwidth = BW_125KHZ; +			} +			if (conf.datarate == DR_UNDEFINED) {  				conf.datarate = DR_LORA_MULTI;  			}  			/* check BW & DR */ -			if ((conf.bandwidth != BW_125KHZ) && (conf.bandwidth != 0)) { /* 0 is for default */ +			if (conf.bandwidth != BW_125KHZ) {  				DEBUG_MSG("ERROR: BANDWIDTH NOT SUPPORTED BY LORA_MULTI IF CHAIN\n");  				return LGW_HAL_ERROR;  			} @@ -539,19 +562,38 @@ int lgw_rxif_setconf(uint8_t if_chain, struct lgw_conf_rxif_s conf) {  			}  			/* set internal configuration  */  			if_enable[if_chain] = conf.enable; -			switch (conf.rf_chain) { -				case 0: if_rf_switch &= ~((uint8_t)1 << if_chain); break; /* force a 0 at the if_chain-th position */ -				case 1: if_rf_switch |= ((uint8_t)1 << if_chain); break; /* force a 1 at the if_chain-th position */ -				default: DEBUG_MSG("ERROR: IMPROPRER IF_CHAIN/RF_CHAIN ASSOCIATION\n"); -			} +			if_rf_chain[if_chain] = conf.rf_chain;  			if_freq[if_chain] = conf.freq_hz; -			lora_multi_sfmask[if_chain] = (uint8_t)(0x007F & conf.datarate); +			lora_multi_sfmask[if_chain] = (uint8_t)(DR_LORA_MULTI & conf.datarate); /* filter SF out of the 7-12 range */ +			  			DEBUG_PRINTF("Note: Lora 'multi' if_chain %d configured; en:%d freq:%d SF_mask:0x%02x\n", if_chain, if_enable[if_chain], if_freq[if_chain], lora_multi_sfmask[if_chain]); -			DEBUG_PRINTF("Note: rf/if switch state 0x%02x\n", if_rf_switch);  			break; -		// case IF_FSK_STD: -			// TODO: fill the correct metadata for a FSK packet to be sent +		case IF_FSK_STD: +			/* fill default parameters if needed */ +			if (conf.bandwidth == BW_UNDEFINED) { +				conf.bandwidth = BW_250KHZ; +			} +			if (conf.datarate == DR_UNDEFINED) { +				conf.datarate = 64000; /* default datarate */ +			} +			/* check BW & DR */ +			if(!IS_FSK_BW(conf.bandwidth)) { +				DEBUG_MSG("ERROR: BANDWIDTH NOT SUPPORTED BY FSK IF CHAIN\n"); +				return LGW_HAL_ERROR; +			} +			if(!IS_FSK_DR(conf.datarate)) { +				DEBUG_MSG("ERROR: DATARATE NOT SUPPORTED BY FSK IF CHAIN\n"); +				return LGW_HAL_ERROR; +			} +			/* set internal configuration  */ +			if_enable[if_chain] = conf.enable; +			if_rf_chain[if_chain] = conf.rf_chain; +			if_freq[if_chain] = conf.freq_hz; +			fsk_rx_bw = conf.bandwidth; +			fsk_rx_dr = conf.datarate; +			DEBUG_PRINTF("Note: FSK if_chain %d configured; en:%d freq:%d bw:%d dr:%d (%d real dr)\n", if_chain, if_enable[if_chain], if_freq[if_chain], fsk_rx_bw, fsk_rx_dr, LGW_XTAL_FREQU/(LGW_XTAL_FREQU/fsk_rx_dr)); +			break;  		default:  			DEBUG_PRINTF("ERROR: IF CHAIN %d TYPE NOT SUPPORTED\n", if_chain); @@ -564,6 +606,7 @@ int lgw_rxif_setconf(uint8_t if_chain, struct lgw_conf_rxif_s conf) {  /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */  int lgw_start(void) { +	int i, j;  	int reg_stat;  	int32_t read_value; @@ -582,8 +625,6 @@ int lgw_start(void) {  	/* Ungate clocks (gated by default) */  	lgw_reg_w(LGW_GLOBAL_EN, 1); -	// lgw_reg_w(LGW_CLK32M_EN, 1); -	// lgw_reg_w(LGW_CLKHS_EN, 1);  	/* switch on and reset the radios (also starts the 32 MHz XTAL) */  	lgw_reg_w(LGW_RADIO_A_EN,1); /* radio A *must* be started to get 32 MHz clk */ @@ -619,8 +660,10 @@ int lgw_start(void) {  	/* load adjusted parameters */  	lgw_constant_adjust(); -	/* configure Lora 'multi' (aka. Lora 'sensor' channels */ -	lgw_reg_w(LGW_RADIO_SELECT, if_rf_switch); /* IF mapping to radio A/B (per bit, 0=A, 1=B) */ +	/* configure Lora 'multi' demodulators aka. Lora 'sensor' channels (IF0-3) */ +	j = 0; +	for(i=0;i<=7;++i) j += (if_rf_chain[i] == 1 ? 1 << i : 0); /* transform bool array into binary word */ +	lgw_reg_w(LGW_RADIO_SELECT, j); /* IF mapping to radio A/B (per bit, 0=A, 1=B) */  	lgw_reg_w(LGW_IF_FREQ_0, IF_HZ_TO_REG(if_freq[0])); /* default -384 */  	lgw_reg_w(LGW_IF_FREQ_1, IF_HZ_TO_REG(if_freq[1])); /* default -128 */ @@ -636,9 +679,10 @@ int lgw_start(void) {  	lgw_reg_w(LGW_CONCENTRATOR_MODEM_ENABLE,1); /* default 0 */ -	/* configure Lora 'stand-alone' modem */ +	/* configure Lora 'stand-alone' modem (IF8) */  	lgw_reg_w(LGW_IF_FREQ_8, IF_HZ_TO_REG(if_freq[8])); /* MBWSSF modem (default 0) */  	if (if_enable[8] == true) { +		lgw_reg_w(LGW_MBWSSF_RADIO_SELECT, if_rf_chain[8]);  		switch(lora_rx_bw) {  			case BW_125KHZ: lgw_reg_w(LGW_MBWSSF_MODEM_BW,0); break;  			case BW_250KHZ: lgw_reg_w(LGW_MBWSSF_MODEM_BW,1); break; @@ -660,9 +704,17 @@ int lgw_start(void) {  		lgw_reg_w(LGW_MBWSSF_MODEM_ENABLE, 0);  	} -	/* configure FSK modem */ -	//lgw_reg_w(LGW_IF_FREQ_9, IF_HZ_TO_REG(if_freq[9])); /* FSK modem	(default 0) */ - +	/* configure FSK modem (IF9) */ +	lgw_reg_w(LGW_IF_FREQ_9, IF_HZ_TO_REG(if_freq[9])); /* FSK modem, default 0 */ +	if (if_enable[9] == true) { +		lgw_reg_w(LGW_FSK_RADIO_SELECT, if_rf_chain[9]); +		lgw_reg_w(LGW_FSK_BR_RATIO,LGW_XTAL_FREQU/fsk_rx_dr); /* setting the dividing ratio for datarate */ +		lgw_reg_w(LGW_FSK_CH_BW_EXPO,fsk_rx_bw); +		lgw_reg_w(LGW_FSK_MODEM_ENABLE,1); /* default 0 */ +	} else { +		lgw_reg_w(LGW_FSK_MODEM_ENABLE,0); +	} +	  	/* Load firmware */  	load_firmware(MCU_ARB, arb_firmware, MCU_ARB_FW_BYTE);  	load_firmware(MCU_AGC, agc_firmware, MCU_AGC_FW_BYTE); @@ -671,6 +723,10 @@ int lgw_start(void) {  	lgw_reg_w(LGW_MCU_RST_0, 0);  	lgw_reg_w(LGW_MCU_RST_1, 0); +	/* enable LEDs */ +	lgw_reg_w(LGW_GPIO_MODE,31); +	// lgw_reg_w(LGW_GPIO_SELECT_OUTPUT,0); /* default 0 */ +	  	lgw_is_started = true;  	return LGW_HAL_SUCCESS;  } @@ -730,23 +786,11 @@ int lgw_receive(uint8_t max_pkt, struct lgw_pkt_rx_s *pkt_data) {  		s = p->size;  		stat_fifo = buff[3]; /* will be used later, need to save it before overwriting buff */ -		/* STILL required */ -		data_addr = (uint16_t)buff[1] + ((uint16_t)buff[2] << 8); -		lgw_reg_w(LGW_RX_DATA_BUF_ADDR, data_addr); -		 -		/* dynamically allocate memory to store payload */ -		p->payload = (uint8_t *)malloc(s); -		if (p->payload == NULL) { -			/* not enough memory to allocate for payload, abort with error */ -			DEBUG_MSG("ERROR: IMPOSSIBLE TO ALLOCATE MEMORY TO FETCH PAYLOAD\n"); -			return LGW_HAL_ERROR; -		} -		  		/* get payload + metadata */  		lgw_reg_rb(LGW_RX_DATA_BUF_DATA, buff, s+RX_METADATA_NB); -		/* copy payload */ -		memcpy(p->payload, buff, s); +		/* copy payload to result struct */ +		memcpy((void *)p->payload, (void *)buff, s);  		/* process metadata */  		p->if_chain = buff[s+0]; @@ -789,16 +833,20 @@ int lgw_receive(uint8_t max_pkt, struct lgw_pkt_rx_s *pkt_data) {  				default: p->coderate = CR_UNDEFINED;  			}  		} else if (ifmod == IF_FSK_STD) { -			// TODO: process received FSK packets  			DEBUG_MSG("Note: FSK packet\n"); -			p->status = STAT_UNDEFINED; +			switch(stat_fifo & 0x07) { +				case 5: p->status = STAT_CRC_OK; break; +				case 7: p->status = STAT_CRC_BAD; break; +				case 1: p->status = STAT_NO_CRC; break; +				default: p->status = STAT_UNDEFINED; +			}  			p->modulation = MOD_FSK; -			p->rssi = NAN; +			p->rssi = (RSSI_OFFSET_FSK + (float)buff[s+5])/RSSI_SLOPE_FSK;  			p->snr = NAN;  			p->snr_min = NAN;  			p->snr_max = NAN; -			p->bandwidth = BW_UNDEFINED; -			p->datarate = DR_UNDEFINED; +			p->bandwidth = fsk_rx_bw; +			p->datarate = fsk_rx_dr;  			p->coderate = CR_UNDEFINED;  		} else {  			DEBUG_MSG("ERROR: UNEXPECTED PACKET ORIGIN\n"); @@ -826,9 +874,12 @@ int lgw_receive(uint8_t max_pkt, struct lgw_pkt_rx_s *pkt_data) {  /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */  int lgw_send(struct lgw_pkt_tx_s pkt_data) { -	uint8_t buff[255+TX_METADATA_NB]; /* buffer to prepare the packet to send + metadata before SPI write burst */ +	uint8_t buff[256+TX_METADATA_NB]; /* buffer to prepare the packet to send + metadata before SPI write burst */  	uint32_t part_int; /* integer part for PLL register value calculation */  	uint32_t part_frac; /* fractional part for PLL register value calculation */ +	uint16_t fsk_dr_div; /* divider to configure for target datarate */ +	int transfer_size = 0; /* data to transfer from host to TX databuffer */ +	int payload_offset = 0; /* start of the payload content in the databuffer */  	int i;  	/* check if the gateway is running */ @@ -838,7 +889,6 @@ int lgw_send(struct lgw_pkt_tx_s pkt_data) {  	}  	/* check input variables */ -	CHECK_NULL(pkt_data.payload);  	if (pkt_data.rf_chain >= LGW_RF_CHAIN_NB) {  		DEBUG_MSG("ERROR: INVALID RF_CHAIN TO SEND PACKETS\n");  		return LGW_HAL_ERROR; @@ -875,9 +925,19 @@ int lgw_send(struct lgw_pkt_tx_s pkt_data) {  			DEBUG_MSG("ERROR: PAYLOAD LENGTH TOO BIG FOR LORA TX\n");  			return LGW_HAL_ERROR;  		} -	}else if ((pkt_data.modulation == MOD_FSK) || (pkt_data.modulation == MOD_GFSK)) { -		DEBUG_MSG("ERROR: (G)FSK TX MODULATION NOT SUPPORTED YET\n"); -		return LGW_HAL_ERROR; +	} else if (pkt_data.modulation == MOD_FSK) { +		if((pkt_data.f_dev < 1) || (pkt_data.f_dev > 200)) { +			DEBUG_MSG("ERROR: TX FREQUENCY DEVIATION OUT OF ACCEPTABLE RANGE\n"); +			return LGW_HAL_ERROR; +		} +		if(!IS_FSK_DR(pkt_data.datarate)) { +			DEBUG_MSG("ERROR: DATARATE NOT SUPPORTED BY FSK IF CHAIN\n"); +			return LGW_HAL_ERROR; +		} +		if (pkt_data.size > 255) { +			DEBUG_MSG("ERROR: PAYLOAD LENGTH TOO BIG FOR FSK TX\n"); +			return LGW_HAL_ERROR; +		}  	} else {  		DEBUG_MSG("ERROR: INVALID TX MODULATION\n");  		return LGW_HAL_ERROR; @@ -888,9 +948,13 @@ int lgw_send(struct lgw_pkt_tx_s pkt_data) {  	lgw_reg_w(LGW_TX_TRIG_DELAYED, 0);  	lgw_reg_w(LGW_TX_TRIG_GPS, 0); +	/* fixed metadata, useful payload and misc metadata compositing */ +	transfer_size = TX_METADATA_NB + pkt_data.size; /*  */ +	payload_offset = TX_METADATA_NB; /* start the payload just after the metadata */ +	  	/* metadata 0 to 2, TX PLL frequency */ -	part_int = pkt_data.freq_hz / LGW_SX1257_DENOMINATOR; /* integer part, gives the MSB and the middle byte */ -	part_frac = ((pkt_data.freq_hz % LGW_SX1257_DENOMINATOR) << 8) / LGW_SX1257_DENOMINATOR; /* fractional part, gives LSB */ +	part_int = pkt_data.freq_hz / SX1257_DENOM; /* integer part, gives the MSB and the middle byte */ +	part_frac = ((pkt_data.freq_hz % SX1257_DENOM) << 8) / SX1257_DENOM; /* fractional part, gives LSB */  	buff[0] = 0xFF & (part_int >> 8); /* Most Significant Byte */  	buff[1] = 0xFF & part_int; /* middle byte */  	buff[2] = 0xFF & part_frac; /* Least Significant Byte */ @@ -962,18 +1026,54 @@ int lgw_send(struct lgw_pkt_tx_s pkt_data) {  		buff[14] = 0;  		buff[15] = 0; +	} else if (pkt_data.modulation == MOD_FSK) { +		/* metadata 7, modulation type, radio chain selection and TX power */ +		buff[7] = (0x20 & (pkt_data.rf_chain << 5)) | 0x10 | (0x0F & pkt_data.rf_power); /* bit 4 is 1 -> FSK modulation */ +		/* fine control over TX power not supported yet, any value other than 8 is 14 dBm */ +		 +		buff[8] = 0; /* metadata 8, not used */ +		 +		/* metadata 9, frequency deviation */ +		buff[9] = pkt_data.f_dev; +		 +		/* metadata 10, payload size */ +		buff[10] = pkt_data.size + 1; /* add a byte to encode payload length in the packet */ +		/* TODO: handle fixed packet length */ +		/* TODO: how to handle 255 bytes packets ?!? */ +		 +		/* metadata 11, packet mode, CRC, encoding */ +		buff[11] = (pkt_data.no_crc?0:0x02); /* always in fixed length packet mode, no DC-free encoding, CCITT CRC if CRC is not disabled  */ +		 +		/* metadata 12 & 13, FSK preamble size */ +		if (pkt_data.preamble < MIN_FSK_PREAMBLE) { /* enforce minimum preamble size */ +			pkt_data.preamble = MIN_FSK_PREAMBLE; +			DEBUG_MSG("Note: preamble length adjusted to respect minimum FSK preamble size\n"); +		} +		buff[12] = 0xFF & (pkt_data.preamble >> 8); +		buff[13] = 0xFF & pkt_data.preamble; +		 +		/* metadata 14 & 15, FSK baudrate */ +		fsk_dr_div = LGW_XTAL_FREQU / pkt_data.datarate; +		buff[14] = 0xFF & (fsk_dr_div >> 8); +		buff[15] = 0xFF & fsk_dr_div; +		 +		/* insert payload size in the packet for variable mode */ +		buff[16] = pkt_data.size; +		++transfer_size; /* one more byte to transfer to the TX modem */ +		++payload_offset; /* start the payload with one more byte of offset */ +		  	} else { -		DEBUG_MSG("ERROR: ONLY LORA TX SUPPORTED FOR NOW\n"); +		DEBUG_MSG("ERROR: INVALID TX MODULATION..\n");  		return LGW_HAL_ERROR;  	} -	/* copy payload */ -	memcpy((void *)(buff + TX_METADATA_NB), pkt_data.payload, pkt_data.size); +	/* copy payload from user struct to buffer containing metadata */ +	memcpy((void *)(buff + payload_offset), (void *)(pkt_data.payload), pkt_data.size);  	/* put metadata + payload in the TX data buffer */  	lgw_reg_w(LGW_TX_DATA_BUF_ADDR, 0); -	lgw_reg_wb(LGW_TX_DATA_BUF_DATA, buff, (pkt_data.size + TX_METADATA_NB)); -	DEBUG_ARRAY(i, pkt_data.size+TX_METADATA_NB, buff); +	lgw_reg_wb(LGW_TX_DATA_BUF_DATA, buff, transfer_size); +	DEBUG_ARRAY(i, transfer_size, buff);  	/* send data */  	switch(pkt_data.tx_mode) { @@ -1029,5 +1129,11 @@ int lgw_status(uint8_t select, uint8_t *code) {  } +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +const char* lgw_version_info() { +	return lgw_version_string; +} +  /* --- EOF ------------------------------------------------------------------ */ diff --git a/loragw_hal/src/loragw_reg.c b/libloragw/src/loragw_reg.c index a9122d2..fea9784 100644 --- a/loragw_hal/src/loragw_reg.c +++ b/libloragw/src/loragw_reg.c @@ -432,13 +432,25 @@ int lgw_connect(void) {  	} else {  		lgw_regpage = 0;  	} +	/* checking the chip ID */ +	spi_stat = lgw_spi_r(lgw_spi_target, loregs[LGW_CHIP_ID].addr, &u); +	if (spi_stat != LGW_SPI_SUCCESS) { +		DEBUG_MSG("ERROR READING CHIP_ID REGISTER\n"); +		return LGW_REG_ERROR; +	} else if (u == 0) { +		DEBUG_MSG("ERROR: CHIP_ID=0, GATEWAY SEEMS DISCONNECTED\n"); +		return LGW_REG_ERROR; +	} else if (u != loregs[LGW_CHIP_ID].dflt) { +		DEBUG_MSG("ERROR: MISMATCH BETWEEN EXPECTED REG CHIP_ID AND READ REG CHIP_ID\n"); +		return LGW_REG_ERROR; +	}  	/* checking the version register */  	spi_stat = lgw_spi_r(lgw_spi_target, loregs[LGW_VERSION].addr, &u);  	if (spi_stat != LGW_SPI_SUCCESS) {  		DEBUG_MSG("ERROR READING VERSION REGISTER\n");  		return LGW_REG_ERROR;  	} else if (u == 0) { -		DEBUG_MSG("ERROR: GATEWAY SEEMS DISCONNECTED\n"); +		DEBUG_MSG("ERROR: VERSION=0, GATEWAY SEEMS DISCONNECTED\n");  		return LGW_REG_ERROR;  	} else if (u != loregs[LGW_VERSION].dflt) {  		DEBUG_MSG("ERROR: MISMATCH BETWEEN EXPECTED REG VERSION AND READ REG VERSION\n"); diff --git a/loragw_hal/src/loragw_spi.ftdi.c b/libloragw/src/loragw_spi.ftdi.c index 7b71901..7b71901 100644 --- a/loragw_hal/src/loragw_spi.ftdi.c +++ b/libloragw/src/loragw_spi.ftdi.c diff --git a/loragw_hal/src/loragw_spi.native.c b/libloragw/src/loragw_spi.native.c index f5f0701..f5f0701 100644 --- a/loragw_hal/src/loragw_spi.native.c +++ b/libloragw/src/loragw_spi.native.c diff --git a/loragw_hal/test/test_loragw_hal.c b/libloragw/tst/test_loragw_hal.c index f23f55c..a210bee 100644 --- a/loragw_hal/test/test_loragw_hal.c +++ b/libloragw/tst/test_loragw_hal.c @@ -22,7 +22,6 @@ Description:  #endif  #include <stdint.h>		/* C99 types */ -#include <stdlib.h>		/* malloc & free */  #include <stdbool.h>	/* bool type */  #include <stdio.h>		/* printf */  #include <string.h>		/* memset */ @@ -70,7 +69,6 @@ int main(int argc, char **argv)  	struct lgw_pkt_rx_s rxpkt[4]; /* array containing up to 4 inbound packets metadata */  	struct lgw_pkt_tx_s txpkt; /* configuration and metadata for an outbound packet */ -	uint8_t txbuf[256]; /* buffer for the TX payload */  	struct lgw_pkt_rx_s *p; /* pointer on a RX packet */  	int i, j; @@ -98,11 +96,11 @@ int main(int argc, char **argv)  	memset(&rfconf, 0, sizeof(rfconf));  	rfconf.enable = true; -	rfconf.freq_hz = 866187500; +	rfconf.freq_hz = 866000000;  	lgw_rxrf_setconf(0, rfconf); /* radio A */  	rfconf.enable = true; -	rfconf.freq_hz = 866437500; +	rfconf.freq_hz = 868000000;  	lgw_rxrf_setconf(1, rfconf); /* radio B */  	/* set configuration for Lora multi-SF channels (bandwidth cannot be set) */ @@ -110,55 +108,75 @@ int main(int argc, char **argv)  	ifconf.enable = true;  	ifconf.rf_chain = 0; -	ifconf.freq_hz = -187500; +	ifconf.freq_hz = -300000;  	ifconf.bandwidth = BW_125KHZ;  	ifconf.datarate = DR_LORA_MULTI; -	lgw_rxif_setconf(0, ifconf); /* chain 0: 1st radio, bleeper channel 1, all SF */ +	lgw_rxif_setconf(0, ifconf); /* chain 0: Lora 125kHz, all SF, on 865.7 MHz */  	ifconf.enable = true;  	ifconf.rf_chain = 0; -	ifconf.freq_hz = -62500; +	ifconf.freq_hz = 300000;  	ifconf.bandwidth = BW_125KHZ; -	ifconf.datarate = DR_LORA_SF8 | DR_LORA_SF10; -	lgw_rxif_setconf(1, ifconf); /* chain 1: 1st radio, bleeper channel 2, SF8 & SF10 only */ +	ifconf.datarate = DR_LORA_MULTI; +	lgw_rxif_setconf(1, ifconf); /* chain 1: Lora 125kHz, all SF, on 866.3 MHz */ -	ifconf.enable = false; -	ifconf.rf_chain = 0; -	ifconf.freq_hz = 0; -	ifconf.bandwidth = 0; -	ifconf.datarate = 0; -	lgw_rxif_setconf(2, ifconf); /* chain 2: 1st radio, disabled */ +	ifconf.enable = true; +	ifconf.rf_chain = 1; +	ifconf.freq_hz = -300000; +	ifconf.bandwidth = BW_125KHZ; +	ifconf.datarate = DR_LORA_MULTI; +	lgw_rxif_setconf(2, ifconf); /* chain 2: Lora 125kHz, all SF, on 867.7 MHz */  	ifconf.enable = true;  	ifconf.rf_chain = 1; -	ifconf.freq_hz = -187500; +	ifconf.freq_hz = 300000;  	ifconf.bandwidth = BW_125KHZ;  	ifconf.datarate = DR_LORA_MULTI; -	lgw_rxif_setconf(3, ifconf); /* chain 3: 2nd radio, bleeper channel 3, all SF */ +	lgw_rxif_setconf(3, ifconf); /* chain 3: Lora 125kHz, all SF, on 868.3 MHz */  	/* set configuration for Lora 'stand alone' channel */  	ifconf.enable = true;  	ifconf.rf_chain = 0; -	ifconf.freq_hz = 187500; -	ifconf.bandwidth = BW_125KHZ; +	ifconf.freq_hz = 0; +	ifconf.bandwidth = BW_250KHZ;  	ifconf.datarate = DR_LORA_SF10; -	lgw_rxif_setconf(8, ifconf); /* chain 8: bleeper channel 4, SF10 only */ +	lgw_rxif_setconf(8, ifconf); /* chain 8: Lora 250kHz, SF10, on 866.0 MHz */ +	/* set configuration for FSK channel */ +	ifconf.enable = true; +	ifconf.rf_chain = 1; +	ifconf.freq_hz = 0; +	ifconf.bandwidth = BW_250KHZ; +	ifconf.datarate = 64000; +	lgw_rxif_setconf(9, ifconf); /* chain 9: FSK 64kbps, fdev 32kHz, variable payload, on 868.0 MHz */ -	/* load the TX payload */ -	strcpy((char *)txbuf, "TX.TEST.LORA.GW.????" ); -		  	/* set configuration for TX packet */ +	  	memset(&txs, 0, sizeof(txs)); -	txs.freq_hz = 866250000; +	txs.freq_hz = 867000000;  	txs.tx_mode = IMMEDIATE;  	txs.modulation = MOD_LORA;  	txs.bandwidth = BW_250KHZ;  	txs.datarate = DR_LORA_SF10;  	txs.coderate = CR_LORA_4_5; -	txs.payload = txbuf; +	strcpy((char *)txs.payload, "TX.TEST.LORA.GW.????" ); +	txs.size = 20; +	txs.preamble = 6; +	txs.rf_chain = 0; +/*	 +	memset(&txs, 0, sizeof(txs)); +	txs.freq_hz = 867000000; +	txs.tx_mode = IMMEDIATE; +	txs.modulation = MOD_FSK; +	txs.f_dev = 50; +	txs.datarate = 64000; +	strcpy((char *)txs.payload, "TX.TEST.LORA.GW.????" );  	txs.size = 20; -	txs.rf_chain = 1; +	txs.preamble = 4; +	txs.rf_chain = 0; +*/	 +	 +//	printf("***\n%s\n***\n", lgw_version_info());  	/* connect, configure and start the Lora gateway */  	lgw_start(); @@ -172,11 +190,10 @@ int main(int argc, char **argv)  		if (nb_pkt == 0) {  			wait_ms(300);  		} else { -			printf("\nLora gateway, %d packets received:\n\n", nb_pkt);  			/* display received packets */  			for(i=0; i < nb_pkt; ++i) {  				p = &rxpkt[i]; -				printf("---\nPkt #%d >>", i+1); +				printf("---\nRcv pkt #%d >>", i+1);  				if (p->status == STAT_CRC_OK) {  					printf(" if_chain:%2d", p->if_chain);  					printf(" tstamp:%010u", p->count_us); @@ -184,7 +201,6 @@ int main(int argc, char **argv)  					switch (p-> modulation) {  						case MOD_LORA: printf(" Lora"); break;  						case MOD_FSK: printf(" FSK"); break; -						case MOD_GFSK: printf(" GFSK"); break;  						default: printf(" modulation?");  					}  					switch (p->datarate) { @@ -205,6 +221,7 @@ int main(int argc, char **argv)  					}  					printf("\n");  					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); +					  					for (j = 0; j < p->size; ++j) {  						printf(" %02X", p->payload[j]);  					} @@ -226,23 +243,18 @@ int main(int argc, char **argv)  					printf(" invalid status ?!?\n\n");  				}  			} -			 -			/* free the memory used for RX payload(s) */ -			for(i=0; i < nb_pkt; ++i) { -				free(rxpkt[i].payload); -			}  		}  		/* send a packet every X loop */  		if (loop_cnt%16 == 0) {  			/* 32b counter in the payload, big endian */ -			txbuf[16] = 0xff & (tx_cnt >> 24); -			txbuf[17] = 0xff & (tx_cnt >> 16); -			txbuf[18] = 0xff & (tx_cnt >> 8); -			txbuf[19] = 0xff & tx_cnt; +			txs.payload[16] = 0xff & (tx_cnt >> 24); +			txs.payload[17] = 0xff & (tx_cnt >> 16); +			txs.payload[18] = 0xff & (tx_cnt >> 8); +			txs.payload[19] = 0xff & tx_cnt;  			i = lgw_send(txs); /* non-blocking scheduling of TX packet */  			j = 0; -			printf("Sending packet #%d, rf path %d, return %d\nstatus -> ", tx_cnt, txs.rf_chain, i); +			printf("+++\nSending packet #%d, rf path %d, return %d\nstatus -> ", tx_cnt, txs.rf_chain, i);  			do {  				++j;  				wait_ms(100); diff --git a/loragw_hal/test/test_loragw_reg.c b/libloragw/tst/test_loragw_reg.c index 2b80109..2b80109 100644 --- a/loragw_hal/test/test_loragw_reg.c +++ b/libloragw/tst/test_loragw_reg.c diff --git a/loragw_hal/test/test_loragw_spi.c b/libloragw/tst/test_loragw_spi.c index 0eae55d..0eae55d 100644 --- a/loragw_hal/test/test_loragw_spi.c +++ b/libloragw/tst/test_loragw_spi.c | 
