diff options
author | Sylvain Miermont <smiermont@semtech.com> | 2013-09-19 15:46:06 +0200 |
---|---|---|
committer | Sylvain Miermont <smiermont@semtech.com> | 2013-10-23 14:03:05 +0200 |
commit | b922932d1c9869d82042b600db2382d8c15f63dc (patch) | |
tree | b97b83a74f5b3faadb674867f6cc004b8426a8a9 | |
parent | 68b8b7a70d9104888997174506fbbaa0abb12a4c (diff) | |
download | lora_gateway-b922932d1c9869d82042b600db2382d8c15f63dc.tar.gz lora_gateway-b922932d1c9869d82042b600db2382d8c15f63dc.tar.bz2 lora_gateway-b922932d1c9869d82042b600db2382d8c15f63dc.zip |
Beta 7 (beta6 skipped)v1.b7
- API: change memory allocation for payload, they are now part of the struct for TX/RX, no need to malloc/free
- 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
- 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
-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 |