summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSylvain Miermont <smiermont@semtech.com>2013-09-19 15:46:06 +0200
committerSylvain Miermont <smiermont@semtech.com>2013-10-23 14:03:05 +0200
commitb922932d1c9869d82042b600db2382d8c15f63dc (patch)
treeb97b83a74f5b3faadb674867f6cc004b8426a8a9
parent68b8b7a70d9104888997174506fbbaa0abb12a4c (diff)
downloadlora_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.TXT30
-rw-r--r--libloragw/VERSION20
-rw-r--r--libloragw/doc/99-libftdi.rules (renamed from loragw_hal/99-libftdi.rules)0
-rw-r--r--libloragw/doc/CHANGELOG.TXT35
-rw-r--r--libloragw/doc/INSTALL_FTDI.TXT (renamed from loragw_hal/INSTALL_FTDI.TXT)0
-rw-r--r--libloragw/doc/LICENSE.TXT8
-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