From b922932d1c9869d82042b600db2382d8c15f63dc Mon Sep 17 00:00:00 2001 From: Sylvain Miermont Date: Thu, 19 Sep 2013 15:46:06 +0200 Subject: Beta 7 (beta6 skipped) - 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 --- libloragw/Makefile | 77 +++ libloragw/README.TXT | 30 + libloragw/VERSION | 20 + libloragw/doc/99-libftdi.rules | 8 + libloragw/doc/CHANGELOG.TXT | 35 ++ libloragw/doc/INSTALL_FTDI.TXT | 46 ++ libloragw/doc/LICENSE.TXT | 8 + libloragw/doc/MANUAL.TXT | 232 ++++++++ libloragw/inc/loragw_aux.h | 28 + libloragw/inc/loragw_hal.h | 283 +++++++++ libloragw/inc/loragw_reg.h | 432 ++++++++++++++ libloragw/inc/loragw_spi.h | 92 +++ libloragw/library.cfg | 26 + libloragw/obj/.gitkeep | 0 libloragw/src/agc_fw.var | 526 +++++++++++++++++ libloragw/src/arb_fw.var | 526 +++++++++++++++++ libloragw/src/loragw_aux.c | 51 ++ libloragw/src/loragw_hal.c | 1139 ++++++++++++++++++++++++++++++++++++ libloragw/src/loragw_reg.c | 768 ++++++++++++++++++++++++ libloragw/src/loragw_spi.ftdi.c | 285 +++++++++ libloragw/src/loragw_spi.native.c | 346 +++++++++++ libloragw/tst/test_loragw_hal.c | 278 +++++++++ libloragw/tst/test_loragw_reg.c | 131 +++++ libloragw/tst/test_loragw_spi.c | 81 +++ loragw_hal/99-libftdi.rules | 8 - loragw_hal/INSTALL_FTDI.TXT | 46 -- loragw_hal/Makefile | 82 --- loragw_hal/README.txt | 219 ------- loragw_hal/inc/loragw_aux.h | 28 - loragw_hal/inc/loragw_hal.h | 270 --------- loragw_hal/inc/loragw_reg.h | 432 -------------- loragw_hal/inc/loragw_spi.h | 92 --- loragw_hal/library.cfg | 26 - loragw_hal/obj/.gitkeep | 0 loragw_hal/src/agc_fw.var | 526 ----------------- loragw_hal/src/arb_fw.var | 526 ----------------- loragw_hal/src/loragw_aux.c | 51 -- loragw_hal/src/loragw_hal.c | 1033 -------------------------------- loragw_hal/src/loragw_reg.c | 756 ------------------------ loragw_hal/src/loragw_spi.ftdi.c | 285 --------- loragw_hal/src/loragw_spi.native.c | 346 ----------- loragw_hal/test/test_loragw_hal.c | 266 --------- loragw_hal/test/test_loragw_reg.c | 131 ----- loragw_hal/test/test_loragw_spi.c | 81 --- 44 files changed, 5448 insertions(+), 5204 deletions(-) create mode 100644 libloragw/Makefile create mode 100644 libloragw/README.TXT create mode 100644 libloragw/VERSION create mode 100644 libloragw/doc/99-libftdi.rules create mode 100644 libloragw/doc/CHANGELOG.TXT create mode 100644 libloragw/doc/INSTALL_FTDI.TXT create mode 100644 libloragw/doc/LICENSE.TXT create mode 100644 libloragw/doc/MANUAL.TXT create mode 100644 libloragw/inc/loragw_aux.h create mode 100644 libloragw/inc/loragw_hal.h create mode 100644 libloragw/inc/loragw_reg.h create mode 100644 libloragw/inc/loragw_spi.h create mode 100644 libloragw/library.cfg create mode 100644 libloragw/obj/.gitkeep create mode 100644 libloragw/src/agc_fw.var create mode 100644 libloragw/src/arb_fw.var create mode 100644 libloragw/src/loragw_aux.c create mode 100644 libloragw/src/loragw_hal.c create mode 100644 libloragw/src/loragw_reg.c create mode 100644 libloragw/src/loragw_spi.ftdi.c create mode 100644 libloragw/src/loragw_spi.native.c create mode 100644 libloragw/tst/test_loragw_hal.c create mode 100644 libloragw/tst/test_loragw_reg.c create mode 100644 libloragw/tst/test_loragw_spi.c delete mode 100644 loragw_hal/99-libftdi.rules delete mode 100644 loragw_hal/INSTALL_FTDI.TXT delete mode 100644 loragw_hal/Makefile delete mode 100644 loragw_hal/README.txt delete mode 100644 loragw_hal/inc/loragw_aux.h delete mode 100644 loragw_hal/inc/loragw_hal.h delete mode 100644 loragw_hal/inc/loragw_reg.h delete mode 100644 loragw_hal/inc/loragw_spi.h delete mode 100644 loragw_hal/library.cfg delete mode 100644 loragw_hal/obj/.gitkeep delete mode 100644 loragw_hal/src/agc_fw.var delete mode 100644 loragw_hal/src/arb_fw.var delete mode 100644 loragw_hal/src/loragw_aux.c delete mode 100644 loragw_hal/src/loragw_hal.c delete mode 100644 loragw_hal/src/loragw_reg.c delete mode 100644 loragw_hal/src/loragw_spi.ftdi.c delete mode 100644 loragw_hal/src/loragw_spi.native.c delete mode 100644 loragw_hal/test/test_loragw_hal.c delete mode 100644 loragw_hal/test/test_loragw_reg.c delete mode 100644 loragw_hal/test/test_loragw_spi.c diff --git a/libloragw/Makefile b/libloragw/Makefile new file mode 100644 index 0000000..38d2fae --- /dev/null +++ b/libloragw/Makefile @@ -0,0 +1,77 @@ +# putting the configuration in a separate file +include library.cfg + +# constant symbols +CC=gcc +CFLAGS=-O2 -Iinc -I. +C99FLAGS=-O2 -std=c99 -Iinc -I. + +# configuration-dependant symbols +ifeq ($(LGW_PHY),native) +LDFLAGS=-lrt +endif +ifeq ($(LGW_PHY),ftdi) +LDFLAGS=-lrt -lmpsse +endif + +# general build targets + +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 + +.conf_ok: library.cfg + @echo "*** Checking Lora gateway HAL library config ***" + @rm -f .conf_ok +ifeq ($(LGW_PHY),native) + @echo "Selected SPI interface type: Linux native driver" +else +ifeq ($(LGW_PHY),ftdi) + @echo "Selected SPI interface type: FTDI SPI-over-USB bridge" +else + $(error No SPI physical layer selected) +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 + +obj/loragw_aux.o: .conf_ok src/loragw_aux.c inc/loragw_aux.h + $(CC) -c $(CFLAGS) src/loragw_aux.c -o obj/loragw_aux.o $(FLAG_AUX) + +obj/loragw_spi.o: .conf_ok src/loragw_spi.native.c src/loragw_spi.ftdi.c inc/loragw_spi.h +ifeq ($(LGW_PHY),native) + $(CC) -c $(C99FLAGS) src/loragw_spi.native.c -o obj/loragw_spi.o $(FLAG_SPI) +endif +ifeq ($(LGW_PHY),ftdi) + $(CC) -c $(C99FLAGS) src/loragw_spi.ftdi.c -o obj/loragw_spi.o $(FLAG_SPI) +endif + +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 -D LGW_PHY="\"$(LGW_PHY)\"" $(FLAG_HAL) + +# test programs + +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: 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: 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/libloragw/doc/99-libftdi.rules b/libloragw/doc/99-libftdi.rules new file mode 100644 index 0000000..8487413 --- /dev/null +++ b/libloragw/doc/99-libftdi.rules @@ -0,0 +1,8 @@ +# FTDI Devices: FT232BM/L/Q, FT245BM/L/Q, FT232RL/Q, FT245RL/Q, VNC1L with VDPS Firmware +SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", MODE="0664", GROUP="plugdev" + +# FTDI Devices: FT2232C/D/L, FT2232HL/Q +SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6010", MODE="0664", GROUP="plugdev" + +# FTDI Devices: FT4232HL/Q +SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6011", MODE="0664", GROUP="plugdev" 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/libloragw/doc/INSTALL_FTDI.TXT b/libloragw/doc/INSTALL_FTDI.TXT new file mode 100644 index 0000000..d26ad4b --- /dev/null +++ b/libloragw/doc/INSTALL_FTDI.TXT @@ -0,0 +1,46 @@ +# / _____) _ | | +# ( (____ _____ ____ _| |_ _____ ____| |__ +# \____ \| ___ | (_ _) ___ |/ ___) _ \ +# _____) ) ____| | | || |_| ____( (___| | | | +# (______/|_____)_|_|_| \__)_____)\____)_| |_| +# ©2013 Semtech-Cycleo +# +# Description: +# Installation procedure for FTDI SPI-over-USB dependencies + +# [STEP 1] Install libftdi +sudo apt-get install libftdi-dev + +# this should install : +# - libftdi-dev 0.19-4 (armhf) +# - libftdil 0.19-4 (armhf) +# - libusb-dev 2:0.1.12-20 (armhf) + +# [STEP 2] Download and unpack the libMPSSE 1.3 +# File must match SHA1 Checksum: 1b994a23b118f83144261e3e786c43df74a81cd5 +wget http://libmpsse.googlecode.com/files/libmpsse-1.3.tar.gz +sha1sum libmpsse-1.3.tar.gz +tar -xzvf libmpsse-1.3.tar.gz + +# Go to the src directory and install the library +./configure --disable-python +make +sudo make install +# Static and dynamic libraries compiled code is put into /usr/local/lib +# Header file is put into /usr/local/include + +# On the Pcduino, you must regenerate the library cache (might some time). +sudo ldconfig + +# [STEP 3] to allow non-root applications to access the FTDI device on USB +# copy the provided 99-libftdi.rules file in /etc/udev/rules.d +# For the nano board, only the FT2232H line is required. +# Non-root users members of plugdev group will be able to access the device. + +# [STEP 4] Unpack the Lora Gateway HAL and go to its directory. +# Configure build options in library.cfg, then build the library and examples. +make all + +# [STEP 5] Connect a nanoconcentrator and run test_loragw_reg to test that +# you have access to Lora registers. +# Less than 50 registers of the ~300 registers should return a mismatch. 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/libloragw/doc/MANUAL.TXT b/libloragw/doc/MANUAL.TXT new file mode 100644 index 0000000..1659f03 --- /dev/null +++ b/libloragw/doc/MANUAL.TXT @@ -0,0 +1,232 @@ + / _____) _ | | + ( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | + (______/|_____)_|_|_| \__)_____)\____)_| |_| + ©2013 Semtech-Cycleo + +Lora Gateway HAL user manual +============================ + +1. Introduction +--------------- + +The Lora Gateway Hardware Abstraction Layer is a C library that allow you to +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 or FSK modulations. + + +2. Components of the library +---------------------------- + +The library is composed of 4 modules: + +* loragw_hal +* loragw_reg +* loragw_spi +* loragw_aux + +The library also contains 3 test program to demonstrate code use and check +functionality. + +### 2.1. loragw_hal ### + +This is the main module and contains the high level functions to configure and +use the Lora gateway: + +* lgw_rxrf_setconf, to set the configuration of the radio channels +* lgw_rxif_setconf, to set the configuration of the IF+modem channels +* lgw_start, to apply the set configuration to the hardware and start it +* lgw_stop, to stop the hardware +* lgw_receive, to fetch packets if any was received +* lgw_send, to send a single packet (non-blocking, see warning in usage section) +* lgw_status, to check when a packet has effectively been sent + +For an standard application, include only this module. +The use of this module is detailed on the usage section. + +### 2.2. loragw_reg ### + +This module is used to access to the Lora gateway registers by name instead of +by address: + +* lgw_connect, to initialise and check the connection with the hardware +* lgw_disconnect, to disconnect the hardware +* lgw_soft_reset, to reset the whole hardware by resetting the register array +* lgw_reg_check, to check all registers vs. their default value and output the +result to a file +* lgw_reg_r, read a named register +* lgw_reg_w, write a named register +* lgw_reg_rb, read a name register in burst +* lgw_reg_wb, write a named register in burst + +This module handles pagination, read-only registers protection, multi-byte +registers management, signed registers management, read-modify-write routines +for sub-byte registers and read/write burst fragmentation to respect SPI +maximum burst length constraints. + +It make the code much easier to read and to debug. +Moreover, if registers are relocated between different hardware revisions but +keep the same function, the code written using register names can be reused "as +is". + +If you need access to all the registers, include this module in your +application. + +**/!\ Warning** please be sure to have a good understanding of the Lora gateway +inner working before accessing the internal registers directly. + +### 2.3. loragw_spi ### + +This module contains the functions to access the Lora gateway register array +through the SPI interface: + +* lgw_spi_r to read one byte +* lgw_spi_w to write one byte +* lgw_spi_rb to read two bytes or more +* lgw_spi_wb to write two bytes or more + +Please *do not* include that module directly into your application. + +**/!\ Warning** Accessing the Lora gateway register array without the checks +and safety provided by the functions in loragw_reg is not recommended. + +### 2.4. loragw_aux ### + +This module contains a single host-dependant function wait_ms to pause for a +defined amount of milliseconds. + +The procedure to start and configure the Lora gateway hardware contained in the +loragw_hal module requires to wait for several milliseconds at certain steps, +typically to allow for supply voltages or clocks to stabilize after been +switched on. + +An accuracy of 1 ms or less is ideal. +If your system doesn't allow that level of accuracy, make sure that the actual +delay is *longer* that the time specified when the function is called (ie. +wait_ms(X) *MUST NOT* before X milliseconds under any circumstance). + +If the minimum delays are not guaranteed during the configuration and start +procedure, the hardware might not work at nominal performance. +Most likely, it will not work at all. + + +3. Software dependencies +------------------------ + +The library is written following ANSI C conventions but using C99 explicit +length data type for all data exchanges with hardware and for parameters. + +The loragw_aux module contains POSIX dependant functions for millisecond +accuracy pause. +For embedded platforms, the function could be rewritten using hardware times. + +All modules use the fprintf(stderr,...) function to display debug diagnostic +messages if the DEBUG_xxx is set to 1 in library.cfg + +Depending on config, SPI module needs LibMPSSE to access the FTDI SPI-over-USB +bridge. Please go to that URL to download that library: +http://code.google.com/p/libmpsse/ + +The code was tested with version 1.3 of LibMPSSE: +http://libmpsse.googlecode.com/files/libmpsse-1.3.tar.gz +SHA1 Checksum: 1b994a23b118f83144261e3e786c43df74a81cd5 + +That library has some dependencies itself, please read the installation +instructions. + + +4. Hardware dependencies +------------------------ + +### 4.1. Hardware revision ### + +The loragw_reg and loragw_hal are written for a specific version on the Semtech +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. +The functions must be rewritten depending on the SPI bridge you use: + +* SPI master matched to the Linux SPI device driver (provided) +* SPI over USB using FTDI components (provided) +* native SPI using a microcontroller peripheral (not provided) + +Edit library.cfg to chose which SPI physical interface you want to use. + +You can use the test program test_loragw_spi to check with a logic analyser +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 +* the configuration is only transferred to hardware when you call the *start* +function +* you cannot receive packets until one (or +) radio is enabled AND one (or +) +IF+modem part is enabled AND the gateway is started +* you cannot send packets until one (or +) radio is enabled AND the gateway is +started +* you must stop the gateway before changing the configuration + +A typical application flow for using the HAL is the following: + + + +loop { + + + +} + + +**/!\ 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. +While a packet is emitted, no packet can be received (limitation intrinsic to +most radio frequency systems). + +Your application *must* take into account the time it takes to send a packet or +check the status (using lgw_status) before attempting to send another packet. + +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 ### + +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/libloragw/inc/loragw_aux.h b/libloragw/inc/loragw_aux.h new file mode 100644 index 0000000..09f543f --- /dev/null +++ b/libloragw/inc/loragw_aux.h @@ -0,0 +1,28 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + ©2013 Semtech-Cycleo + +Description: + Lora gateway Hardware Abstraction Layer +*/ + + +#ifndef _LORAGW_AUX_H +#define _LORAGW_AUX_H + +/* -------------------------------------------------------------------------- */ +/* --- PUBLIC FUNCTIONS PROTOTYPES ------------------------------------------ */ + +/** +@brief Wait for a certain time (millisecond accuracy) +@param t number of milliseconds to wait. +*/ +void wait_ms(unsigned long t); + +#endif + +/* --- EOF ------------------------------------------------------------------ */ diff --git a/libloragw/inc/loragw_hal.h b/libloragw/inc/loragw_hal.h new file mode 100644 index 0000000..08aa945 --- /dev/null +++ b/libloragw/inc/loragw_hal.h @@ -0,0 +1,283 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + ©2013 Semtech-Cycleo + +Description: + Lora gateway Hardware Abstraction Layer +*/ + + +#ifndef _LORAGW_HAL_H +#define _LORAGW_HAL_H + +/* -------------------------------------------------------------------------- */ +/* --- DEPENDANCIES --------------------------------------------------------- */ + +#include /* C99 types */ +#include /* bool type */ + +/* -------------------------------------------------------------------------- */ +/* --- PUBLIC MACROS -------------------------------------------------------- */ + +#define IS_LORA_BW(bw) ((bw == BW_125KHZ) || (bw == BW_250KHZ) || (bw == BW_500KHZ)) +#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)) + +/* -------------------------------------------------------------------------- */ +/* --- PUBLIC CONSTANTS ----------------------------------------------------- */ + +/* return status code */ +#define LGW_HAL_SUCCESS 0 +#define LGW_HAL_ERROR -1 + +/* hardware characteristics */ +#define LGW_RF_CHAIN_NB 2 /* number of RF chains */ +#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 /* 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} /* 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 +#define IF_LORA_STD 0x10 /* if + standard single-SF Lora modem */ +#define IF_LORA_MULTI 0x11 /* if + Lora receiver with multi-SF capability */ +#define IF_FSK_STD 0x20 /* if + standard FSK modem */ + +/* configuration of available IF chains and modems on the hardware */ +/* to use, declare a local constant, and use 'if_chain' as index */ +#define LGW_IFMODEM_CONFIG {\ + IF_LORA_MULTI, \ + IF_LORA_MULTI, \ + IF_LORA_MULTI, \ + IF_LORA_MULTI, \ + IF_UNDEFINED, \ + IF_UNDEFINED, \ + IF_UNDEFINED, \ + IF_UNDEFINED, \ + IF_LORA_STD, \ + IF_FSK_STD } + +/* values available for the 'modulation' parameters */ +/* NOTE: arbitrary values */ +#define MOD_UNDEFINED 0 +#define MOD_LORA 0x10 +#define MOD_FSK 0x20 + +/* values available for the 'bandwidth' parameters (Lora & FSK) */ +/* NOTE: directly encode FSK RX bandwidth, do not change */ +#define BW_UNDEFINED 0 +#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 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 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 +#define STAT_CRC_OK 0x10 + +/* values available for the 'tx_mode' parameter */ +#define IMMEDIATE 0 +#define TIMESTAMPED 1 +#define ON_GPS 2 +//#define ON_EVENT 3 +//#define GPS_DELAYED 4 +//#define EVENT_DELAYED 5 + +/* values available for 'select' in the status function */ +#define TX_STATUS 1 +#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 */ +#define TX_SCHEDULED 3 /* TX modem is loaded, ready to send the packet after an event and/or delay */ +#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 */ +#define RX_SUSPENDED 3 /* RX is suspended while a TX is ongoing */ + +/* -------------------------------------------------------------------------- */ +/* --- PUBLIC TYPES --------------------------------------------------------- */ + +/** +@struct lgw_conf_rxrf_s +@brief Configuration structure for a RF chain +*/ +struct lgw_conf_rxrf_s { + bool enable; /*!> enable or disable that RF chain */ + uint32_t freq_hz; /*!> center frequency of the radio in Hz */ +}; + +/** +@struct lgw_conf_rxif_s +@brief Configuration structure for an IF chain +*/ +struct lgw_conf_rxif_s { + bool enable; /*!> enable or disable that IF chain */ + 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 */ + uint32_t datarate; /*!> RX datarate, 0 for default */ +}; + +/** +@struct lgw_pkt_rx_s +@brief Structure containing the metadata of a packet that was received and a pointer to the payload +*/ +struct lgw_pkt_rx_s { + uint8_t if_chain; /*!> by which IF chain was packet received */ + uint8_t status; /*!> status of the received packet */ + uint8_t modulation; /*!> modulation used by the packet */ + uint8_t bandwidth; /*!> modulation bandwidth (Lora only) */ + uint16_t datarate; /*!> RX datarate of the packet */ + uint8_t coderate; /*!> error-correcting code of the packet */ + uint32_t count_us; /*!> internal gateway counter for timestamping, 1 microsecond resolution */ + float rssi; /*!> average packet RSSI in dB */ + float snr; /*!> average packet SNR, in dB (Lora only) */ + float snr_min; /*!> minimum packet SNR, in dB (Lora only) */ + 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[256]; /*!> buffer containing the payload */ +}; + +/** +@struct lgw_pkt_tx_s +@brief Structure containing the configuration of a packet to send and a pointer to the payload +*/ +struct lgw_pkt_tx_s { + uint32_t freq_hz; /*!> center frequency of TX */ + uint8_t tx_mode; /*!> select on what event/time the TX is triggered */ + uint32_t count_us; /*!> timestamp or delay in microseconds for TX trigger */ + uint8_t rf_chain; /*!> through which RF chain will the packet be sent */ + int8_t rf_power; /*!> TX power, in dBm */ + 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) */ + 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 (Lora), fixed length (FSK) */ + uint16_t size; /*!> payload size in bytes */ + uint8_t payload[256]; /*!> buffer containing the payload */ +}; + +/* -------------------------------------------------------------------------- */ +/* --- PUBLIC FUNCTIONS PROTOTYPES ------------------------------------------ */ + +/** +@brief Configure an RF chain (must configure before start) +@param rf_chain number of the RF chain to configure [0, LGW_RF_CHAIN_NB - 1] +@param conf structure containing the configuration parameters +@return LGW_HAL_ERROR id the operation failed, LGW_HAL_SUCCESS else +*/ +int lgw_rxrf_setconf(uint8_t rf_chain, struct lgw_conf_rxrf_s conf); + +/** +@brief Configure an IF chain + modem (must configure before start) +@param if_chain number of the IF chain + modem to configure [0, LGW_IF_CHAIN_NB - 1] +@param conf structure containing the configuration parameters +@return LGW_HAL_ERROR id the operation failed, LGW_HAL_SUCCESS else +*/ +int lgw_rxif_setconf(uint8_t if_chain, struct lgw_conf_rxif_s conf); + +/** +@brief Connect to the Lora gateway, reset it and configure it according to previously set parameters +@return LGW_HAL_ERROR id the operation failed, LGW_HAL_SUCCESS else +*/ +int lgw_start(void); + +/** +@brief Stop the Lora gateway and disconnect it +@return LGW_HAL_ERROR id the operation failed, LGW_HAL_SUCCESS else +*/ +int lgw_stop(void); + +/** +@brief A non-blocking function that will fetch up to 'max_pkt' packets from the Lora gateway FIFO and data buffer +@param max_pkt maximum number of packet that must be retrieved (equal to the size of the array of struct) +@param pkt_data pointer to an array of struct that will receive the packet metadata and payload pointers +@return LGW_HAL_ERROR id the operation failed, else the number of packets retrieved +*/ +int lgw_receive(uint8_t max_pkt, struct lgw_pkt_rx_s *pkt_data); + +/** +@brief Schedule a packet to be send immediately or after a delay depending on tx_mode +@param pkt_data structure containing the data and metadata for the packet to send +@return LGW_HAL_ERROR id the operation failed, LGW_HAL_SUCCESS else +*/ +int lgw_send(struct lgw_pkt_tx_s pkt_data); + +/** +@brief Give the the status of different part of the Lora gateway +@param select is used to select what status we want to know +@param code is used to return the status code +@return LGW_HAL_ERROR id the operation failed, LGW_HAL_SUCCESS else +*/ +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/libloragw/inc/loragw_reg.h b/libloragw/inc/loragw_reg.h new file mode 100644 index 0000000..870780f --- /dev/null +++ b/libloragw/inc/loragw_reg.h @@ -0,0 +1,432 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + ©2013 Semtech-Cycleo + +Description: + Functions used to handle a single Lora gateway. + Registers are addressed by name. + Multi-bytes registers are handled automatically. + Read-modify-write is handled automatically. +*/ + + +#ifndef _LORAGW_REG_H +#define _LORAGW_REG_H + +/* -------------------------------------------------------------------------- */ +/* --- DEPENDANCIES --------------------------------------------------------- */ + +#include /* C99 types */ +#include /* bool type */ + +/* -------------------------------------------------------------------------- */ +/* --- PUBLIC CONSTANTS ----------------------------------------------------- */ + +#define LGW_REG_SUCCESS 0 +#define LGW_REG_ERROR -1 + +/* +auto generated register mapping for C code : 11-Jul-2013 13:20:40 +this file contains autogenerated C struct used to access the LORA register from the Primer firmware +this file is autogenerated from registers description +293 registers are defined +*/ + +#define LGW_PAGE_REG 0 +#define LGW_SOFT_RESET 1 +#define LGW_VERSION 2 +#define LGW_RX_DATA_BUF_ADDR 3 +#define LGW_RX_DATA_BUF_DATA 4 +#define LGW_TX_DATA_BUF_ADDR 5 +#define LGW_TX_DATA_BUF_DATA 6 +#define LGW_CAPTURE_RAM_ADDR 7 +#define LGW_CAPTURE_RAM_DATA 8 +#define LGW_MCU_PROM_ADDR 9 +#define LGW_MCU_PROM_DATA 10 +#define LGW_RX_PACKET_DATA_FIFO_NUM_STORED 11 +#define LGW_RX_PACKET_DATA_FIFO_ADDR_POINTER 12 +#define LGW_RX_PACKET_DATA_FIFO_STATUS 13 +#define LGW_RX_PACKET_DATA_FIFO_PAYLOAD_SIZE 14 +#define LGW_MBWSSF_MODEM_ENABLE 15 +#define LGW_CONCENTRATOR_MODEM_ENABLE 16 +#define LGW_FSK_MODEM_ENABLE 17 +#define LGW_GLOBAL_EN 18 +#define LGW_CLK32M_EN 19 +#define LGW_CLKHS_EN 20 +#define LGW_START_BIST0 21 +#define LGW_START_BIST1 22 +#define LGW_CLEAR_BIST0 23 +#define LGW_CLEAR_BIST1 24 +#define LGW_BIST0_FINISHED 25 +#define LGW_BIST1_FINISHED 26 +#define LGW_MCU_AGC_PROG_RAM_BIST_STATUS 27 +#define LGW_MCU_ARB_PROG_RAM_BIST_STATUS 28 +#define LGW_CAPTURE_RAM_BIST_STATUS 29 +#define LGW_CHAN_FIR_RAM0_BIST_STATUS 30 +#define LGW_CHAN_FIR_RAM1_BIST_STATUS 31 +#define LGW_CORR0_RAM_BIST_STATUS 32 +#define LGW_CORR1_RAM_BIST_STATUS 33 +#define LGW_CORR2_RAM_BIST_STATUS 34 +#define LGW_CORR3_RAM_BIST_STATUS 35 +#define LGW_CORR4_RAM_BIST_STATUS 36 +#define LGW_CORR5_RAM_BIST_STATUS 37 +#define LGW_CORR6_RAM_BIST_STATUS 38 +#define LGW_CORR7_RAM_BIST_STATUS 39 +#define LGW_MODEM0_RAM0_BIST_STATUS 40 +#define LGW_MODEM1_RAM0_BIST_STATUS 41 +#define LGW_MODEM2_RAM0_BIST_STATUS 42 +#define LGW_MODEM3_RAM0_BIST_STATUS 43 +#define LGW_MODEM4_RAM0_BIST_STATUS 44 +#define LGW_MODEM5_RAM0_BIST_STATUS 45 +#define LGW_MODEM6_RAM0_BIST_STATUS 46 +#define LGW_MODEM7_RAM0_BIST_STATUS 47 +#define LGW_MODEM0_RAM1_BIST_STATUS 48 +#define LGW_MODEM1_RAM1_BIST_STATUS 49 +#define LGW_MODEM2_RAM1_BIST_STATUS 50 +#define LGW_MODEM3_RAM1_BIST_STATUS 51 +#define LGW_MODEM4_RAM1_BIST_STATUS 52 +#define LGW_MODEM5_RAM1_BIST_STATUS 53 +#define LGW_MODEM6_RAM1_BIST_STATUS 54 +#define LGW_MODEM7_RAM1_BIST_STATUS 55 +#define LGW_MODEM0_RAM2_BIST_STATUS 56 +#define LGW_MODEM1_RAM2_BIST_STATUS 57 +#define LGW_MODEM2_RAM2_BIST_STATUS 58 +#define LGW_MODEM3_RAM2_BIST_STATUS 59 +#define LGW_MODEM4_RAM2_BIST_STATUS 60 +#define LGW_MODEM5_RAM2_BIST_STATUS 61 +#define LGW_MODEM6_RAM2_BIST_STATUS 62 +#define LGW_MODEM7_RAM2_BIST_STATUS 63 +#define LGW_MODEM_MBWSSF_RAM0_BIST_STATUS 64 +#define LGW_MODEM_MBWSSF_RAM1_BIST_STATUS 65 +#define LGW_MODEM_MBWSSF_RAM2_BIST_STATUS 66 +#define LGW_MCU_AGC_DATA_RAM_BIST0_STATUS 67 +#define LGW_MCU_AGC_DATA_RAM_BIST1_STATUS 68 +#define LGW_MCU_ARB_DATA_RAM_BIST0_STATUS 69 +#define LGW_MCU_ARB_DATA_RAM_BIST1_STATUS 70 +#define LGW_TX_TOP_RAM_BIST0_STATUS 71 +#define LGW_TX_TOP_RAM_BIST1_STATUS 72 +#define LGW_DATA_MNGT_RAM_BIST0_STATUS 73 +#define LGW_DATA_MNGT_RAM_BIST1_STATUS 74 +#define LGW_GPIO_SELECT_INPUT 75 +#define LGW_GPIO_SELECT_OUTPUT 76 +#define LGW_GPIO_MODE 77 +#define LGW_GPIO_PIN_REG_IN 78 +#define LGW_GPIO_PIN_REG_OUT 79 +#define LGW_MCU_AGC_STATUS 80 +#define LGW_MCU_ARB_STATUS 81 +#define LGW_CHIP_ID 82 +#define LGW_EMERGENCY_FORCE_HOST_CTRL 83 +#define LGW_RX_INVERT_IQ 84 +#define LGW_MODEM_INVERT_IQ 85 +#define LGW_MBWSSF_MODEM_INVERT_IQ 86 +#define LGW_RX_EDGE_SELECT 87 +#define LGW_MISC_RADIO_EN 88 +#define LGW_FSK_MODEM_INVERT_IQ 89 +#define LGW_FILTER_GAIN 90 +#define LGW_RADIO_SELECT 91 +#define LGW_IF_FREQ_0 92 +#define LGW_IF_FREQ_1 93 +#define LGW_IF_FREQ_2 94 +#define LGW_IF_FREQ_3 95 +#define LGW_IF_FREQ_4 96 +#define LGW_IF_FREQ_5 97 +#define LGW_IF_FREQ_6 98 +#define LGW_IF_FREQ_7 99 +#define LGW_IF_FREQ_8 100 +#define LGW_IF_FREQ_9 101 +#define LGW_CHANN_OVERRIDE_AGC_GAIN 102 +#define LGW_CHANN_AGC_GAIN 103 +#define LGW_CORR0_DETECT_EN 104 +#define LGW_CORR1_DETECT_EN 105 +#define LGW_CORR2_DETECT_EN 106 +#define LGW_CORR3_DETECT_EN 107 +#define LGW_CORR4_DETECT_EN 108 +#define LGW_CORR5_DETECT_EN 109 +#define LGW_CORR6_DETECT_EN 110 +#define LGW_CORR7_DETECT_EN 111 +#define LGW_CORR_SAME_PEAKS_OPTION_SF6 112 +#define LGW_CORR_SAME_PEAKS_OPTION_SF7 113 +#define LGW_CORR_SAME_PEAKS_OPTION_SF8 114 +#define LGW_CORR_SAME_PEAKS_OPTION_SF9 115 +#define LGW_CORR_SAME_PEAKS_OPTION_SF10 116 +#define LGW_CORR_SAME_PEAKS_OPTION_SF11 117 +#define LGW_CORR_SAME_PEAKS_OPTION_SF12 118 +#define LGW_CORR_SIG_NOISE_RATIO_SF6 119 +#define LGW_CORR_SIG_NOISE_RATIO_SF7 120 +#define LGW_CORR_SIG_NOISE_RATIO_SF8 121 +#define LGW_CORR_SIG_NOISE_RATIO_SF9 122 +#define LGW_CORR_SIG_NOISE_RATIO_SF10 123 +#define LGW_CORR_SIG_NOISE_RATIO_SF11 124 +#define LGW_CORR_SIG_NOISE_RATIO_SF12 125 +#define LGW_CORR_NUM_SAME_PEAK 126 +#define LGW_CORR_MAC_GAIN 127 +#define LGW_ADJUST_MODEM_START_OFFSET_RDX4 128 +#define LGW_ADJUST_MODEM_START_OFFSET_SF12_RDX4 129 +#define LGW_DBG_CORR_SELECT_SF 130 +#define LGW_DBG_CORR_SELECT_CHANNEL 131 +#define LGW_DBG_DETECT_CPT 132 +#define LGW_DBG_SYMB_CPT 133 +#define LGW_CHIRP_INVERT_RX 134 +#define LGW_DC_NOTCH_EN 135 +#define LGW_IMPLICIT_CRC_EN 136 +#define LGW_IMPLICIT_CODING_RATE 137 +#define LGW_IMPLICIT_PAYLOAD_LENGHT 138 +#define LGW_FREQ_TO_TIME_INVERT 139 +#define LGW_FREQ_TO_TIME_DRIFT 140 +#define LGW_PAYLOAD_FINE_TIMING_GAIN 141 +#define LGW_PREAMBLE_FINE_TIMING_GAIN 142 +#define LGW_TRACKING_INTEGRAL 143 +#define LGW_FRAME_SYNCH_PEAK1_POS 144 +#define LGW_FRAME_SYNCH_PEAK2_POS 145 +#define LGW_PREAMBLE_SYMB1_NB 146 +#define LGW_FRAME_SYNCH_GAIN 147 +#define LGW_SYNCH_DETECT_TH 148 +#define LGW_LLR_SCALE 149 +#define LGW_SNR_AVG_CST 150 +#define LGW_PPM_OFFSET 151 +#define LGW_MAX_PAYLOAD_LEN 152 +#define LGW_ONLY_CRC_EN 153 +#define LGW_ZERO_PAD 154 +#define LGW_DEC_GAIN_OFFSET 155 +#define LGW_CHAN_GAIN_OFFSET 156 +#define LGW_FORCE_HOST_RADIO_CTRL 157 +#define LGW_FORCE_HOST_FE_CTRL 158 +#define LGW_FORCE_DEC_FILTER_GAIN 159 +#define LGW_MCU_RST_0 160 +#define LGW_MCU_RST_1 161 +#define LGW_MCU_SELECT_MUX_0 162 +#define LGW_MCU_SELECT_MUX_1 163 +#define LGW_MCU_CORRUPTION_DETECTED_0 164 +#define LGW_MCU_CORRUPTION_DETECTED_1 165 +#define LGW_MCU_SELECT_EDGE_0 166 +#define LGW_MCU_SELECT_EDGE_1 167 +#define LGW_CHANN_SELECT_RSSI 168 +#define LGW_RSSI_BB_DEFAULT_VALUE 169 +#define LGW_RSSI_DEC_DEFAULT_VALUE 170 +#define LGW_RSSI_CHANN_DEFAULT_VALUE 171 +#define LGW_RSSI_BB_FILTER_ALPHA 172 +#define LGW_RSSI_DEC_FILTER_ALPHA 173 +#define LGW_RSSI_CHANN_FILTER_ALPHA 174 +#define LGW_IQ_MISMATCH_A_AMP_COEFF 175 +#define LGW_IQ_MISMATCH_A_PHI_COEFF 176 +#define LGW_IQ_MISMATCH_B_AMP_COEFF 177 +#define LGW_IQ_MISMATCH_B_SEL_I 178 +#define LGW_IQ_MISMATCH_B_PHI_COEFF 179 +#define LGW_TX_TRIG_IMMEDIATE 180 +#define LGW_TX_TRIG_DELAYED 181 +#define LGW_TX_TRIG_GPS 182 +#define LGW_TX_START_DELAY 183 +#define LGW_TX_FRAME_SYNCH_PEAK1_POS 184 +#define LGW_TX_FRAME_SYNCH_PEAK2_POS 185 +#define LGW_TX_RAMP_DURATION 186 +#define LGW_TX_OFFSET_I 187 +#define LGW_TX_OFFSET_Q 188 +#define LGW_TX_MODE 189 +#define LGW_TX_ZERO_PAD 190 +#define LGW_TX_EDGE_SELECT 191 +#define LGW_TX_EDGE_SELECT_TOP 192 +#define LGW_TX_GAIN 193 +#define LGW_TX_CHIRP_LOW_PASS 194 +#define LGW_TX_FCC_WIDEBAND 195 +#define LGW_TX_SWAP_IQ 196 +#define LGW_MBWSSF_IMPLICIT_HEADER 197 +#define LGW_MBWSSF_IMPLICIT_CRC_EN 198 +#define LGW_MBWSSF_IMPLICIT_CODING_RATE 199 +#define LGW_MBWSSF_IMPLICIT_PAYLOAD_LENGHT 200 +#define LGW_MBWSSF_AGC_FREEZE_ON_DETECT 201 +#define LGW_MBWSSF_FRAME_SYNCH_PEAK1_POS 202 +#define LGW_MBWSSF_FRAME_SYNCH_PEAK2_POS 203 +#define LGW_MBWSSF_PREAMBLE_SYMB1_NB 204 +#define LGW_MBWSSF_FRAME_SYNCH_GAIN 205 +#define LGW_MBWSSF_SYNCH_DETECT_TH 206 +#define LGW_MBWSSF_DETECT_MIN_SINGLE_PEAK 207 +#define LGW_MBWSSF_DETECT_TRIG_SAME_PEAK_NB 208 +#define LGW_MBWSSF_FREQ_TO_TIME_INVERT 209 +#define LGW_MBWSSF_FREQ_TO_TIME_DRIFT 210 +#define LGW_MBWSSF_PPM_CORRECTION 211 +#define LGW_MBWSSF_PAYLOAD_FINE_TIMING_GAIN 212 +#define LGW_MBWSSF_PREAMBLE_FINE_TIMING_GAIN 213 +#define LGW_MBWSSF_TRACKING_INTEGRAL 214 +#define LGW_MBWSSF_ZERO_PAD 215 +#define LGW_MBWSSF_MODEM_BW 216 +#define LGW_MBWSSF_RADIO_SELECT 217 +#define LGW_MBWSSF_RX_CHIRP_INVERT 218 +#define LGW_MBWSSF_LLR_SCALE 219 +#define LGW_MBWSSF_SNR_AVG_CST 220 +#define LGW_MBWSSF_PPM_OFFSET 221 +#define LGW_MBWSSF_RATE_SF 222 +#define LGW_MBWSSF_ONLY_CRC_EN 223 +#define LGW_MBWSSF_MAX_PAYLOAD_LEN 224 +#define LGW_TX_STATUS 225 +#define LGW_FSK_CH_BW_EXPO 226 +#define LGW_FSK_RSSI_LENGTH 227 +#define LGW_FSK_RX_INVERT 228 +#define LGW_FSK_PKT_MODE 229 +#define LGW_FSK_PSIZE 230 +#define LGW_FSK_CRC_EN 231 +#define LGW_FSK_DCFREE_ENC 232 +#define LGW_FSK_CRC_IBM 233 +#define LGW_FSK_ERROR_OSR_TOL 234 +#define LGW_FSK_RADIO_SELECT 235 +#define LGW_FSK_BR_RATIO 236 +#define LGW_FSK_REF_PATTERN_LSB 237 +#define LGW_FSK_REF_PATTERN_MSB 238 +#define LGW_FSK_PKT_LENGTH 239 +#define LGW_FSK_TX_GAUSSIAN_EN 240 +#define LGW_FSK_TX_GAUSSIAN_SELECT_BT 241 +#define LGW_FSK_TX_PATTERN_EN 242 +#define LGW_FSK_TX_PREAMBLE_SEQ 243 +#define LGW_FSK_TX_PSIZE 244 +#define LGW_FSK_NODE_ADRS 245 +#define LGW_FSK_BROADCAST 246 +#define LGW_FSK_AUTO_AFC_ON 247 +#define LGW_FSK_PATTERN_TIMEOUT_CFG 248 +#define LGW_SPI_RADIO_A__DATA 249 +#define LGW_SPI_RADIO_A__DATA_READBACK 250 +#define LGW_SPI_RADIO_A__ADDR 251 +#define LGW_SPI_RADIO_A__CS 252 +#define LGW_SPI_RADIO_B__DATA 253 +#define LGW_SPI_RADIO_B__DATA_READBACK 254 +#define LGW_SPI_RADIO_B__ADDR 255 +#define LGW_SPI_RADIO_B__CS 256 +#define LGW_RADIO_A_EN 257 +#define LGW_RADIO_B_EN 258 +#define LGW_RADIO_RST 259 +#define LGW_LNA_A_EN 260 +#define LGW_PA_A_EN 261 +#define LGW_LNA_B_EN 262 +#define LGW_PA_B_EN 263 +#define LGW_PA_GAIN 264 +#define LGW_LNA_A_CTRL_LUT 265 +#define LGW_PA_A_CTRL_LUT 266 +#define LGW_LNA_B_CTRL_LUT 267 +#define LGW_PA_B_CTRL_LUT 268 +#define LGW_CAPTURE_SOURCE 269 +#define LGW_CAPTURE_START 270 +#define LGW_CAPTURE_FORCE_TRIGGER 271 +#define LGW_CAPTURE_WRAP 272 +#define LGW_CAPTURE_PERIOD 273 +#define LGW_MODEM_STATUS 274 +#define LGW_VALID_HEADER_COUNTER_0 275 +#define LGW_VALID_PACKET_COUNTER_0 276 +#define LGW_VALID_HEADER_COUNTER_MBWSSF 277 +#define LGW_VALID_HEADER_COUNTER_FSK 278 +#define LGW_VALID_PACKET_COUNTER_MBWSSF 279 +#define LGW_VALID_PACKET_COUNTER_FSK 280 +#define LGW_CHANN_RSSI 281 +#define LGW_BB_RSSI 282 +#define LGW_DEC_RSSI 283 +#define LGW_DBG_MCU_DATA 284 +#define LGW_DBG_ARB_MCU_RAM_DATA 285 +#define LGW_DBG_AGC_MCU_RAM_DATA 286 +#define LGW_NEXT_PACKET_CNT 287 +#define LGW_ADDR_CAPTURE_COUNT 288 +#define LGW_TIMESTAMP 289 +#define LGW_DBG_CHANN0_GAIN 290 +#define LGW_DBG_CHANN1_GAIN 291 +#define LGW_DBG_CHANN2_GAIN 292 +#define LGW_DBG_CHANN3_GAIN 293 +#define LGW_DBG_CHANN4_GAIN 294 +#define LGW_DBG_CHANN5_GAIN 295 +#define LGW_DBG_CHANN6_GAIN 296 +#define LGW_DBG_CHANN7_GAIN 297 +#define LGW_DBG_DEC_FILT_GAIN 298 +#define LGW_SPI_DATA_FIFO_PTR 299 +#define LGW_PACKET_DATA_FIFO_PTR 300 +#define LGW_DBG_ARB_MCU_RAM_ADDR 301 +#define LGW_DBG_AGC_MCU_RAM_ADDR 302 +#define LGW_SPI_MASTER_CHIP_SELECT_POLARITY 303 +#define LGW_SPI_MASTER_CPOL 304 +#define LGW_SPI_MASTER_CPHA 305 +#define LGW_SIG_GEN_ANALYSER_MUX_SEL 306 +#define LGW_SIG_GEN_EN 307 +#define LGW_SIG_ANALYSER_EN 308 +#define LGW_SIG_ANALYSER_AVG_LEN 309 +#define LGW_SIG_ANALYSER_PRECISION 310 +#define LGW_SIG_ANALYSER_VALID_OUT 311 +#define LGW_SIG_GEN_FREQ 312 +#define LGW_SIG_ANALYSER_FREQ 313 +#define LGW_SIG_ANALYSER_I_OUT 314 +#define LGW_SIG_ANALYSER_Q_OUT 315 +#define LGW_GPS_EN 316 +#define LGW_GPS_POL 317 +#define LGW_SW_TEST_REG1 318 +#define LGW_SW_TEST_REG2 319 +#define LGW_SW_TEST_REG3 320 +#define LGW_DATA_MNGT_STATUS 321 +#define LGW_DATA_MNGT_CPT_FRAME_ALLOCATED 322 +#define LGW_DATA_MNGT_CPT_FRAME_FINISHED 323 +#define LGW_DATA_MNGT_CPT_FRAME_READEN 324 + +#define LGW_TOTALREGS 325 + +/* -------------------------------------------------------------------------- */ +/* --- PUBLIC FUNCTIONS PROTOTYPES ------------------------------------------ */ + +/** +@brief Connect Lora gateway by opening SPI link +@return status of register operation (LGW_REG_SUCCESS/LGW_REG_ERROR) +*/ +int lgw_connect(void); + +/** +@brief Disconnect Lora gateway by closing SPI link +@return status of register operation (LGW_REG_SUCCESS/LGW_REG_ERROR) +*/ +int lgw_disconnect(void); + +/** +@brief Use the soft-reset register to put the gateway in initial state +@return status of register operation (LGW_REG_SUCCESS/LGW_REG_ERROR) +*/ +int lgw_soft_reset(void); + +/** +@brief Check if the registers are ok, send diagnostics to stdio/stderr/file +@param f file descriptor to to which the check result will be written +@return status of register operation (LGW_REG_SUCCESS/LGW_REG_ERROR) +*/ +int lgw_reg_check(FILE *f); + +/** +@brief Lora gateway register write +@param register_id register number in the data structure describing registers +@param reg_value signed value to write to the register (for u32, use cast) +@return status of register operation (LGW_REG_SUCCESS/LGW_REG_ERROR) +*/ +int lgw_reg_w(uint16_t register_id, int32_t reg_value); + +/** +@brief Lora gateway register read +@param register_id register number in the data structure describing registers +@param reg_value pointer to a variable where to write register read value +@return status of register operation (LGW_REG_SUCCESS/LGW_REG_ERROR) +*/ +int lgw_reg_r(uint16_t register_id, int32_t *reg_value); + +/** +@brief Lora gateway register burst write +@param register_id register number in the data structure describing registers +@param data pointer to byte array that will be sent to the Lora gateway +@param size size of the transfer, in byte(s) +@return status of register operation (LGW_REG_SUCCESS/LGW_REG_ERROR) +*/ +int lgw_reg_wb(uint16_t register_id, uint8_t *data, uint16_t size); + +/** +@brief Lora gateway register burst read +@param register_id register number in the data structure describing registers +@param data pointer to byte array that will be written from the Lora gateway +@param size size of the transfer, in byte(s) +@return status of register operation (LGW_REG_SUCCESS/LGW_REG_ERROR) +*/ +int lgw_reg_rb(uint16_t register_id, uint8_t *data, uint16_t size); + + +#endif + +/* --- EOF ------------------------------------------------------------------ */ diff --git a/libloragw/inc/loragw_spi.h b/libloragw/inc/loragw_spi.h new file mode 100644 index 0000000..68d8bcf --- /dev/null +++ b/libloragw/inc/loragw_spi.h @@ -0,0 +1,92 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + ©2013 Semtech-Cycleo + +Description: + Host specific functions to address the LoRa™ gateway registers through a + SPI interface. + Single-byte read/write and burst read/write. + Does not handle pagination. + Could be used with multiple SPI ports in parallel (explicit file descriptor) +*/ + + +#ifndef _LORAGW_SPI_H +#define _LORAGW_SPI_H + +/* -------------------------------------------------------------------------- */ +/* --- DEPENDANCIES --------------------------------------------------------- */ + +#include /* C99 types*/ + +/* -------------------------------------------------------------------------- */ +/* --- PUBLIC CONSTANTS ----------------------------------------------------- */ + +#define LGW_SPI_SUCCESS 0 +#define LGW_SPI_ERROR -1 +#define LGW_BURST_CHUNK 1024 + +/* -------------------------------------------------------------------------- */ +/* --- PUBLIC FUNCTIONS PROTOTYPES ------------------------------------------ */ + +/** +@brief Lora gateway SPI setup (configure I/O and peripherals) +@param spi_target_ptr pointer on a generic pointer to SPI target (implementation dependant) +@return status of register operation (LGW_SPI_SUCCESS/LGW_SPI_ERROR) +*/ + +int lgw_spi_open(void **spi_target_ptr); + +/** +@brief Lora gateway SPI close +@param spi_target generic pointer to SPI target (implementation dependant) +@return status of register operation (LGW_SPI_SUCCESS/LGW_SPI_ERROR) +*/ + +int lgw_spi_close(void *spi_target); + +/** +@brief Lora gateway SPI single-byte write +@param spi_target generic pointer to SPI target (implementation dependant) +@param address 7-bit register address +@param data data byte to write +@return status of register operation (LGW_SPI_SUCCESS/LGW_SPI_ERROR) +*/ +int lgw_spi_w(void *spi_target, uint8_t address, uint8_t data); + +/** +@brief Lora gateway SPI single-byte read +@param spi_target generic pointer to SPI target (implementation dependant) +@param address 7-bit register address +@param data data byte to write +@return status of register operation (LGW_SPI_SUCCESS/LGW_SPI_ERROR) +*/ +int lgw_spi_r(void *spi_target, uint8_t address, uint8_t *data); + +/** +@brief Lora gateway SPI burst (multiple-byte) write +@param spi_target generic pointer to SPI target (implementation dependant) +@param address 7-bit register address +@param data pointer to byte array that will be sent to the Lora gateway +@param size size of the transfer, in byte(s) +@return status of register operation (LGW_SPI_SUCCESS/LGW_SPI_ERROR) +*/ +int lgw_spi_wb(void *spi_target, uint8_t address, uint8_t *data, uint16_t size); + +/** +@brief Lora gateway SPI burst (multiple-byte) read +@param spi_target generic pointer to SPI target (implementation dependant) +@param address 7-bit register address +@param data pointer to byte array that will be written from the Lora gateway +@param size size of the transfer, in byte(s) +@return status of register operation (LGW_SPI_SUCCESS/LGW_SPI_ERROR) +*/ +int lgw_spi_rb(void *spi_target, uint8_t address, uint8_t *data, uint16_t size); + +#endif + +/* --- EOF ------------------------------------------------------------------ */ diff --git a/libloragw/library.cfg b/libloragw/library.cfg new file mode 100644 index 0000000..ac24416 --- /dev/null +++ b/libloragw/library.cfg @@ -0,0 +1,26 @@ +# / _____) _ | | +# ( (____ _____ ____ _| |_ _____ ____| |__ +# \____ \| ___ | (_ _) ___ |/ ___) _ \ +# _____) ) ____| | | || |_| ____( (___| | | | +# (______/|_____)_|_|_| \__)_____)\____)_| |_| +# ©2013 Semtech-Cycleo +# +# Description: +# Lora gateway Hardware Abstraction Layer library configuration + + +# Set the DEBUG_* to 1 to activate debug mode in individual modules. +# Warning: that makes the module *very verbose*, do not use for production +FLAG_AUX= -D DEBUG_AUX=0 +FLAG_SPI= -D DEBUG_SPI=0 +FLAG_REG= -D DEBUG_REG=0 +FLAG_HAL= -D DEBUG_HAL=0 + +# The flags bellow define which physical link to the nano board will be used +# Pick one and comment the other(s) + +# Pcduino native SPI (Linux device in /dev) +LGW_PHY= native + +# FTDI SPI-over-USB bridge +#LGW_PHY= ftdi diff --git a/libloragw/obj/.gitkeep b/libloragw/obj/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/libloragw/src/agc_fw.var b/libloragw/src/agc_fw.var new file mode 100644 index 0000000..7d30fb9 --- /dev/null +++ b/libloragw/src/agc_fw.var @@ -0,0 +1,526 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + ©2013 Semtech-Cycleo + +Description: + AGC firmware +*/ + +static uint8_t agc_firmware[MCU_AGC_FW_BYTE] = { +0x8A, 0x51, 0x11, 0x28, 0xFF, 0xBF, 0xFF, 0xBF, 0x80, 0x40, 0x03, 0x4E, 0x83, 0x52, 0x03, 0x53, +0xA8, 0xC0, 0x04, 0x88, 0xA9, 0x00, 0x0A, 0xC8, 0xAA, 0x00, 0x01, 0x88, 0xAB, 0x40, 0x8A, 0x51, +0x79, 0x6E, 0x8A, 0x51, 0x3A, 0x2E, 0xA2, 0x70, 0x84, 0x80, 0x37, 0xF0, 0x83, 0x52, 0x03, 0x53, +0xB3, 0x40, 0x04, 0x88, 0xB4, 0x00, 0x08, 0xF0, 0xB5, 0x40, 0x33, 0x48, 0x84, 0x80, 0x83, 0x93, +0x00, 0x48, 0xB6, 0x40, 0xB3, 0xCA, 0x34, 0x08, 0x84, 0x80, 0x36, 0x48, 0x80, 0x40, 0xB4, 0x8A, +0xB5, 0x0B, 0x1D, 0xA8, 0x2B, 0xA8, 0x19, 0x54, 0x99, 0x50, 0x19, 0x95, 0x99, 0x91, 0x19, 0x52, +0x99, 0x92, 0x18, 0x56, 0x38, 0x68, 0x90, 0x30, 0xB3, 0x40, 0x33, 0x48, 0x8B, 0x00, 0x39, 0xA8, +0x8B, 0x41, 0x98, 0x10, 0x18, 0x11, 0x98, 0x51, 0x97, 0x81, 0x9C, 0x41, 0x9A, 0x41, 0x9B, 0x81, +0x9E, 0x81, 0x83, 0x96, 0x03, 0x53, 0xE4, 0x41, 0xE5, 0x81, 0xD2, 0x41, 0xD2, 0x8A, 0x0F, 0xB0, +0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, 0x03, 0x53, 0xDA, 0x40, 0xCA, 0x41, +0xD3, 0x81, 0xD3, 0xCA, 0x0C, 0x30, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, +0x03, 0x53, 0xDB, 0x80, 0x06, 0x30, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, +0x03, 0x53, 0xCB, 0x40, 0x02, 0xF0, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, +0x03, 0x53, 0xD4, 0x00, 0x0C, 0x30, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, +0x03, 0x53, 0xDC, 0x40, 0x0C, 0x30, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, +0x03, 0x53, 0xCC, 0x00, 0x03, 0x30, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, +0x03, 0x53, 0xD5, 0x40, 0x0C, 0x30, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, +0x03, 0x53, 0xDD, 0x80, 0x12, 0x30, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, +0x03, 0x53, 0xCD, 0x40, 0x04, 0xF0, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, +0x03, 0x53, 0xD6, 0x40, 0x0F, 0xB0, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, +0x03, 0x53, 0xDE, 0x80, 0x18, 0x30, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, +0x03, 0x53, 0xCE, 0x40, 0x04, 0xF0, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, +0x03, 0x53, 0xD7, 0x80, 0x0C, 0x30, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, +0x03, 0x53, 0xDF, 0xC0, 0x1E, 0xB0, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, +0x03, 0x53, 0xCF, 0x80, 0x05, 0x30, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, +0x03, 0x53, 0xD8, 0x00, 0x0C, 0x30, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, +0x03, 0x53, 0xE0, 0xC0, 0x24, 0x30, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, +0x03, 0x53, 0xD0, 0xC0, 0x05, 0x30, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, +0x03, 0x53, 0xD9, 0x40, 0x0C, 0x30, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, +0x03, 0x53, 0xE1, 0x00, 0x2A, 0x70, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, +0x03, 0x53, 0xD1, 0x00, 0xB2, 0x41, 0xB3, 0x81, 0xB4, 0x41, 0xB5, 0x81, 0xB6, 0x81, 0xB7, 0xC1, +0xB8, 0x41, 0xB9, 0x81, 0xBA, 0x81, 0x06, 0x30, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, +0x83, 0x96, 0x03, 0x53, 0xBB, 0x80, 0x0C, 0x30, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, +0x83, 0x96, 0x03, 0x53, 0xBC, 0x40, 0x12, 0x30, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, +0x83, 0x96, 0x03, 0x53, 0xBD, 0x80, 0x18, 0x30, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, +0x83, 0x96, 0x03, 0x53, 0xBE, 0x80, 0x1E, 0xB0, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, +0x83, 0x96, 0x03, 0x53, 0xBF, 0xC0, 0x24, 0x30, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, +0x83, 0x96, 0x03, 0x53, 0xC0, 0x80, 0x2A, 0x70, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, +0x83, 0x96, 0x03, 0x53, 0xC1, 0xC0, 0xEB, 0xC1, 0x02, 0xF0, 0x6B, 0x82, 0x03, 0x5C, 0x39, 0xE9, +0x3A, 0xE9, 0x3C, 0xE9, 0xB2, 0xE9, 0xB2, 0xE9, 0x6B, 0x88, 0xE8, 0x7E, 0x84, 0x80, 0x83, 0x93, +0x80, 0x81, 0x08, 0xF0, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x83, 0x96, 0x03, 0x53, 0x6B, 0x88, +0xE6, 0xBE, 0x84, 0x80, 0x83, 0x52, 0x03, 0x53, 0x33, 0x48, 0x80, 0x40, 0x83, 0x96, 0x03, 0x53, +0x6B, 0x88, 0xE8, 0x7E, 0x84, 0x80, 0x00, 0x48, 0xD2, 0x7E, 0x84, 0x80, 0x00, 0x48, 0x83, 0x52, +0x03, 0x53, 0xB3, 0x40, 0x05, 0x30, 0x03, 0xD0, 0xB3, 0x0D, 0xFF, 0x7E, 0x03, 0x9D, 0x5B, 0x29, +0x83, 0x96, 0x03, 0x53, 0x6B, 0x88, 0xE8, 0x7E, 0x84, 0x80, 0x00, 0x48, 0xDA, 0xBE, 0x84, 0x80, +0x00, 0x48, 0x83, 0x52, 0x03, 0x53, 0xB4, 0x00, 0x34, 0x87, 0x33, 0x44, 0xB5, 0x40, 0x35, 0x48, +0x83, 0x96, 0x03, 0x53, 0xA0, 0x80, 0x6B, 0x88, 0x83, 0x52, 0x03, 0x53, 0xB6, 0x40, 0x36, 0x48, +0x83, 0x96, 0x03, 0x53, 0xA1, 0xC0, 0x0C, 0x30, 0x8A, 0x51, 0x16, 0xA6, 0x8A, 0x51, 0x83, 0x52, +0x03, 0x53, 0x98, 0x95, 0x98, 0x51, 0x83, 0x96, 0x03, 0x53, 0x6B, 0x88, 0xE6, 0xBE, 0x84, 0x80, +0x83, 0x93, 0x00, 0x48, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x03, 0x30, 0x03, 0xD0, 0xB3, 0x0D, +0xFF, 0x7E, 0x03, 0x9D, 0x8E, 0xE9, 0x03, 0xD0, 0x33, 0xCD, 0xB4, 0x00, 0x34, 0x08, 0x96, 0x00, +0x83, 0x96, 0x03, 0x53, 0x6B, 0xD8, 0x9D, 0x29, 0xA1, 0xA9, 0x83, 0x52, 0x03, 0x53, 0x18, 0x14, +0xA4, 0xA9, 0x83, 0x52, 0x03, 0x53, 0x18, 0xD0, 0x18, 0x55, 0x18, 0x11, 0x01, 0xF0, 0xB3, 0x40, +0x33, 0x48, 0x83, 0x96, 0x03, 0x53, 0xEB, 0x47, 0x02, 0xF0, 0x6B, 0x82, 0x03, 0x5C, 0xB1, 0xE9, +0xB2, 0xE9, 0x3C, 0xE9, 0xEA, 0x81, 0x08, 0xF0, 0x6A, 0x42, 0x03, 0x5C, 0xB8, 0xE9, 0xB9, 0x29, +0xBB, 0x69, 0xF9, 0x69, 0xF9, 0x69, 0x07, 0x70, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x83, 0x96, +0x03, 0x53, 0x6A, 0x48, 0xC2, 0x3E, 0x84, 0x80, 0x83, 0x52, 0x03, 0x53, 0x33, 0x48, 0x83, 0x93, +0x80, 0x40, 0x83, 0x96, 0x03, 0x53, 0x6A, 0x48, 0xC2, 0x3E, 0x84, 0x80, 0x00, 0x48, 0x83, 0x52, +0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x96, 0x00, 0x83, 0x96, 0x03, 0x53, 0x6A, 0x48, 0xA2, 0x3E, +0x84, 0x80, 0x00, 0x48, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x95, 0x00, 0x98, 0x54, +0x98, 0x10, 0x01, 0xF0, 0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, 0x03, 0x53, 0xEA, 0x07, 0x08, 0xF0, +0x6A, 0x42, 0x03, 0x5C, 0xEC, 0x29, 0xED, 0x69, 0xBB, 0x69, 0xF9, 0x69, 0xF9, 0x69, 0xF9, 0x69, +0x83, 0x52, 0x03, 0x53, 0x18, 0x9E, 0xF5, 0x69, 0xF6, 0x69, 0x04, 0x2A, 0x18, 0x12, 0x2B, 0xA8, +0x04, 0x2A, 0x83, 0x52, 0x03, 0x53, 0x93, 0x5F, 0xFE, 0xA9, 0xFF, 0xE9, 0x04, 0x2A, 0x8A, 0x51, +0x38, 0x64, 0x8A, 0x51, 0x04, 0x2A, 0x04, 0x2A, 0x83, 0x96, 0x03, 0x53, 0x68, 0x08, 0xCA, 0x7E, +0x84, 0x80, 0x83, 0x93, 0x00, 0x48, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, +0x03, 0x53, 0xE4, 0x00, 0x66, 0x48, 0xB2, 0x7E, 0x84, 0x80, 0x00, 0x48, 0x83, 0x52, 0x03, 0x53, +0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, 0x03, 0x53, 0xE5, 0x40, 0x83, 0x52, 0x03, 0x53, 0x1E, 0x48, +0x01, 0xBE, 0xB3, 0x40, 0x33, 0x48, 0x9E, 0x40, 0x83, 0x96, 0x03, 0x53, 0x65, 0x48, 0x64, 0x87, +0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x97, 0x40, 0x83, 0x96, 0x03, 0x53, 0x69, 0x48, +0xCA, 0x7E, 0x84, 0x80, 0x00, 0x48, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, +0x03, 0x53, 0xE4, 0x00, 0x67, 0x88, 0xB2, 0x7E, 0x84, 0x80, 0x00, 0x48, 0x83, 0x52, 0x03, 0x53, +0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, 0x03, 0x53, 0xE5, 0x40, 0x65, 0x48, 0x64, 0x87, 0x83, 0x52, +0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x9C, 0x00, 0x17, 0x48, 0xB3, 0x40, 0x33, 0x48, 0x9A, 0x00, +0x83, 0x96, 0x03, 0x53, 0xEA, 0x81, 0x08, 0xF0, 0x6A, 0x42, 0x03, 0x5C, 0x58, 0xAA, 0x59, 0xEA, +0x5B, 0x2A, 0xE3, 0x2A, 0xE3, 0x2A, 0x6A, 0x48, 0xA2, 0x3E, 0x84, 0x80, 0x00, 0x48, 0x83, 0x52, +0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x95, 0x00, 0x0D, 0x08, 0xB3, 0x40, 0x83, 0x96, 0x03, 0x53, +0x6A, 0x48, 0xAA, 0x7E, 0x84, 0x80, 0x83, 0x52, 0x03, 0x53, 0x33, 0x48, 0x80, 0x40, 0x83, 0x96, +0x03, 0x53, 0x6A, 0x48, 0xAA, 0x7E, 0x84, 0x80, 0x88, 0x30, 0x00, 0x42, 0x03, 0x5C, 0x79, 0x2A, +0x7A, 0x2A, 0xA2, 0xAA, 0x6A, 0x48, 0xC2, 0x3E, 0x84, 0x80, 0x0F, 0xB0, 0x00, 0x42, 0x03, 0x18, +0x82, 0x6A, 0x83, 0xAA, 0xA2, 0xAA, 0x6A, 0x48, 0xC2, 0x3E, 0x84, 0x80, 0x00, 0x48, 0x01, 0xBE, +0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x83, 0x96, 0x03, 0x53, 0x6A, 0x48, 0xC2, 0x3E, 0x84, 0x80, +0x83, 0x52, 0x03, 0x53, 0x33, 0x48, 0x80, 0x40, 0x83, 0x96, 0x03, 0x53, 0x6A, 0x48, 0xC2, 0x3E, +0x84, 0x80, 0x00, 0x48, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x96, 0x00, 0x98, 0x54, +0x98, 0x10, 0xD6, 0x2A, 0x83, 0x96, 0x03, 0x53, 0x6A, 0x48, 0xAA, 0x7E, 0x84, 0x80, 0x2D, 0xB0, +0x00, 0x42, 0x03, 0x18, 0xAC, 0xEA, 0xAD, 0x2A, 0xD6, 0x2A, 0x6A, 0x48, 0xC2, 0x3E, 0x84, 0x80, +0x08, 0xF0, 0x00, 0x42, 0x03, 0x5C, 0xB5, 0x2A, 0xB6, 0x2A, 0xD6, 0x2A, 0x6A, 0x48, 0xC2, 0x3E, +0x84, 0x80, 0x00, 0x48, 0xFF, 0x7E, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x83, 0x96, 0x03, 0x53, +0x6A, 0x48, 0xC2, 0x3E, 0x84, 0x80, 0x83, 0x52, 0x03, 0x53, 0x33, 0x48, 0x80, 0x40, 0x83, 0x96, +0x03, 0x53, 0x6A, 0x48, 0xC2, 0x3E, 0x84, 0x80, 0x00, 0x48, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, +0x33, 0x48, 0x96, 0x00, 0x98, 0x54, 0x98, 0x10, 0xD6, 0x2A, 0xD6, 0x2A, 0x01, 0xF0, 0x83, 0x52, +0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, 0x03, 0x53, 0xEA, 0x07, 0x08, 0xF0, 0x6A, 0x42, 0x03, 0x5C, +0xE2, 0xEA, 0xE3, 0x2A, 0x5B, 0x2A, 0xEB, 0xC1, 0x02, 0xF0, 0x6B, 0x82, 0x03, 0x5C, 0xE9, 0x2A, +0xEA, 0x2A, 0xEC, 0x2A, 0xF9, 0x69, 0xF9, 0x69, 0x6B, 0xD8, 0xEF, 0xAA, 0xF3, 0x6A, 0x83, 0x52, +0x03, 0x53, 0x18, 0x14, 0xF6, 0x6A, 0x83, 0x52, 0x03, 0x53, 0x18, 0xD0, 0x0E, 0x08, 0xB3, 0x40, +0x33, 0x48, 0x83, 0x96, 0x03, 0x53, 0xE3, 0x40, 0x88, 0x30, 0x63, 0x42, 0x03, 0x5C, 0x01, 0x6B, +0x02, 0x6B, 0x34, 0xEB, 0x6B, 0x88, 0xE6, 0xBE, 0x84, 0x80, 0x0B, 0x70, 0x83, 0x93, 0x00, 0x42, +0x03, 0x18, 0x0B, 0xEB, 0x0C, 0xAB, 0x34, 0xEB, 0x6B, 0x88, 0xE6, 0xBE, 0x84, 0x80, 0x00, 0x48, +0x01, 0xBE, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x83, 0x96, 0x03, 0x53, 0x6B, 0x88, 0xE6, 0xBE, +0x84, 0x80, 0x83, 0x52, 0x03, 0x53, 0x33, 0x48, 0x80, 0x40, 0x83, 0x96, 0x03, 0x53, 0x6B, 0x88, +0xE6, 0xBE, 0x84, 0x80, 0x00, 0x48, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x03, 0x30, 0x03, 0xD0, +0xB3, 0x0D, 0xFF, 0x7E, 0x03, 0x9D, 0x27, 0x2B, 0x03, 0xD0, 0x33, 0xCD, 0xB4, 0x00, 0x34, 0x08, +0x96, 0x00, 0x18, 0x55, 0x18, 0x11, 0x6F, 0xAB, 0x2D, 0xB0, 0x83, 0x96, 0x03, 0x53, 0x63, 0x42, +0x03, 0x18, 0x3B, 0x6B, 0x3C, 0x2B, 0x6F, 0xAB, 0x6B, 0x88, 0xE6, 0xBE, 0x84, 0x80, 0x09, 0x30, +0x83, 0x93, 0x00, 0x42, 0x03, 0x5C, 0x45, 0xEB, 0x46, 0xEB, 0x6F, 0xAB, 0x6B, 0x88, 0xE6, 0xBE, +0x84, 0x80, 0x00, 0x48, 0xFF, 0x7E, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x83, 0x96, 0x03, 0x53, +0x6B, 0x88, 0xE6, 0xBE, 0x84, 0x80, 0x83, 0x52, 0x03, 0x53, 0x33, 0x48, 0x80, 0x40, 0x83, 0x96, +0x03, 0x53, 0x6B, 0x88, 0xE6, 0xBE, 0x84, 0x80, 0x00, 0x48, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, +0x03, 0x30, 0x03, 0xD0, 0xB3, 0x0D, 0xFF, 0x7E, 0x03, 0x9D, 0x61, 0xEB, 0x03, 0xD0, 0x33, 0xCD, +0xB4, 0x00, 0x34, 0x08, 0x96, 0x00, 0x18, 0x55, 0x18, 0x11, 0x6F, 0xAB, 0x6F, 0xAB, 0x83, 0x52, +0x0F, 0x48, 0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, 0x03, 0x53, 0xE2, 0x00, 0x29, 0x70, 0x62, 0x02, +0x03, 0x5C, 0x7B, 0xAB, 0x7C, 0x6B, 0xCD, 0x6B, 0x6B, 0x88, 0xE8, 0x7E, 0x84, 0x80, 0x07, 0x70, +0x83, 0x93, 0x00, 0x42, 0x03, 0x18, 0x85, 0xEB, 0x86, 0xEB, 0xCD, 0x6B, 0x6B, 0x88, 0xE8, 0x7E, +0x84, 0x80, 0x00, 0x48, 0x01, 0xBE, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x83, 0x96, 0x03, 0x53, +0x6B, 0x88, 0xE8, 0x7E, 0x84, 0x80, 0x83, 0x52, 0x03, 0x53, 0x33, 0x48, 0x80, 0x40, 0x83, 0x96, +0x03, 0x53, 0x6B, 0x88, 0xE8, 0x7E, 0x84, 0x80, 0x00, 0x48, 0xD2, 0x7E, 0x84, 0x80, 0x00, 0x48, +0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x05, 0x30, 0x03, 0xD0, 0xB3, 0x0D, 0xFF, 0x7E, 0x03, 0x9D, +0xA4, 0xEB, 0x83, 0x96, 0x03, 0x53, 0x6B, 0x88, 0xE8, 0x7E, 0x84, 0x80, 0x00, 0x48, 0xDA, 0xBE, +0x84, 0x80, 0x00, 0x48, 0x83, 0x52, 0x03, 0x53, 0xB4, 0x00, 0x34, 0x87, 0x33, 0x44, 0xB5, 0x40, +0x35, 0x48, 0x83, 0x96, 0x03, 0x53, 0xA0, 0x80, 0x6B, 0x88, 0x83, 0x52, 0x03, 0x53, 0xB6, 0x40, +0x36, 0x48, 0x83, 0x96, 0x03, 0x53, 0xA1, 0xC0, 0x0C, 0x30, 0x8A, 0x51, 0x16, 0xA6, 0x8A, 0x51, +0x83, 0x52, 0x03, 0x53, 0x98, 0x95, 0x98, 0x51, 0x26, 0xAC, 0x0F, 0xB0, 0x83, 0x96, 0x03, 0x53, +0x62, 0x02, 0x03, 0x18, 0xD4, 0x2B, 0xD5, 0x6B, 0x26, 0xAC, 0x6B, 0x88, 0xE8, 0x7E, 0x84, 0x80, +0x83, 0x93, 0x80, 0x88, 0x03, 0x59, 0xDD, 0xAB, 0xDE, 0xAB, 0x26, 0xAC, 0x6B, 0x88, 0xE8, 0x7E, +0x84, 0x80, 0x00, 0x48, 0xFF, 0x7E, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x83, 0x96, 0x03, 0x53, +0x6B, 0x88, 0xE8, 0x7E, 0x84, 0x80, 0x83, 0x52, 0x03, 0x53, 0x33, 0x48, 0x80, 0x40, 0x83, 0x96, +0x03, 0x53, 0x6B, 0x88, 0xE8, 0x7E, 0x84, 0x80, 0x00, 0x48, 0xD2, 0x7E, 0x84, 0x80, 0x00, 0x48, +0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x05, 0x30, 0x03, 0xD0, 0xB3, 0x0D, 0xFF, 0x7E, 0x03, 0x9D, +0xFC, 0xAB, 0x83, 0x96, 0x03, 0x53, 0x6B, 0x88, 0xE8, 0x7E, 0x84, 0x80, 0x00, 0x48, 0xDA, 0xBE, +0x84, 0x80, 0x00, 0x48, 0x83, 0x52, 0x03, 0x53, 0xB4, 0x00, 0x34, 0x87, 0x33, 0x44, 0xB5, 0x40, +0x35, 0x48, 0x83, 0x96, 0x03, 0x53, 0xA0, 0x80, 0x6B, 0x88, 0x83, 0x52, 0x03, 0x53, 0xB6, 0x40, +0x36, 0x48, 0x83, 0x96, 0x03, 0x53, 0xA1, 0xC0, 0x0C, 0x30, 0x8A, 0x51, 0x16, 0xA6, 0x8A, 0x51, +0x83, 0x52, 0x03, 0x53, 0x98, 0x95, 0x98, 0x51, 0x26, 0xAC, 0x26, 0xAC, 0x01, 0xF0, 0x83, 0x52, +0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, 0x03, 0x53, 0xEB, 0x47, 0x02, 0xF0, 0x6B, 0x82, 0x03, 0x5C, +0x32, 0xAC, 0x33, 0xEC, 0xEC, 0x2A, 0xF9, 0x69, 0xF9, 0x69, 0xF9, 0x69, 0x8A, 0x51, 0x11, 0x28, +0x83, 0x52, 0x03, 0x53, 0x18, 0x12, 0x00, 0xB0, 0x13, 0xDB, 0x01, 0xF0, 0xAE, 0x40, 0x2E, 0x48, +0xB2, 0x00, 0x00, 0xB0, 0x18, 0x18, 0x01, 0xF0, 0xAE, 0x40, 0x2E, 0x48, 0xB0, 0xC0, 0x32, 0x58, +0x4A, 0xAC, 0x4E, 0xEC, 0x83, 0x52, 0x03, 0x53, 0x18, 0x14, 0x51, 0xAC, 0x83, 0x52, 0x03, 0x53, +0x18, 0xD0, 0x12, 0xC8, 0xAE, 0x40, 0x2E, 0x48, 0x83, 0x96, 0x03, 0x53, 0xA0, 0x80, 0x83, 0x52, +0x03, 0x53, 0x32, 0x08, 0xAF, 0x80, 0x2F, 0x88, 0x83, 0x96, 0x03, 0x53, 0xA1, 0xC0, 0x04, 0xF0, +0x8A, 0x51, 0x16, 0xA6, 0x8A, 0x51, 0x83, 0x52, 0x03, 0x53, 0x11, 0xC8, 0xAE, 0x40, 0x2E, 0x48, +0x83, 0x96, 0x03, 0x53, 0xA0, 0x80, 0x83, 0x52, 0x03, 0x53, 0x32, 0x08, 0xAF, 0x80, 0x2F, 0x88, +0x83, 0x96, 0x03, 0x53, 0xA1, 0xC0, 0x05, 0x30, 0x8A, 0x51, 0x16, 0xA6, 0x8A, 0x51, 0x83, 0x52, +0x03, 0x53, 0x10, 0x88, 0xAE, 0x40, 0x2E, 0x48, 0x83, 0x96, 0x03, 0x53, 0xA0, 0x80, 0x83, 0x52, +0x03, 0x53, 0x32, 0x08, 0xAF, 0x80, 0x2F, 0x88, 0x83, 0x96, 0x03, 0x53, 0xA1, 0xC0, 0x06, 0x30, +0x8A, 0x51, 0x16, 0xA6, 0x8A, 0x51, 0x07, 0x70, 0x83, 0x52, 0x03, 0x53, 0xAE, 0x40, 0x2E, 0x48, +0x83, 0x96, 0x03, 0x53, 0xA0, 0x80, 0x83, 0x52, 0x03, 0x53, 0x32, 0x08, 0xAF, 0x80, 0x2F, 0x88, +0x83, 0x96, 0x03, 0x53, 0xA1, 0xC0, 0x00, 0xB0, 0x8A, 0x51, 0x16, 0xA6, 0x8A, 0x51, 0x83, 0x52, +0x03, 0x53, 0x93, 0x1D, 0xA4, 0xAC, 0xA5, 0xEC, 0xB8, 0xEC, 0x1D, 0xB0, 0xAE, 0x40, 0x2E, 0x48, +0x83, 0x96, 0x03, 0x53, 0xA0, 0x80, 0x83, 0x52, 0x03, 0x53, 0x32, 0x08, 0xAF, 0x80, 0x2F, 0x88, +0x83, 0x96, 0x03, 0x53, 0xA1, 0xC0, 0x08, 0xF0, 0x8A, 0x51, 0x16, 0xA6, 0x8A, 0x51, 0xCC, 0xEC, +0x3B, 0xF0, 0x83, 0x52, 0x03, 0x53, 0xAE, 0x40, 0x2E, 0x48, 0x83, 0x96, 0x03, 0x53, 0xA0, 0x80, +0x83, 0x52, 0x03, 0x53, 0x32, 0x08, 0xAF, 0x80, 0x2F, 0x88, 0x83, 0x96, 0x03, 0x53, 0xA1, 0xC0, +0x08, 0xF0, 0x8A, 0x51, 0x16, 0xA6, 0x8A, 0x51, 0x0F, 0xB0, 0x83, 0x52, 0x03, 0x53, 0xAE, 0x40, +0x2E, 0x48, 0x83, 0x96, 0x03, 0x53, 0xA0, 0x80, 0x83, 0x52, 0x03, 0x53, 0x32, 0x08, 0xAF, 0x80, +0x2F, 0x88, 0x83, 0x96, 0x03, 0x53, 0xA1, 0xC0, 0x00, 0xB0, 0x8A, 0x51, 0x16, 0xA6, 0x8A, 0x51, +0x83, 0x52, 0x03, 0x53, 0x19, 0x52, 0x99, 0x92, 0x32, 0x08, 0x03, 0x9D, 0xE8, 0xEC, 0xEB, 0x6C, +0x19, 0x51, 0x99, 0xD5, 0xED, 0x6C, 0x19, 0x10, 0x99, 0x94, 0x93, 0x1D, 0xF0, 0xEC, 0xF4, 0x2C, +0x83, 0x52, 0x03, 0x53, 0x19, 0x96, 0xF7, 0xAC, 0x83, 0x52, 0x03, 0x53, 0x19, 0x52, 0x93, 0xD9, +0xFA, 0x6C, 0xFE, 0xAC, 0x83, 0x52, 0x03, 0x53, 0x99, 0xD6, 0x01, 0x6D, 0x83, 0x52, 0x03, 0x53, +0x99, 0x92, 0x02, 0x6D, 0x93, 0x1B, 0x05, 0xAD, 0x06, 0xAD, 0x02, 0x6D, 0x07, 0xED, 0x32, 0x08, +0x03, 0x9D, 0x0B, 0xED, 0x0E, 0xED, 0x99, 0x91, 0x19, 0x95, 0x11, 0xAD, 0x99, 0x50, 0x19, 0x54, +0x11, 0xAD, 0x03, 0x30, 0xAE, 0x40, 0x2E, 0x48, 0x83, 0x96, 0x03, 0x53, 0xA0, 0x80, 0x83, 0x52, +0x03, 0x53, 0x32, 0x08, 0xAF, 0x80, 0x2F, 0x88, 0x83, 0x96, 0x03, 0x53, 0xA1, 0xC0, 0x00, 0xB0, +0x8A, 0x51, 0x16, 0xA6, 0x8A, 0x51, 0x83, 0x52, 0x03, 0x53, 0xB1, 0x41, 0x2D, 0x2D, 0x31, 0x08, +0x01, 0xBE, 0xAE, 0x40, 0x2E, 0x48, 0xB1, 0x00, 0x2D, 0x2D, 0x64, 0x70, 0x31, 0x02, 0x03, 0x5C, +0x32, 0xED, 0x33, 0x2D, 0x27, 0x2D, 0x18, 0x56, 0x30, 0x18, 0x37, 0x6D, 0x3B, 0x6D, 0x83, 0x52, +0x03, 0x53, 0x18, 0x14, 0x3E, 0x6D, 0x83, 0x52, 0x03, 0x53, 0x18, 0xD0, 0x08, 0x40, 0x83, 0x52, +0x03, 0x53, 0x18, 0x12, 0x00, 0xB0, 0x13, 0xDB, 0x01, 0xF0, 0xA2, 0xC0, 0x22, 0xC8, 0xA6, 0x00, +0x00, 0xB0, 0x18, 0x18, 0x01, 0xF0, 0xA2, 0xC0, 0x22, 0xC8, 0xA4, 0xC0, 0x26, 0x58, 0x51, 0xED, +0x55, 0x2D, 0x83, 0x52, 0x03, 0x53, 0x18, 0x14, 0x58, 0xED, 0x83, 0x52, 0x03, 0x53, 0x18, 0xD0, +0x12, 0xC8, 0xA2, 0xC0, 0x22, 0xC8, 0xBF, 0xC0, 0x26, 0x08, 0xA3, 0x00, 0x23, 0x08, 0xC0, 0x80, +0x04, 0xF0, 0x8A, 0x51, 0x5D, 0x26, 0x8A, 0x51, 0x83, 0x52, 0x03, 0x53, 0x11, 0xC8, 0xA2, 0xC0, +0x22, 0xC8, 0xBF, 0xC0, 0x26, 0x08, 0xA3, 0x00, 0x23, 0x08, 0xC0, 0x80, 0x05, 0x30, 0x8A, 0x51, +0x5D, 0x26, 0x8A, 0x51, 0x83, 0x52, 0x03, 0x53, 0x10, 0x88, 0xA2, 0xC0, 0x22, 0xC8, 0xBF, 0xC0, +0x26, 0x08, 0xA3, 0x00, 0x23, 0x08, 0xC0, 0x80, 0x06, 0x30, 0x8A, 0x51, 0x5D, 0x26, 0x8A, 0x51, +0x07, 0x70, 0x83, 0x52, 0x03, 0x53, 0xA2, 0xC0, 0x22, 0xC8, 0xBF, 0xC0, 0x26, 0x08, 0xA3, 0x00, +0x23, 0x08, 0xC0, 0x80, 0x00, 0xB0, 0x8A, 0x51, 0x5D, 0x26, 0x8A, 0x51, 0x83, 0x52, 0x03, 0x53, +0x93, 0x1D, 0x93, 0x2D, 0x94, 0xED, 0xA1, 0xED, 0x1D, 0xB0, 0xA2, 0xC0, 0x22, 0xC8, 0xBF, 0xC0, +0x26, 0x08, 0xA3, 0x00, 0x23, 0x08, 0xC0, 0x80, 0x08, 0xF0, 0x8A, 0x51, 0x5D, 0x26, 0x8A, 0x51, +0xAF, 0xAD, 0x3B, 0xF0, 0x83, 0x52, 0x03, 0x53, 0xA2, 0xC0, 0x22, 0xC8, 0xBF, 0xC0, 0x26, 0x08, +0xA3, 0x00, 0x23, 0x08, 0xC0, 0x80, 0x08, 0xF0, 0x8A, 0x51, 0x5D, 0x26, 0x8A, 0x51, 0x0F, 0xB0, +0x83, 0x52, 0x03, 0x53, 0xA2, 0xC0, 0x22, 0xC8, 0xBF, 0xC0, 0x26, 0x08, 0xA3, 0x00, 0x23, 0x08, +0xC0, 0x80, 0x00, 0xB0, 0x8A, 0x51, 0x5D, 0x26, 0x8A, 0x51, 0x83, 0x52, 0x03, 0x53, 0x19, 0x52, +0x99, 0x92, 0x26, 0x08, 0x03, 0x9D, 0xC5, 0x2D, 0xC8, 0xED, 0x19, 0x51, 0x99, 0xD5, 0xCA, 0x2D, +0x19, 0x10, 0x99, 0x94, 0x93, 0x1D, 0xCD, 0x6D, 0xD1, 0x2D, 0x83, 0x52, 0x03, 0x53, 0x19, 0x96, +0xD4, 0x2D, 0x83, 0x52, 0x03, 0x53, 0x19, 0x52, 0x93, 0xD9, 0xD7, 0xAD, 0xDB, 0xAD, 0x83, 0x52, +0x03, 0x53, 0x99, 0xD6, 0xDE, 0xAD, 0x83, 0x52, 0x03, 0x53, 0x99, 0x92, 0xDF, 0xED, 0x93, 0x1B, +0xE2, 0x2D, 0xE3, 0x6D, 0xDF, 0xED, 0xE4, 0x2D, 0x26, 0x08, 0x03, 0x9D, 0xE8, 0x2D, 0xEB, 0xAD, +0x99, 0x91, 0x19, 0x95, 0xEE, 0xAD, 0x99, 0x50, 0x19, 0x54, 0xEE, 0xAD, 0x03, 0x30, 0xA2, 0xC0, +0x22, 0xC8, 0xBF, 0xC0, 0x26, 0x08, 0xA3, 0x00, 0x23, 0x08, 0xC0, 0x80, 0x00, 0xB0, 0x8A, 0x51, +0x5D, 0x26, 0x8A, 0x51, 0x83, 0x52, 0x03, 0x53, 0xA5, 0x41, 0x04, 0x6E, 0x25, 0x08, 0x01, 0xBE, +0xA2, 0xC0, 0x22, 0xC8, 0xA5, 0x00, 0x04, 0x6E, 0x64, 0x70, 0x25, 0x02, 0x03, 0x5C, 0x09, 0xAE, +0x0A, 0xAE, 0xFE, 0xED, 0x18, 0x56, 0x24, 0x18, 0x0E, 0xEE, 0x12, 0xAE, 0x83, 0x52, 0x03, 0x53, +0x18, 0x14, 0x15, 0xEE, 0x83, 0x52, 0x03, 0x53, 0x18, 0xD0, 0x08, 0x40, 0x83, 0x52, 0x03, 0x53, +0xAD, 0x40, 0x83, 0x96, 0x03, 0x53, 0x21, 0xC8, 0x03, 0x9D, 0x1F, 0x6E, 0x2B, 0x2E, 0x20, 0x88, +0x83, 0x52, 0x03, 0x53, 0xAC, 0x00, 0x2C, 0x08, 0x88, 0x80, 0x2D, 0x48, 0x80, 0x38, 0xAC, 0x00, +0x2C, 0x08, 0x86, 0xC0, 0x39, 0x2E, 0x83, 0x96, 0x03, 0x53, 0x20, 0x88, 0x83, 0x52, 0x03, 0x53, +0xAC, 0x00, 0x2C, 0x08, 0x88, 0x80, 0x2D, 0x48, 0x80, 0x38, 0xAC, 0x00, 0x2C, 0x08, 0x85, 0xC0, +0x39, 0x2E, 0x08, 0x40, 0x8A, 0x51, 0x92, 0xA6, 0x8A, 0x51, 0xB7, 0x80, 0x8A, 0x51, 0x93, 0xE6, +0x8A, 0x51, 0xB8, 0x00, 0x8A, 0x51, 0x94, 0xA6, 0x8A, 0x51, 0xB9, 0x40, 0x8A, 0x51, 0x95, 0xE6, +0x8A, 0x51, 0xBA, 0x40, 0x8A, 0x51, 0x96, 0xE6, 0x8A, 0x51, 0xBB, 0x80, 0x8A, 0x51, 0x97, 0x26, +0x8A, 0x51, 0xBC, 0x40, 0x8A, 0x51, 0x98, 0xA6, 0x8A, 0x51, 0xBD, 0x80, 0x8A, 0x51, 0x99, 0xE6, +0x8A, 0x51, 0xBE, 0x80, 0x83, 0x01, 0x8A, 0x51, 0x13, 0x68, 0x83, 0x52, 0x03, 0x53, 0xA1, 0xC0, +0x40, 0x88, 0x03, 0x9D, 0x64, 0xEE, 0x6E, 0x6E, 0x3F, 0xC8, 0xA0, 0x80, 0x20, 0x88, 0x88, 0x80, +0x21, 0xC8, 0x80, 0x38, 0xA0, 0x80, 0x20, 0x88, 0x86, 0xC0, 0x78, 0x2E, 0x3F, 0xC8, 0xA0, 0x80, +0x20, 0x88, 0x88, 0x80, 0x21, 0xC8, 0x80, 0x38, 0xA0, 0x80, 0x20, 0x88, 0x85, 0xC0, 0x78, 0x2E, +0x08, 0x40, 0x8B, 0xDC, 0x7C, 0x6E, 0x7D, 0xAE, 0x81, 0xAE, 0x8A, 0x51, 0x3F, 0x65, 0x8A, 0x51, +0x81, 0xAE, 0x10, 0xF0, 0x83, 0x52, 0x03, 0x53, 0xA7, 0x40, 0x27, 0x48, 0x8B, 0x00, 0x2B, 0x48, +0x81, 0x80, 0x2A, 0x08, 0x8A, 0xC0, 0x29, 0x08, 0x84, 0x80, 0x28, 0x4E, 0x83, 0xC0, 0x80, 0x0E, +0x00, 0xCE, 0x09, 0x80, 0x00, 0xF4, 0x01, 0x34, 0x02, 0x34, 0x03, 0x74, 0x04, 0x34, 0x05, 0x74, +0x06, 0x74, 0x07, 0xB4, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF +}; diff --git a/libloragw/src/arb_fw.var b/libloragw/src/arb_fw.var new file mode 100644 index 0000000..014a8e5 --- /dev/null +++ b/libloragw/src/arb_fw.var @@ -0,0 +1,526 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + ©2013 Semtech-Cycleo + +Description: + Arbiter firmware +*/ + +static uint8_t arb_firmware[MCU_ARB_FW_BYTE] = { +0x8A, 0x51, 0x0E, 0xEE, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0x64, 0xC0, 0x80, 0x81, +0x84, 0x0A, 0x04, 0xC6, 0x03, 0x59, 0x00, 0xF4, 0x04, 0xC6, 0x07, 0xEE, 0xDC, 0x81, 0x83, 0x93, +0x20, 0xF0, 0x84, 0x80, 0x57, 0xF0, 0x8A, 0x51, 0x06, 0x66, 0x8A, 0x51, 0xDD, 0xC1, 0xDE, 0xC1, +0xA0, 0x30, 0x84, 0x80, 0xA9, 0xB0, 0x8A, 0x51, 0x06, 0x66, 0x83, 0x01, 0x8A, 0x51, 0x44, 0xAE, +0x83, 0x52, 0xD7, 0x80, 0xDC, 0x90, 0x96, 0x00, 0x57, 0x88, 0x96, 0x00, 0x57, 0x88, 0x96, 0x00, +0x57, 0x88, 0x96, 0x00, 0x8D, 0xDC, 0x08, 0x40, 0x15, 0x54, 0xDC, 0xD4, 0x0D, 0xDD, 0x2E, 0x2E, +0x10, 0x88, 0x83, 0x96, 0xA6, 0x00, 0x83, 0x52, 0x11, 0xC8, 0x83, 0x96, 0xA7, 0x40, 0x83, 0x52, +0x0F, 0x48, 0x83, 0x96, 0xA8, 0xC0, 0x83, 0x52, 0x0E, 0x08, 0x83, 0x96, 0xA4, 0xC0, 0x83, 0x52, +0x12, 0xC8, 0xDD, 0x80, 0x15, 0x10, 0x08, 0x40, 0x8A, 0x51, 0x99, 0xE6, 0x8A, 0x51, 0x83, 0x52, +0x0D, 0x58, 0x61, 0xEE, 0x83, 0x96, 0xA5, 0x41, 0x08, 0xF0, 0x25, 0x02, 0x03, 0x18, 0x47, 0x2E, +0x83, 0x52, 0x5C, 0x94, 0x83, 0x96, 0x25, 0x08, 0x8A, 0x51, 0x20, 0x26, 0x8A, 0x51, 0xDC, 0x1C, +0x5C, 0x2E, 0x8A, 0x51, 0xF0, 0xE6, 0x8A, 0x51, 0x0D, 0x58, 0x47, 0x2E, 0x83, 0x96, 0xA5, 0x8A, +0x4C, 0xEE, 0x5C, 0xDC, 0x47, 0x2E, 0x8A, 0x51, 0x68, 0xA6, 0x8A, 0x51, 0x5C, 0x50, 0x47, 0x2E, +0xDE, 0xC1, 0x08, 0xF0, 0x5E, 0x82, 0x03, 0x18, 0x08, 0x40, 0x5E, 0x88, 0x28, 0xFE, 0x84, 0x80, +0x83, 0x93, 0x00, 0xCB, 0x97, 0x6E, 0x5E, 0x88, 0x28, 0xFE, 0x84, 0x80, 0x80, 0x81, 0x5E, 0x88, +0x40, 0xBE, 0x84, 0x80, 0x00, 0x48, 0x97, 0x40, 0x5E, 0x88, 0x20, 0xBE, 0x84, 0x80, 0x00, 0x48, +0x98, 0xC0, 0x5E, 0x88, 0x30, 0xFE, 0x84, 0x80, 0x00, 0x48, 0x99, 0x00, 0x5E, 0x88, 0x38, 0x3E, +0x84, 0x80, 0x00, 0x48, 0x9A, 0x00, 0x5E, 0x88, 0x9B, 0x40, 0x5E, 0x88, 0x48, 0xFE, 0x84, 0x80, +0x00, 0x48, 0x9C, 0x00, 0x95, 0x94, 0x95, 0x94, 0x95, 0x94, 0x95, 0x94, 0x95, 0x50, 0xDE, 0x0A, +0x69, 0x2E, 0x95, 0x41, 0x96, 0x41, 0x97, 0x81, 0x98, 0x01, 0x99, 0x41, 0x9A, 0x41, 0x9B, 0x81, +0x9C, 0x41, 0x9E, 0x81, 0xDE, 0xC1, 0x08, 0xF0, 0x5E, 0x82, 0x03, 0x18, 0xC1, 0xEE, 0x5E, 0x88, +0x30, 0xFE, 0x84, 0x80, 0x80, 0x81, 0x5E, 0x88, 0x38, 0x3E, 0x84, 0x80, 0x80, 0x81, 0x5E, 0x88, +0x48, 0xFE, 0x84, 0x80, 0x80, 0x81, 0x5E, 0x88, 0x20, 0xBE, 0x84, 0x80, 0x80, 0x81, 0x5E, 0x88, +0x40, 0xBE, 0x84, 0x80, 0x80, 0x81, 0x5E, 0x88, 0x28, 0xFE, 0x84, 0x80, 0x80, 0x81, 0xDE, 0x0A, +0xA3, 0x2E, 0x83, 0x96, 0xA5, 0x41, 0x83, 0x52, 0x5C, 0x50, 0xDC, 0x90, 0x5C, 0x91, 0x83, 0x96, +0xA8, 0x01, 0xA0, 0xC1, 0xA1, 0x01, 0xA2, 0x01, 0xA3, 0x41, 0x83, 0x52, 0x97, 0x81, 0x98, 0x01, +0x99, 0x41, 0x9A, 0x41, 0x9B, 0x81, 0x9C, 0x41, 0x83, 0x96, 0xA6, 0x41, 0xA7, 0x81, 0xA8, 0x01, +0xA4, 0x01, 0x83, 0x52, 0xDD, 0xC1, 0xDE, 0xC1, 0x83, 0x96, 0xA5, 0x41, 0x83, 0x52, 0x02, 0xF0, +0x5C, 0x50, 0xDC, 0x90, 0x5C, 0x91, 0xD0, 0xC0, 0x03, 0x30, 0xD1, 0x00, 0xD2, 0x00, 0x04, 0xF0, +0xD3, 0x40, 0x05, 0x30, 0xD4, 0x00, 0x06, 0x30, 0xD5, 0x40, 0x07, 0x70, 0xD6, 0x40, 0x08, 0x40, +0x5C, 0x91, 0xDE, 0xC1, 0x08, 0xF0, 0x5E, 0x82, 0x03, 0x18, 0xA2, 0x2F, 0x0A, 0x30, 0x83, 0x96, +0x28, 0xC2, 0x83, 0x52, 0x03, 0x5C, 0x5C, 0xD5, 0x83, 0x96, 0x27, 0x48, 0xA1, 0xC0, 0xA0, 0xC1, +0x26, 0x08, 0xA0, 0x47, 0x03, 0x18, 0xA1, 0x4A, 0x83, 0x52, 0x5E, 0x88, 0x30, 0xFE, 0x84, 0x80, +0x83, 0x93, 0x00, 0x48, 0xD9, 0x40, 0x5E, 0x88, 0x38, 0x3E, 0x84, 0x80, 0x00, 0x48, 0x83, 0x96, +0xA3, 0x00, 0x83, 0x52, 0x59, 0x48, 0x83, 0x96, 0xA2, 0xC0, 0x01, 0xF0, 0x83, 0x52, 0xD9, 0x40, +0x5E, 0xCA, 0x1C, 0x2F, 0x03, 0xD0, 0xD9, 0x0D, 0xFF, 0x7E, 0x03, 0x9D, 0x1A, 0x2F, 0x59, 0x48, +0x13, 0x45, 0x03, 0x9D, 0x28, 0xEF, 0x5E, 0x88, 0x28, 0xFE, 0x84, 0x80, 0x00, 0xCB, 0x9C, 0x6F, +0x5E, 0x88, 0x40, 0xBE, 0x84, 0x80, 0x00, 0x48, 0x5D, 0xC6, 0x03, 0x9D, 0x9C, 0x6F, 0x5E, 0x88, +0x20, 0xBE, 0x84, 0x80, 0x00, 0x48, 0x83, 0x96, 0x24, 0x06, 0x03, 0x9D, 0x3B, 0xAF, 0x83, 0x52, +0x03, 0x53, 0x5C, 0xD5, 0x9C, 0x6F, 0x83, 0x52, 0x5D, 0x88, 0x4A, 0x3E, 0x84, 0x80, 0x00, 0x48, +0x83, 0x96, 0x22, 0x47, 0x83, 0x52, 0xD9, 0x40, 0x83, 0x96, 0x23, 0x08, 0x03, 0x18, 0x23, 0x4A, +0x83, 0x52, 0xDA, 0x40, 0x80, 0x7A, 0xDB, 0x80, 0x83, 0x96, 0x21, 0xC8, 0x80, 0x7A, 0x83, 0x52, +0x5B, 0x82, 0x03, 0x9D, 0x57, 0xAF, 0x83, 0x96, 0x20, 0x88, 0x83, 0x52, 0x59, 0x42, 0x03, 0x5C, +0x9C, 0x6F, 0x83, 0x52, 0x03, 0x53, 0x5D, 0x88, 0x4A, 0x3E, 0x84, 0x80, 0x83, 0x96, 0x23, 0x08, +0x83, 0x52, 0xDA, 0x40, 0x83, 0x93, 0x00, 0x48, 0x83, 0x96, 0x22, 0xC2, 0x83, 0x52, 0xD9, 0x40, +0x03, 0x5C, 0xDA, 0xC3, 0x83, 0x96, 0x21, 0xC8, 0x80, 0x7A, 0x83, 0x52, 0xDB, 0x80, 0x5A, 0x48, +0x80, 0x7A, 0x5B, 0x82, 0x03, 0x9D, 0x77, 0xEF, 0x59, 0x48, 0x83, 0x96, 0x20, 0x82, 0x03, 0x5C, +0x9C, 0x6F, 0x83, 0x52, 0x03, 0x53, 0x5E, 0x88, 0x48, 0xFE, 0x84, 0x80, 0x83, 0x93, 0x00, 0x48, +0x02, 0xBE, 0xD9, 0x40, 0x00, 0xB0, 0x03, 0x18, 0x01, 0xF0, 0xDA, 0x40, 0x80, 0x7A, 0xDB, 0x80, +0x80, 0xF0, 0x5B, 0x82, 0x03, 0x9D, 0x90, 0xEF, 0x83, 0x96, 0x28, 0xC8, 0x83, 0x52, 0x59, 0x42, +0x03, 0x18, 0x37, 0xAF, 0x83, 0x52, 0x03, 0x53, 0x5E, 0x88, 0x28, 0xFE, 0x84, 0x80, 0x83, 0x93, +0x80, 0x81, 0x5E, 0x88, 0xE8, 0x27, 0x8A, 0x51, 0x83, 0x52, 0x03, 0x53, 0x5C, 0xD9, 0xA2, 0x2F, +0xDE, 0x0A, 0xF2, 0x6E, 0x5C, 0xD9, 0x08, 0x40, 0xDE, 0xC1, 0x08, 0xF0, 0x5E, 0x82, 0x03, 0x18, +0x08, 0x40, 0x01, 0xF0, 0xD9, 0x40, 0x5E, 0xCA, 0xAF, 0xEF, 0x03, 0xD0, 0xD9, 0x0D, 0xFF, 0x7E, +0x03, 0x9D, 0xAD, 0xAF, 0x59, 0x48, 0x13, 0x45, 0x03, 0x9D, 0xE6, 0xAF, 0x5E, 0x88, 0x28, 0xFE, +0x84, 0x80, 0x83, 0x93, 0x80, 0x88, 0x03, 0x9D, 0xE6, 0xAF, 0x5E, 0x88, 0x30, 0xFE, 0x84, 0x80, +0x83, 0x96, 0x26, 0x08, 0x80, 0x40, 0x83, 0x52, 0x5E, 0x88, 0x38, 0x3E, 0x84, 0x80, 0x83, 0x96, +0x27, 0x48, 0x80, 0x40, 0x83, 0x52, 0x5E, 0x88, 0x48, 0xFE, 0x84, 0x80, 0x83, 0x96, 0x28, 0xC8, +0x80, 0x40, 0x83, 0x52, 0x5E, 0x88, 0x20, 0xBE, 0x84, 0x80, 0x83, 0x96, 0x24, 0xC8, 0x80, 0x40, +0x83, 0x52, 0x5E, 0x88, 0x40, 0xBE, 0x84, 0x80, 0x5D, 0x88, 0x80, 0x40, 0x5E, 0x88, 0x28, 0xFE, +0x84, 0x80, 0x80, 0x81, 0x80, 0xCA, 0x9E, 0xCA, 0x5C, 0xD5, 0x08, 0x40, 0xDE, 0x0A, 0xA5, 0x6F, +0xD8, 0x00, 0x9B, 0x40, 0x15, 0x95, 0x15, 0x95, 0x15, 0x95, 0x15, 0x95, 0x15, 0x95, 0x15, 0x95, +0x15, 0x95, 0x15, 0x51, 0x01, 0xF0, 0xD7, 0x80, 0x58, 0x4A, 0xF8, 0xAF, 0x03, 0xD0, 0xD7, 0x4D, +0xFF, 0x7E, 0x03, 0x9D, 0xF6, 0xEF, 0x57, 0x88, 0x13, 0x45, 0x03, 0x59, 0x08, 0x40, 0xF2, 0xAF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, +0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF +}; diff --git a/libloragw/src/loragw_aux.c b/libloragw/src/loragw_aux.c new file mode 100644 index 0000000..1c7e354 --- /dev/null +++ b/libloragw/src/loragw_aux.c @@ -0,0 +1,51 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + ©2013 Semtech-Cycleo + +Description: + Lora gateway auxiliary functions +*/ + + +/* -------------------------------------------------------------------------- */ +/* --- DEPENDANCIES --------------------------------------------------------- */ + +#include /* printf fprintf */ +#include /* clock_nanosleep */ + +/* -------------------------------------------------------------------------- */ +/* --- PRIVATE MACROS ------------------------------------------------------- */ + +#if DEBUG_AUX == 1 + #define DEBUG_MSG(str) fprintf(stderr, str) + #define DEBUG_PRINTF(fmt, args...) fprintf(stderr,"%s:%d: "fmt, __FUNCTION__, __LINE__, args) +#else + #define DEBUG_MSG(str) + #define DEBUG_PRINTF(fmt, args...) +#endif + +/* -------------------------------------------------------------------------- */ +/* --- PUBLIC FUNCTIONS DEFINITION ------------------------------------------ */ + +/* This implementation is POSIX-pecific and require a fix to be compatible with C99 */ +void wait_ms(unsigned long a) { + struct timespec dly; + struct timespec rem; + + dly.tv_sec = a / 1000; + dly.tv_nsec = ((long)a % 1000) * 1000000; + + DEBUG_PRINTF("NOTE dly: %ld sec %ld ns\n", dly.tv_sec, dly.tv_nsec); + + if((dly.tv_sec > 0) || ((dly.tv_sec == 0) && (dly.tv_nsec > 100000))) { + clock_nanosleep(CLOCK_MONOTONIC, 0, &dly, &rem); + DEBUG_PRINTF("NOTE remain: %ld sec %ld ns\n", rem.tv_sec, rem.tv_nsec); + } + return; +} + +/* --- EOF ------------------------------------------------------------------ */ diff --git a/libloragw/src/loragw_hal.c b/libloragw/src/loragw_hal.c new file mode 100644 index 0000000..a57d9f1 --- /dev/null +++ b/libloragw/src/loragw_hal.c @@ -0,0 +1,1139 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + ©2013 Semtech-Cycleo + +Description: + Lora gateway Hardware Abstraction Layer +*/ + + +/* -------------------------------------------------------------------------- */ +/* --- DEPENDANCIES --------------------------------------------------------- */ + +#include /* C99 types */ +#include /* bool type */ +#include /* printf fprintf */ +#include /* NaN */ +#include /* memcpy */ + +#include "loragw_reg.h" +#include "loragw_hal.h" +#include "loragw_aux.h" + +/* -------------------------------------------------------------------------- */ +/* --- PRIVATE MACROS ------------------------------------------------------- */ + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) +#if DEBUG_HAL == 1 + #define DEBUG_MSG(str) fprintf(stderr, str) + #define DEBUG_PRINTF(fmt, args...) fprintf(stderr,"%s:%d: "fmt, __FUNCTION__, __LINE__, args) + #define DEBUG_ARRAY(a,b,c) for(a=0;a 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; /* 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 ---------------------------------------- */ + +int load_firmware(uint8_t target, uint8_t *firmware, uint16_t size); + +void sx125x_write(uint8_t rf_chain, uint8_t addr, uint8_t data); + +uint8_t sx125x_read(uint8_t rf_chain, uint8_t addr); + +int setup_sx1257(uint8_t rf_chain, uint32_t freq_hz); + +void lgw_constant_adjust(void); + +/* -------------------------------------------------------------------------- */ +/* --- PRIVATE FUNCTIONS DEFINITION ----------------------------------------- */ + +/* size is the firmware size in bytes (not 14b words) */ +int load_firmware(uint8_t target, uint8_t *firmware, uint16_t size) { + int32_t read_value; + int reg_rst; + int reg_sel; + + /* check parameters */ + CHECK_NULL(firmware); + if (target == MCU_ARB) { + if (size != MCU_ARB_FW_BYTE) { + DEBUG_MSG("ERROR: NOT A VALID SIZE FOR MCU ARG FIRMWARE\n"); + return -1; + } + reg_rst = LGW_MCU_RST_0; + reg_sel = LGW_MCU_SELECT_MUX_0; + }else if (target == MCU_AGC) { + if (size != MCU_AGC_FW_BYTE) { + DEBUG_MSG("ERROR: NOT A VALID SIZE FOR MCU AGC FIRMWARE\n"); + return -1; + } + reg_rst = LGW_MCU_RST_1; + reg_sel = LGW_MCU_SELECT_MUX_1; + } else { + DEBUG_MSG("ERROR: NOT A VALID TARGET FOR LOADING FIRMWARE\n"); + return -1; + } + + /* reset the targeted MCU */ + lgw_reg_w(reg_rst, 1); + + /* set mux to access MCU program RAM and set address to 0 */ + lgw_reg_w(reg_sel, 0); + lgw_reg_w(LGW_MCU_PROM_ADDR, 0); + + /* write the program in one burst */ + lgw_reg_wb(LGW_MCU_PROM_DATA, firmware, size); + + /* give back control of the MCU program ram to the MCU */ + lgw_reg_w(reg_sel, 1); + + return 0; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +void sx125x_write(uint8_t channel, uint8_t addr, uint8_t data) { + int reg_add, reg_dat, reg_cs; + + /* checking input parameters */ + if (channel >= LGW_RF_CHAIN_NB) { + DEBUG_MSG("ERROR: INVALID RF_CHAIN\n"); + return; + } + if (addr >= 0x7F) { + DEBUG_MSG("ERROR: ADDRESS OUT OF RANGE\n"); + return; + } + + /* selecting the target radio */ + switch (channel) { + case 0: + reg_add = LGW_SPI_RADIO_A__ADDR; + reg_dat = LGW_SPI_RADIO_A__DATA; + reg_cs = LGW_SPI_RADIO_A__CS; + break; + + case 1: + reg_add = LGW_SPI_RADIO_B__ADDR; + reg_dat = LGW_SPI_RADIO_B__DATA; + reg_cs = LGW_SPI_RADIO_B__CS; + break; + + default: + DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", channel); + return; + } + + /* SPI master data write procedure */ + lgw_reg_w(reg_cs, 0); + lgw_reg_w(reg_add, 0x80 | addr); /* MSB at 1 for write operation */ + lgw_reg_w(reg_dat, data); + lgw_reg_w(reg_cs, 1); + lgw_reg_w(reg_cs, 0); + + return; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +uint8_t sx125x_read(uint8_t channel, uint8_t addr) { + int reg_add, reg_dat, reg_cs, reg_rb; + int32_t read_value; + + /* checking input parameters */ + if (channel >= LGW_RF_CHAIN_NB) { + DEBUG_MSG("ERROR: INVALID RF_CHAIN\n"); + return 0; + } + if (addr >= 0x7F) { + DEBUG_MSG("ERROR: ADDRESS OUT OF RANGE\n"); + return 0; + } + + /* selecting the target radio */ + switch (channel) { + case 0: + reg_add = LGW_SPI_RADIO_A__ADDR; + reg_dat = LGW_SPI_RADIO_A__DATA; + reg_cs = LGW_SPI_RADIO_A__CS; + reg_rb = LGW_SPI_RADIO_A__DATA_READBACK; + break; + + case 1: + reg_add = LGW_SPI_RADIO_B__ADDR; + reg_dat = LGW_SPI_RADIO_B__DATA; + reg_cs = LGW_SPI_RADIO_B__CS; + reg_rb = LGW_SPI_RADIO_B__DATA_READBACK; + break; + + default: + DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", channel); + return 0; + } + + /* SPI master data read procedure */ + lgw_reg_w(reg_cs, 0); + lgw_reg_w(reg_add, addr); /* MSB at 0 for read operation */ + lgw_reg_w(reg_dat, 0); + lgw_reg_w(reg_cs, 1); + lgw_reg_w(reg_cs, 0); + lgw_reg_r(reg_rb, &read_value); + + return (uint8_t)read_value; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +int setup_sx1257(uint8_t rf_chain, uint32_t freq_hz) { + uint32_t part_int; + uint32_t part_frac; + int cpt_attempts = 0; + + if (rf_chain >= LGW_RF_CHAIN_NB) { + DEBUG_MSG("ERROR: INVALID RF_CHAIN\n"); + return -1; + } + + /* misc */ + sx125x_write(rf_chain, 0x10, SX1257_TX_DAC_CLK_SEL + SX1257_CLK_OUT*2); + + /* Tx gain and trim */ + sx125x_write(rf_chain, 0x08, SX1257_TX_MIX_GAIN + SX1257_TX_DAC_GAIN*16); + sx125x_write(rf_chain, 0x0A, SX1257_TX_ANA_BW + SX1257_TX_PLL_BW*32); + sx125x_write(rf_chain, 0x0B, SX1257_TX_DAC_BW); + + /* Rx gain and trim */ + sx125x_write(rf_chain, 0x0C, 0 + SX1257_RX_BB_GAIN*2 + SX1257_RX_LNA_GAIN*32); + 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 / 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 */ + + /* start and PLL lock */ + do { + if (cpt_attempts >= PLL_LOCK_MAX_ATTEMPTS) { + DEBUG_MSG("ERROR: FAIL TO LOCK PLL\n"); + return -1; + } + sx125x_write(rf_chain, 0x00, 1); /* enable Xtal oscillator */ + sx125x_write(rf_chain, 0x00, 3); /* Enable RX (PLL+FE) */ + ++cpt_attempts; + DEBUG_PRINTF("Note: SX1257 #%d PLL start (attempt %d)\n", rf_chain, cpt_attempts); + wait_ms(1); + } while(sx125x_read(rf_chain, 0x11) & 0x02 == 0); + + return 0; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +void lgw_constant_adjust(void) { + + /* I/Q path setup */ + // lgw_reg_w(LGW_RX_INVERT_IQ,0); /* default 0 */ + // lgw_reg_w(LGW_MODEM_INVERT_IQ,1); /* default 1 */ + // lgw_reg_w(LGW_CHIRP_INVERT_RX,1); /* default 1 */ + // lgw_reg_w(LGW_RX_EDGE_SELECT,0); /* default 0 */ + // lgw_reg_w(LGW_MBWSSF_MODEM_INVERT_IQ,0); /* default 0 */ + // lgw_reg_w(LGW_DC_NOTCH_EN,1); /* default 1 */ + lgw_reg_w(LGW_RSSI_BB_FILTER_ALPHA,9); /* default 7 */ + lgw_reg_w(LGW_RSSI_DEC_FILTER_ALPHA,7); /* default 5 */ + lgw_reg_w(LGW_RSSI_CHANN_FILTER_ALPHA,7); /* default 8 */ + // lgw_reg_w(LGW_RSSI_BB_DEFAULT_VALUE,32); /* default 32 */ + lgw_reg_w(LGW_RSSI_CHANN_DEFAULT_VALUE,90); /* default 100 */ + lgw_reg_w(LGW_RSSI_DEC_DEFAULT_VALUE,90); /* default 100 */ + // lgw_reg_w(LGW_DEC_GAIN_OFFSET, 8); /* default 8 */ + // lgw_reg_w(LGW_CHAN_GAIN_OFFSET, 7); /* default 7 */ + + /* Correlator setup */ + // lgw_reg_w(LGW_CORR_DETECT_EN,126); /* default 126 */ + // lgw_reg_w(LGW_CORR_NUM_SAME_PEAK,4); /* default 4 */ + // lgw_reg_w(LGW_CORR_MAC_GAIN,5); /* default 5 */ + // lgw_reg_w(LGW_CORR_SAME_PEAKS_OPTION_SF6,0); /* default 0 */ + // lgw_reg_w(LGW_CORR_SAME_PEAKS_OPTION_SF7,1); /* default 1 */ + // lgw_reg_w(LGW_CORR_SAME_PEAKS_OPTION_SF8,1); /* default 1 */ + // lgw_reg_w(LGW_CORR_SAME_PEAKS_OPTION_SF9,1); /* default 1 */ + // lgw_reg_w(LGW_CORR_SAME_PEAKS_OPTION_SF10,1); /* default 1 */ + // lgw_reg_w(LGW_CORR_SAME_PEAKS_OPTION_SF11,1); /* default 1 */ + // lgw_reg_w(LGW_CORR_SAME_PEAKS_OPTION_SF12,1); /* default 1 */ + // lgw_reg_w(LGW_CORR_SIG_NOISE_RATIO_SF6,4); /* default 4 */ + // lgw_reg_w(LGW_CORR_SIG_NOISE_RATIO_SF7,4); /* default 4 */ + // lgw_reg_w(LGW_CORR_SIG_NOISE_RATIO_SF8,4); /* default 4 */ + // lgw_reg_w(LGW_CORR_SIG_NOISE_RATIO_SF9,4); /* default 4 */ + // lgw_reg_w(LGW_CORR_SIG_NOISE_RATIO_SF10,4); /* default 4 */ + // 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' 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 */ + // lgw_reg_w(LGW_FRAME_SYNCH_GAIN,1); /* default 1 */ + // lgw_reg_w(LGW_SYNCH_DETECT_TH,1); /* default 1 */ + // lgw_reg_w(LGW_ZERO_PAD,0); /* default 0 */ + lgw_reg_w(LGW_SNR_AVG_CST,3); /* default 2 */ + // lgw_reg_w(LGW_FRAME_SYNCH_PEAK1_POS,1); /* default 1 */ + // lgw_reg_w(LGW_FRAME_SYNCH_PEAK2_POS,2); /* default 2 */ + // lgw_reg_w(LGW_PREAMBLE_FINE_TIMING_GAIN,1); /* default 1 */ + // lgw_reg_w(LGW_ONLY_CRC_EN,1); /* default 1 */ + // lgw_reg_w(LGW_PAYLOAD_FINE_TIMING_GAIN,2); /* default 2 */ + // lgw_reg_w(LGW_TRACKING_INTEGRAL,0); /* default 0 */ + // lgw_reg_w(LGW_ADJUST_MODEM_START_OFFSET_RDX8,0); /* default 0 */ + // lgw_reg_w(LGW_ADJUST_MODEM_START_OFFSET_SF12_RDX4,4092); /* default 4092 */ + // lgw_reg_w(LGW_MAX_PAYLOAD_LEN,255); /* default 255 */ + + /* 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 */ + // lgw_reg_w(LGW_MBWSSF_FREQ_TO_TIME_INVERT,29); /* default 29 */ + // lgw_reg_w(LGW_MBWSSF_FRAME_SYNCH_GAIN,1); /* default 1 */ + // lgw_reg_w(LGW_MBWSSF_SYNCH_DETECT_TH,1); /* default 1 */ + // lgw_reg_w(LGW_MBWSSF_ZERO_PAD,0); /* default 0 */ + // lgw_reg_w(LGW_MBWSSF_FRAME_SYNCH_PEAK1_POS,1); /* default 1 */ + // lgw_reg_w(LGW_MBWSSF_FRAME_SYNCH_PEAK2_POS,2); /* default 2 */ + // lgw_reg_w(LGW_MBWSSF_ONLY_CRC_EN,1); /* default 1 */ + // lgw_reg_w(LGW_MBWSSF_PAYLOAD_FINE_TIMING_GAIN,2); /* default 2 */ + // lgw_reg_w(LGW_MBWSSF_PREAMBLE_FINE_TIMING_GAIN,1); /* default 1 */ + // lgw_reg_w(LGW_MBWSSF_TRACKING_INTEGRAL,0); /* default 0 */ + // lgw_reg_w(LGW_MBWSSF_AGC_FREEZE_ON_DETECT,1); /* default 1 */ + + /* 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 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_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_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_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 */ + + /* TX general parameters */ + lgw_reg_w(LGW_TX_START_DELAY,1000); /* default 0 */ + + /* TX Lora */ + // lgw_reg_w(LGW_TX_MODE,0); /* 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; +} + +/* -------------------------------------------------------------------------- */ +/* --- PUBLIC FUNCTIONS DEFINITION ------------------------------------------ */ + +int lgw_rxrf_setconf(uint8_t rf_chain, struct lgw_conf_rxrf_s conf) { + + /* check if the gateway is running */ + if (lgw_is_started == true) { + DEBUG_MSG("ERROR: GATEWAY IS RUNNING, STOP IT BEFORE TOUCHING CONFIGURATION\n"); + return LGW_HAL_ERROR; + } + + /* check input parameters */ + if (rf_chain > LGW_RF_CHAIN_NB) { + DEBUG_MSG("ERROR: NOT A VALID RF_CHAIN NUMBER\n"); + return LGW_HAL_ERROR; + } + if (conf.freq_hz > rf_rx_upfreq[rf_chain]) { + DEBUG_MSG("ERROR: FREQUENCY TOO HIGH FOR THAT RF_CHAIN\n"); + return LGW_HAL_ERROR; + } else if (conf.freq_hz < rf_rx_lowfreq[rf_chain]) { + DEBUG_MSG("ERROR: FREQUENCY TOO LOW FOR THAT RF_CHAIN\n"); + return LGW_HAL_ERROR; + } + + /* set internal config according to parameters */ + rf_enable[rf_chain] = conf.enable; + rf_rx_freq[rf_chain] = conf.freq_hz; + + return LGW_HAL_SUCCESS; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +int lgw_rxif_setconf(uint8_t if_chain, struct lgw_conf_rxif_s conf) { + /* check if the gateway is running */ + if (lgw_is_started == true) { + DEBUG_MSG("ERROR: GATEWAY IS RUNNING, STOP IT BEFORE TOUCHING CONFIGURATION\n"); + return LGW_HAL_ERROR; + } + + /* if chain is disabled, don't care about most parameters */ + if (conf.enable == false) { + if_enable[if_chain] = false; + if_freq[if_chain] = 0; + DEBUG_PRINTF("Note: if_chain %d disabled\n", if_chain); + return LGW_HAL_SUCCESS; + } + + /* check 'general' parameters */ + if (if_chain > LGW_IF_CHAIN_NB) { + DEBUG_PRINTF("ERROR: %d NOT A VALID IF_CHAIN NUMBER\n", if_chain); + return LGW_HAL_ERROR; + } + if (ifmod_config[if_chain] == IF_UNDEFINED) { + DEBUG_PRINTF("ERROR: IF CHAIN %d NOT CONFIGURABLE\n", if_chain); + } + if (conf.rf_chain >= LGW_RF_CHAIN_NB) { + DEBUG_MSG("ERROR: INVALID RF_CHAIN TO ASSOCIATE WITH A LORA_STD IF CHAIN\n"); + return LGW_HAL_ERROR; + } + if ((conf.freq_hz + LGW_REF_BW/2) > ((int32_t)rf_rx_bandwidth[conf.rf_chain] / 2)) { + DEBUG_PRINTF("ERROR: IF FREQUENCY %d TOO HIGH\n", conf.freq_hz); + return LGW_HAL_ERROR; + } else if ((conf.freq_hz - LGW_REF_BW/2) < -((int32_t)rf_rx_bandwidth[conf.rf_chain] / 2)) { + DEBUG_PRINTF("ERROR: IF FREQUENCY %d TOO LOW\n", conf.freq_hz); + return LGW_HAL_ERROR; + } + /* WARNING: if the channel is 250 or 500kHz wide, that check is insufficient */ + + /* check parameters according to the type of IF chain + modem, + fill default if necessary, and commit configuration if everything is OK */ + switch (ifmod_config[if_chain]) { + case IF_LORA_STD: + /* fill default parameters if needed */ + if (conf.bandwidth == BW_UNDEFINED) { + conf.bandwidth = BW_250KHZ; + } + if (conf.datarate == DR_UNDEFINED) { + conf.datarate = DR_LORA_SF9; + } + /* check BW & DR */ + if (!IS_LORA_BW(conf.bandwidth)) { + DEBUG_MSG("ERROR: BANDWIDTH NOT SUPPORTED BY LORA_STD IF CHAIN\n"); + return LGW_HAL_ERROR; + } + if (!IS_LORA_STD_DR(conf.datarate)) { + DEBUG_MSG("ERROR: DATARATE NOT SUPPORTED BY LORA_STD 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; + lora_rx_bw = conf.bandwidth; + 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 { + lora_rx_ppm_offset = 0; + } + + DEBUG_PRINTF("Note: Lora 'std' if_chain %d configured; en:%d freq:%d bw:%d dr:%d\n", if_chain, if_enable[if_chain], if_freq[if_chain], lora_rx_bw, lora_rx_sf); + break; + + case IF_LORA_MULTI: + /* fill default parameters if needed */ + 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) { + DEBUG_MSG("ERROR: BANDWIDTH NOT SUPPORTED BY LORA_MULTI IF CHAIN\n"); + return LGW_HAL_ERROR; + } + if (!IS_LORA_MULTI_DR(conf.datarate)) { + DEBUG_MSG("ERROR: DATARATE(S) NOT SUPPORTED BY LORA_MULTI 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; + 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]); + break; + + 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); + return LGW_HAL_ERROR; + } + + return LGW_HAL_SUCCESS; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +int lgw_start(void) { + int i, j; + int reg_stat; + int32_t read_value; + + if (lgw_is_started == true) { + DEBUG_MSG("Note: Lora Gateway already started, restarting it now\n"); + } + + reg_stat = lgw_connect(); + if (reg_stat == LGW_REG_ERROR) { + DEBUG_MSG("ERROR: FAIL TO CONNECT BOARD\n"); + return LGW_HAL_ERROR; + } + + /* reset the registers (also shuts the radios down) */ + lgw_soft_reset(); + + /* Ungate clocks (gated by default) */ + lgw_reg_w(LGW_GLOBAL_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 */ + lgw_reg_w(LGW_RADIO_B_EN,1); /* radio B *must* be started because they share the same XTAL I/O is clamped to ground when off */ + wait_ms(500); + lgw_reg_w(LGW_RADIO_RST,1); + wait_ms(5); + lgw_reg_w(LGW_RADIO_RST,0); + + /* setup the radios */ + if (rf_enable[0] == 1) { + setup_sx1257(0, rf_rx_freq[0]); + } + if (rf_enable[1] == 1) { + setup_sx1257(1, rf_rx_freq[1]); + } + + /* gives the AGC MCU control over radio, RF front-end and filter gain */ + lgw_reg_w(LGW_FORCE_HOST_RADIO_CTRL,0); + lgw_reg_w(LGW_FORCE_HOST_FE_CTRL,0); + lgw_reg_w(LGW_FORCE_DEC_FILTER_GAIN,0); + + /* TODO load the calibration firmware and wait for calibration to end */ + + /* in the absence of calibration firmware, do a "manual" calibration */ + lgw_reg_w(LGW_TX_OFFSET_I,10); + lgw_reg_w(LGW_TX_OFFSET_Q,5); + lgw_reg_w(LGW_IQ_MISMATCH_A_AMP_COEFF,63); + lgw_reg_w(LGW_IQ_MISMATCH_A_PHI_COEFF,9); + lgw_reg_w(LGW_IQ_MISMATCH_B_AMP_COEFF,0); + lgw_reg_w(LGW_IQ_MISMATCH_B_PHI_COEFF,0); + + /* load adjusted parameters */ + lgw_constant_adjust(); + + /* 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 */ + lgw_reg_w(LGW_IF_FREQ_2, IF_HZ_TO_REG(if_freq[2])); /* default 128 */ + lgw_reg_w(LGW_IF_FREQ_3, IF_HZ_TO_REG(if_freq[3])); /* default 384 */ + + lgw_reg_w(LGW_CORR0_DETECT_EN, (if_enable[0] == true) ? lora_multi_sfmask[0] : 0); /* default 0 */ + lgw_reg_w(LGW_CORR1_DETECT_EN, (if_enable[1] == true) ? lora_multi_sfmask[1] : 0); /* default 0 */ + lgw_reg_w(LGW_CORR2_DETECT_EN, (if_enable[2] == true) ? lora_multi_sfmask[2] : 0); /* default 0 */ + lgw_reg_w(LGW_CORR3_DETECT_EN, (if_enable[3] == true) ? lora_multi_sfmask[3] : 0); /* default 0 */ + + lgw_reg_w(LGW_PPM_OFFSET, 0x60); /* as the threshold is 16ms, use 0x60 to enable ppm_offset for SF12 and SF11 @125kHz*/ + + lgw_reg_w(LGW_CONCENTRATOR_MODEM_ENABLE,1); /* default 0 */ + + /* 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; + case BW_500KHZ: lgw_reg_w(LGW_MBWSSF_MODEM_BW,2); break; + default: DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", lora_rx_bw); return LGW_HAL_ERROR; + } + switch(lora_rx_sf) { + case DR_LORA_SF7: lgw_reg_w(LGW_MBWSSF_RATE_SF,7); break; + case DR_LORA_SF8: lgw_reg_w(LGW_MBWSSF_RATE_SF,8); break; + case DR_LORA_SF9: lgw_reg_w(LGW_MBWSSF_RATE_SF,9); break; + case DR_LORA_SF10: lgw_reg_w(LGW_MBWSSF_RATE_SF,10); break; + case DR_LORA_SF11: lgw_reg_w(LGW_MBWSSF_RATE_SF,11); break; + case DR_LORA_SF12: lgw_reg_w(LGW_MBWSSF_RATE_SF,12); break; + default: DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", lora_rx_sf); return LGW_HAL_ERROR; + } + lgw_reg_w(LGW_MBWSSF_PPM_OFFSET, lora_rx_ppm_offset); /* default 0 */ + lgw_reg_w(LGW_MBWSSF_MODEM_ENABLE, 1); /* default 0 */ + } else { + lgw_reg_w(LGW_MBWSSF_MODEM_ENABLE, 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); + + /* Get MCUs out of reset */ + 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; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +int lgw_stop(void) { + lgw_soft_reset(); + lgw_disconnect(); + + lgw_is_started = false; + return LGW_HAL_SUCCESS; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +int lgw_receive(uint8_t max_pkt, struct lgw_pkt_rx_s *pkt_data) { + int nb_pkt_fetch; /* loop variable and return value */ + struct lgw_pkt_rx_s *p; /* pointer to the current structure in the struct array */ + uint8_t buff[255+RX_METADATA_NB]; /* buffer to store the result of SPI read bursts */ + uint16_t data_addr; /* address read from the FIFO and programmed before the data buffer read operation */ + int s; /* size of the payload, uses to address metadata */ + int ifmod; /* type of if_chain/modem a packet was received by */ + int stat_fifo; /* the packet status as indicated in the FIFO */ + + /* check if the gateway is running */ + if (lgw_is_started == false) { + DEBUG_MSG("ERROR: GATEWAY IS NOT RUNNING, START IT BEFORE RECEIVING\n"); + return LGW_HAL_ERROR; + } + + /* check input variables */ + if (max_pkt <= 0) { + DEBUG_PRINTF("ERROR: %d = INVALID MAX NUMBER OF PACKETS TO FETCH\n", max_pkt); + return LGW_HAL_ERROR; + } + CHECK_NULL(pkt_data); + + /* iterate max_pkt times at most */ + for (nb_pkt_fetch = 0; nb_pkt_fetch < max_pkt; ++nb_pkt_fetch) { + + /* point to the proper struct in the struct array */ + p = &pkt_data[nb_pkt_fetch]; + + /* fetch all the RX FIFO data */ + lgw_reg_rb(LGW_RX_PACKET_DATA_FIFO_NUM_STORED, buff, 5); + + /* how many packets are in the RX buffer ? Break if zero */ + if (buff[0] == 0) { + DEBUG_MSG("Note: RX packet buffer empty, receive function returning nothing\n"); + break; /* no more packets to fetch, exit out of FOR loop */ + } + + DEBUG_PRINTF("FIFO content: %x %x %x %x %x\n",buff[0],buff[1],buff[2],buff[3],buff[4]); + + p->size = buff[4]; + s = p->size; + stat_fifo = buff[3]; /* will be used later, need to save it before overwriting buff */ + + /* get payload + metadata */ + lgw_reg_rb(LGW_RX_DATA_BUF_DATA, buff, s+RX_METADATA_NB); + + /* copy payload to result struct */ + memcpy((void *)p->payload, (void *)buff, s); + + /* process metadata */ + p->if_chain = buff[s+0]; + ifmod = ifmod_config[p->if_chain]; + DEBUG_PRINTF("[%d %d]\n", p->if_chain, ifmod); + + if ((ifmod == IF_LORA_MULTI) || (ifmod == IF_LORA_STD)) { + DEBUG_MSG("Note: Lora packet\n"); + 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_LORA; + p->snr = ((float)((int8_t)buff[s+2]))/4; + p->snr_min = ((float)((int8_t)buff[s+3]))/4; + p->snr_max = ((float)((int8_t)buff[s+4]))/4; + if (ifmod == IF_LORA_MULTI) { + p->rssi = RSSI_OFFSET_LORA_MULTI + (float)buff[s+5]; + p->bandwidth = BW_125KHZ; /* fixed in hardware */ + } else { + p->rssi = RSSI_OFFSET_LORA_STD + (float)buff[s+5]; + p->bandwidth = lora_rx_bw; /* get the parameter from the config variable */ + } + switch ((buff[s+1] >> 4) & 0x0F) { + case 7: p->datarate = DR_LORA_SF7; break; + case 8: p->datarate = DR_LORA_SF8; break; + case 9: p->datarate = DR_LORA_SF9; break; + case 10: p->datarate = DR_LORA_SF10; break; + case 11: p->datarate = DR_LORA_SF11; break; + case 12: p->datarate = DR_LORA_SF12; break; + default: p->datarate = DR_UNDEFINED; + } + switch ((buff[s+1] >> 1) & 0x07) { + case 1: p->coderate = CR_LORA_4_5; break; + case 2: p->coderate = CR_LORA_4_6; break; + case 3: p->coderate = CR_LORA_4_7; break; + case 4: p->coderate = CR_LORA_4_8; break; + default: p->coderate = CR_UNDEFINED; + } + } else if (ifmod == IF_FSK_STD) { + DEBUG_MSG("Note: FSK packet\n"); + 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 = (RSSI_OFFSET_FSK + (float)buff[s+5])/RSSI_SLOPE_FSK; + p->snr = NAN; + p->snr_min = NAN; + p->snr_max = NAN; + p->bandwidth = fsk_rx_bw; + p->datarate = fsk_rx_dr; + p->coderate = CR_UNDEFINED; + } else { + DEBUG_MSG("ERROR: UNEXPECTED PACKET ORIGIN\n"); + p->status = STAT_UNDEFINED; + p->modulation = MOD_UNDEFINED; + p->rssi = NAN; + p->snr = NAN; + p->snr_min = NAN; + p->snr_max = NAN; + p->bandwidth = BW_UNDEFINED; + p->datarate = DR_UNDEFINED; + p->coderate = CR_UNDEFINED; + } + + p->count_us = (uint32_t)buff[s+6] + ((uint32_t)buff[s+7] << 8) + ((uint32_t)buff[s+8] << 16) + ((uint32_t)buff[s+9] << 24); + p->crc = (uint16_t)buff[s+10] + ((uint16_t)buff[s+11] << 8); + + /* advance packet FIFO */ + lgw_reg_w(LGW_RX_PACKET_DATA_FIFO_NUM_STORED, 0); + } + + return nb_pkt_fetch; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +int lgw_send(struct lgw_pkt_tx_s pkt_data) { + 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 */ + if (lgw_is_started == false) { + DEBUG_MSG("ERROR: GATEWAY IS NOT RUNNING, START IT BEFORE SENDING\n"); + return LGW_HAL_ERROR; + } + + /* check input variables */ + if (pkt_data.rf_chain >= LGW_RF_CHAIN_NB) { + DEBUG_MSG("ERROR: INVALID RF_CHAIN TO SEND PACKETS\n"); + return LGW_HAL_ERROR; + } + if (rf_enable[pkt_data.rf_chain] == false) { + DEBUG_MSG("ERROR: SELECTED RF_CHAIN IS DISABLED\n"); + return LGW_HAL_ERROR; + } + if (pkt_data.freq_hz > rf_tx_upfreq[pkt_data.rf_chain]) { + DEBUG_PRINTF("ERROR: FREQUENCY %d HIGHER THAN UPPER LIMIT %d OF RF_CHAIN %d\n", pkt_data.freq_hz, rf_tx_upfreq[pkt_data.rf_chain], pkt_data.rf_chain); + return LGW_HAL_ERROR; + } else if (pkt_data.freq_hz < rf_tx_lowfreq[pkt_data.rf_chain]) { + DEBUG_PRINTF("ERROR: FREQUENCY %d LOWER THAN LOWER LIMIT %d OF RF_CHAIN %d\n", pkt_data.freq_hz, rf_tx_lowfreq[pkt_data.rf_chain], pkt_data.rf_chain); + return LGW_HAL_ERROR; + } + if (!IS_TX_MODE(pkt_data.tx_mode)) { + DEBUG_MSG("ERROR: TX_MODE NOT SUPPORTED\n"); + return LGW_HAL_ERROR; + } + if (pkt_data.modulation == MOD_LORA) { + if (!IS_LORA_BW(pkt_data.bandwidth)) { + DEBUG_MSG("ERROR: BANDWIDTH NOT SUPPORTED BY LORA TX\n"); + return LGW_HAL_ERROR; + } + if (!IS_LORA_STD_DR(pkt_data.datarate)) { + DEBUG_MSG("ERROR: DATARATE NOT SUPPORTED BY LORA TX\n"); + return LGW_HAL_ERROR; + } + if (!IS_LORA_CR(pkt_data.coderate)) { + DEBUG_MSG("ERROR: CODERATE NOT SUPPORTED BY LORA TX\n"); + return LGW_HAL_ERROR; + } + if (pkt_data.size > 255) { + DEBUG_MSG("ERROR: PAYLOAD LENGTH TOO BIG FOR LORA TX\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; + } + + /* reset TX command flags */ + lgw_reg_w(LGW_TX_TRIG_IMMEDIATE, 0); + 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 / 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 */ + + /* metadata 3 to 6, timestamp trigger value */ + buff[3] = 0xFF & (pkt_data.count_us >> 24); + buff[4] = 0xFF & (pkt_data.count_us >> 16); + buff[5] = 0xFF & (pkt_data.count_us >> 8); + buff[6] = 0xFF & pkt_data.count_us; + + /* parameters depending on modulation */ + if (pkt_data.modulation == MOD_LORA) { + /* metadata 7, modulation type, radio chain selection and TX power */ + buff[7] = (0x20 & (pkt_data.rf_chain << 5)) | (0x0F & pkt_data.rf_power); /* bit 4 is 0 -> Lora 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, CRC, Lora CR & SF */ + switch (pkt_data.datarate) { + case DR_LORA_SF7: buff[9] = 7; break; + case DR_LORA_SF8: buff[9] = 8; break; + case DR_LORA_SF9: buff[9] = 9; break; + case DR_LORA_SF10: buff[9] = 10; break; + case DR_LORA_SF11: buff[9] = 11; break; + case DR_LORA_SF12: buff[9] = 12; break; + default: DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", pkt_data.datarate); + } + switch (pkt_data.coderate) { + case CR_LORA_4_5: buff[9] |= 1 << 4; break; + case CR_LORA_4_6: buff[9] |= 2 << 4; break; + case CR_LORA_4_7: buff[9] |= 3 << 4; break; + case CR_LORA_4_8: buff[9] |= 4 << 4; break; + default: DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", pkt_data.coderate); + } + if (pkt_data.no_crc == false) { + buff[9] |= 0x80; /* set 'CRC enable' bit */ + } + + /* metadata 10, payload size */ + buff[10] = pkt_data.size; + + /* metadata 11, implicit header, modulation bandwidth, PPM offset & polarity */ + switch (pkt_data.bandwidth) { + case BW_125KHZ: buff[11] = 0; break; + case BW_250KHZ: buff[11] = 1; break; + case BW_500KHZ: buff[11] = 2; break; + default: DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", pkt_data.bandwidth); + } + if (pkt_data.no_header == true) { + buff[11] |= 0x04; /* set 'implicit header' bit */ + } + if (SET_PPM_ON(pkt_data.bandwidth,pkt_data.datarate)) { + buff[11] |= 0x08; /* set 'PPM offset' bit at 1 */ + } + if (pkt_data.invert_pol == true) { + buff[11] |= 0x10; /* set 'TX polarity' bit at 1 */ + } + + /* metadata 12 & 13, Lora preamble size */ + if (pkt_data.preamble < MIN_LORA_PREAMBLE) { /* enforce minimum preamble size */ + pkt_data.preamble = MIN_LORA_PREAMBLE; + DEBUG_MSG("Note: preamble length adjusted to respect minimum Lora preamble size\n"); + } + buff[12] = 0xFF & (pkt_data.preamble >> 8); + buff[13] = 0xFF & pkt_data.preamble; + + /* metadata 14 & 15, not used */ + 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: INVALID TX MODULATION..\n"); + return LGW_HAL_ERROR; + } + + /* 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, transfer_size); + DEBUG_ARRAY(i, transfer_size, buff); + + /* send data */ + switch(pkt_data.tx_mode) { + case IMMEDIATE: + lgw_reg_w(LGW_TX_TRIG_IMMEDIATE, 1); + break; + + case TIMESTAMPED: + lgw_reg_w(LGW_TX_TRIG_DELAYED, 1); + break; + + case ON_GPS: + lgw_reg_w(LGW_TX_TRIG_GPS, 1); + break; + + default: + DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", pkt_data.tx_mode); + return LGW_HAL_ERROR; + } + + return LGW_HAL_SUCCESS; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +int lgw_status(uint8_t select, uint8_t *code) { + int32_t read_value; + + /* check input variables */ + CHECK_NULL(code); + + if (select == TX_STATUS) { + lgw_reg_r(LGW_TX_STATUS, &read_value); + if (lgw_is_started == false) { + *code = TX_OFF; + } else if ((read_value & 0x10) == 0) { /* bit 4 @1: TX programmed */ + *code = TX_FREE; + } else if ((read_value & 0x60) != 0) { /* bit 5 or 6 @1: TX sequence */ + *code = TX_EMITTING; + } else { + *code = TX_SCHEDULED; + } + return LGW_HAL_SUCCESS; + + } else if (select == RX_STATUS) { + *code = RX_STATUS_UNKNOWN; /* todo */ + return LGW_HAL_SUCCESS; + + } else { + DEBUG_MSG("ERROR: SELECTION INVALID, NO STATUS TO RETURN\n"); + return LGW_HAL_ERROR; + } + +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +const char* lgw_version_info() { + return lgw_version_string; +} + + +/* --- EOF ------------------------------------------------------------------ */ diff --git a/libloragw/src/loragw_reg.c b/libloragw/src/loragw_reg.c new file mode 100644 index 0000000..fea9784 --- /dev/null +++ b/libloragw/src/loragw_reg.c @@ -0,0 +1,768 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + ©2013 Semtech-Cycleo + +Description: + Functions used to handle a single Lora gateway. + Registers are addressed by name. + Multi-bytes registers are handled automatically. + Read-modify-write is handled automatically. +*/ + + +/* -------------------------------------------------------------------------- */ +/* --- DEPENDANCIES --------------------------------------------------------- */ + +#include /* C99 types */ +#include /* bool type */ +#include /* printf fprintf */ + +#include "loragw_spi.h" +#include "loragw_reg.h" + +/* -------------------------------------------------------------------------- */ +/* --- PRIVATE MACROS ------------------------------------------------------- */ + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) +#if DEBUG_REG == 1 + #define DEBUG_MSG(str) fprintf(stderr, str) + #define DEBUG_PRINTF(fmt, args...) fprintf(stderr,"%s:%d: "fmt, __FUNCTION__, __LINE__, args) + #define CHECK_NULL(a) if(a==NULL){fprintf(stderr,"%s:%d: ERROR: NULL POINTER AS ARGUMENT\n", __FUNCTION__, __LINE__);return LGW_REG_ERROR;} +#else + #define DEBUG_MSG(str) + #define DEBUG_PRINTF(fmt, args...) + #define CHECK_NULL(a) if(a==NULL){return LGW_REG_ERROR;} +#endif + +/* -------------------------------------------------------------------------- */ +/* --- PRIVATE TYPES -------------------------------------------------------- */ + +struct lgw_reg_s { + int8_t page; /*!< page containing the register (-1 for all pages) */ + uint8_t addr; /*!< base address of the register (7 bit) */ + uint8_t offs; /*!< position of the register LSB (between 0 to 7) */ + bool sign; /*!< 1 indicates the register is signed (2 complem.) */ + uint8_t leng; /*!< number of bits in the register */ + bool rdon; /*!< 1 indicates a read-only register */ + int32_t dflt; /*!< register default value */ +}; + +/* -------------------------------------------------------------------------- */ +/* --- PRIVATE CONSTANTS ---------------------------------------------------- */ + +#define PAGE_ADDR 0x00 +#define PAGE_MASK 0x03 + +/* +auto generated register mapping for C code : 11-Jul-2013 13:20:40 +this file contains autogenerated C struct used to access the Lora register from the Primer firmware +this file is autogenerated from registers description +293 registers are defined +*/ +const struct lgw_reg_s loregs[LGW_TOTALREGS] = { + {-1,0,0,0,2,0,0}, /* PAGE_REG */ + {-1,0,7,0,1,0,0}, /* SOFT_RESET */ + {-1,1,0,0,8,1,103}, /* VERSION */ + {-1,2,0,0,16,0,0}, /* RX_DATA_BUF_ADDR */ + {-1,4,0,0,8,0,0}, /* RX_DATA_BUF_DATA */ + {-1,5,0,0,8,0,0}, /* TX_DATA_BUF_ADDR */ + {-1,6,0,0,8,0,0}, /* TX_DATA_BUF_DATA */ + {-1,7,0,0,8,0,0}, /* CAPTURE_RAM_ADDR */ + {-1,8,0,0,8,1,0}, /* CAPTURE_RAM_DATA */ + {-1,9,0,0,8,0,0}, /* MCU_PROM_ADDR */ + {-1,10,0,0,8,0,0}, /* MCU_PROM_DATA */ + {-1,11,0,0,8,0,0}, /* RX_PACKET_DATA_FIFO_NUM_STORED */ + {-1,12,0,0,16,1,0}, /* RX_PACKET_DATA_FIFO_ADDR_POINTER */ + {-1,14,0,0,8,1,0}, /* RX_PACKET_DATA_FIFO_STATUS */ + {-1,15,0,0,8,1,0}, /* RX_PACKET_DATA_FIFO_PAYLOAD_SIZE */ + {-1,16,0,0,1,0,0}, /* MBWSSF_MODEM_ENABLE */ + {-1,16,1,0,1,0,0}, /* CONCENTRATOR_MODEM_ENABLE */ + {-1,16,2,0,1,0,0}, /* FSK_MODEM_ENABLE */ + {-1,16,3,0,1,0,0}, /* GLOBAL_EN */ + {-1,17,0,0,1,0,1}, /* CLK32M_EN */ + {-1,17,1,0,1,0,1}, /* CLKHS_EN */ + {-1,18,0,0,1,0,0}, /* START_BIST0 */ + {-1,18,1,0,1,0,0}, /* START_BIST1 */ + {-1,18,2,0,1,0,0}, /* CLEAR_BIST0 */ + {-1,18,3,0,1,0,0}, /* CLEAR_BIST1 */ + {-1,19,0,0,1,1,0}, /* BIST0_FINISHED */ + {-1,19,1,0,1,1,0}, /* BIST1_FINISHED */ + {-1,20,0,0,1,1,0}, /* MCU_AGC_PROG_RAM_BIST_STATUS */ + {-1,20,1,0,1,1,0}, /* MCU_ARB_PROG_RAM_BIST_STATUS */ + {-1,20,2,0,1,1,0}, /* CAPTURE_RAM_BIST_STATUS */ + {-1,20,3,0,1,1,0}, /* CHAN_FIR_RAM0_BIST_STATUS */ + {-1,20,4,0,1,1,0}, /* CHAN_FIR_RAM1_BIST_STATUS */ + {-1,21,0,0,1,1,0}, /* CORR0_RAM_BIST_STATUS */ + {-1,21,1,0,1,1,0}, /* CORR1_RAM_BIST_STATUS */ + {-1,21,2,0,1,1,0}, /* CORR2_RAM_BIST_STATUS */ + {-1,21,3,0,1,1,0}, /* CORR3_RAM_BIST_STATUS */ + {-1,21,4,0,1,1,0}, /* CORR4_RAM_BIST_STATUS */ + {-1,21,5,0,1,1,0}, /* CORR5_RAM_BIST_STATUS */ + {-1,21,6,0,1,1,0}, /* CORR6_RAM_BIST_STATUS */ + {-1,21,7,0,1,1,0}, /* CORR7_RAM_BIST_STATUS */ + {-1,22,0,0,1,1,0}, /* MODEM0_RAM0_BIST_STATUS */ + {-1,22,1,0,1,1,0}, /* MODEM1_RAM0_BIST_STATUS */ + {-1,22,2,0,1,1,0}, /* MODEM2_RAM0_BIST_STATUS */ + {-1,22,3,0,1,1,0}, /* MODEM3_RAM0_BIST_STATUS */ + {-1,22,4,0,1,1,0}, /* MODEM4_RAM0_BIST_STATUS */ + {-1,22,5,0,1,1,0}, /* MODEM5_RAM0_BIST_STATUS */ + {-1,22,6,0,1,1,0}, /* MODEM6_RAM0_BIST_STATUS */ + {-1,22,7,0,1,1,0}, /* MODEM7_RAM0_BIST_STATUS */ + {-1,23,0,0,1,1,0}, /* MODEM0_RAM1_BIST_STATUS */ + {-1,23,1,0,1,1,0}, /* MODEM1_RAM1_BIST_STATUS */ + {-1,23,2,0,1,1,0}, /* MODEM2_RAM1_BIST_STATUS */ + {-1,23,3,0,1,1,0}, /* MODEM3_RAM1_BIST_STATUS */ + {-1,23,4,0,1,1,0}, /* MODEM4_RAM1_BIST_STATUS */ + {-1,23,5,0,1,1,0}, /* MODEM5_RAM1_BIST_STATUS */ + {-1,23,6,0,1,1,0}, /* MODEM6_RAM1_BIST_STATUS */ + {-1,23,7,0,1,1,0}, /* MODEM7_RAM1_BIST_STATUS */ + {-1,24,0,0,1,1,0}, /* MODEM0_RAM2_BIST_STATUS */ + {-1,24,1,0,1,1,0}, /* MODEM1_RAM2_BIST_STATUS */ + {-1,24,2,0,1,1,0}, /* MODEM2_RAM2_BIST_STATUS */ + {-1,24,3,0,1,1,0}, /* MODEM3_RAM2_BIST_STATUS */ + {-1,24,4,0,1,1,0}, /* MODEM4_RAM2_BIST_STATUS */ + {-1,24,5,0,1,1,0}, /* MODEM5_RAM2_BIST_STATUS */ + {-1,24,6,0,1,1,0}, /* MODEM6_RAM2_BIST_STATUS */ + {-1,24,7,0,1,1,0}, /* MODEM7_RAM2_BIST_STATUS */ + {-1,25,0,0,1,1,0}, /* MODEM_MBWSSF_RAM0_BIST_STATUS */ + {-1,25,1,0,1,1,0}, /* MODEM_MBWSSF_RAM1_BIST_STATUS */ + {-1,25,2,0,1,1,0}, /* MODEM_MBWSSF_RAM2_BIST_STATUS */ + {-1,26,0,0,1,1,0}, /* MCU_AGC_DATA_RAM_BIST0_STATUS */ + {-1,26,1,0,1,1,0}, /* MCU_AGC_DATA_RAM_BIST1_STATUS */ + {-1,26,2,0,1,1,0}, /* MCU_ARB_DATA_RAM_BIST0_STATUS */ + {-1,26,3,0,1,1,0}, /* MCU_ARB_DATA_RAM_BIST1_STATUS */ + {-1,26,4,0,1,1,0}, /* TX_TOP_RAM_BIST0_STATUS */ + {-1,26,5,0,1,1,0}, /* TX_TOP_RAM_BIST1_STATUS */ + {-1,26,6,0,1,1,0}, /* DATA_MNGT_RAM_BIST0_STATUS */ + {-1,26,7,0,1,1,0}, /* DATA_MNGT_RAM_BIST1_STATUS */ + {-1,27,0,0,4,0,0}, /* GPIO_SELECT_INPUT */ + {-1,28,0,0,4,0,0}, /* GPIO_SELECT_OUTPUT */ + {-1,29,0,0,5,0,0}, /* GPIO_MODE */ + {-1,30,0,0,5,1,0}, /* GPIO_PIN_REG_IN */ + {-1,31,0,0,5,0,0}, /* GPIO_PIN_REG_OUT */ + {-1,32,0,0,8,1,0}, /* MCU_AGC_STATUS */ + {-1,125,0,0,8,1,0}, /* MCU_ARB_STATUS */ + {-1,126,0,0,8,1,1}, /* CHIP_ID */ + {-1,127,0,0,1,0,1}, /* EMERGENCY_FORCE_HOST_CTRL */ + {0,33,0,0,1,0,0}, /* RX_INVERT_IQ */ + {0,33,1,0,1,0,1}, /* MODEM_INVERT_IQ */ + {0,33,2,0,1,0,0}, /* MBWSSF_MODEM_INVERT_IQ */ + {0,33,3,0,1,0,0}, /* RX_EDGE_SELECT */ + {0,33,4,0,1,0,0}, /* MISC_RADIO_EN */ + {0,33,5,0,1,0,0}, /* FSK_MODEM_INVERT_IQ */ + {0,34,0,0,4,0,7}, /* FILTER_GAIN */ + {0,35,0,0,8,0,240}, /* RADIO_SELECT */ + {0,36,0,1,13,0,-384}, /* IF_FREQ_0 */ + {0,38,0,1,13,0,-128}, /* IF_FREQ_1 */ + {0,40,0,1,13,0,128}, /* IF_FREQ_2 */ + {0,42,0,1,13,0,384}, /* IF_FREQ_3 */ + {0,44,0,1,13,0,-384}, /* IF_FREQ_4 */ + {0,46,0,1,13,0,-128}, /* IF_FREQ_5 */ + {0,48,0,1,13,0,128}, /* IF_FREQ_6 */ + {0,50,0,1,13,0,384}, /* IF_FREQ_7 */ + {0,52,0,1,13,0,0}, /* IF_FREQ_8 */ + {0,54,0,1,13,0,0}, /* IF_FREQ_9 */ + {0,64,0,0,1,0,0}, /* CHANN_OVERRIDE_AGC_GAIN */ + {0,64,1,0,4,0,7}, /* CHANN_AGC_GAIN */ + {0,65,0,0,7,0,0}, /* CORR0_DETECT_EN */ + {0,66,0,0,7,0,0}, /* CORR1_DETECT_EN */ + {0,67,0,0,7,0,0}, /* CORR2_DETECT_EN */ + {0,68,0,0,7,0,0}, /* CORR3_DETECT_EN */ + {0,69,0,0,7,0,0}, /* CORR4_DETECT_EN */ + {0,70,0,0,7,0,0}, /* CORR5_DETECT_EN */ + {0,71,0,0,7,0,0}, /* CORR6_DETECT_EN */ + {0,72,0,0,7,0,0}, /* CORR7_DETECT_EN */ + {0,73,0,0,1,0,0}, /* CORR_SAME_PEAKS_OPTION_SF6 */ + {0,73,1,0,1,0,1}, /* CORR_SAME_PEAKS_OPTION_SF7 */ + {0,73,2,0,1,0,1}, /* CORR_SAME_PEAKS_OPTION_SF8 */ + {0,73,3,0,1,0,1}, /* CORR_SAME_PEAKS_OPTION_SF9 */ + {0,73,4,0,1,0,1}, /* CORR_SAME_PEAKS_OPTION_SF10 */ + {0,73,5,0,1,0,1}, /* CORR_SAME_PEAKS_OPTION_SF11 */ + {0,73,6,0,1,0,1}, /* CORR_SAME_PEAKS_OPTION_SF12 */ + {0,74,0,0,4,0,4}, /* CORR_SIG_NOISE_RATIO_SF6 */ + {0,74,4,0,4,0,4}, /* CORR_SIG_NOISE_RATIO_SF7 */ + {0,75,0,0,4,0,4}, /* CORR_SIG_NOISE_RATIO_SF8 */ + {0,75,4,0,4,0,4}, /* CORR_SIG_NOISE_RATIO_SF9 */ + {0,76,0,0,4,0,4}, /* CORR_SIG_NOISE_RATIO_SF10 */ + {0,76,4,0,4,0,4}, /* CORR_SIG_NOISE_RATIO_SF11 */ + {0,77,0,0,4,0,4}, /* CORR_SIG_NOISE_RATIO_SF12 */ + {0,78,0,0,4,0,4}, /* CORR_NUM_SAME_PEAK */ + {0,78,4,0,3,0,5}, /* CORR_MAC_GAIN */ + {0,81,0,0,12,0,0}, /* ADJUST_MODEM_START_OFFSET_RDX4 */ + {0,83,0,0,12,0,4092}, /* ADJUST_MODEM_START_OFFSET_SF12_RDX4 */ + {0,85,0,0,8,0,7}, /* DBG_CORR_SELECT_SF */ + {0,86,0,0,8,0,0}, /* DBG_CORR_SELECT_CHANNEL */ + {0,87,0,0,8,1,0}, /* DBG_DETECT_CPT */ + {0,88,0,0,8,1,0}, /* DBG_SYMB_CPT */ + {0,89,0,0,1,0,1}, /* CHIRP_INVERT_RX */ + {0,89,1,0,1,0,1}, /* DC_NOTCH_EN */ + {0,90,0,0,1,0,0}, /* IMPLICIT_CRC_EN */ + {0,90,1,0,3,0,0}, /* IMPLICIT_CODING_RATE */ + {0,91,0,0,8,0,0}, /* IMPLICIT_PAYLOAD_LENGHT */ + {0,92,0,0,8,0,29}, /* FREQ_TO_TIME_INVERT */ + {0,93,0,0,6,0,9}, /* FREQ_TO_TIME_DRIFT */ + {0,94,0,0,2,0,2}, /* PAYLOAD_FINE_TIMING_GAIN */ + {0,94,2,0,2,0,1}, /* PREAMBLE_FINE_TIMING_GAIN */ + {0,94,4,0,2,0,0}, /* TRACKING_INTEGRAL */ + {0,95,0,0,4,0,1}, /* FRAME_SYNCH_PEAK1_POS */ + {0,95,4,0,4,0,2}, /* FRAME_SYNCH_PEAK2_POS */ + {0,96,0,0,16,0,10}, /* PREAMBLE_SYMB1_NB */ + {0,98,0,0,1,0,1}, /* FRAME_SYNCH_GAIN */ + {0,98,1,0,1,0,1}, /* SYNCH_DETECT_TH */ + {0,99,0,0,4,0,8}, /* LLR_SCALE */ + {0,99,4,0,2,0,2}, /* SNR_AVG_CST */ + {0,100,0,0,7,0,0}, /* PPM_OFFSET */ + {0,101,0,0,8,0,255}, /* MAX_PAYLOAD_LEN */ + {0,102,0,0,1,0,1}, /* ONLY_CRC_EN */ + {0,103,0,0,8,0,0}, /* ZERO_PAD */ + {0,104,0,0,4,0,8}, /* DEC_GAIN_OFFSET */ + {0,104,4,0,4,0,7}, /* CHAN_GAIN_OFFSET */ + {0,105,1,0,1,0,1}, /* FORCE_HOST_RADIO_CTRL */ + {0,105,2,0,1,0,1}, /* FORCE_HOST_FE_CTRL */ + {0,105,3,0,1,0,1}, /* FORCE_DEC_FILTER_GAIN */ + {0,106,0,0,1,0,1}, /* MCU_RST_0 */ + {0,106,1,0,1,0,1}, /* MCU_RST_1 */ + {0,106,2,0,1,0,0}, /* MCU_SELECT_MUX_0 */ + {0,106,3,0,1,0,0}, /* MCU_SELECT_MUX_1 */ + {0,106,4,0,1,1,0}, /* MCU_CORRUPTION_DETECTED_0 */ + {0,106,5,0,1,1,0}, /* MCU_CORRUPTION_DETECTED_1 */ + {0,106,6,0,1,0,0}, /* MCU_SELECT_EDGE_0 */ + {0,106,7,0,1,0,0}, /* MCU_SELECT_EDGE_1 */ + {0,107,0,0,8,0,1}, /* CHANN_SELECT_RSSI */ + {0,108,0,0,8,0,32}, /* RSSI_BB_DEFAULT_VALUE */ + {0,109,0,0,8,0,100}, /* RSSI_DEC_DEFAULT_VALUE */ + {0,110,0,0,8,0,100}, /* RSSI_CHANN_DEFAULT_VALUE */ + {0,111,0,0,5,0,7}, /* RSSI_BB_FILTER_ALPHA */ + {0,112,0,0,5,0,5}, /* RSSI_DEC_FILTER_ALPHA */ + {0,113,0,0,5,0,8}, /* RSSI_CHANN_FILTER_ALPHA */ + {0,114,0,0,6,0,0}, /* IQ_MISMATCH_A_AMP_COEFF */ + {0,115,0,0,6,0,0}, /* IQ_MISMATCH_A_PHI_COEFF */ + {0,116,0,0,6,0,0}, /* IQ_MISMATCH_B_AMP_COEFF */ + {0,116,6,0,1,0,0}, /* IQ_MISMATCH_B_SEL_I */ + {0,117,0,0,6,0,0}, /* IQ_MISMATCH_B_PHI_COEFF */ + {1,33,0,0,1,0,0}, /* TX_TRIG_IMMEDIATE */ + {1,33,1,0,1,0,0}, /* TX_TRIG_DELAYED */ + {1,33,2,0,1,0,0}, /* TX_TRIG_GPS */ + {1,34,0,0,16,0,0}, /* TX_START_DELAY */ + {1,36,0,0,4,0,1}, /* TX_FRAME_SYNCH_PEAK1_POS */ + {1,36,4,0,4,0,2}, /* TX_FRAME_SYNCH_PEAK2_POS */ + {1,37,0,0,3,0,0}, /* TX_RAMP_DURATION */ + {1,39,0,1,8,0,0}, /* TX_OFFSET_I */ + {1,40,0,1,8,0,0}, /* TX_OFFSET_Q */ + {1,41,0,0,1,0,0}, /* TX_MODE */ + {1,41,1,0,4,0,0}, /* TX_ZERO_PAD */ + {1,41,5,0,1,0,0}, /* TX_EDGE_SELECT */ + {1,41,6,0,1,0,0}, /* TX_EDGE_SELECT_TOP */ + {1,42,0,0,2,0,0}, /* TX_GAIN */ + {1,42,2,0,3,0,5}, /* TX_CHIRP_LOW_PASS */ + {1,42,5,0,2,0,0}, /* TX_FCC_WIDEBAND */ + {1,42,7,0,1,0,1}, /* TX_SWAP_IQ */ + {1,43,0,0,1,0,0}, /* MBWSSF_IMPLICIT_HEADER */ + {1,43,1,0,1,0,0}, /* MBWSSF_IMPLICIT_CRC_EN */ + {1,43,2,0,3,0,0}, /* MBWSSF_IMPLICIT_CODING_RATE */ + {1,44,0,0,8,0,0}, /* MBWSSF_IMPLICIT_PAYLOAD_LENGHT */ + {1,45,0,0,1,0,1}, /* MBWSSF_AGC_FREEZE_ON_DETECT */ + {1,46,0,0,4,0,1}, /* MBWSSF_FRAME_SYNCH_PEAK1_POS */ + {1,46,4,0,4,0,2}, /* MBWSSF_FRAME_SYNCH_PEAK2_POS */ + {1,47,0,0,16,0,10}, /* MBWSSF_PREAMBLE_SYMB1_NB */ + {1,49,0,0,1,0,1}, /* MBWSSF_FRAME_SYNCH_GAIN */ + {1,49,1,0,1,0,1}, /* MBWSSF_SYNCH_DETECT_TH */ + {1,50,0,0,8,0,10}, /* MBWSSF_DETECT_MIN_SINGLE_PEAK */ + {1,51,0,0,3,0,3}, /* MBWSSF_DETECT_TRIG_SAME_PEAK_NB */ + {1,52,0,0,8,0,29}, /* MBWSSF_FREQ_TO_TIME_INVERT */ + {1,53,0,0,6,0,36}, /* MBWSSF_FREQ_TO_TIME_DRIFT */ + {1,54,0,0,12,0,0}, /* MBWSSF_PPM_CORRECTION */ + {1,56,0,0,2,0,2}, /* MBWSSF_PAYLOAD_FINE_TIMING_GAIN */ + {1,56,2,0,2,0,1}, /* MBWSSF_PREAMBLE_FINE_TIMING_GAIN */ + {1,56,4,0,2,0,0}, /* MBWSSF_TRACKING_INTEGRAL */ + {1,57,0,0,8,0,0}, /* MBWSSF_ZERO_PAD */ + {1,58,0,0,2,0,0}, /* MBWSSF_MODEM_BW */ + {1,58,2,0,1,0,0}, /* MBWSSF_RADIO_SELECT */ + {1,58,3,0,1,0,1}, /* MBWSSF_RX_CHIRP_INVERT */ + {1,59,0,0,4,0,8}, /* MBWSSF_LLR_SCALE */ + {1,59,4,0,2,0,3}, /* MBWSSF_SNR_AVG_CST */ + {1,59,6,0,1,0,0}, /* MBWSSF_PPM_OFFSET */ + {1,60,0,0,4,0,7}, /* MBWSSF_RATE_SF */ + {1,60,4,0,1,0,1}, /* MBWSSF_ONLY_CRC_EN */ + {1,61,0,0,8,0,255}, /* MBWSSF_MAX_PAYLOAD_LEN */ + {1,62,0,0,8,1,128}, /* TX_STATUS */ + {1,63,0,0,3,0,0}, /* FSK_CH_BW_EXPO */ + {1,63,3,0,3,0,0}, /* FSK_RSSI_LENGTH */ + {1,63,6,0,1,0,0}, /* FSK_RX_INVERT */ + {1,63,7,0,1,0,0}, /* FSK_PKT_MODE */ + {1,64,0,0,3,0,0}, /* FSK_PSIZE */ + {1,64,3,0,1,0,0}, /* FSK_CRC_EN */ + {1,64,4,0,2,0,0}, /* FSK_DCFREE_ENC */ + {1,64,6,0,1,0,0}, /* FSK_CRC_IBM */ + {1,65,0,0,5,0,0}, /* FSK_ERROR_OSR_TOL */ + {1,65,7,0,1,0,0}, /* FSK_RADIO_SELECT */ + {1,66,0,0,16,0,0}, /* FSK_BR_RATIO */ + {1,68,0,0,32,0,0}, /* FSK_REF_PATTERN_LSB */ + {1,72,0,0,32,0,0}, /* FSK_REF_PATTERN_MSB */ + {1,76,0,0,8,0,0}, /* FSK_PKT_LENGTH */ + {1,77,0,0,1,0,1}, /* FSK_TX_GAUSSIAN_EN */ + {1,77,1,0,2,0,0}, /* FSK_TX_GAUSSIAN_SELECT_BT */ + {1,77,3,0,1,0,1}, /* FSK_TX_PATTERN_EN */ + {1,77,4,0,1,0,0}, /* FSK_TX_PREAMBLE_SEQ */ + {1,77,5,0,3,0,0}, /* FSK_TX_PSIZE */ + {1,80,0,0,8,0,0}, /* FSK_NODE_ADRS */ + {1,81,0,0,8,0,0}, /* FSK_BROADCAST */ + {1,82,0,0,1,0,1}, /* FSK_AUTO_AFC_ON */ + {1,83,0,0,10,0,0}, /* FSK_PATTERN_TIMEOUT_CFG */ + {2,33,0,0,8,0,0}, /* SPI_RADIO_A__DATA */ + {2,34,0,0,8,1,0}, /* SPI_RADIO_A__DATA_READBACK */ + {2,35,0,0,8,0,0}, /* SPI_RADIO_A__ADDR */ + {2,37,0,0,1,0,0}, /* SPI_RADIO_A__CS */ + {2,38,0,0,8,0,0}, /* SPI_RADIO_B__DATA */ + {2,39,0,0,8,1,0}, /* SPI_RADIO_B__DATA_READBACK */ + {2,40,0,0,8,0,0}, /* SPI_RADIO_B__ADDR */ + {2,42,0,0,1,0,0}, /* SPI_RADIO_B__CS */ + {2,43,0,0,1,0,0}, /* RADIO_A_EN */ + {2,43,1,0,1,0,0}, /* RADIO_B_EN */ + {2,43,2,0,1,0,1}, /* RADIO_RST */ + {2,43,3,0,1,0,0}, /* LNA_A_EN */ + {2,43,4,0,1,0,0}, /* PA_A_EN */ + {2,43,5,0,1,0,0}, /* LNA_B_EN */ + {2,43,6,0,1,0,0}, /* PA_B_EN */ + {2,44,0,0,2,0,0}, /* PA_GAIN */ + {2,45,0,0,4,0,2}, /* LNA_A_CTRL_LUT */ + {2,45,4,0,4,0,4}, /* PA_A_CTRL_LUT */ + {2,46,0,0,4,0,2}, /* LNA_B_CTRL_LUT */ + {2,46,4,0,4,0,4}, /* PA_B_CTRL_LUT */ + {2,47,0,0,5,0,0}, /* CAPTURE_SOURCE */ + {2,47,5,0,1,0,0}, /* CAPTURE_START */ + {2,47,6,0,1,0,0}, /* CAPTURE_FORCE_TRIGGER */ + {2,47,7,0,1,0,0}, /* CAPTURE_WRAP */ + {2,48,0,0,16,0,0}, /* CAPTURE_PERIOD */ + {2,51,0,0,8,1,0}, /* MODEM_STATUS */ + {2,52,0,0,8,1,0}, /* VALID_HEADER_COUNTER_0 */ + {2,54,0,0,8,1,0}, /* VALID_PACKET_COUNTER_0 */ + {2,56,0,0,8,1,0}, /* VALID_HEADER_COUNTER_MBWSSF */ + {2,57,0,0,8,1,0}, /* VALID_HEADER_COUNTER_FSK */ + {2,58,0,0,8,1,0}, /* VALID_PACKET_COUNTER_MBWSSF */ + {2,59,0,0,8,1,0}, /* VALID_PACKET_COUNTER_FSK */ + {2,60,0,0,8,1,0}, /* CHANN_RSSI */ + {2,61,0,0,8,1,0}, /* BB_RSSI */ + {2,62,0,0,8,1,0}, /* DEC_RSSI */ + {2,63,0,0,8,1,0}, /* DBG_MCU_DATA */ + {2,64,0,0,8,1,0}, /* DBG_ARB_MCU_RAM_DATA */ + {2,65,0,0,8,1,0}, /* DBG_AGC_MCU_RAM_DATA */ + {2,66,0,0,16,1,0}, /* NEXT_PACKET_CNT */ + {2,68,0,0,16,1,0}, /* ADDR_CAPTURE_COUNT */ + {2,70,0,0,32,1,0}, /* TIMESTAMP */ + {2,74,0,0,4,1,0}, /* DBG_CHANN0_GAIN */ + {2,74,4,0,4,1,0}, /* DBG_CHANN1_GAIN */ + {2,75,0,0,4,1,0}, /* DBG_CHANN2_GAIN */ + {2,75,4,0,4,1,0}, /* DBG_CHANN3_GAIN */ + {2,76,0,0,4,1,0}, /* DBG_CHANN4_GAIN */ + {2,76,4,0,4,1,0}, /* DBG_CHANN5_GAIN */ + {2,77,0,0,4,1,0}, /* DBG_CHANN6_GAIN */ + {2,77,4,0,4,1,0}, /* DBG_CHANN7_GAIN */ + {2,78,0,0,4,1,0}, /* DBG_DEC_FILT_GAIN */ + {2,79,0,0,3,1,0}, /* SPI_DATA_FIFO_PTR */ + {2,79,3,0,3,1,0}, /* PACKET_DATA_FIFO_PTR */ + {2,80,0,0,8,0,0}, /* DBG_ARB_MCU_RAM_ADDR */ + {2,81,0,0,8,0,0}, /* DBG_AGC_MCU_RAM_ADDR */ + {2,82,0,0,1,0,0}, /* SPI_MASTER_CHIP_SELECT_POLARITY */ + {2,82,1,0,1,0,0}, /* SPI_MASTER_CPOL */ + {2,82,2,0,1,0,0}, /* SPI_MASTER_CPHA */ + {2,83,0,0,1,0,0}, /* SIG_GEN_ANALYSER_MUX_SEL */ + {2,84,0,0,1,0,0}, /* SIG_GEN_EN */ + {2,84,1,0,1,0,0}, /* SIG_ANALYSER_EN */ + {2,84,2,0,2,0,0}, /* SIG_ANALYSER_AVG_LEN */ + {2,84,4,0,3,0,0}, /* SIG_ANALYSER_PRECISION */ + {2,84,7,0,1,1,0}, /* SIG_ANALYSER_VALID_OUT */ + {2,85,0,0,8,0,0}, /* SIG_GEN_FREQ */ + {2,86,0,0,8,0,0}, /* SIG_ANALYSER_FREQ */ + {2,87,0,0,8,1,0}, /* SIG_ANALYSER_I_OUT */ + {2,88,0,0,8,1,0}, /* SIG_ANALYSER_Q_OUT */ + {2,89,0,0,1,0,0}, /* GPS_EN */ + {2,89,1,0,1,0,1}, /* GPS_POL */ + {2,90,0,1,8,0,0}, /* SW_TEST_REG1 */ + {2,91,2,1,6,0,0}, /* SW_TEST_REG2 */ + {2,92,0,1,16,0,0}, /* SW_TEST_REG3 */ + {2,94,0,0,4,1,0}, /* DATA_MNGT_STATUS */ + {2,95,0,0,5,1,0}, /* DATA_MNGT_CPT_FRAME_ALLOCATED */ + {2,96,0,0,5,1,0}, /* DATA_MNGT_CPT_FRAME_FINISHED */ + {2,97,0,0,5,1,0} /* DATA_MNGT_CPT_FRAME_READEN */ +}; + +/* -------------------------------------------------------------------------- */ +/* --- PRIVATE VARIABLES ---------------------------------------------------- */ + +void *lgw_spi_target = NULL; /*! generic pointer to the SPI device */ +static int lgw_regpage = -1; /*! keep the value of the register page selected */ + +/* -------------------------------------------------------------------------- */ +/* --- PRIVATE FUNCTIONS ---------------------------------------------------- */ + +int page_switch(uint8_t target) { + lgw_regpage = PAGE_MASK & target; + lgw_spi_w(lgw_spi_target, PAGE_ADDR, (uint8_t)lgw_regpage); + return LGW_REG_SUCCESS; +} + +/* -------------------------------------------------------------------------- */ +/* --- PUBLIC FUNCTIONS DEFINITION ------------------------------------------ */ + +/* Gateway connect */ +int lgw_connect(void) { + int spi_stat = LGW_SPI_SUCCESS; + uint8_t u = 0; + + if (lgw_spi_target != NULL) { + DEBUG_MSG("WARNING: gateway was already connected\n"); + lgw_spi_close(lgw_spi_target); + } + /* open the SPI link */ + spi_stat = lgw_spi_open(&lgw_spi_target); + if (spi_stat != LGW_SPI_SUCCESS) { + DEBUG_MSG("ERROR CONNECTING GATEWAY\n"); + return LGW_REG_ERROR; + } + /* write 0 to the page/reset register */ + spi_stat = lgw_spi_w(lgw_spi_target, loregs[LGW_PAGE_REG].addr, 0); + if (spi_stat != LGW_SPI_SUCCESS) { + DEBUG_MSG("ERROR WRITING PAGE REGISTER\n"); + return LGW_REG_ERROR; + } 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: 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"); + return LGW_REG_ERROR; + } + DEBUG_MSG("Note: success connecting the gateway\n"); + return LGW_REG_SUCCESS; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +/* Gateway disconnect */ +int lgw_disconnect(void) { + if (lgw_spi_target != NULL) { + lgw_spi_close(lgw_spi_target); + lgw_spi_target = NULL; + DEBUG_MSG("Note: success disconnecting the gateway\n"); + return LGW_REG_SUCCESS; + } else { + DEBUG_MSG("WARNING: gateway was already disconnected\n"); + return LGW_REG_ERROR; + } +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +/* soft-reset function */ +int lgw_soft_reset(void) { + int32_t read_value; + /* check if SPI is initialised */ + if ((lgw_spi_target == NULL) || (lgw_regpage < 0)) { + DEBUG_MSG("ERROR: GATEWAY UNCONNECTED\n"); + return LGW_REG_ERROR; + } + lgw_spi_w(lgw_spi_target, 0, 0x80); /* 1 -> SOFT_RESET bit */ + lgw_regpage = 0; /* reset the paging static variable */ + return LGW_REG_SUCCESS; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +/* register verification */ +int lgw_reg_check(FILE *f) { + struct lgw_reg_s r; + int32_t read_value; + char ok_msg[] = "+++MATCH+++"; + char notok_msg[] = "###MISMATCH###"; + char *ptr; + int i; + + /* check if SPI is initialised */ + if ((lgw_spi_target == NULL) || (lgw_regpage < 0)) { + DEBUG_MSG("ERROR: GATEWAY UNCONNECTED\n"); + fprintf(f, "ERROR: GATEWAY UNCONNECTED\n"); + return LGW_REG_ERROR; + } + + fprintf(f, "Start of register verification\n"); + for (i=0; i= LGW_TOTALREGS) { + DEBUG_MSG("ERROR: REGISTER NUMBER OUT OF DEFINED RANGE\n"); + return LGW_REG_ERROR; + } + + /* check if SPI is initialised */ + if ((lgw_spi_target == NULL) || (lgw_regpage < 0)) { + DEBUG_MSG("ERROR: GATEWAY UNCONNECTED\n"); + return LGW_REG_ERROR; + } + + /* intercept direct access to PAGE_REG & SOFT_RESET */ + if (register_id == LGW_PAGE_REG) { + page_switch(reg_value); + return LGW_REG_SUCCESS; + } else if (register_id == LGW_SOFT_RESET) { + /* only reset if lsb is 1 */ + if ((reg_value & 0x01) != 0) + lgw_soft_reset(); + return LGW_REG_SUCCESS; + } + + /* get register struct from the struct array */ + r = loregs[register_id]; + + /* reject write to read-only registers */ + if (r.rdon == 1){ + DEBUG_MSG("ERROR: TRYING TO WRITE A READ-ONLY REGISTER\n"); + return LGW_REG_ERROR; + } + + /* select proper register page if needed */ + if ((r.page != -1) && (r.page != lgw_regpage)) { + spi_stat += page_switch(r.page); + } + + if ((r.leng == 8) && (r.offs == 0)) { + /* direct write */ + spi_stat += lgw_spi_w(lgw_spi_target, r.addr, (uint8_t)reg_value); + } else if ((r.offs + r.leng) <= 8) { + /* single-byte read-modify-write, offs:[0-7], leng:[1-7] */ + spi_stat += lgw_spi_r(lgw_spi_target, r.addr, &buf[0]); + buf[1] = ((1 << r.leng) - 1) << r.offs; /* bit mask */ + buf[2] = ((uint8_t)reg_value) << r.offs; /* new data offsetted */ + buf[3] = (~buf[1] & buf[0]) | (buf[1] & buf[2]); /* mixing old & new data */ + spi_stat += lgw_spi_w(lgw_spi_target, r.addr, buf[3]); + } else if ((r.offs == 0) && (r.leng > 0) && (r.leng <= 32)) { + /* multi-byte direct write routine */ + size_byte = (r.leng + 7) / 8; /* add a byte if it's not an exact multiple of 8 */ + for (i=0; i> 8); + } + spi_stat += lgw_spi_wb(lgw_spi_target, r.addr, buf, size_byte); /* write the register in one burst */ + } else { + /* register spanning multiple memory bytes but with an offset */ + DEBUG_MSG("ERROR: REGISTER SIZE AND OFFSET ARE NOT SUPPORTED\n"); + return LGW_REG_ERROR; + } + + if (spi_stat != LGW_SPI_SUCCESS) { + DEBUG_MSG("ERROR: SPI ERROR DURING REGISTER WRITE\n"); + return LGW_REG_ERROR; + } else { + return LGW_REG_SUCCESS; + } +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +/* Read to a register addressed by name */ +int lgw_reg_r(uint16_t register_id, int32_t *reg_value) { + int spi_stat = LGW_SPI_SUCCESS; + struct lgw_reg_s r; + uint8_t bufu[4] = "\x00\x00\x00\x00"; + int8_t *bufs = bufu; + int i, size_byte; + uint32_t u = 0; + + /* check input parameters */ + CHECK_NULL(reg_value); + if (register_id >= LGW_TOTALREGS) { + DEBUG_MSG("ERROR: REGISTER NUMBER OUT OF DEFINED RANGE\n"); + return LGW_REG_ERROR; + } + + /* check if SPI is initialised */ + if ((lgw_spi_target == NULL) || (lgw_regpage < 0)) { + DEBUG_MSG("ERROR: GATEWAY UNCONNECTED\n"); + return LGW_REG_ERROR; + } + + /* get register struct from the struct array */ + r = loregs[register_id]; + + /* select proper register page if needed */ + if ((r.page != -1) && (r.page != lgw_regpage)) { + spi_stat += page_switch(r.page); + } + + if ((r.offs + r.leng) <= 8) { + /* read one byte, then shift and mask bits to get reg value with sign extension if needed */ + spi_stat += lgw_spi_r(lgw_spi_target, r.addr, &bufu[0]); + bufu[1] = bufu[0] << (8 - r.leng - r.offs); /* left-align the data */ + if (r.sign == true) { + bufs[2] = bufs[1] >> (8 - r.leng); /* right align the data with sign extension (ARITHMETIC right shift) */ + *reg_value = (int32_t)bufs[2]; /* signed pointer -> 32b sign extension */ + } else { + bufu[2] = bufu[1] >> (8 - r.leng); /* right align the data, no sign extension */ + *reg_value = (int32_t)bufu[2]; /* unsigned pointer -> no sign extension */ + } + } else if ((r.offs == 0) && (r.leng > 0) && (r.leng <= 32)) { + size_byte = (r.leng + 7) / 8; /* add a byte if it's not an exact multiple of 8 */ + spi_stat += lgw_spi_rb(lgw_spi_target, r.addr, bufu, size_byte); + u = 0; + for (i=(size_byte-1); i>=0; --i) { + u = (uint32_t)bufu[i] + (u << 8); /* transform a 4-byte array into a 32 bit word */ + } + if (r.sign == true) { + u = u << (32 - r.leng); /* left-align the data */ + *reg_value = (int32_t)u >> (32 - r.leng); /* right-align the data with sign extension (ARITHMETIC right shift) */ + } else { + *reg_value = (int32_t)u; /* unsigned value -> return 'as is' */ + } + } else { + /* register spanning multiple memory bytes but with an offset */ + DEBUG_MSG("ERROR: REGISTER SIZE AND OFFSET ARE NOT SUPPORTED\n"); + return LGW_REG_ERROR; + } + + if (spi_stat != LGW_SPI_SUCCESS) { + DEBUG_MSG("ERROR: SPI ERROR DURING REGISTER WRITE\n"); + return LGW_REG_ERROR; + } else { + return LGW_REG_SUCCESS; + } +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +/* Point to a register by name and do a burst write */ +int lgw_reg_wb(uint16_t register_id, uint8_t *data, uint16_t size) { + int spi_stat; + struct lgw_reg_s r; + + /* check input parameters */ + CHECK_NULL(data); + if (size == 0) { + DEBUG_MSG("ERROR: BURST OF NULL LENGTH\n"); + return LGW_REG_ERROR; + } + if (register_id >= LGW_TOTALREGS) { + DEBUG_MSG("ERROR: REGISTER NUMBER OUT OF DEFINED RANGE\n"); + return LGW_REG_ERROR; + } + + /* check if SPI is initialised */ + if ((lgw_spi_target == NULL) || (lgw_regpage < 0)) { + DEBUG_MSG("ERROR: GATEWAY UNCONNECTED\n"); + return LGW_REG_ERROR; + } + + /* get register struct from the struct array */ + r = loregs[register_id]; + + /* reject write to read-only registers */ + if (r.rdon == 1){ + DEBUG_MSG("ERROR: TRYING TO BURST WRITE A READ-ONLY REGISTER\n"); + return LGW_REG_ERROR; + } + + /* select proper register page if needed */ + if ((r.page != -1) && (r.page != lgw_regpage)) { + spi_stat += page_switch(r.page); + } + + /* do the burst write */ + spi_stat = lgw_spi_wb(lgw_spi_target, r.addr, data, size); + + if (spi_stat != LGW_SPI_SUCCESS) { + DEBUG_MSG("ERROR: SPI ERROR DURING REGISTER BURST WRITE\n"); + return LGW_REG_ERROR; + } else { + return LGW_REG_SUCCESS; + } +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +/* Point to a register by name and do a burst read */ +int lgw_reg_rb(uint16_t register_id, uint8_t *data, uint16_t size) { + int spi_stat; + struct lgw_reg_s r; + + /* check input parameters */ + CHECK_NULL(data); + if (size == 0) { + DEBUG_MSG("ERROR: BURST OF NULL LENGTH\n"); + return LGW_REG_ERROR; + } + if (register_id >= LGW_TOTALREGS) { + DEBUG_MSG("ERROR: REGISTER NUMBER OUT OF DEFINED RANGE\n"); + return LGW_REG_ERROR; + } + + /* check if SPI is initialised */ + if ((lgw_spi_target == NULL) || (lgw_regpage < 0)) { + DEBUG_MSG("ERROR: GATEWAY UNCONNECTED\n"); + return LGW_REG_ERROR; + } + + /* get register struct from the struct array */ + r = loregs[register_id]; + + /* select proper register page if needed */ + if ((r.page != -1) && (r.page != lgw_regpage)) { + spi_stat += page_switch(r.page); + } + + /* do the burst read */ + spi_stat = lgw_spi_rb(lgw_spi_target, r.addr, data, size); + + if (spi_stat != LGW_SPI_SUCCESS) { + DEBUG_MSG("ERROR: SPI ERROR DURING REGISTER BURST READ\n"); + return LGW_REG_ERROR; + } else { + return LGW_REG_SUCCESS; + } +} + +/* --- EOF ------------------------------------------------------------------ */ diff --git a/libloragw/src/loragw_spi.ftdi.c b/libloragw/src/loragw_spi.ftdi.c new file mode 100644 index 0000000..7b71901 --- /dev/null +++ b/libloragw/src/loragw_spi.ftdi.c @@ -0,0 +1,285 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + ©2013 Semtech-Cycleo + +Description: + Host specific functions to address the LoRa™ gateway registers through a + SPI interface. + Single-byte read/write and burst read/write. + Does not handle pagination. + Could be used with multiple SPI ports in parallel (explicit file descriptor) +*/ + + +/* -------------------------------------------------------------------------- */ +/* --- DEPENDANCIES --------------------------------------------------------- */ + +#include /* C99 types */ +#include /* printf fprintf */ +#include /* malloc free */ +#include /* memcpy */ + +#include + +#include "loragw_spi.h" + +/* -------------------------------------------------------------------------- */ +/* --- PRIVATE MACROS ------------------------------------------------------- */ + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) +#if DEBUG_SPI == 1 + #define DEBUG_MSG(str) fprintf(stderr, str) + #define DEBUG_PRINTF(fmt, args...) fprintf(stderr,"%s:%d: "fmt, __FUNCTION__, __LINE__, args) + #define CHECK_NULL(a) if(a==NULL){fprintf(stderr,"%s:%d: ERROR: NULL POINTER AS ARGUMENT\n", __FUNCTION__, __LINE__);return LGW_SPI_ERROR;} +#else + #define DEBUG_MSG(str) + #define DEBUG_PRINTF(fmt, args...) + #define CHECK_NULL(a) if(a==NULL){return LGW_SPI_ERROR;} +#endif + +/* -------------------------------------------------------------------------- */ +/* --- PRIVATE CONSTANTS ---------------------------------------------------- */ + +#define READ_ACCESS 0x00 +#define WRITE_ACCESS 0x80 + +/* parameters for a FT2232H */ +#define VID 0x0403 +#define PID 0x6010 + +/* -------------------------------------------------------------------------- */ +/* --- PUBLIC FUNCTIONS DEFINITION ------------------------------------------ */ + +/* SPI initialization and configuration */ +int lgw_spi_open(void **spi_target_ptr) { + struct mpsse_context *mpsse = NULL; + + /* check input variables */ + CHECK_NULL(spi_target_ptr); /* cannot be null, must point on a void pointer (*spi_target_ptr can be null) */ + + /* try to open the first available FTDI device matching VID/PID parameters */ + mpsse = OpenIndex(VID,PID,SPI0, SIX_MHZ, MSB, IFACE_A, NULL, NULL, 0); + if (mpsse == NULL) { + DEBUG_MSG("ERROR: MPSSE OPEN FUNCTION RETURNED NULL\n"); + return LGW_SPI_ERROR; + } + if (mpsse->open != 1) { + DEBUG_MSG("ERROR: MPSSE OPEN FUNCTION FAILED\n"); + return LGW_SPI_ERROR; + } + + DEBUG_PRINTF("SPI port opened and configured ok\ndesc: %s\nPID: 0x%04X\nVID: 0x%04X\nclock: %d\nLibmpsse version: 0x%02X\n", GetDescription(mpsse), GetPid(mpsse), GetVid(mpsse), GetClock(mpsse), Version()); + *spi_target_ptr = (void *)mpsse; + return LGW_SPI_SUCCESS; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +/* SPI release */ +int lgw_spi_close(void *spi_target) { + struct mpsse_context *mpsse = spi_target; + + /* check input variables */ + CHECK_NULL(spi_target); + + Close(mpsse); + + /* close return no status, assume success (0_o) */ + return LGW_SPI_SUCCESS; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +/* Simple write */ +/* transaction time: .6 to 1 ms typically */ +int lgw_spi_w(void *spi_target, uint8_t address, uint8_t data) { + struct mpsse_context *mpsse = spi_target; + uint8_t out_buf[2]; + int a, b, c; + + /* check input variables */ + CHECK_NULL(spi_target); + if ((address & 0x80) != 0) { + DEBUG_MSG("WARNING: SPI address > 127\n"); + } + + /* prepare frame to be sent */ + out_buf[0] = WRITE_ACCESS | (address & 0x7F); + out_buf[1] = data; + + /* MPSSE transaction */ + a = Start(mpsse); + b = FastWrite(mpsse, (char *)out_buf, 2); + c = Stop(mpsse); + + /* determine return code */ + if ((a != MPSSE_OK) || (b != MPSSE_OK) || (c != MPSSE_OK)) { + DEBUG_MSG("ERROR: SPI WRITE FAILURE\n"); + return LGW_SPI_ERROR; + } else { + DEBUG_MSG("Note: SPI write success\n"); + return LGW_SPI_SUCCESS; + } +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +/* Simple read (using Transfer function) */ +/* transaction time: 1.1 to 2 ms typically */ +int lgw_spi_r(void *spi_target, uint8_t address, uint8_t *data) { + struct mpsse_context *mpsse = spi_target; + uint8_t out_buf[2]; + uint8_t *in_buf = NULL; + int a, b; + + /* check input variables */ + CHECK_NULL(spi_target); + if ((address & 0x80) != 0) { + DEBUG_MSG("WARNING: SPI address > 127\n"); + } + CHECK_NULL(data); + + /* prepare frame to be sent */ + out_buf[0] = READ_ACCESS | (address & 0x7F); + out_buf[1] = 0x00; + + /* MPSSE transaction */ + a = Start(mpsse); + in_buf = (uint8_t *)Transfer(mpsse, (char *)out_buf, 2); + b = Stop(mpsse); + + /* determine return code */ + if ((in_buf == NULL) || (a != MPSSE_OK) || (b != MPSSE_OK)) { + DEBUG_MSG("ERROR: SPI READ FAILURE\n"); + if (in_buf != NULL) { + free(in_buf); + } + return LGW_SPI_ERROR; + } else { + DEBUG_MSG("Note: SPI read success\n"); + *data = in_buf[1]; + free(in_buf); + return LGW_SPI_SUCCESS; + } +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +/* Burst (multiple-byte) write */ +/* transaction time: 3.7ms for 2500 data bytes @6MHz, 1kB chunks */ +/* transaction time: 0.5ms for 16 data bytes @6MHz, 1kB chunks */ +int lgw_spi_wb(void *spi_target, uint8_t address, uint8_t *data, uint16_t size) { + struct mpsse_context *mpsse = spi_target; + uint8_t command; + uint8_t *out_buf = NULL; + int size_to_do, buf_size, chunk_size, offset; + int a, b, c; + int i; + + /* check input parameters */ + CHECK_NULL(spi_target); + if ((address & 0x80) != 0) { + DEBUG_MSG("WARNING: SPI address > 127\n"); + } + CHECK_NULL(data); + if (size == 0) { + DEBUG_MSG("ERROR: BURST OF NULL LENGTH\n"); + return LGW_SPI_ERROR; + } + + /* prepare command byte */ + command = WRITE_ACCESS | (address & 0x7F); + size_to_do = size + 1; /* add a byte for the address */ + + /* allocate data buffer */ + buf_size = (size_to_do < LGW_BURST_CHUNK) ? size_to_do : LGW_BURST_CHUNK; + out_buf = malloc(buf_size); + if (out_buf == NULL) { + DEBUG_MSG("ERROR: MALLOC FAIL\n"); + return LGW_SPI_ERROR; + } + + /* start MPSSE transaction */ + a = Start(mpsse); + for (i=0; size_to_do > 0; ++i) { + chunk_size = (size_to_do < LGW_BURST_CHUNK) ? size_to_do : LGW_BURST_CHUNK; + if (i == 0) { + /* first chunk, need to append the address */ + out_buf[0] = command; + memcpy(out_buf+1, data, chunk_size-1); + } else { + /* following chunks, just copy the data */ + offset = (i * LGW_BURST_CHUNK) - 1; + memcpy(out_buf, data + offset, chunk_size); + } + b = FastWrite(mpsse, (char *)out_buf, chunk_size); + size_to_do -= chunk_size; /* subtract the quantity of data already transferred */ + } + c = Stop(mpsse); + + /* deallocate data buffer */ + free(out_buf); + + /* determine return code (only the last FastWrite is checked) */ + if ((a != MPSSE_OK) || (b != MPSSE_OK) || (c != MPSSE_OK)) { + DEBUG_MSG("ERROR: SPI BURST WRITE FAILURE\n"); + return LGW_SPI_ERROR; + } else { + DEBUG_MSG("Note: SPI burst write success\n"); + return LGW_SPI_SUCCESS; + } +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +/* Burst (multiple-byte) read (using FastWrite & FastRead functions) */ +/* transaction time: 7-12ms for 2500 data bytes @6MHz, 1kB chunks */ +/* transaction time: 2ms for 16 data bytes @6MHz, 1kB chunks */ +int lgw_spi_rb(void *spi_target, uint8_t address, uint8_t *data, uint16_t size) { + struct mpsse_context *mpsse = spi_target; + uint8_t command; + int size_to_do, chunk_size, offset; + int a, b, c, d; + int i; + + /* check input parameters */ + CHECK_NULL(spi_target); + if ((address & 0x80) != 0) { + DEBUG_MSG("WARNING: SPI address > 127\n"); + } + CHECK_NULL(data); + if (size == 0) { + DEBUG_MSG("ERROR: BURST OF NULL LENGTH\n"); + return LGW_SPI_ERROR; + } + + /* prepare command byte */ + command = READ_ACCESS | (address & 0x7F); + size_to_do = size; + + /* start MPSSE transaction */ + a = Start(mpsse); + b = FastWrite(mpsse, (char *)&command, 1); + for (i=0; size_to_do > 0; ++i) { + chunk_size = (size_to_do < LGW_BURST_CHUNK) ? size_to_do : LGW_BURST_CHUNK; + offset = i * LGW_BURST_CHUNK; + c = FastRead(mpsse, (char *)(data + offset), chunk_size); + size_to_do -= chunk_size; /* subtract the quantity of data already transferred */ + } + d = Stop(mpsse); + + /* determine return code (only the last FastRead is checked) */ + if ((a != MPSSE_OK) || (b != MPSSE_OK) || (c != MPSSE_OK) || (d != MPSSE_OK)) { + DEBUG_MSG("ERROR: SPI BURST READ FAILURE\n"); + return LGW_SPI_ERROR; + } else { + DEBUG_MSG("Note: SPI burst read success\n"); + return LGW_SPI_SUCCESS; + } +} + +/* --- EOF ------------------------------------------------------------------ */ diff --git a/libloragw/src/loragw_spi.native.c b/libloragw/src/loragw_spi.native.c new file mode 100644 index 0000000..f5f0701 --- /dev/null +++ b/libloragw/src/loragw_spi.native.c @@ -0,0 +1,346 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + ©2013 Semtech-Cycleo + +Description: + Host specific functions to address the LoRa™ gateway registers through a + SPI interface. + Single-byte read/write and burst read/write. + Does not handle pagination. + Could be used with multiple SPI ports in parallel (explicit file descriptor) +*/ + + +/* -------------------------------------------------------------------------- */ +/* --- DEPENDANCIES --------------------------------------------------------- */ + +#include /* C99 types */ +#include /* printf fprintf */ +#include /* malloc free */ +#include /* lseek, close */ +#include /* open */ +#include /* memset */ + +#include +#include + +#include "loragw_spi.h" + +/* -------------------------------------------------------------------------- */ +/* --- PRIVATE MACROS ------------------------------------------------------- */ + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) +#if DEBUG_SPI == 1 + #define DEBUG_MSG(str) fprintf(stderr, str) + #define DEBUG_PRINTF(fmt, args...) fprintf(stderr,"%s:%d: "fmt, __FUNCTION__, __LINE__, args) + #define CHECK_NULL(a) if(a==NULL){fprintf(stderr,"%s:%d: ERROR: NULL POINTER AS ARGUMENT\n", __FUNCTION__, __LINE__);return LGW_SPI_ERROR;} +#else + #define DEBUG_MSG(str) + #define DEBUG_PRINTF(fmt, args...) + #define CHECK_NULL(a) if(a==NULL){return LGW_SPI_ERROR;} +#endif + +/* -------------------------------------------------------------------------- */ +/* --- PRIVATE CONSTANTS ---------------------------------------------------- */ + +#define READ_ACCESS 0x00 +#define WRITE_ACCESS 0x80 +#define SPI_SPEED 8000000 +#define SPI_DEV_PATH "/dev/spidev0.0" + +/* -------------------------------------------------------------------------- */ +/* --- PUBLIC FUNCTIONS DEFINITION ------------------------------------------ */ + +/* SPI initialization and configuration */ +int lgw_spi_open(void **spi_target_ptr) { + int *spi_device = NULL; + int dev; + int a,b,c; + int i; + + /* check input variables */ + CHECK_NULL(spi_target_ptr); /* cannot be null, must point on a void pointer (*spi_target_ptr can be null) */ + + /* allocate memory for the device descriptor */ + spi_device = malloc(sizeof(int)); + if (spi_device == NULL) { + DEBUG_MSG("ERROR: MALLOC FAIL\n"); + return LGW_SPI_ERROR; + } + + /* open SPI device */ + dev = open(SPI_DEV_PATH, O_RDWR); + if (dev < 0) { + DEBUG_MSG("SPI port fail to open\n"); + return LGW_SPI_ERROR; + } + + /* setting SPI mode to 'mode 0' */ + i = SPI_MODE_0; + a = ioctl(dev, SPI_IOC_WR_MODE, &i); + b = ioctl(dev, SPI_IOC_RD_MODE, &i); + if ((a < 0) || (b < 0)) { + DEBUG_MSG("ERROR: SPI PORT FAIL TO SET IN MODE 0\n"); + close(dev); + free(spi_device); + return LGW_SPI_ERROR; + } + + /* setting SPI max clk (in Hz) */ + i = SPI_SPEED; + a = ioctl(dev, SPI_IOC_WR_MAX_SPEED_HZ, &i); + b = ioctl(dev, SPI_IOC_RD_MAX_SPEED_HZ, &i); + if ((a < 0) || (b < 0)) { + DEBUG_MSG("ERROR: SPI PORT FAIL TO SET MAX SPEED\n"); + close(dev); + free(spi_device); + return LGW_SPI_ERROR; + } + + /* setting SPI to MSB first */ + i = 0; + a = ioctl(dev, SPI_IOC_WR_LSB_FIRST, &i); + b = ioctl(dev, SPI_IOC_RD_LSB_FIRST, &i); + if ((a < 0) || (b < 0)) { + DEBUG_MSG("ERROR: SPI PORT FAIL TO SET MSB FIRST\n"); + close(dev); + free(spi_device); + return LGW_SPI_ERROR; + } + + /* setting SPI to 8 bits per word */ + i = 0; + a = ioctl(dev, SPI_IOC_WR_BITS_PER_WORD, &i); + b = ioctl(dev, SPI_IOC_RD_BITS_PER_WORD, &i); + if ((a < 0) || (b < 0)) { + DEBUG_MSG("ERROR: SPI PORT FAIL TO SET 8 BITS-PER-WORD\n"); + close(dev); + return LGW_SPI_ERROR; + } + + *spi_device = dev; + *spi_target_ptr = (void *)spi_device; + DEBUG_MSG("Note: SPI port opened and configured ok\n"); + return LGW_SPI_SUCCESS; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +/* SPI release */ +int lgw_spi_close(void *spi_target) { + int spi_device; + int a; + + /* check input variables */ + CHECK_NULL(spi_target); + + /* close file & deallocate file descriptor */ + spi_device = *(int *)spi_target; /* must check that spi_target is not null beforehand */ + a = close(spi_device); + free(spi_target); + + /* determine return code */ + if (a < 0) { + DEBUG_MSG("ERROR: SPI PORT FAILED TO CLOSE\n"); + return LGW_SPI_ERROR; + } else { + DEBUG_MSG("Note: SPI port closed\n"); + return LGW_SPI_SUCCESS; + } +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +/* Simple write */ +int lgw_spi_w(void *spi_target, uint8_t address, uint8_t data) { + int spi_device; + uint8_t out_buf[2]; + struct spi_ioc_transfer k; + int a; + + /* check input variables */ + CHECK_NULL(spi_target); + if ((address & 0x80) != 0) { + DEBUG_MSG("WARNING: SPI address > 127\n"); + } + + spi_device = *(int *)spi_target; /* must check that spi_target is not null beforehand */ + + /* prepare frame to be sent */ + out_buf[0] = WRITE_ACCESS | (address & 0x7F); + out_buf[1] = data; + + /* I/O transaction */ + memset(&k, 0, sizeof(k)); /* clear k */ + k.tx_buf = (unsigned long) out_buf; + k.len = ARRAY_SIZE(out_buf); + k.speed_hz = SPI_SPEED; + k.cs_change = 1; + k.bits_per_word = 8; + a = ioctl(spi_device, SPI_IOC_MESSAGE(1), &k); + + /* determine return code */ + if (a != 2) { + DEBUG_MSG("ERROR: SPI WRITE FAILURE\n"); + return LGW_SPI_ERROR; + } else { + DEBUG_MSG("Note: SPI write success\n"); + return LGW_SPI_SUCCESS; + } +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +/* Simple read */ +int lgw_spi_r(void *spi_target, uint8_t address, uint8_t *data) { + int spi_device; + uint8_t out_buf[2]; + uint8_t in_buf[ARRAY_SIZE(out_buf)]; + struct spi_ioc_transfer k; + int a; + + /* check input variables */ + CHECK_NULL(spi_target); + if ((address & 0x80) != 0) { + DEBUG_MSG("WARNING: SPI address > 127\n"); + } + CHECK_NULL(data); + + spi_device = *(int *)spi_target; /* must check that spi_target is not null beforehand */ + + /* prepare frame to be sent */ + out_buf[0] = READ_ACCESS | (address & 0x7F); + out_buf[1] = 0x00; + + /* I/O transaction */ + memset(&k, 0, sizeof(k)); /* clear k */ + k.tx_buf = (unsigned long) out_buf; + k.rx_buf = (unsigned long) in_buf; + k.len = ARRAY_SIZE(out_buf); + k.cs_change = 1; + a = ioctl(spi_device, SPI_IOC_MESSAGE(1), &k); + + /* determine return code */ + if (a != 2) { + DEBUG_MSG("ERROR: SPI READ FAILURE\n"); + return LGW_SPI_ERROR; + } else { + DEBUG_MSG("Note: SPI read success\n"); + *data = in_buf[1]; + return LGW_SPI_SUCCESS; + } +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +/* Burst (multiple-byte) write */ +int lgw_spi_wb(void *spi_target, uint8_t address, uint8_t *data, uint16_t size) { + int spi_device; + uint8_t command; + struct spi_ioc_transfer k[2]; + int size_to_do, chunk_size, offset; + int byte_transfered = 0; + int i; + + /* check input parameters */ + CHECK_NULL(spi_target); + if ((address & 0x80) != 0) { + DEBUG_MSG("WARNING: SPI address > 127\n"); + } + CHECK_NULL(data); + if (size == 0) { + DEBUG_MSG("ERROR: BURST OF NULL LENGTH\n"); + return LGW_SPI_ERROR; + } + + spi_device = *(int *)spi_target; /* must check that spi_target is not null beforehand */ + + /* prepare command byte */ + command = WRITE_ACCESS | (address & 0x7F); + size_to_do = size; + + /* I/O transaction */ + memset(&k, 0, sizeof(k)); /* clear k */ + k[0].tx_buf = (unsigned long) &command; + k[0].len = 1; + k[0].cs_change = 0; + k[1].cs_change = 1; + for (i=0; size_to_do > 0; ++i) { + chunk_size = (size_to_do < LGW_BURST_CHUNK) ? size_to_do : LGW_BURST_CHUNK; + offset = i * LGW_BURST_CHUNK; + k[1].tx_buf = (unsigned long)(data + offset); + k[1].len = chunk_size; + byte_transfered += (ioctl(spi_device, SPI_IOC_MESSAGE(2), &k) - 1 ); + DEBUG_PRINTF("BURST WRITE: to trans %d # chunk %d # transferred %d \n", size_to_do, chunk_size, byte_transfered); + size_to_do -= chunk_size; /* subtract the quantity of data already transferred */ + } + + /* determine return code */ + if (byte_transfered != size) { + DEBUG_MSG("ERROR: SPI BURST WRITE FAILURE\n"); + return LGW_SPI_ERROR; + } else { + DEBUG_MSG("Note: SPI burst write success\n"); + return LGW_SPI_SUCCESS; + } +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +/* Burst (multiple-byte) read */ +int lgw_spi_rb(void *spi_target, uint8_t address, uint8_t *data, uint16_t size) { + int spi_device; + uint8_t command; + struct spi_ioc_transfer k[2]; + int size_to_do, chunk_size, offset; + int byte_transfered = 0; + int i; + + /* check input parameters */ + CHECK_NULL(spi_target); + if ((address & 0x80) != 0) { + DEBUG_MSG("WARNING: SPI address > 127\n"); + } + CHECK_NULL(data); + if (size == 0) { + DEBUG_MSG("ERROR: BURST OF NULL LENGTH\n"); + return LGW_SPI_ERROR; + } + + spi_device = *(int *)spi_target; /* must check that spi_target is not null beforehand */ + + /* prepare command byte */ + command = READ_ACCESS | (address & 0x7F); + size_to_do = size; + + /* I/O transaction */ + memset(&k, 0, sizeof(k)); /* clear k */ + k[0].tx_buf = (unsigned long) &command; + k[0].len = 1; + k[0].cs_change = 0; + k[1].cs_change = 1; + for (i=0; size_to_do > 0; ++i) { + chunk_size = (size_to_do < LGW_BURST_CHUNK) ? size_to_do : LGW_BURST_CHUNK; + offset = i * LGW_BURST_CHUNK; + k[1].rx_buf = (unsigned long)(data + offset); + k[1].len = chunk_size; + byte_transfered += (ioctl(spi_device, SPI_IOC_MESSAGE(2), &k) - 1 ); + DEBUG_PRINTF("BURST READ: to trans %d # chunk %d # transferred %d \n", size_to_do, chunk_size, byte_transfered); + size_to_do -= chunk_size; /* subtract the quantity of data already transferred */ + } + + /* determine return code */ + if (byte_transfered != size) { + DEBUG_MSG("ERROR: SPI BURST READ FAILURE\n"); + return LGW_SPI_ERROR; + } else { + DEBUG_MSG("Note: SPI burst read success\n"); + return LGW_SPI_SUCCESS; + } +} + +/* --- EOF ------------------------------------------------------------------ */ diff --git a/libloragw/tst/test_loragw_hal.c b/libloragw/tst/test_loragw_hal.c new file mode 100644 index 0000000..a210bee --- /dev/null +++ b/libloragw/tst/test_loragw_hal.c @@ -0,0 +1,278 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + ©2013 Semtech-Cycleo + +Description: + Minimum test program for the loragw_hal 'library' +*/ + + +/* -------------------------------------------------------------------------- */ +/* --- DEPENDANCIES --------------------------------------------------------- */ + +/* fix an issue between POSIX and C99 */ +#if __STDC_VERSION__ >= 199901L + #define _XOPEN_SOURCE 600 +#else + #define _XOPEN_SOURCE 500 +#endif + +#include /* C99 types */ +#include /* bool type */ +#include /* printf */ +#include /* memset */ +#include /* sigaction */ + +#include "loragw_hal.h" +#include "loragw_aux.h" + +/* -------------------------------------------------------------------------- */ +/* --- PRIVATE MACROS ------------------------------------------------------- */ + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) + +/* -------------------------------------------------------------------------- */ +/* --- PRIVATE VARIABLES ---------------------------------------------------- */ + +static int exit_sig = 0; /* 1 -> application terminates cleanly (shut down hardware, close open files, etc) */ +static int quit_sig = 0; /* 1 -> application terminates without shutting down the hardware */ + +/* -------------------------------------------------------------------------- */ +/* --- PRIVATE FUNCTIONS DECLARATION ---------------------------------------- */ + +static void sig_handler(int sigio); + +/* -------------------------------------------------------------------------- */ +/* --- PRIVATE FUNCTIONS DEFINITION ----------------------------------------- */ + +static void sig_handler(int sigio) { + if (sigio == SIGQUIT) { + quit_sig = 1;; + } else if ((sigio == SIGINT) || (sigio == SIGTERM)) { + exit_sig = 1; + } +} + +/* -------------------------------------------------------------------------- */ +/* --- MAIN FUNCTION -------------------------------------------------------- */ + +int main(int argc, char **argv) +{ + struct sigaction sigact; /* SIGQUIT&SIGINT&SIGTERM signal handling */ + + struct lgw_conf_rxrf_s rfconf; + struct lgw_conf_rxif_s ifconf; + + 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 */ + struct lgw_pkt_rx_s *p; /* pointer on a RX packet */ + + int i, j; + int nb_pkt; + uint8_t x; + + uint32_t tx_cnt = 0; + unsigned long loop_cnt = 0; + int tx_path = 0; + struct lgw_pkt_tx_s txs; + uint8_t status_var = 0; + + /* configure signal handling */ + sigemptyset(&sigact.sa_mask); + sigact.sa_flags = 0; + sigact.sa_handler = sig_handler; + sigaction(SIGQUIT, &sigact, NULL); + sigaction(SIGINT, &sigact, NULL); + sigaction(SIGTERM, &sigact, NULL); + + /* beginning of Lora gateway-specific code */ + printf("Beginning of test for loragw_hal.c\n"); + + /* set configuration for RF chains */ + memset(&rfconf, 0, sizeof(rfconf)); + + rfconf.enable = true; + rfconf.freq_hz = 866000000; + lgw_rxrf_setconf(0, rfconf); /* radio A */ + + rfconf.enable = true; + rfconf.freq_hz = 868000000; + lgw_rxrf_setconf(1, rfconf); /* radio B */ + + /* set configuration for Lora multi-SF channels (bandwidth cannot be set) */ + memset(&ifconf, 0, sizeof(ifconf)); + + ifconf.enable = true; + ifconf.rf_chain = 0; + ifconf.freq_hz = -300000; + ifconf.bandwidth = BW_125KHZ; + ifconf.datarate = DR_LORA_MULTI; + 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 = 300000; + ifconf.bandwidth = BW_125KHZ; + ifconf.datarate = DR_LORA_MULTI; + lgw_rxif_setconf(1, ifconf); /* chain 1: Lora 125kHz, all SF, on 866.3 MHz */ + + 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 = 300000; + ifconf.bandwidth = BW_125KHZ; + ifconf.datarate = DR_LORA_MULTI; + 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 = 0; + ifconf.bandwidth = BW_250KHZ; + ifconf.datarate = DR_LORA_SF10; + 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 */ + + /* set configuration for TX packet */ + + memset(&txs, 0, sizeof(txs)); + 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; + 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.preamble = 4; + txs.rf_chain = 0; +*/ + +// printf("***\n%s\n***\n", lgw_version_info()); + + /* connect, configure and start the Lora gateway */ + lgw_start(); + + while ((quit_sig != 1) && (exit_sig != 1)) { + loop_cnt++; + + /* fetch N packets */ + nb_pkt = lgw_receive(ARRAY_SIZE(rxpkt), rxpkt); + + if (nb_pkt == 0) { + wait_ms(300); + } else { + /* display received packets */ + for(i=0; i < nb_pkt; ++i) { + p = &rxpkt[i]; + 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); + printf(" size:%3u", p->size); + switch (p-> modulation) { + case MOD_LORA: printf(" Lora"); break; + case MOD_FSK: printf(" FSK"); break; + default: printf(" modulation?"); + } + switch (p->datarate) { + case DR_LORA_SF7: printf(" SF7"); break; + case DR_LORA_SF8: printf(" SF8"); break; + case DR_LORA_SF9: printf(" SF9"); break; + case DR_LORA_SF10: printf(" SF10"); break; + case DR_LORA_SF11: printf(" SF11"); break; + case DR_LORA_SF12: printf(" SF12"); break; + default: printf(" datarate?"); + } + switch (p->coderate) { + case CR_LORA_4_5: printf(" CR1(4/5)"); break; + case CR_LORA_4_6: printf(" CR2(2/3)"); break; + case CR_LORA_4_7: printf(" CR3(4/7)"); break; + case CR_LORA_4_8: printf(" CR4(1/2)"); break; + default: printf(" coderate?"); + } + 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]); + } + printf(" #\n"); + } else if (p->status == STAT_CRC_BAD) { + printf(" if_chain:%2d", p->if_chain); + printf(" tstamp:%010u", p->count_us); + printf(" size:%3u\n", p->size); + printf(" CRC error, damaged packet\n\n"); + } else if (p->status == STAT_NO_CRC){ + printf(" if_chain:%2d", p->if_chain); + printf(" tstamp:%010u", p->count_us); + printf(" size:%3u\n", p->size); + printf(" no CRC\n\n"); + } else { + printf(" if_chain:%2d", p->if_chain); + printf(" tstamp:%010u", p->count_us); + printf(" size:%3u\n", p->size); + printf(" invalid status ?!?\n\n"); + } + } + } + + /* send a packet every X loop */ + if (loop_cnt%16 == 0) { + /* 32b counter in the payload, big endian */ + 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("+++\nSending packet #%d, rf path %d, return %d\nstatus -> ", tx_cnt, txs.rf_chain, i); + do { + ++j; + wait_ms(100); + lgw_status(TX_STATUS, &status_var); /* get TX status */ + printf("%d:", status_var); + } while ((status_var != TX_FREE) && (j < 100)); + ++tx_cnt; + printf("\nTX finished\n"); + } + } + + if (exit_sig == 1) { + /* clean up before leaving */ + lgw_stop(); + } + + printf("\nEnd of test for loragw_hal.c\n"); + return 0; +} + +/* --- EOF ------------------------------------------------------------------ */ diff --git a/libloragw/tst/test_loragw_reg.c b/libloragw/tst/test_loragw_reg.c new file mode 100644 index 0000000..2b80109 --- /dev/null +++ b/libloragw/tst/test_loragw_reg.c @@ -0,0 +1,131 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + ©2013 Semtech-Cycleo + +Description: + Minimum test program for the loragw_spi 'library' +*/ + + +/* -------------------------------------------------------------------------- */ +/* --- DEPENDANCIES --------------------------------------------------------- */ + +#include +#include + +#include "loragw_reg.h" + +/* -------------------------------------------------------------------------- */ +/* --- MAIN FUNCTION -------------------------------------------------------- */ + +#define BURST_TEST_LENGTH 8192 + +int main(int argc, char **argv) +{ + int32_t read_value, test_value; + uint16_t lfsr; + uint8_t burst_buffout[BURST_TEST_LENGTH]; + uint8_t burst_buffin[BURST_TEST_LENGTH]; + int i; + + printf("Beginning of test for loragw_reg.c\n"); + + lgw_connect(); + /* 2 SPI transactions: + -> 0x80 0x00 <- 0x00 0x00 forcing page 0 + -> 0x01 0x00 <- 0x00 0x64 checking version + */ + + /* --- READ TEST --- */ + + lgw_reg_w(LGW_SOFT_RESET, 1); + lgw_reg_check(stdout); + + /* --- READ/WRITE COHERENCY TEST --- */ + + /* 8b unsigned */ + test_value = 197; /* 11000101b */ + lgw_reg_w(LGW_IMPLICIT_PAYLOAD_LENGHT, test_value); + lgw_reg_r(LGW_IMPLICIT_PAYLOAD_LENGHT, &read_value); + printf("IMPLICIT_PAYLOAD_LENGHT = %d (should be %d)\n", read_value, test_value); + + /* 8b signed */ + /* NO SUCH REG AVAILABLE */ + // /* RADIO_SELECT is normally unsigned, modify it manually in loragw_reg.c */ + // test_value = -59; /* 11000101b */ + // lgw_reg_w(LGW_RADIO_SELECT, test_value); + // lgw_reg_r(LGW_RADIO_SELECT, &read_value); + // printf("RADIO_SELECT = %d (should be %d)\n", read_value, test_value); + + /* less than 8b, with offset, unsigned */ + test_value = 11; /* 1011b */ + lgw_reg_w(LGW_FRAME_SYNCH_PEAK2_POS, test_value); + lgw_reg_r(LGW_FRAME_SYNCH_PEAK2_POS, &read_value); + printf("FRAME_SYNCH_PEAK2_POS = %d (should be %d)\n", read_value, test_value); + + /* less than 8b, with offset, signed */ + /* NO SUCH REG AVAILABLE */ + // /* MBWSSF_FRAME_SYNCH_PEAK2_POS is normally unsigned, modify it manually in loragw_reg.c */ + // test_value = -5; /* 1011b */ + // lgw_reg_w(LGW_MBWSSF_FRAME_SYNCH_PEAK2_POS, test_value); + // lgw_reg_r(LGW_MBWSSF_FRAME_SYNCH_PEAK2_POS, &read_value); + // printf("MBWSSF_FRAME_SYNCH_PEAK2_POS = %d (should be %d)\n", read_value, test_value); + + /* 16b unsigned */ + test_value = 49253; /* 11000000 01100101b */ + lgw_reg_w(LGW_PREAMBLE_SYMB1_NB, test_value); + lgw_reg_r(LGW_PREAMBLE_SYMB1_NB, &read_value); + printf("PREAMBLE_SYMB1_NB = %d (should be %d)\n", read_value, test_value); + + /* 16b signed */ + /* NO SUCH REG AVAILABLE */ + // /* CAPTURE_PERIOD is normally unsigned, modify it manually in loragw_reg.c */ + // test_value = -16283; /* 11000000 01100101b */ + // lgw_reg_w(LGW_CAPTURE_PERIOD, test_value); + // lgw_reg_r(LGW_CAPTURE_PERIOD, &read_value); + // printf("CAPTURE_PERIOD = %d (should be %d)\n", read_value, test_value); + + /* between 8b and 16b, unsigned */ + test_value = 3173; /* 1100 01100101b */ + lgw_reg_w(LGW_ADJUST_MODEM_START_OFFSET_SF12_RDX4, test_value); + lgw_reg_r(LGW_ADJUST_MODEM_START_OFFSET_SF12_RDX4, &read_value); + printf("ADJUST_MODEM_START_OFFSET_SF12_RDX4 = %d (should be %d)\n", read_value, test_value); + + /* between 8b and 16b, signed */ + test_value = -1947; /* 11000 01100101b */ + lgw_reg_w(LGW_IF_FREQ_1, test_value); + lgw_reg_r(LGW_IF_FREQ_1, &read_value); + printf("IF_FREQ_1 = %d (should be %d)\n", read_value, test_value); + + /* --- BURST WRITE AND READ TEST --- */ + + /* initialize data for SPI test */ + lfsr = 0xFFFF; + for(i=0; i> 4)); + /* printf("%05d # 0x%04x 0x%02x\n", i, lfsr, burst_buffout[i]); */ + lfsr = (lfsr & 1) ? ((lfsr >> 1) ^ 0x8679) : (lfsr >> 1); + } + + lgw_reg_wb(LGW_TX_DATA_BUF_DATA, burst_buffout, 256); + lgw_reg_rb(LGW_RX_DATA_BUF_DATA, burst_buffin, 256); + + /* impossible to check in software, + RX_DATA_BUF_DATA is read-only, + TX_DATA_BUF_DATA is write only, + use a logic analyser */ + + /* --- END OF TEST --- */ + + lgw_disconnect(); + /* no SPI transaction */ + + printf("End of test for loragw_reg.c\n"); + return 0; +} + +/* --- EOF ------------------------------------------------------------------ */ diff --git a/libloragw/tst/test_loragw_spi.c b/libloragw/tst/test_loragw_spi.c new file mode 100644 index 0000000..0eae55d --- /dev/null +++ b/libloragw/tst/test_loragw_spi.c @@ -0,0 +1,81 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + ©2013 Semtech-Cycleo + +Description: + Minimum test program for the loragw_spi 'library' + Use logic analyser to check the results. +*/ + + +/* -------------------------------------------------------------------------- */ +/* --- DEPENDANCIES --------------------------------------------------------- */ + +#include +#include + +#include "loragw_spi.h" + +/* -------------------------------------------------------------------------- */ +/* --- PRIVATE MACROS ------------------------------------------------------- */ + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) + +/* -------------------------------------------------------------------------- */ +/* --- PRIVATE CONSTANTS ---------------------------------------------------- */ + +#define BURST_TEST_SIZE 2500 /* >> LGW_BURST_CHUNK */ +#define TIMING_REPEAT 1 /* repeat transactions multiple times for timing characterisation */ + +/* -------------------------------------------------------------------------- */ +/* --- MAIN FUNCTION -------------------------------------------------------- */ + +int main(int argc, char **argv) +{ + int i; + void *spi_target = NULL; + uint8_t data = 0; + uint8_t dataout[BURST_TEST_SIZE]; + uint8_t datain[BURST_TEST_SIZE]; + + for (i = 0; i < BURST_TEST_SIZE; ++i) { + dataout[i] = 0x30 + (i % 10); /* ASCCI code for 0 -> 9 */ + datain[i] = 0x23; /* garbage data, to be overwritten by received data */ + } + + printf("Beginning of test for loragw_spi.c\n"); + lgw_spi_open(&spi_target); + + /* normal R/W test */ + for (i = 0; i < TIMING_REPEAT; ++i) + lgw_spi_w(spi_target, 0xAA, 0x96); + for (i = 0; i < TIMING_REPEAT; ++i) + lgw_spi_r(spi_target, 0x55, &data); + + /* burst R/W test, small bursts << LGW_BURST_CHUNK */ + for (i = 0; i < TIMING_REPEAT; ++i) + lgw_spi_wb(spi_target, 0x55, dataout, 16); + for (i = 0; i < TIMING_REPEAT; ++i) + lgw_spi_rb(spi_target, 0x55, datain, 16); + + /* burst R/W test, large bursts >> LGW_BURST_CHUNK */ + for (i = 0; i < TIMING_REPEAT; ++i) + lgw_spi_wb(spi_target, 0x5A, dataout, ARRAY_SIZE(dataout)); + for (i = 0; i < TIMING_REPEAT; ++i) + lgw_spi_rb(spi_target, 0x5A, datain, ARRAY_SIZE(datain)); + + /* last read (blocking), just to be sure no to quit before the FTDI buffer is flushed */ + lgw_spi_r(spi_target, 0x55, &data); + printf("data received (simple read): %d\n",data); + + lgw_spi_close(spi_target); + printf("End of test for loragw_spi.c\n"); + + return 0; +} + +/* --- EOF ------------------------------------------------------------------ */ diff --git a/loragw_hal/99-libftdi.rules b/loragw_hal/99-libftdi.rules deleted file mode 100644 index 8487413..0000000 --- a/loragw_hal/99-libftdi.rules +++ /dev/null @@ -1,8 +0,0 @@ -# FTDI Devices: FT232BM/L/Q, FT245BM/L/Q, FT232RL/Q, FT245RL/Q, VNC1L with VDPS Firmware -SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", MODE="0664", GROUP="plugdev" - -# FTDI Devices: FT2232C/D/L, FT2232HL/Q -SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6010", MODE="0664", GROUP="plugdev" - -# FTDI Devices: FT4232HL/Q -SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6011", MODE="0664", GROUP="plugdev" diff --git a/loragw_hal/INSTALL_FTDI.TXT b/loragw_hal/INSTALL_FTDI.TXT deleted file mode 100644 index d26ad4b..0000000 --- a/loragw_hal/INSTALL_FTDI.TXT +++ /dev/null @@ -1,46 +0,0 @@ -# / _____) _ | | -# ( (____ _____ ____ _| |_ _____ ____| |__ -# \____ \| ___ | (_ _) ___ |/ ___) _ \ -# _____) ) ____| | | || |_| ____( (___| | | | -# (______/|_____)_|_|_| \__)_____)\____)_| |_| -# ©2013 Semtech-Cycleo -# -# Description: -# Installation procedure for FTDI SPI-over-USB dependencies - -# [STEP 1] Install libftdi -sudo apt-get install libftdi-dev - -# this should install : -# - libftdi-dev 0.19-4 (armhf) -# - libftdil 0.19-4 (armhf) -# - libusb-dev 2:0.1.12-20 (armhf) - -# [STEP 2] Download and unpack the libMPSSE 1.3 -# File must match SHA1 Checksum: 1b994a23b118f83144261e3e786c43df74a81cd5 -wget http://libmpsse.googlecode.com/files/libmpsse-1.3.tar.gz -sha1sum libmpsse-1.3.tar.gz -tar -xzvf libmpsse-1.3.tar.gz - -# Go to the src directory and install the library -./configure --disable-python -make -sudo make install -# Static and dynamic libraries compiled code is put into /usr/local/lib -# Header file is put into /usr/local/include - -# On the Pcduino, you must regenerate the library cache (might some time). -sudo ldconfig - -# [STEP 3] to allow non-root applications to access the FTDI device on USB -# copy the provided 99-libftdi.rules file in /etc/udev/rules.d -# For the nano board, only the FT2232H line is required. -# Non-root users members of plugdev group will be able to access the device. - -# [STEP 4] Unpack the Lora Gateway HAL and go to its directory. -# Configure build options in library.cfg, then build the library and examples. -make all - -# [STEP 5] Connect a nanoconcentrator and run test_loragw_reg to test that -# you have access to Lora registers. -# Less than 50 registers of the ~300 registers should return a mismatch. diff --git a/loragw_hal/Makefile b/loragw_hal/Makefile deleted file mode 100644 index 872952a..0000000 --- a/loragw_hal/Makefile +++ /dev/null @@ -1,82 +0,0 @@ -# putting the configuration in a separate file -include library.cfg - -# constant symbols -CC=gcc -CFLAGS=-O2 -Iinc -C99FLAGS=-O2 -std=c99 -Iinc - -# configuration-dependant symbols -ifeq ($(LGW_PHY),native) -LDFLAGS=-lrt -endif -ifeq ($(LGW_PHY),ftdi) -LDFLAGS=-lrt -lmpsse -endif - - -# general build targets - -all: test_loragw_spi test_loragw_reg test_loragw_hal - -clean: - rm -f test_* - rm -f obj/*.o - rm -f .conf_ok - -.conf_ok: library.cfg - @echo "*** Checking Lora gateway HAL library config ***" - @rm -f .conf_ok -ifeq ($(LGW_PHY),native) - @echo "Selected SPI interface type: Linux native driver" -else -ifeq ($(LGW_PHY),ftdi) - @echo "Selected SPI interface type: FTDI SPI-over-USB bridge" -else - $(error No SPI physical layer selected) -endif -endif - @echo "*** Config seems ok ***" - @touch .conf_ok - - -# library module target - -obj/loragw_aux.o: .conf_ok src/loragw_aux.c inc/loragw_aux.h - $(CC) -c $(CFLAGS) src/loragw_aux.c -o obj/loragw_aux.o $(FLAG_AUX) - -obj/loragw_spi.o: .conf_ok src/loragw_spi.native.c src/loragw_spi.ftdi.c inc/loragw_spi.h -ifeq ($(LGW_PHY),native) - $(CC) -c $(C99FLAGS) src/loragw_spi.native.c -o obj/loragw_spi.o $(FLAG_SPI) -endif -ifeq ($(LGW_PHY),ftdi) - $(CC) -c $(C99FLAGS) src/loragw_spi.ftdi.c -o obj/loragw_spi.o $(FLAG_SPI) -endif - -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) - - -# 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_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_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) - diff --git a/loragw_hal/README.txt b/loragw_hal/README.txt deleted file mode 100644 index 58e7fbe..0000000 --- a/loragw_hal/README.txt +++ /dev/null @@ -1,219 +0,0 @@ -+===============================================+ -| / _____) _ | | | -| ( (____ _____ ____ _| |_ _____ ____| |__ | -| \____ \| ___ | (_ _) ___ |/ ___) _ \ | -| _____) ) ____| | | || |_| ____( (___| | | | | -| (______/|_____)_|_|_| \__)_____)\____)_| |_| | -| ©2013 Semtech-Cycleo | -| | -| Description: | -| Lora Gateway HAL documentation | -+===============================================+ - -1. Introduction ---------------- - -The Lora Gateway Hardware Abstraction Layer is a C library that allow you to -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. - - -2. Components of the library ----------------------------- - -The library is composed of 4 modules: - -* loragw_hal -* loragw_reg -* loragw_spi -* loragw_aux - -The library also contains 3 test program to demonstrate code use and check -functionality. - -### 2.1. loragw_hal ### - -This is the main module and contains the high level functions to configure and -use the Lora gateway: - -* lgw_rxrf_setconf, to set the configuration of the radio channels -* lgw_rxif_setconf, to set the configuration of the IF+modem channels -* lgw_start, to apply the set configuration to the hardware and start it -* lgw_stop, to stop the hardware -* lgw_receive, to fetch packets if any was received -* lgw_send, to send a single packet (non-blocking, see warning in usage section) -* lgw_status, to check when a packet has effectively been sent - -For an standard application, include only this module. -The use of this module is detailed on the usage section. - -### 2.2. loragw_reg ### - -This module is used to access to the Lora gateway registers by name instead of -by address: - -* lgw_connect, to initialise and check the connection with the hardware -* lgw_disconnect, to disconnect the hardware -* lgw_soft_reset, to reset the whole hardware by resetting the register array -* lgw_reg_check, to check all registers vs. their default value and output the -result to a file -* lgw_reg_r, read a named register -* lgw_reg_w, write a named register -* lgw_reg_rb, read a name register in burst -* lgw_reg_wb, write a named register in burst - -This module handles pagination, read-only registers protection, multi-byte -registers management, signed registers management, read-modify-write routines -for sub-byte registers and read/write burst fragmentation to respect SPI -maximum burst length constraints. - -It make the code much easier to read and to debug. -Moreover, if registers are relocated between different hardware revisions but -keep the same function, the code written using register names can be reused "as -is". - -If you need access to all the registers, include this module in your -application. - -**/!\ Warning** please be sure to have a good understanding of the Lora gateway -inner working before accessing the internal registers directly. - -### 2.3. loragw_spi ### - -This module contains the functions to access the Lora gateway register array -through the SPI interface: - -* lgw_spi_r to read one byte -* lgw_spi_w to write one byte -* lgw_spi_rb to read two bytes or more -* lgw_spi_wb to write two bytes or more - -Please *do not* include that module directly into your application. - -**/!\ Warning** Accessing the Lora gateway register array without the checks -and safety provided by the functions in loragw_reg is not recommended. - -### 2.4. loragw_aux ### - -This module contains a single host-dependant function wait_ms to pause for a -defined amount of milliseconds. - -The procedure to start and configure the Lora gateway hardware contained in the -loragw_hal module requires to wait for several milliseconds at certain steps, -typically to allow for supply voltages or clocks to stabilize after been -switched on. - -An accuracy of 1 ms or less is ideal. -If your system doesn't allow that level of accuracy, make sure that the actual -delay is *longer* that the time specified when the function is called (ie. -wait_ms(X) *MUST NOT* before X milliseconds under any circumstance). - -If the minimum delays are not guaranteed during the configuration and start -procedure, the hardware might not work at nominal performance. -Most likely, it will not work at all. - - -3. Software dependencies ------------------------- - -The library is written following ANSI C conventions but using C99 explicit -length data type for all data exchanges with hardware and for parameters. - -The loragw_aux module contains POSIX dependant functions for millisecond -accuracy pause. -For embedded platforms, the function could be rewritten using hardware times. - -All modules use the fprintf(stderr,...) function to display debug diagnostic -messages if the DEBUG_xxx is set to 1 in library.cfg - -Depending on config, SPI module needs LibMPSSE to access the FTDI SPI-over-USB -bridge. Please go to that URL to download that library: -http://code.google.com/p/libmpsse/ - -The code was tested with version 1.3 of LibMPSSE: -http://libmpsse.googlecode.com/files/libmpsse-1.3.tar.gz -SHA1 Checksum: 1b994a23b118f83144261e3e786c43df74a81cd5 - -That library has some dependencies itself, please read the installation -instructions. - - -4. Hardware dependencies ------------------------- - -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. - -loragw_spi contains 4 SPI functions (read, write, burst read, burst write) that -are platform-dependant. -The functions must be rewritten depending on the SPI bridge you use: - -* SPI master matched to the Linux SPI device driver (provided) -* SPI over USB using FTDI components (provided) -* native SPI using a microcontroller peripheral (not provided) - -Edit library.cfg to chose which SPI physical interface you want to use. - -You can use the test program test_loragw_spi to check with a logic analyser -that the SPI communication is working - - -5. Usage --------- - -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 -* the configuration is only transferred to hardware when you call the *start* -function -* you cannot receive packets until one (or +) radio is enabled AND one (or +) -IF+modem part is enabled AND the gateway is started -* you cannot send packets until one (or +) radio is enabled AND the gateway is -started -* you must stop the gateway before changing the configuration - -A typical application flow for using the HAL is the following: - - - -loop { - - - -} - - -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. -While a packet is emitted, no packet can be received (limitation intrinsic to -most radio frequency systems). - -Your application *must* take into account the time it takes to send a packet or -check the status (using lgw_status) before attempting to send another packet. - -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). - - -6. License ----------- - -To Be Defined. - - -*EOF* \ No newline at end of file diff --git a/loragw_hal/inc/loragw_aux.h b/loragw_hal/inc/loragw_aux.h deleted file mode 100644 index 09f543f..0000000 --- a/loragw_hal/inc/loragw_aux.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - / _____) _ | | -( (____ _____ ____ _| |_ _____ ____| |__ - \____ \| ___ | (_ _) ___ |/ ___) _ \ - _____) ) ____| | | || |_| ____( (___| | | | -(______/|_____)_|_|_| \__)_____)\____)_| |_| - ©2013 Semtech-Cycleo - -Description: - Lora gateway Hardware Abstraction Layer -*/ - - -#ifndef _LORAGW_AUX_H -#define _LORAGW_AUX_H - -/* -------------------------------------------------------------------------- */ -/* --- PUBLIC FUNCTIONS PROTOTYPES ------------------------------------------ */ - -/** -@brief Wait for a certain time (millisecond accuracy) -@param t number of milliseconds to wait. -*/ -void wait_ms(unsigned long t); - -#endif - -/* --- EOF ------------------------------------------------------------------ */ diff --git a/loragw_hal/inc/loragw_hal.h b/loragw_hal/inc/loragw_hal.h deleted file mode 100644 index d5daafd..0000000 --- a/loragw_hal/inc/loragw_hal.h +++ /dev/null @@ -1,270 +0,0 @@ -/* - / _____) _ | | -( (____ _____ ____ _| |_ _____ ____| |__ - \____ \| ___ | (_ _) ___ |/ ___) _ \ - _____) ) ____| | | || |_| ____( (___| | | | -(______/|_____)_|_|_| \__)_____)\____)_| |_| - ©2013 Semtech-Cycleo - -Description: - Lora gateway Hardware Abstraction Layer -*/ - - -#ifndef _LORAGW_HAL_H -#define _LORAGW_HAL_H - -/* -------------------------------------------------------------------------- */ -/* --- DEPENDANCIES --------------------------------------------------------- */ - -#include /* C99 types */ -#include /* bool type */ - -/* -------------------------------------------------------------------------- */ -/* --- PUBLIC MACROS -------------------------------------------------------- */ - -#define IS_LORA_BW(bw) ((bw == BW_125KHZ) || (bw == BW_250KHZ) || (bw == BW_500KHZ)) -#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_TX_MODE(mode) ((mode == IMMEDIATE) || (mode == TIMESTAMPED) || (mode == ON_GPS)) - -/* -------------------------------------------------------------------------- */ -/* --- PUBLIC CONSTANTS ----------------------------------------------------- */ - -/* return status code */ -#define LGW_HAL_SUCCESS 0 -#define LGW_HAL_ERROR -1 - -/* hardware characteristics */ -#define LGW_RF_CHAIN_NB 2 /* number of RF chains */ -#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 */ - -/* 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} - -/* type of if_chain + modem */ -#define IF_UNDEFINED 0 -#define IF_LORA_STD 0x10 /* if + standard single-SF Lora modem */ -#define IF_LORA_MULTI 0x11 /* if + Lora receiver with multi-SF capability */ -#define IF_FSK_STD 0x20 /* if + standard FSK modem */ - -/* configuration of available IF chains and modems on the hardware */ -/* to use, declare a local constant, and use 'if_chain' as index */ -#define LGW_IFMODEM_CONFIG {\ - IF_LORA_MULTI, \ - IF_LORA_MULTI, \ - IF_LORA_MULTI, \ - IF_LORA_MULTI, \ - IF_UNDEFINED, \ - IF_UNDEFINED, \ - IF_UNDEFINED, \ - IF_UNDEFINED, \ - IF_LORA_STD, \ - IF_FSK_STD } - -/* values available for the 'modulation' parameters */ -#define MOD_UNDEFINED 0 -#define MOD_LORA 0x10 -#define MOD_FSK 0x20 -#define MOD_GFSK 0x21 - -/* values available for the 'bandwidth' parameters */ -#define BW_UNDEFINED 0 -#define BW_500KHZ 0x04 -#define BW_250KHZ 0x08 -#define BW_125KHZ 0x0C -// TODO: add all the supported FSK bandwidth - -/* values available for the 'datarate' parameters */ -#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 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 - -/* values available for the 'status' parameter */ -#define STAT_UNDEFINED 0x00 -#define STAT_NO_CRC 0x01 -#define STAT_CRC_BAD 0x11 -#define STAT_CRC_OK 0x10 - -/* values available for the 'tx_mode' parameter */ -#define IMMEDIATE 0 -#define TIMESTAMPED 1 -#define ON_GPS 2 -//#define ON_EVENT 3 -//#define GPS_DELAYED 4 -//#define EVENT_DELAYED 5 - -/* values available for 'select' in the status function */ -#define TX_STATUS 1 -#define RX_STATUS 2 - -/* status code for TX_STATUS */ -#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 */ -#define TX_SCHEDULED 3 /* TX modem is loaded, ready to send the packet after an event and/or delay */ -#define TX_EMITTING 4 /* TX modem is emitting */ - -/* status code for RX_STATUS */ -#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 */ -#define RX_SUSPENDED 3 /* RX is suspended while a TX is ongoing */ - -/* -------------------------------------------------------------------------- */ -/* --- PUBLIC TYPES --------------------------------------------------------- */ - -/** -@struct lgw_conf_rxrf_s -@brief Configuration structure for a RF chain -*/ -struct lgw_conf_rxrf_s { - bool enable; /*!> enable or disable that RF chain */ - uint32_t freq_hz; /*!> center frequency of the radio in Hz */ -}; - -/** -@struct lgw_conf_rxif_s -@brief Configuration structure for an IF chain -*/ -struct lgw_conf_rxif_s { - bool enable; /*!> enable or disable that IF chain */ - 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 */ -}; - -/** -@struct lgw_pkt_rx_s -@brief Structure containing the metadata of a packet that was received and a pointer to the payload -*/ -struct lgw_pkt_rx_s { - uint8_t if_chain; /*!> by which IF chain was packet received */ - uint8_t status; /*!> status of the received packet */ - uint8_t modulation; /*!> modulation used by the packet */ - uint8_t bandwidth; /*!> modulation bandwidth (Lora only) */ - uint16_t datarate; /*!> RX datarate of the packet */ - uint8_t coderate; /*!> error-correcting code of the packet */ - uint32_t count_us; /*!> internal gateway counter for timestamping, 1 microsecond resolution */ - float rssi; /*!> average packet RSSI in dB */ - float snr; /*!> average packet SNR, in dB (Lora only) */ - float snr_min; /*!> minimum packet SNR, in dB (Lora only) */ - 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 */ -}; - -/** -@struct lgw_pkt_tx_s -@brief Structure containing the configuration of a packet to send and a pointer to the payload -*/ -struct lgw_pkt_tx_s { - uint32_t freq_hz; /*!> center frequency of TX */ - uint8_t tx_mode; /*!> select on what event/time the TX is triggered */ - uint32_t count_us; /*!> timestamp or delay in microseconds for TX trigger */ - uint8_t rf_chain; /*!> through which RF chain will the packet be sent */ - int8_t rf_power; /*!> TX power, in dBm */ - 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 */ - 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 */ - uint16_t size; /*!> payload size in bytes */ - uint8_t *payload; /*!> pointer to the payload */ -}; - -/* -------------------------------------------------------------------------- */ -/* --- PUBLIC FUNCTIONS PROTOTYPES ------------------------------------------ */ - -/** -@brief Configure an RF chain (must configure before start) -@param rf_chain number of the RF chain to configure [0, LGW_RF_CHAIN_NB - 1] -@param conf structure containing the configuration parameters -@return LGW_HAL_ERROR id the operation failed, LGW_HAL_SUCCESS else -*/ -int lgw_rxrf_setconf(uint8_t rf_chain, struct lgw_conf_rxrf_s conf); - -/** -@brief Configure an IF chain + modem (must configure before start) -@param if_chain number of the IF chain + modem to configure [0, LGW_IF_CHAIN_NB - 1] -@param conf structure containing the configuration parameters -@return LGW_HAL_ERROR id the operation failed, LGW_HAL_SUCCESS else -*/ -int lgw_rxif_setconf(uint8_t if_chain, struct lgw_conf_rxif_s conf); - -/** -@brief Connect to the Lora gateway, reset it and configure it according to previously set parameters -@return LGW_HAL_ERROR id the operation failed, LGW_HAL_SUCCESS else -*/ -int lgw_start(void); - -/** -@brief Stop the Lora gateway and disconnect it -@return LGW_HAL_ERROR id the operation failed, LGW_HAL_SUCCESS else -*/ -int lgw_stop(void); - -/** -@brief A non-blocking function that will fetch up to 'max_pkt' packets from the Lora gateway FIFO and data buffer -@param max_pkt maximum number of packet that must be retrieved (equal to the size of the array of struct) -@param pkt_data pointer to an array of struct that will receive the packet metadata and payload pointers -@return LGW_HAL_ERROR id the operation failed, else the number of packets retrieved -*/ -int lgw_receive(uint8_t max_pkt, struct lgw_pkt_rx_s *pkt_data); - -/** -@brief Schedule a packet to be send immediately or after a delay depending on tx_mode -@param pkt_data structure containing the data and metadata for the packet to send -@return LGW_HAL_ERROR id the operation failed, LGW_HAL_SUCCESS else -*/ -int lgw_send(struct lgw_pkt_tx_s pkt_data); - -/** -@brief Give the the status of different part of the Lora gateway -@param select is used to select what status we want to know -@param code is used to return the status code -@return LGW_HAL_ERROR id the operation failed, LGW_HAL_SUCCESS else -*/ -int lgw_status(uint8_t select, uint8_t *code); - -#endif - -/* --- EOF ------------------------------------------------------------------ */ diff --git a/loragw_hal/inc/loragw_reg.h b/loragw_hal/inc/loragw_reg.h deleted file mode 100644 index 870780f..0000000 --- a/loragw_hal/inc/loragw_reg.h +++ /dev/null @@ -1,432 +0,0 @@ -/* - / _____) _ | | -( (____ _____ ____ _| |_ _____ ____| |__ - \____ \| ___ | (_ _) ___ |/ ___) _ \ - _____) ) ____| | | || |_| ____( (___| | | | -(______/|_____)_|_|_| \__)_____)\____)_| |_| - ©2013 Semtech-Cycleo - -Description: - Functions used to handle a single Lora gateway. - Registers are addressed by name. - Multi-bytes registers are handled automatically. - Read-modify-write is handled automatically. -*/ - - -#ifndef _LORAGW_REG_H -#define _LORAGW_REG_H - -/* -------------------------------------------------------------------------- */ -/* --- DEPENDANCIES --------------------------------------------------------- */ - -#include /* C99 types */ -#include /* bool type */ - -/* -------------------------------------------------------------------------- */ -/* --- PUBLIC CONSTANTS ----------------------------------------------------- */ - -#define LGW_REG_SUCCESS 0 -#define LGW_REG_ERROR -1 - -/* -auto generated register mapping for C code : 11-Jul-2013 13:20:40 -this file contains autogenerated C struct used to access the LORA register from the Primer firmware -this file is autogenerated from registers description -293 registers are defined -*/ - -#define LGW_PAGE_REG 0 -#define LGW_SOFT_RESET 1 -#define LGW_VERSION 2 -#define LGW_RX_DATA_BUF_ADDR 3 -#define LGW_RX_DATA_BUF_DATA 4 -#define LGW_TX_DATA_BUF_ADDR 5 -#define LGW_TX_DATA_BUF_DATA 6 -#define LGW_CAPTURE_RAM_ADDR 7 -#define LGW_CAPTURE_RAM_DATA 8 -#define LGW_MCU_PROM_ADDR 9 -#define LGW_MCU_PROM_DATA 10 -#define LGW_RX_PACKET_DATA_FIFO_NUM_STORED 11 -#define LGW_RX_PACKET_DATA_FIFO_ADDR_POINTER 12 -#define LGW_RX_PACKET_DATA_FIFO_STATUS 13 -#define LGW_RX_PACKET_DATA_FIFO_PAYLOAD_SIZE 14 -#define LGW_MBWSSF_MODEM_ENABLE 15 -#define LGW_CONCENTRATOR_MODEM_ENABLE 16 -#define LGW_FSK_MODEM_ENABLE 17 -#define LGW_GLOBAL_EN 18 -#define LGW_CLK32M_EN 19 -#define LGW_CLKHS_EN 20 -#define LGW_START_BIST0 21 -#define LGW_START_BIST1 22 -#define LGW_CLEAR_BIST0 23 -#define LGW_CLEAR_BIST1 24 -#define LGW_BIST0_FINISHED 25 -#define LGW_BIST1_FINISHED 26 -#define LGW_MCU_AGC_PROG_RAM_BIST_STATUS 27 -#define LGW_MCU_ARB_PROG_RAM_BIST_STATUS 28 -#define LGW_CAPTURE_RAM_BIST_STATUS 29 -#define LGW_CHAN_FIR_RAM0_BIST_STATUS 30 -#define LGW_CHAN_FIR_RAM1_BIST_STATUS 31 -#define LGW_CORR0_RAM_BIST_STATUS 32 -#define LGW_CORR1_RAM_BIST_STATUS 33 -#define LGW_CORR2_RAM_BIST_STATUS 34 -#define LGW_CORR3_RAM_BIST_STATUS 35 -#define LGW_CORR4_RAM_BIST_STATUS 36 -#define LGW_CORR5_RAM_BIST_STATUS 37 -#define LGW_CORR6_RAM_BIST_STATUS 38 -#define LGW_CORR7_RAM_BIST_STATUS 39 -#define LGW_MODEM0_RAM0_BIST_STATUS 40 -#define LGW_MODEM1_RAM0_BIST_STATUS 41 -#define LGW_MODEM2_RAM0_BIST_STATUS 42 -#define LGW_MODEM3_RAM0_BIST_STATUS 43 -#define LGW_MODEM4_RAM0_BIST_STATUS 44 -#define LGW_MODEM5_RAM0_BIST_STATUS 45 -#define LGW_MODEM6_RAM0_BIST_STATUS 46 -#define LGW_MODEM7_RAM0_BIST_STATUS 47 -#define LGW_MODEM0_RAM1_BIST_STATUS 48 -#define LGW_MODEM1_RAM1_BIST_STATUS 49 -#define LGW_MODEM2_RAM1_BIST_STATUS 50 -#define LGW_MODEM3_RAM1_BIST_STATUS 51 -#define LGW_MODEM4_RAM1_BIST_STATUS 52 -#define LGW_MODEM5_RAM1_BIST_STATUS 53 -#define LGW_MODEM6_RAM1_BIST_STATUS 54 -#define LGW_MODEM7_RAM1_BIST_STATUS 55 -#define LGW_MODEM0_RAM2_BIST_STATUS 56 -#define LGW_MODEM1_RAM2_BIST_STATUS 57 -#define LGW_MODEM2_RAM2_BIST_STATUS 58 -#define LGW_MODEM3_RAM2_BIST_STATUS 59 -#define LGW_MODEM4_RAM2_BIST_STATUS 60 -#define LGW_MODEM5_RAM2_BIST_STATUS 61 -#define LGW_MODEM6_RAM2_BIST_STATUS 62 -#define LGW_MODEM7_RAM2_BIST_STATUS 63 -#define LGW_MODEM_MBWSSF_RAM0_BIST_STATUS 64 -#define LGW_MODEM_MBWSSF_RAM1_BIST_STATUS 65 -#define LGW_MODEM_MBWSSF_RAM2_BIST_STATUS 66 -#define LGW_MCU_AGC_DATA_RAM_BIST0_STATUS 67 -#define LGW_MCU_AGC_DATA_RAM_BIST1_STATUS 68 -#define LGW_MCU_ARB_DATA_RAM_BIST0_STATUS 69 -#define LGW_MCU_ARB_DATA_RAM_BIST1_STATUS 70 -#define LGW_TX_TOP_RAM_BIST0_STATUS 71 -#define LGW_TX_TOP_RAM_BIST1_STATUS 72 -#define LGW_DATA_MNGT_RAM_BIST0_STATUS 73 -#define LGW_DATA_MNGT_RAM_BIST1_STATUS 74 -#define LGW_GPIO_SELECT_INPUT 75 -#define LGW_GPIO_SELECT_OUTPUT 76 -#define LGW_GPIO_MODE 77 -#define LGW_GPIO_PIN_REG_IN 78 -#define LGW_GPIO_PIN_REG_OUT 79 -#define LGW_MCU_AGC_STATUS 80 -#define LGW_MCU_ARB_STATUS 81 -#define LGW_CHIP_ID 82 -#define LGW_EMERGENCY_FORCE_HOST_CTRL 83 -#define LGW_RX_INVERT_IQ 84 -#define LGW_MODEM_INVERT_IQ 85 -#define LGW_MBWSSF_MODEM_INVERT_IQ 86 -#define LGW_RX_EDGE_SELECT 87 -#define LGW_MISC_RADIO_EN 88 -#define LGW_FSK_MODEM_INVERT_IQ 89 -#define LGW_FILTER_GAIN 90 -#define LGW_RADIO_SELECT 91 -#define LGW_IF_FREQ_0 92 -#define LGW_IF_FREQ_1 93 -#define LGW_IF_FREQ_2 94 -#define LGW_IF_FREQ_3 95 -#define LGW_IF_FREQ_4 96 -#define LGW_IF_FREQ_5 97 -#define LGW_IF_FREQ_6 98 -#define LGW_IF_FREQ_7 99 -#define LGW_IF_FREQ_8 100 -#define LGW_IF_FREQ_9 101 -#define LGW_CHANN_OVERRIDE_AGC_GAIN 102 -#define LGW_CHANN_AGC_GAIN 103 -#define LGW_CORR0_DETECT_EN 104 -#define LGW_CORR1_DETECT_EN 105 -#define LGW_CORR2_DETECT_EN 106 -#define LGW_CORR3_DETECT_EN 107 -#define LGW_CORR4_DETECT_EN 108 -#define LGW_CORR5_DETECT_EN 109 -#define LGW_CORR6_DETECT_EN 110 -#define LGW_CORR7_DETECT_EN 111 -#define LGW_CORR_SAME_PEAKS_OPTION_SF6 112 -#define LGW_CORR_SAME_PEAKS_OPTION_SF7 113 -#define LGW_CORR_SAME_PEAKS_OPTION_SF8 114 -#define LGW_CORR_SAME_PEAKS_OPTION_SF9 115 -#define LGW_CORR_SAME_PEAKS_OPTION_SF10 116 -#define LGW_CORR_SAME_PEAKS_OPTION_SF11 117 -#define LGW_CORR_SAME_PEAKS_OPTION_SF12 118 -#define LGW_CORR_SIG_NOISE_RATIO_SF6 119 -#define LGW_CORR_SIG_NOISE_RATIO_SF7 120 -#define LGW_CORR_SIG_NOISE_RATIO_SF8 121 -#define LGW_CORR_SIG_NOISE_RATIO_SF9 122 -#define LGW_CORR_SIG_NOISE_RATIO_SF10 123 -#define LGW_CORR_SIG_NOISE_RATIO_SF11 124 -#define LGW_CORR_SIG_NOISE_RATIO_SF12 125 -#define LGW_CORR_NUM_SAME_PEAK 126 -#define LGW_CORR_MAC_GAIN 127 -#define LGW_ADJUST_MODEM_START_OFFSET_RDX4 128 -#define LGW_ADJUST_MODEM_START_OFFSET_SF12_RDX4 129 -#define LGW_DBG_CORR_SELECT_SF 130 -#define LGW_DBG_CORR_SELECT_CHANNEL 131 -#define LGW_DBG_DETECT_CPT 132 -#define LGW_DBG_SYMB_CPT 133 -#define LGW_CHIRP_INVERT_RX 134 -#define LGW_DC_NOTCH_EN 135 -#define LGW_IMPLICIT_CRC_EN 136 -#define LGW_IMPLICIT_CODING_RATE 137 -#define LGW_IMPLICIT_PAYLOAD_LENGHT 138 -#define LGW_FREQ_TO_TIME_INVERT 139 -#define LGW_FREQ_TO_TIME_DRIFT 140 -#define LGW_PAYLOAD_FINE_TIMING_GAIN 141 -#define LGW_PREAMBLE_FINE_TIMING_GAIN 142 -#define LGW_TRACKING_INTEGRAL 143 -#define LGW_FRAME_SYNCH_PEAK1_POS 144 -#define LGW_FRAME_SYNCH_PEAK2_POS 145 -#define LGW_PREAMBLE_SYMB1_NB 146 -#define LGW_FRAME_SYNCH_GAIN 147 -#define LGW_SYNCH_DETECT_TH 148 -#define LGW_LLR_SCALE 149 -#define LGW_SNR_AVG_CST 150 -#define LGW_PPM_OFFSET 151 -#define LGW_MAX_PAYLOAD_LEN 152 -#define LGW_ONLY_CRC_EN 153 -#define LGW_ZERO_PAD 154 -#define LGW_DEC_GAIN_OFFSET 155 -#define LGW_CHAN_GAIN_OFFSET 156 -#define LGW_FORCE_HOST_RADIO_CTRL 157 -#define LGW_FORCE_HOST_FE_CTRL 158 -#define LGW_FORCE_DEC_FILTER_GAIN 159 -#define LGW_MCU_RST_0 160 -#define LGW_MCU_RST_1 161 -#define LGW_MCU_SELECT_MUX_0 162 -#define LGW_MCU_SELECT_MUX_1 163 -#define LGW_MCU_CORRUPTION_DETECTED_0 164 -#define LGW_MCU_CORRUPTION_DETECTED_1 165 -#define LGW_MCU_SELECT_EDGE_0 166 -#define LGW_MCU_SELECT_EDGE_1 167 -#define LGW_CHANN_SELECT_RSSI 168 -#define LGW_RSSI_BB_DEFAULT_VALUE 169 -#define LGW_RSSI_DEC_DEFAULT_VALUE 170 -#define LGW_RSSI_CHANN_DEFAULT_VALUE 171 -#define LGW_RSSI_BB_FILTER_ALPHA 172 -#define LGW_RSSI_DEC_FILTER_ALPHA 173 -#define LGW_RSSI_CHANN_FILTER_ALPHA 174 -#define LGW_IQ_MISMATCH_A_AMP_COEFF 175 -#define LGW_IQ_MISMATCH_A_PHI_COEFF 176 -#define LGW_IQ_MISMATCH_B_AMP_COEFF 177 -#define LGW_IQ_MISMATCH_B_SEL_I 178 -#define LGW_IQ_MISMATCH_B_PHI_COEFF 179 -#define LGW_TX_TRIG_IMMEDIATE 180 -#define LGW_TX_TRIG_DELAYED 181 -#define LGW_TX_TRIG_GPS 182 -#define LGW_TX_START_DELAY 183 -#define LGW_TX_FRAME_SYNCH_PEAK1_POS 184 -#define LGW_TX_FRAME_SYNCH_PEAK2_POS 185 -#define LGW_TX_RAMP_DURATION 186 -#define LGW_TX_OFFSET_I 187 -#define LGW_TX_OFFSET_Q 188 -#define LGW_TX_MODE 189 -#define LGW_TX_ZERO_PAD 190 -#define LGW_TX_EDGE_SELECT 191 -#define LGW_TX_EDGE_SELECT_TOP 192 -#define LGW_TX_GAIN 193 -#define LGW_TX_CHIRP_LOW_PASS 194 -#define LGW_TX_FCC_WIDEBAND 195 -#define LGW_TX_SWAP_IQ 196 -#define LGW_MBWSSF_IMPLICIT_HEADER 197 -#define LGW_MBWSSF_IMPLICIT_CRC_EN 198 -#define LGW_MBWSSF_IMPLICIT_CODING_RATE 199 -#define LGW_MBWSSF_IMPLICIT_PAYLOAD_LENGHT 200 -#define LGW_MBWSSF_AGC_FREEZE_ON_DETECT 201 -#define LGW_MBWSSF_FRAME_SYNCH_PEAK1_POS 202 -#define LGW_MBWSSF_FRAME_SYNCH_PEAK2_POS 203 -#define LGW_MBWSSF_PREAMBLE_SYMB1_NB 204 -#define LGW_MBWSSF_FRAME_SYNCH_GAIN 205 -#define LGW_MBWSSF_SYNCH_DETECT_TH 206 -#define LGW_MBWSSF_DETECT_MIN_SINGLE_PEAK 207 -#define LGW_MBWSSF_DETECT_TRIG_SAME_PEAK_NB 208 -#define LGW_MBWSSF_FREQ_TO_TIME_INVERT 209 -#define LGW_MBWSSF_FREQ_TO_TIME_DRIFT 210 -#define LGW_MBWSSF_PPM_CORRECTION 211 -#define LGW_MBWSSF_PAYLOAD_FINE_TIMING_GAIN 212 -#define LGW_MBWSSF_PREAMBLE_FINE_TIMING_GAIN 213 -#define LGW_MBWSSF_TRACKING_INTEGRAL 214 -#define LGW_MBWSSF_ZERO_PAD 215 -#define LGW_MBWSSF_MODEM_BW 216 -#define LGW_MBWSSF_RADIO_SELECT 217 -#define LGW_MBWSSF_RX_CHIRP_INVERT 218 -#define LGW_MBWSSF_LLR_SCALE 219 -#define LGW_MBWSSF_SNR_AVG_CST 220 -#define LGW_MBWSSF_PPM_OFFSET 221 -#define LGW_MBWSSF_RATE_SF 222 -#define LGW_MBWSSF_ONLY_CRC_EN 223 -#define LGW_MBWSSF_MAX_PAYLOAD_LEN 224 -#define LGW_TX_STATUS 225 -#define LGW_FSK_CH_BW_EXPO 226 -#define LGW_FSK_RSSI_LENGTH 227 -#define LGW_FSK_RX_INVERT 228 -#define LGW_FSK_PKT_MODE 229 -#define LGW_FSK_PSIZE 230 -#define LGW_FSK_CRC_EN 231 -#define LGW_FSK_DCFREE_ENC 232 -#define LGW_FSK_CRC_IBM 233 -#define LGW_FSK_ERROR_OSR_TOL 234 -#define LGW_FSK_RADIO_SELECT 235 -#define LGW_FSK_BR_RATIO 236 -#define LGW_FSK_REF_PATTERN_LSB 237 -#define LGW_FSK_REF_PATTERN_MSB 238 -#define LGW_FSK_PKT_LENGTH 239 -#define LGW_FSK_TX_GAUSSIAN_EN 240 -#define LGW_FSK_TX_GAUSSIAN_SELECT_BT 241 -#define LGW_FSK_TX_PATTERN_EN 242 -#define LGW_FSK_TX_PREAMBLE_SEQ 243 -#define LGW_FSK_TX_PSIZE 244 -#define LGW_FSK_NODE_ADRS 245 -#define LGW_FSK_BROADCAST 246 -#define LGW_FSK_AUTO_AFC_ON 247 -#define LGW_FSK_PATTERN_TIMEOUT_CFG 248 -#define LGW_SPI_RADIO_A__DATA 249 -#define LGW_SPI_RADIO_A__DATA_READBACK 250 -#define LGW_SPI_RADIO_A__ADDR 251 -#define LGW_SPI_RADIO_A__CS 252 -#define LGW_SPI_RADIO_B__DATA 253 -#define LGW_SPI_RADIO_B__DATA_READBACK 254 -#define LGW_SPI_RADIO_B__ADDR 255 -#define LGW_SPI_RADIO_B__CS 256 -#define LGW_RADIO_A_EN 257 -#define LGW_RADIO_B_EN 258 -#define LGW_RADIO_RST 259 -#define LGW_LNA_A_EN 260 -#define LGW_PA_A_EN 261 -#define LGW_LNA_B_EN 262 -#define LGW_PA_B_EN 263 -#define LGW_PA_GAIN 264 -#define LGW_LNA_A_CTRL_LUT 265 -#define LGW_PA_A_CTRL_LUT 266 -#define LGW_LNA_B_CTRL_LUT 267 -#define LGW_PA_B_CTRL_LUT 268 -#define LGW_CAPTURE_SOURCE 269 -#define LGW_CAPTURE_START 270 -#define LGW_CAPTURE_FORCE_TRIGGER 271 -#define LGW_CAPTURE_WRAP 272 -#define LGW_CAPTURE_PERIOD 273 -#define LGW_MODEM_STATUS 274 -#define LGW_VALID_HEADER_COUNTER_0 275 -#define LGW_VALID_PACKET_COUNTER_0 276 -#define LGW_VALID_HEADER_COUNTER_MBWSSF 277 -#define LGW_VALID_HEADER_COUNTER_FSK 278 -#define LGW_VALID_PACKET_COUNTER_MBWSSF 279 -#define LGW_VALID_PACKET_COUNTER_FSK 280 -#define LGW_CHANN_RSSI 281 -#define LGW_BB_RSSI 282 -#define LGW_DEC_RSSI 283 -#define LGW_DBG_MCU_DATA 284 -#define LGW_DBG_ARB_MCU_RAM_DATA 285 -#define LGW_DBG_AGC_MCU_RAM_DATA 286 -#define LGW_NEXT_PACKET_CNT 287 -#define LGW_ADDR_CAPTURE_COUNT 288 -#define LGW_TIMESTAMP 289 -#define LGW_DBG_CHANN0_GAIN 290 -#define LGW_DBG_CHANN1_GAIN 291 -#define LGW_DBG_CHANN2_GAIN 292 -#define LGW_DBG_CHANN3_GAIN 293 -#define LGW_DBG_CHANN4_GAIN 294 -#define LGW_DBG_CHANN5_GAIN 295 -#define LGW_DBG_CHANN6_GAIN 296 -#define LGW_DBG_CHANN7_GAIN 297 -#define LGW_DBG_DEC_FILT_GAIN 298 -#define LGW_SPI_DATA_FIFO_PTR 299 -#define LGW_PACKET_DATA_FIFO_PTR 300 -#define LGW_DBG_ARB_MCU_RAM_ADDR 301 -#define LGW_DBG_AGC_MCU_RAM_ADDR 302 -#define LGW_SPI_MASTER_CHIP_SELECT_POLARITY 303 -#define LGW_SPI_MASTER_CPOL 304 -#define LGW_SPI_MASTER_CPHA 305 -#define LGW_SIG_GEN_ANALYSER_MUX_SEL 306 -#define LGW_SIG_GEN_EN 307 -#define LGW_SIG_ANALYSER_EN 308 -#define LGW_SIG_ANALYSER_AVG_LEN 309 -#define LGW_SIG_ANALYSER_PRECISION 310 -#define LGW_SIG_ANALYSER_VALID_OUT 311 -#define LGW_SIG_GEN_FREQ 312 -#define LGW_SIG_ANALYSER_FREQ 313 -#define LGW_SIG_ANALYSER_I_OUT 314 -#define LGW_SIG_ANALYSER_Q_OUT 315 -#define LGW_GPS_EN 316 -#define LGW_GPS_POL 317 -#define LGW_SW_TEST_REG1 318 -#define LGW_SW_TEST_REG2 319 -#define LGW_SW_TEST_REG3 320 -#define LGW_DATA_MNGT_STATUS 321 -#define LGW_DATA_MNGT_CPT_FRAME_ALLOCATED 322 -#define LGW_DATA_MNGT_CPT_FRAME_FINISHED 323 -#define LGW_DATA_MNGT_CPT_FRAME_READEN 324 - -#define LGW_TOTALREGS 325 - -/* -------------------------------------------------------------------------- */ -/* --- PUBLIC FUNCTIONS PROTOTYPES ------------------------------------------ */ - -/** -@brief Connect Lora gateway by opening SPI link -@return status of register operation (LGW_REG_SUCCESS/LGW_REG_ERROR) -*/ -int lgw_connect(void); - -/** -@brief Disconnect Lora gateway by closing SPI link -@return status of register operation (LGW_REG_SUCCESS/LGW_REG_ERROR) -*/ -int lgw_disconnect(void); - -/** -@brief Use the soft-reset register to put the gateway in initial state -@return status of register operation (LGW_REG_SUCCESS/LGW_REG_ERROR) -*/ -int lgw_soft_reset(void); - -/** -@brief Check if the registers are ok, send diagnostics to stdio/stderr/file -@param f file descriptor to to which the check result will be written -@return status of register operation (LGW_REG_SUCCESS/LGW_REG_ERROR) -*/ -int lgw_reg_check(FILE *f); - -/** -@brief Lora gateway register write -@param register_id register number in the data structure describing registers -@param reg_value signed value to write to the register (for u32, use cast) -@return status of register operation (LGW_REG_SUCCESS/LGW_REG_ERROR) -*/ -int lgw_reg_w(uint16_t register_id, int32_t reg_value); - -/** -@brief Lora gateway register read -@param register_id register number in the data structure describing registers -@param reg_value pointer to a variable where to write register read value -@return status of register operation (LGW_REG_SUCCESS/LGW_REG_ERROR) -*/ -int lgw_reg_r(uint16_t register_id, int32_t *reg_value); - -/** -@brief Lora gateway register burst write -@param register_id register number in the data structure describing registers -@param data pointer to byte array that will be sent to the Lora gateway -@param size size of the transfer, in byte(s) -@return status of register operation (LGW_REG_SUCCESS/LGW_REG_ERROR) -*/ -int lgw_reg_wb(uint16_t register_id, uint8_t *data, uint16_t size); - -/** -@brief Lora gateway register burst read -@param register_id register number in the data structure describing registers -@param data pointer to byte array that will be written from the Lora gateway -@param size size of the transfer, in byte(s) -@return status of register operation (LGW_REG_SUCCESS/LGW_REG_ERROR) -*/ -int lgw_reg_rb(uint16_t register_id, uint8_t *data, uint16_t size); - - -#endif - -/* --- EOF ------------------------------------------------------------------ */ diff --git a/loragw_hal/inc/loragw_spi.h b/loragw_hal/inc/loragw_spi.h deleted file mode 100644 index 68d8bcf..0000000 --- a/loragw_hal/inc/loragw_spi.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - / _____) _ | | -( (____ _____ ____ _| |_ _____ ____| |__ - \____ \| ___ | (_ _) ___ |/ ___) _ \ - _____) ) ____| | | || |_| ____( (___| | | | -(______/|_____)_|_|_| \__)_____)\____)_| |_| - ©2013 Semtech-Cycleo - -Description: - Host specific functions to address the LoRa™ gateway registers through a - SPI interface. - Single-byte read/write and burst read/write. - Does not handle pagination. - Could be used with multiple SPI ports in parallel (explicit file descriptor) -*/ - - -#ifndef _LORAGW_SPI_H -#define _LORAGW_SPI_H - -/* -------------------------------------------------------------------------- */ -/* --- DEPENDANCIES --------------------------------------------------------- */ - -#include /* C99 types*/ - -/* -------------------------------------------------------------------------- */ -/* --- PUBLIC CONSTANTS ----------------------------------------------------- */ - -#define LGW_SPI_SUCCESS 0 -#define LGW_SPI_ERROR -1 -#define LGW_BURST_CHUNK 1024 - -/* -------------------------------------------------------------------------- */ -/* --- PUBLIC FUNCTIONS PROTOTYPES ------------------------------------------ */ - -/** -@brief Lora gateway SPI setup (configure I/O and peripherals) -@param spi_target_ptr pointer on a generic pointer to SPI target (implementation dependant) -@return status of register operation (LGW_SPI_SUCCESS/LGW_SPI_ERROR) -*/ - -int lgw_spi_open(void **spi_target_ptr); - -/** -@brief Lora gateway SPI close -@param spi_target generic pointer to SPI target (implementation dependant) -@return status of register operation (LGW_SPI_SUCCESS/LGW_SPI_ERROR) -*/ - -int lgw_spi_close(void *spi_target); - -/** -@brief Lora gateway SPI single-byte write -@param spi_target generic pointer to SPI target (implementation dependant) -@param address 7-bit register address -@param data data byte to write -@return status of register operation (LGW_SPI_SUCCESS/LGW_SPI_ERROR) -*/ -int lgw_spi_w(void *spi_target, uint8_t address, uint8_t data); - -/** -@brief Lora gateway SPI single-byte read -@param spi_target generic pointer to SPI target (implementation dependant) -@param address 7-bit register address -@param data data byte to write -@return status of register operation (LGW_SPI_SUCCESS/LGW_SPI_ERROR) -*/ -int lgw_spi_r(void *spi_target, uint8_t address, uint8_t *data); - -/** -@brief Lora gateway SPI burst (multiple-byte) write -@param spi_target generic pointer to SPI target (implementation dependant) -@param address 7-bit register address -@param data pointer to byte array that will be sent to the Lora gateway -@param size size of the transfer, in byte(s) -@return status of register operation (LGW_SPI_SUCCESS/LGW_SPI_ERROR) -*/ -int lgw_spi_wb(void *spi_target, uint8_t address, uint8_t *data, uint16_t size); - -/** -@brief Lora gateway SPI burst (multiple-byte) read -@param spi_target generic pointer to SPI target (implementation dependant) -@param address 7-bit register address -@param data pointer to byte array that will be written from the Lora gateway -@param size size of the transfer, in byte(s) -@return status of register operation (LGW_SPI_SUCCESS/LGW_SPI_ERROR) -*/ -int lgw_spi_rb(void *spi_target, uint8_t address, uint8_t *data, uint16_t size); - -#endif - -/* --- EOF ------------------------------------------------------------------ */ diff --git a/loragw_hal/library.cfg b/loragw_hal/library.cfg deleted file mode 100644 index ac24416..0000000 --- a/loragw_hal/library.cfg +++ /dev/null @@ -1,26 +0,0 @@ -# / _____) _ | | -# ( (____ _____ ____ _| |_ _____ ____| |__ -# \____ \| ___ | (_ _) ___ |/ ___) _ \ -# _____) ) ____| | | || |_| ____( (___| | | | -# (______/|_____)_|_|_| \__)_____)\____)_| |_| -# ©2013 Semtech-Cycleo -# -# Description: -# Lora gateway Hardware Abstraction Layer library configuration - - -# Set the DEBUG_* to 1 to activate debug mode in individual modules. -# Warning: that makes the module *very verbose*, do not use for production -FLAG_AUX= -D DEBUG_AUX=0 -FLAG_SPI= -D DEBUG_SPI=0 -FLAG_REG= -D DEBUG_REG=0 -FLAG_HAL= -D DEBUG_HAL=0 - -# The flags bellow define which physical link to the nano board will be used -# Pick one and comment the other(s) - -# Pcduino native SPI (Linux device in /dev) -LGW_PHY= native - -# FTDI SPI-over-USB bridge -#LGW_PHY= ftdi diff --git a/loragw_hal/obj/.gitkeep b/loragw_hal/obj/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/loragw_hal/src/agc_fw.var b/loragw_hal/src/agc_fw.var deleted file mode 100644 index 7d30fb9..0000000 --- a/loragw_hal/src/agc_fw.var +++ /dev/null @@ -1,526 +0,0 @@ -/* - / _____) _ | | -( (____ _____ ____ _| |_ _____ ____| |__ - \____ \| ___ | (_ _) ___ |/ ___) _ \ - _____) ) ____| | | || |_| ____( (___| | | | -(______/|_____)_|_|_| \__)_____)\____)_| |_| - ©2013 Semtech-Cycleo - -Description: - AGC firmware -*/ - -static uint8_t agc_firmware[MCU_AGC_FW_BYTE] = { -0x8A, 0x51, 0x11, 0x28, 0xFF, 0xBF, 0xFF, 0xBF, 0x80, 0x40, 0x03, 0x4E, 0x83, 0x52, 0x03, 0x53, -0xA8, 0xC0, 0x04, 0x88, 0xA9, 0x00, 0x0A, 0xC8, 0xAA, 0x00, 0x01, 0x88, 0xAB, 0x40, 0x8A, 0x51, -0x79, 0x6E, 0x8A, 0x51, 0x3A, 0x2E, 0xA2, 0x70, 0x84, 0x80, 0x37, 0xF0, 0x83, 0x52, 0x03, 0x53, -0xB3, 0x40, 0x04, 0x88, 0xB4, 0x00, 0x08, 0xF0, 0xB5, 0x40, 0x33, 0x48, 0x84, 0x80, 0x83, 0x93, -0x00, 0x48, 0xB6, 0x40, 0xB3, 0xCA, 0x34, 0x08, 0x84, 0x80, 0x36, 0x48, 0x80, 0x40, 0xB4, 0x8A, -0xB5, 0x0B, 0x1D, 0xA8, 0x2B, 0xA8, 0x19, 0x54, 0x99, 0x50, 0x19, 0x95, 0x99, 0x91, 0x19, 0x52, -0x99, 0x92, 0x18, 0x56, 0x38, 0x68, 0x90, 0x30, 0xB3, 0x40, 0x33, 0x48, 0x8B, 0x00, 0x39, 0xA8, -0x8B, 0x41, 0x98, 0x10, 0x18, 0x11, 0x98, 0x51, 0x97, 0x81, 0x9C, 0x41, 0x9A, 0x41, 0x9B, 0x81, -0x9E, 0x81, 0x83, 0x96, 0x03, 0x53, 0xE4, 0x41, 0xE5, 0x81, 0xD2, 0x41, 0xD2, 0x8A, 0x0F, 0xB0, -0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, 0x03, 0x53, 0xDA, 0x40, 0xCA, 0x41, -0xD3, 0x81, 0xD3, 0xCA, 0x0C, 0x30, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, -0x03, 0x53, 0xDB, 0x80, 0x06, 0x30, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, -0x03, 0x53, 0xCB, 0x40, 0x02, 0xF0, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, -0x03, 0x53, 0xD4, 0x00, 0x0C, 0x30, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, -0x03, 0x53, 0xDC, 0x40, 0x0C, 0x30, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, -0x03, 0x53, 0xCC, 0x00, 0x03, 0x30, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, -0x03, 0x53, 0xD5, 0x40, 0x0C, 0x30, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, -0x03, 0x53, 0xDD, 0x80, 0x12, 0x30, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, -0x03, 0x53, 0xCD, 0x40, 0x04, 0xF0, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, -0x03, 0x53, 0xD6, 0x40, 0x0F, 0xB0, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, -0x03, 0x53, 0xDE, 0x80, 0x18, 0x30, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, -0x03, 0x53, 0xCE, 0x40, 0x04, 0xF0, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, -0x03, 0x53, 0xD7, 0x80, 0x0C, 0x30, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, -0x03, 0x53, 0xDF, 0xC0, 0x1E, 0xB0, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, -0x03, 0x53, 0xCF, 0x80, 0x05, 0x30, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, -0x03, 0x53, 0xD8, 0x00, 0x0C, 0x30, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, -0x03, 0x53, 0xE0, 0xC0, 0x24, 0x30, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, -0x03, 0x53, 0xD0, 0xC0, 0x05, 0x30, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, -0x03, 0x53, 0xD9, 0x40, 0x0C, 0x30, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, -0x03, 0x53, 0xE1, 0x00, 0x2A, 0x70, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, -0x03, 0x53, 0xD1, 0x00, 0xB2, 0x41, 0xB3, 0x81, 0xB4, 0x41, 0xB5, 0x81, 0xB6, 0x81, 0xB7, 0xC1, -0xB8, 0x41, 0xB9, 0x81, 0xBA, 0x81, 0x06, 0x30, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, -0x83, 0x96, 0x03, 0x53, 0xBB, 0x80, 0x0C, 0x30, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, -0x83, 0x96, 0x03, 0x53, 0xBC, 0x40, 0x12, 0x30, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, -0x83, 0x96, 0x03, 0x53, 0xBD, 0x80, 0x18, 0x30, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, -0x83, 0x96, 0x03, 0x53, 0xBE, 0x80, 0x1E, 0xB0, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, -0x83, 0x96, 0x03, 0x53, 0xBF, 0xC0, 0x24, 0x30, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, -0x83, 0x96, 0x03, 0x53, 0xC0, 0x80, 0x2A, 0x70, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, -0x83, 0x96, 0x03, 0x53, 0xC1, 0xC0, 0xEB, 0xC1, 0x02, 0xF0, 0x6B, 0x82, 0x03, 0x5C, 0x39, 0xE9, -0x3A, 0xE9, 0x3C, 0xE9, 0xB2, 0xE9, 0xB2, 0xE9, 0x6B, 0x88, 0xE8, 0x7E, 0x84, 0x80, 0x83, 0x93, -0x80, 0x81, 0x08, 0xF0, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x83, 0x96, 0x03, 0x53, 0x6B, 0x88, -0xE6, 0xBE, 0x84, 0x80, 0x83, 0x52, 0x03, 0x53, 0x33, 0x48, 0x80, 0x40, 0x83, 0x96, 0x03, 0x53, -0x6B, 0x88, 0xE8, 0x7E, 0x84, 0x80, 0x00, 0x48, 0xD2, 0x7E, 0x84, 0x80, 0x00, 0x48, 0x83, 0x52, -0x03, 0x53, 0xB3, 0x40, 0x05, 0x30, 0x03, 0xD0, 0xB3, 0x0D, 0xFF, 0x7E, 0x03, 0x9D, 0x5B, 0x29, -0x83, 0x96, 0x03, 0x53, 0x6B, 0x88, 0xE8, 0x7E, 0x84, 0x80, 0x00, 0x48, 0xDA, 0xBE, 0x84, 0x80, -0x00, 0x48, 0x83, 0x52, 0x03, 0x53, 0xB4, 0x00, 0x34, 0x87, 0x33, 0x44, 0xB5, 0x40, 0x35, 0x48, -0x83, 0x96, 0x03, 0x53, 0xA0, 0x80, 0x6B, 0x88, 0x83, 0x52, 0x03, 0x53, 0xB6, 0x40, 0x36, 0x48, -0x83, 0x96, 0x03, 0x53, 0xA1, 0xC0, 0x0C, 0x30, 0x8A, 0x51, 0x16, 0xA6, 0x8A, 0x51, 0x83, 0x52, -0x03, 0x53, 0x98, 0x95, 0x98, 0x51, 0x83, 0x96, 0x03, 0x53, 0x6B, 0x88, 0xE6, 0xBE, 0x84, 0x80, -0x83, 0x93, 0x00, 0x48, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x03, 0x30, 0x03, 0xD0, 0xB3, 0x0D, -0xFF, 0x7E, 0x03, 0x9D, 0x8E, 0xE9, 0x03, 0xD0, 0x33, 0xCD, 0xB4, 0x00, 0x34, 0x08, 0x96, 0x00, -0x83, 0x96, 0x03, 0x53, 0x6B, 0xD8, 0x9D, 0x29, 0xA1, 0xA9, 0x83, 0x52, 0x03, 0x53, 0x18, 0x14, -0xA4, 0xA9, 0x83, 0x52, 0x03, 0x53, 0x18, 0xD0, 0x18, 0x55, 0x18, 0x11, 0x01, 0xF0, 0xB3, 0x40, -0x33, 0x48, 0x83, 0x96, 0x03, 0x53, 0xEB, 0x47, 0x02, 0xF0, 0x6B, 0x82, 0x03, 0x5C, 0xB1, 0xE9, -0xB2, 0xE9, 0x3C, 0xE9, 0xEA, 0x81, 0x08, 0xF0, 0x6A, 0x42, 0x03, 0x5C, 0xB8, 0xE9, 0xB9, 0x29, -0xBB, 0x69, 0xF9, 0x69, 0xF9, 0x69, 0x07, 0x70, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x83, 0x96, -0x03, 0x53, 0x6A, 0x48, 0xC2, 0x3E, 0x84, 0x80, 0x83, 0x52, 0x03, 0x53, 0x33, 0x48, 0x83, 0x93, -0x80, 0x40, 0x83, 0x96, 0x03, 0x53, 0x6A, 0x48, 0xC2, 0x3E, 0x84, 0x80, 0x00, 0x48, 0x83, 0x52, -0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x96, 0x00, 0x83, 0x96, 0x03, 0x53, 0x6A, 0x48, 0xA2, 0x3E, -0x84, 0x80, 0x00, 0x48, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x95, 0x00, 0x98, 0x54, -0x98, 0x10, 0x01, 0xF0, 0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, 0x03, 0x53, 0xEA, 0x07, 0x08, 0xF0, -0x6A, 0x42, 0x03, 0x5C, 0xEC, 0x29, 0xED, 0x69, 0xBB, 0x69, 0xF9, 0x69, 0xF9, 0x69, 0xF9, 0x69, -0x83, 0x52, 0x03, 0x53, 0x18, 0x9E, 0xF5, 0x69, 0xF6, 0x69, 0x04, 0x2A, 0x18, 0x12, 0x2B, 0xA8, -0x04, 0x2A, 0x83, 0x52, 0x03, 0x53, 0x93, 0x5F, 0xFE, 0xA9, 0xFF, 0xE9, 0x04, 0x2A, 0x8A, 0x51, -0x38, 0x64, 0x8A, 0x51, 0x04, 0x2A, 0x04, 0x2A, 0x83, 0x96, 0x03, 0x53, 0x68, 0x08, 0xCA, 0x7E, -0x84, 0x80, 0x83, 0x93, 0x00, 0x48, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, -0x03, 0x53, 0xE4, 0x00, 0x66, 0x48, 0xB2, 0x7E, 0x84, 0x80, 0x00, 0x48, 0x83, 0x52, 0x03, 0x53, -0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, 0x03, 0x53, 0xE5, 0x40, 0x83, 0x52, 0x03, 0x53, 0x1E, 0x48, -0x01, 0xBE, 0xB3, 0x40, 0x33, 0x48, 0x9E, 0x40, 0x83, 0x96, 0x03, 0x53, 0x65, 0x48, 0x64, 0x87, -0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x97, 0x40, 0x83, 0x96, 0x03, 0x53, 0x69, 0x48, -0xCA, 0x7E, 0x84, 0x80, 0x00, 0x48, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, -0x03, 0x53, 0xE4, 0x00, 0x67, 0x88, 0xB2, 0x7E, 0x84, 0x80, 0x00, 0x48, 0x83, 0x52, 0x03, 0x53, -0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, 0x03, 0x53, 0xE5, 0x40, 0x65, 0x48, 0x64, 0x87, 0x83, 0x52, -0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x9C, 0x00, 0x17, 0x48, 0xB3, 0x40, 0x33, 0x48, 0x9A, 0x00, -0x83, 0x96, 0x03, 0x53, 0xEA, 0x81, 0x08, 0xF0, 0x6A, 0x42, 0x03, 0x5C, 0x58, 0xAA, 0x59, 0xEA, -0x5B, 0x2A, 0xE3, 0x2A, 0xE3, 0x2A, 0x6A, 0x48, 0xA2, 0x3E, 0x84, 0x80, 0x00, 0x48, 0x83, 0x52, -0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x95, 0x00, 0x0D, 0x08, 0xB3, 0x40, 0x83, 0x96, 0x03, 0x53, -0x6A, 0x48, 0xAA, 0x7E, 0x84, 0x80, 0x83, 0x52, 0x03, 0x53, 0x33, 0x48, 0x80, 0x40, 0x83, 0x96, -0x03, 0x53, 0x6A, 0x48, 0xAA, 0x7E, 0x84, 0x80, 0x88, 0x30, 0x00, 0x42, 0x03, 0x5C, 0x79, 0x2A, -0x7A, 0x2A, 0xA2, 0xAA, 0x6A, 0x48, 0xC2, 0x3E, 0x84, 0x80, 0x0F, 0xB0, 0x00, 0x42, 0x03, 0x18, -0x82, 0x6A, 0x83, 0xAA, 0xA2, 0xAA, 0x6A, 0x48, 0xC2, 0x3E, 0x84, 0x80, 0x00, 0x48, 0x01, 0xBE, -0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x83, 0x96, 0x03, 0x53, 0x6A, 0x48, 0xC2, 0x3E, 0x84, 0x80, -0x83, 0x52, 0x03, 0x53, 0x33, 0x48, 0x80, 0x40, 0x83, 0x96, 0x03, 0x53, 0x6A, 0x48, 0xC2, 0x3E, -0x84, 0x80, 0x00, 0x48, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x33, 0x48, 0x96, 0x00, 0x98, 0x54, -0x98, 0x10, 0xD6, 0x2A, 0x83, 0x96, 0x03, 0x53, 0x6A, 0x48, 0xAA, 0x7E, 0x84, 0x80, 0x2D, 0xB0, -0x00, 0x42, 0x03, 0x18, 0xAC, 0xEA, 0xAD, 0x2A, 0xD6, 0x2A, 0x6A, 0x48, 0xC2, 0x3E, 0x84, 0x80, -0x08, 0xF0, 0x00, 0x42, 0x03, 0x5C, 0xB5, 0x2A, 0xB6, 0x2A, 0xD6, 0x2A, 0x6A, 0x48, 0xC2, 0x3E, -0x84, 0x80, 0x00, 0x48, 0xFF, 0x7E, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x83, 0x96, 0x03, 0x53, -0x6A, 0x48, 0xC2, 0x3E, 0x84, 0x80, 0x83, 0x52, 0x03, 0x53, 0x33, 0x48, 0x80, 0x40, 0x83, 0x96, -0x03, 0x53, 0x6A, 0x48, 0xC2, 0x3E, 0x84, 0x80, 0x00, 0x48, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, -0x33, 0x48, 0x96, 0x00, 0x98, 0x54, 0x98, 0x10, 0xD6, 0x2A, 0xD6, 0x2A, 0x01, 0xF0, 0x83, 0x52, -0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, 0x03, 0x53, 0xEA, 0x07, 0x08, 0xF0, 0x6A, 0x42, 0x03, 0x5C, -0xE2, 0xEA, 0xE3, 0x2A, 0x5B, 0x2A, 0xEB, 0xC1, 0x02, 0xF0, 0x6B, 0x82, 0x03, 0x5C, 0xE9, 0x2A, -0xEA, 0x2A, 0xEC, 0x2A, 0xF9, 0x69, 0xF9, 0x69, 0x6B, 0xD8, 0xEF, 0xAA, 0xF3, 0x6A, 0x83, 0x52, -0x03, 0x53, 0x18, 0x14, 0xF6, 0x6A, 0x83, 0x52, 0x03, 0x53, 0x18, 0xD0, 0x0E, 0x08, 0xB3, 0x40, -0x33, 0x48, 0x83, 0x96, 0x03, 0x53, 0xE3, 0x40, 0x88, 0x30, 0x63, 0x42, 0x03, 0x5C, 0x01, 0x6B, -0x02, 0x6B, 0x34, 0xEB, 0x6B, 0x88, 0xE6, 0xBE, 0x84, 0x80, 0x0B, 0x70, 0x83, 0x93, 0x00, 0x42, -0x03, 0x18, 0x0B, 0xEB, 0x0C, 0xAB, 0x34, 0xEB, 0x6B, 0x88, 0xE6, 0xBE, 0x84, 0x80, 0x00, 0x48, -0x01, 0xBE, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x83, 0x96, 0x03, 0x53, 0x6B, 0x88, 0xE6, 0xBE, -0x84, 0x80, 0x83, 0x52, 0x03, 0x53, 0x33, 0x48, 0x80, 0x40, 0x83, 0x96, 0x03, 0x53, 0x6B, 0x88, -0xE6, 0xBE, 0x84, 0x80, 0x00, 0x48, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x03, 0x30, 0x03, 0xD0, -0xB3, 0x0D, 0xFF, 0x7E, 0x03, 0x9D, 0x27, 0x2B, 0x03, 0xD0, 0x33, 0xCD, 0xB4, 0x00, 0x34, 0x08, -0x96, 0x00, 0x18, 0x55, 0x18, 0x11, 0x6F, 0xAB, 0x2D, 0xB0, 0x83, 0x96, 0x03, 0x53, 0x63, 0x42, -0x03, 0x18, 0x3B, 0x6B, 0x3C, 0x2B, 0x6F, 0xAB, 0x6B, 0x88, 0xE6, 0xBE, 0x84, 0x80, 0x09, 0x30, -0x83, 0x93, 0x00, 0x42, 0x03, 0x5C, 0x45, 0xEB, 0x46, 0xEB, 0x6F, 0xAB, 0x6B, 0x88, 0xE6, 0xBE, -0x84, 0x80, 0x00, 0x48, 0xFF, 0x7E, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x83, 0x96, 0x03, 0x53, -0x6B, 0x88, 0xE6, 0xBE, 0x84, 0x80, 0x83, 0x52, 0x03, 0x53, 0x33, 0x48, 0x80, 0x40, 0x83, 0x96, -0x03, 0x53, 0x6B, 0x88, 0xE6, 0xBE, 0x84, 0x80, 0x00, 0x48, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, -0x03, 0x30, 0x03, 0xD0, 0xB3, 0x0D, 0xFF, 0x7E, 0x03, 0x9D, 0x61, 0xEB, 0x03, 0xD0, 0x33, 0xCD, -0xB4, 0x00, 0x34, 0x08, 0x96, 0x00, 0x18, 0x55, 0x18, 0x11, 0x6F, 0xAB, 0x6F, 0xAB, 0x83, 0x52, -0x0F, 0x48, 0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, 0x03, 0x53, 0xE2, 0x00, 0x29, 0x70, 0x62, 0x02, -0x03, 0x5C, 0x7B, 0xAB, 0x7C, 0x6B, 0xCD, 0x6B, 0x6B, 0x88, 0xE8, 0x7E, 0x84, 0x80, 0x07, 0x70, -0x83, 0x93, 0x00, 0x42, 0x03, 0x18, 0x85, 0xEB, 0x86, 0xEB, 0xCD, 0x6B, 0x6B, 0x88, 0xE8, 0x7E, -0x84, 0x80, 0x00, 0x48, 0x01, 0xBE, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x83, 0x96, 0x03, 0x53, -0x6B, 0x88, 0xE8, 0x7E, 0x84, 0x80, 0x83, 0x52, 0x03, 0x53, 0x33, 0x48, 0x80, 0x40, 0x83, 0x96, -0x03, 0x53, 0x6B, 0x88, 0xE8, 0x7E, 0x84, 0x80, 0x00, 0x48, 0xD2, 0x7E, 0x84, 0x80, 0x00, 0x48, -0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x05, 0x30, 0x03, 0xD0, 0xB3, 0x0D, 0xFF, 0x7E, 0x03, 0x9D, -0xA4, 0xEB, 0x83, 0x96, 0x03, 0x53, 0x6B, 0x88, 0xE8, 0x7E, 0x84, 0x80, 0x00, 0x48, 0xDA, 0xBE, -0x84, 0x80, 0x00, 0x48, 0x83, 0x52, 0x03, 0x53, 0xB4, 0x00, 0x34, 0x87, 0x33, 0x44, 0xB5, 0x40, -0x35, 0x48, 0x83, 0x96, 0x03, 0x53, 0xA0, 0x80, 0x6B, 0x88, 0x83, 0x52, 0x03, 0x53, 0xB6, 0x40, -0x36, 0x48, 0x83, 0x96, 0x03, 0x53, 0xA1, 0xC0, 0x0C, 0x30, 0x8A, 0x51, 0x16, 0xA6, 0x8A, 0x51, -0x83, 0x52, 0x03, 0x53, 0x98, 0x95, 0x98, 0x51, 0x26, 0xAC, 0x0F, 0xB0, 0x83, 0x96, 0x03, 0x53, -0x62, 0x02, 0x03, 0x18, 0xD4, 0x2B, 0xD5, 0x6B, 0x26, 0xAC, 0x6B, 0x88, 0xE8, 0x7E, 0x84, 0x80, -0x83, 0x93, 0x80, 0x88, 0x03, 0x59, 0xDD, 0xAB, 0xDE, 0xAB, 0x26, 0xAC, 0x6B, 0x88, 0xE8, 0x7E, -0x84, 0x80, 0x00, 0x48, 0xFF, 0x7E, 0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x83, 0x96, 0x03, 0x53, -0x6B, 0x88, 0xE8, 0x7E, 0x84, 0x80, 0x83, 0x52, 0x03, 0x53, 0x33, 0x48, 0x80, 0x40, 0x83, 0x96, -0x03, 0x53, 0x6B, 0x88, 0xE8, 0x7E, 0x84, 0x80, 0x00, 0x48, 0xD2, 0x7E, 0x84, 0x80, 0x00, 0x48, -0x83, 0x52, 0x03, 0x53, 0xB3, 0x40, 0x05, 0x30, 0x03, 0xD0, 0xB3, 0x0D, 0xFF, 0x7E, 0x03, 0x9D, -0xFC, 0xAB, 0x83, 0x96, 0x03, 0x53, 0x6B, 0x88, 0xE8, 0x7E, 0x84, 0x80, 0x00, 0x48, 0xDA, 0xBE, -0x84, 0x80, 0x00, 0x48, 0x83, 0x52, 0x03, 0x53, 0xB4, 0x00, 0x34, 0x87, 0x33, 0x44, 0xB5, 0x40, -0x35, 0x48, 0x83, 0x96, 0x03, 0x53, 0xA0, 0x80, 0x6B, 0x88, 0x83, 0x52, 0x03, 0x53, 0xB6, 0x40, -0x36, 0x48, 0x83, 0x96, 0x03, 0x53, 0xA1, 0xC0, 0x0C, 0x30, 0x8A, 0x51, 0x16, 0xA6, 0x8A, 0x51, -0x83, 0x52, 0x03, 0x53, 0x98, 0x95, 0x98, 0x51, 0x26, 0xAC, 0x26, 0xAC, 0x01, 0xF0, 0x83, 0x52, -0xB3, 0x40, 0x33, 0x48, 0x83, 0x96, 0x03, 0x53, 0xEB, 0x47, 0x02, 0xF0, 0x6B, 0x82, 0x03, 0x5C, -0x32, 0xAC, 0x33, 0xEC, 0xEC, 0x2A, 0xF9, 0x69, 0xF9, 0x69, 0xF9, 0x69, 0x8A, 0x51, 0x11, 0x28, -0x83, 0x52, 0x03, 0x53, 0x18, 0x12, 0x00, 0xB0, 0x13, 0xDB, 0x01, 0xF0, 0xAE, 0x40, 0x2E, 0x48, -0xB2, 0x00, 0x00, 0xB0, 0x18, 0x18, 0x01, 0xF0, 0xAE, 0x40, 0x2E, 0x48, 0xB0, 0xC0, 0x32, 0x58, -0x4A, 0xAC, 0x4E, 0xEC, 0x83, 0x52, 0x03, 0x53, 0x18, 0x14, 0x51, 0xAC, 0x83, 0x52, 0x03, 0x53, -0x18, 0xD0, 0x12, 0xC8, 0xAE, 0x40, 0x2E, 0x48, 0x83, 0x96, 0x03, 0x53, 0xA0, 0x80, 0x83, 0x52, -0x03, 0x53, 0x32, 0x08, 0xAF, 0x80, 0x2F, 0x88, 0x83, 0x96, 0x03, 0x53, 0xA1, 0xC0, 0x04, 0xF0, -0x8A, 0x51, 0x16, 0xA6, 0x8A, 0x51, 0x83, 0x52, 0x03, 0x53, 0x11, 0xC8, 0xAE, 0x40, 0x2E, 0x48, -0x83, 0x96, 0x03, 0x53, 0xA0, 0x80, 0x83, 0x52, 0x03, 0x53, 0x32, 0x08, 0xAF, 0x80, 0x2F, 0x88, -0x83, 0x96, 0x03, 0x53, 0xA1, 0xC0, 0x05, 0x30, 0x8A, 0x51, 0x16, 0xA6, 0x8A, 0x51, 0x83, 0x52, -0x03, 0x53, 0x10, 0x88, 0xAE, 0x40, 0x2E, 0x48, 0x83, 0x96, 0x03, 0x53, 0xA0, 0x80, 0x83, 0x52, -0x03, 0x53, 0x32, 0x08, 0xAF, 0x80, 0x2F, 0x88, 0x83, 0x96, 0x03, 0x53, 0xA1, 0xC0, 0x06, 0x30, -0x8A, 0x51, 0x16, 0xA6, 0x8A, 0x51, 0x07, 0x70, 0x83, 0x52, 0x03, 0x53, 0xAE, 0x40, 0x2E, 0x48, -0x83, 0x96, 0x03, 0x53, 0xA0, 0x80, 0x83, 0x52, 0x03, 0x53, 0x32, 0x08, 0xAF, 0x80, 0x2F, 0x88, -0x83, 0x96, 0x03, 0x53, 0xA1, 0xC0, 0x00, 0xB0, 0x8A, 0x51, 0x16, 0xA6, 0x8A, 0x51, 0x83, 0x52, -0x03, 0x53, 0x93, 0x1D, 0xA4, 0xAC, 0xA5, 0xEC, 0xB8, 0xEC, 0x1D, 0xB0, 0xAE, 0x40, 0x2E, 0x48, -0x83, 0x96, 0x03, 0x53, 0xA0, 0x80, 0x83, 0x52, 0x03, 0x53, 0x32, 0x08, 0xAF, 0x80, 0x2F, 0x88, -0x83, 0x96, 0x03, 0x53, 0xA1, 0xC0, 0x08, 0xF0, 0x8A, 0x51, 0x16, 0xA6, 0x8A, 0x51, 0xCC, 0xEC, -0x3B, 0xF0, 0x83, 0x52, 0x03, 0x53, 0xAE, 0x40, 0x2E, 0x48, 0x83, 0x96, 0x03, 0x53, 0xA0, 0x80, -0x83, 0x52, 0x03, 0x53, 0x32, 0x08, 0xAF, 0x80, 0x2F, 0x88, 0x83, 0x96, 0x03, 0x53, 0xA1, 0xC0, -0x08, 0xF0, 0x8A, 0x51, 0x16, 0xA6, 0x8A, 0x51, 0x0F, 0xB0, 0x83, 0x52, 0x03, 0x53, 0xAE, 0x40, -0x2E, 0x48, 0x83, 0x96, 0x03, 0x53, 0xA0, 0x80, 0x83, 0x52, 0x03, 0x53, 0x32, 0x08, 0xAF, 0x80, -0x2F, 0x88, 0x83, 0x96, 0x03, 0x53, 0xA1, 0xC0, 0x00, 0xB0, 0x8A, 0x51, 0x16, 0xA6, 0x8A, 0x51, -0x83, 0x52, 0x03, 0x53, 0x19, 0x52, 0x99, 0x92, 0x32, 0x08, 0x03, 0x9D, 0xE8, 0xEC, 0xEB, 0x6C, -0x19, 0x51, 0x99, 0xD5, 0xED, 0x6C, 0x19, 0x10, 0x99, 0x94, 0x93, 0x1D, 0xF0, 0xEC, 0xF4, 0x2C, -0x83, 0x52, 0x03, 0x53, 0x19, 0x96, 0xF7, 0xAC, 0x83, 0x52, 0x03, 0x53, 0x19, 0x52, 0x93, 0xD9, -0xFA, 0x6C, 0xFE, 0xAC, 0x83, 0x52, 0x03, 0x53, 0x99, 0xD6, 0x01, 0x6D, 0x83, 0x52, 0x03, 0x53, -0x99, 0x92, 0x02, 0x6D, 0x93, 0x1B, 0x05, 0xAD, 0x06, 0xAD, 0x02, 0x6D, 0x07, 0xED, 0x32, 0x08, -0x03, 0x9D, 0x0B, 0xED, 0x0E, 0xED, 0x99, 0x91, 0x19, 0x95, 0x11, 0xAD, 0x99, 0x50, 0x19, 0x54, -0x11, 0xAD, 0x03, 0x30, 0xAE, 0x40, 0x2E, 0x48, 0x83, 0x96, 0x03, 0x53, 0xA0, 0x80, 0x83, 0x52, -0x03, 0x53, 0x32, 0x08, 0xAF, 0x80, 0x2F, 0x88, 0x83, 0x96, 0x03, 0x53, 0xA1, 0xC0, 0x00, 0xB0, -0x8A, 0x51, 0x16, 0xA6, 0x8A, 0x51, 0x83, 0x52, 0x03, 0x53, 0xB1, 0x41, 0x2D, 0x2D, 0x31, 0x08, -0x01, 0xBE, 0xAE, 0x40, 0x2E, 0x48, 0xB1, 0x00, 0x2D, 0x2D, 0x64, 0x70, 0x31, 0x02, 0x03, 0x5C, -0x32, 0xED, 0x33, 0x2D, 0x27, 0x2D, 0x18, 0x56, 0x30, 0x18, 0x37, 0x6D, 0x3B, 0x6D, 0x83, 0x52, -0x03, 0x53, 0x18, 0x14, 0x3E, 0x6D, 0x83, 0x52, 0x03, 0x53, 0x18, 0xD0, 0x08, 0x40, 0x83, 0x52, -0x03, 0x53, 0x18, 0x12, 0x00, 0xB0, 0x13, 0xDB, 0x01, 0xF0, 0xA2, 0xC0, 0x22, 0xC8, 0xA6, 0x00, -0x00, 0xB0, 0x18, 0x18, 0x01, 0xF0, 0xA2, 0xC0, 0x22, 0xC8, 0xA4, 0xC0, 0x26, 0x58, 0x51, 0xED, -0x55, 0x2D, 0x83, 0x52, 0x03, 0x53, 0x18, 0x14, 0x58, 0xED, 0x83, 0x52, 0x03, 0x53, 0x18, 0xD0, -0x12, 0xC8, 0xA2, 0xC0, 0x22, 0xC8, 0xBF, 0xC0, 0x26, 0x08, 0xA3, 0x00, 0x23, 0x08, 0xC0, 0x80, -0x04, 0xF0, 0x8A, 0x51, 0x5D, 0x26, 0x8A, 0x51, 0x83, 0x52, 0x03, 0x53, 0x11, 0xC8, 0xA2, 0xC0, -0x22, 0xC8, 0xBF, 0xC0, 0x26, 0x08, 0xA3, 0x00, 0x23, 0x08, 0xC0, 0x80, 0x05, 0x30, 0x8A, 0x51, -0x5D, 0x26, 0x8A, 0x51, 0x83, 0x52, 0x03, 0x53, 0x10, 0x88, 0xA2, 0xC0, 0x22, 0xC8, 0xBF, 0xC0, -0x26, 0x08, 0xA3, 0x00, 0x23, 0x08, 0xC0, 0x80, 0x06, 0x30, 0x8A, 0x51, 0x5D, 0x26, 0x8A, 0x51, -0x07, 0x70, 0x83, 0x52, 0x03, 0x53, 0xA2, 0xC0, 0x22, 0xC8, 0xBF, 0xC0, 0x26, 0x08, 0xA3, 0x00, -0x23, 0x08, 0xC0, 0x80, 0x00, 0xB0, 0x8A, 0x51, 0x5D, 0x26, 0x8A, 0x51, 0x83, 0x52, 0x03, 0x53, -0x93, 0x1D, 0x93, 0x2D, 0x94, 0xED, 0xA1, 0xED, 0x1D, 0xB0, 0xA2, 0xC0, 0x22, 0xC8, 0xBF, 0xC0, -0x26, 0x08, 0xA3, 0x00, 0x23, 0x08, 0xC0, 0x80, 0x08, 0xF0, 0x8A, 0x51, 0x5D, 0x26, 0x8A, 0x51, -0xAF, 0xAD, 0x3B, 0xF0, 0x83, 0x52, 0x03, 0x53, 0xA2, 0xC0, 0x22, 0xC8, 0xBF, 0xC0, 0x26, 0x08, -0xA3, 0x00, 0x23, 0x08, 0xC0, 0x80, 0x08, 0xF0, 0x8A, 0x51, 0x5D, 0x26, 0x8A, 0x51, 0x0F, 0xB0, -0x83, 0x52, 0x03, 0x53, 0xA2, 0xC0, 0x22, 0xC8, 0xBF, 0xC0, 0x26, 0x08, 0xA3, 0x00, 0x23, 0x08, -0xC0, 0x80, 0x00, 0xB0, 0x8A, 0x51, 0x5D, 0x26, 0x8A, 0x51, 0x83, 0x52, 0x03, 0x53, 0x19, 0x52, -0x99, 0x92, 0x26, 0x08, 0x03, 0x9D, 0xC5, 0x2D, 0xC8, 0xED, 0x19, 0x51, 0x99, 0xD5, 0xCA, 0x2D, -0x19, 0x10, 0x99, 0x94, 0x93, 0x1D, 0xCD, 0x6D, 0xD1, 0x2D, 0x83, 0x52, 0x03, 0x53, 0x19, 0x96, -0xD4, 0x2D, 0x83, 0x52, 0x03, 0x53, 0x19, 0x52, 0x93, 0xD9, 0xD7, 0xAD, 0xDB, 0xAD, 0x83, 0x52, -0x03, 0x53, 0x99, 0xD6, 0xDE, 0xAD, 0x83, 0x52, 0x03, 0x53, 0x99, 0x92, 0xDF, 0xED, 0x93, 0x1B, -0xE2, 0x2D, 0xE3, 0x6D, 0xDF, 0xED, 0xE4, 0x2D, 0x26, 0x08, 0x03, 0x9D, 0xE8, 0x2D, 0xEB, 0xAD, -0x99, 0x91, 0x19, 0x95, 0xEE, 0xAD, 0x99, 0x50, 0x19, 0x54, 0xEE, 0xAD, 0x03, 0x30, 0xA2, 0xC0, -0x22, 0xC8, 0xBF, 0xC0, 0x26, 0x08, 0xA3, 0x00, 0x23, 0x08, 0xC0, 0x80, 0x00, 0xB0, 0x8A, 0x51, -0x5D, 0x26, 0x8A, 0x51, 0x83, 0x52, 0x03, 0x53, 0xA5, 0x41, 0x04, 0x6E, 0x25, 0x08, 0x01, 0xBE, -0xA2, 0xC0, 0x22, 0xC8, 0xA5, 0x00, 0x04, 0x6E, 0x64, 0x70, 0x25, 0x02, 0x03, 0x5C, 0x09, 0xAE, -0x0A, 0xAE, 0xFE, 0xED, 0x18, 0x56, 0x24, 0x18, 0x0E, 0xEE, 0x12, 0xAE, 0x83, 0x52, 0x03, 0x53, -0x18, 0x14, 0x15, 0xEE, 0x83, 0x52, 0x03, 0x53, 0x18, 0xD0, 0x08, 0x40, 0x83, 0x52, 0x03, 0x53, -0xAD, 0x40, 0x83, 0x96, 0x03, 0x53, 0x21, 0xC8, 0x03, 0x9D, 0x1F, 0x6E, 0x2B, 0x2E, 0x20, 0x88, -0x83, 0x52, 0x03, 0x53, 0xAC, 0x00, 0x2C, 0x08, 0x88, 0x80, 0x2D, 0x48, 0x80, 0x38, 0xAC, 0x00, -0x2C, 0x08, 0x86, 0xC0, 0x39, 0x2E, 0x83, 0x96, 0x03, 0x53, 0x20, 0x88, 0x83, 0x52, 0x03, 0x53, -0xAC, 0x00, 0x2C, 0x08, 0x88, 0x80, 0x2D, 0x48, 0x80, 0x38, 0xAC, 0x00, 0x2C, 0x08, 0x85, 0xC0, -0x39, 0x2E, 0x08, 0x40, 0x8A, 0x51, 0x92, 0xA6, 0x8A, 0x51, 0xB7, 0x80, 0x8A, 0x51, 0x93, 0xE6, -0x8A, 0x51, 0xB8, 0x00, 0x8A, 0x51, 0x94, 0xA6, 0x8A, 0x51, 0xB9, 0x40, 0x8A, 0x51, 0x95, 0xE6, -0x8A, 0x51, 0xBA, 0x40, 0x8A, 0x51, 0x96, 0xE6, 0x8A, 0x51, 0xBB, 0x80, 0x8A, 0x51, 0x97, 0x26, -0x8A, 0x51, 0xBC, 0x40, 0x8A, 0x51, 0x98, 0xA6, 0x8A, 0x51, 0xBD, 0x80, 0x8A, 0x51, 0x99, 0xE6, -0x8A, 0x51, 0xBE, 0x80, 0x83, 0x01, 0x8A, 0x51, 0x13, 0x68, 0x83, 0x52, 0x03, 0x53, 0xA1, 0xC0, -0x40, 0x88, 0x03, 0x9D, 0x64, 0xEE, 0x6E, 0x6E, 0x3F, 0xC8, 0xA0, 0x80, 0x20, 0x88, 0x88, 0x80, -0x21, 0xC8, 0x80, 0x38, 0xA0, 0x80, 0x20, 0x88, 0x86, 0xC0, 0x78, 0x2E, 0x3F, 0xC8, 0xA0, 0x80, -0x20, 0x88, 0x88, 0x80, 0x21, 0xC8, 0x80, 0x38, 0xA0, 0x80, 0x20, 0x88, 0x85, 0xC0, 0x78, 0x2E, -0x08, 0x40, 0x8B, 0xDC, 0x7C, 0x6E, 0x7D, 0xAE, 0x81, 0xAE, 0x8A, 0x51, 0x3F, 0x65, 0x8A, 0x51, -0x81, 0xAE, 0x10, 0xF0, 0x83, 0x52, 0x03, 0x53, 0xA7, 0x40, 0x27, 0x48, 0x8B, 0x00, 0x2B, 0x48, -0x81, 0x80, 0x2A, 0x08, 0x8A, 0xC0, 0x29, 0x08, 0x84, 0x80, 0x28, 0x4E, 0x83, 0xC0, 0x80, 0x0E, -0x00, 0xCE, 0x09, 0x80, 0x00, 0xF4, 0x01, 0x34, 0x02, 0x34, 0x03, 0x74, 0x04, 0x34, 0x05, 0x74, -0x06, 0x74, 0x07, 0xB4, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF -}; diff --git a/loragw_hal/src/arb_fw.var b/loragw_hal/src/arb_fw.var deleted file mode 100644 index 014a8e5..0000000 --- a/loragw_hal/src/arb_fw.var +++ /dev/null @@ -1,526 +0,0 @@ -/* - / _____) _ | | -( (____ _____ ____ _| |_ _____ ____| |__ - \____ \| ___ | (_ _) ___ |/ ___) _ \ - _____) ) ____| | | || |_| ____( (___| | | | -(______/|_____)_|_|_| \__)_____)\____)_| |_| - ©2013 Semtech-Cycleo - -Description: - Arbiter firmware -*/ - -static uint8_t arb_firmware[MCU_ARB_FW_BYTE] = { -0x8A, 0x51, 0x0E, 0xEE, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0x64, 0xC0, 0x80, 0x81, -0x84, 0x0A, 0x04, 0xC6, 0x03, 0x59, 0x00, 0xF4, 0x04, 0xC6, 0x07, 0xEE, 0xDC, 0x81, 0x83, 0x93, -0x20, 0xF0, 0x84, 0x80, 0x57, 0xF0, 0x8A, 0x51, 0x06, 0x66, 0x8A, 0x51, 0xDD, 0xC1, 0xDE, 0xC1, -0xA0, 0x30, 0x84, 0x80, 0xA9, 0xB0, 0x8A, 0x51, 0x06, 0x66, 0x83, 0x01, 0x8A, 0x51, 0x44, 0xAE, -0x83, 0x52, 0xD7, 0x80, 0xDC, 0x90, 0x96, 0x00, 0x57, 0x88, 0x96, 0x00, 0x57, 0x88, 0x96, 0x00, -0x57, 0x88, 0x96, 0x00, 0x8D, 0xDC, 0x08, 0x40, 0x15, 0x54, 0xDC, 0xD4, 0x0D, 0xDD, 0x2E, 0x2E, -0x10, 0x88, 0x83, 0x96, 0xA6, 0x00, 0x83, 0x52, 0x11, 0xC8, 0x83, 0x96, 0xA7, 0x40, 0x83, 0x52, -0x0F, 0x48, 0x83, 0x96, 0xA8, 0xC0, 0x83, 0x52, 0x0E, 0x08, 0x83, 0x96, 0xA4, 0xC0, 0x83, 0x52, -0x12, 0xC8, 0xDD, 0x80, 0x15, 0x10, 0x08, 0x40, 0x8A, 0x51, 0x99, 0xE6, 0x8A, 0x51, 0x83, 0x52, -0x0D, 0x58, 0x61, 0xEE, 0x83, 0x96, 0xA5, 0x41, 0x08, 0xF0, 0x25, 0x02, 0x03, 0x18, 0x47, 0x2E, -0x83, 0x52, 0x5C, 0x94, 0x83, 0x96, 0x25, 0x08, 0x8A, 0x51, 0x20, 0x26, 0x8A, 0x51, 0xDC, 0x1C, -0x5C, 0x2E, 0x8A, 0x51, 0xF0, 0xE6, 0x8A, 0x51, 0x0D, 0x58, 0x47, 0x2E, 0x83, 0x96, 0xA5, 0x8A, -0x4C, 0xEE, 0x5C, 0xDC, 0x47, 0x2E, 0x8A, 0x51, 0x68, 0xA6, 0x8A, 0x51, 0x5C, 0x50, 0x47, 0x2E, -0xDE, 0xC1, 0x08, 0xF0, 0x5E, 0x82, 0x03, 0x18, 0x08, 0x40, 0x5E, 0x88, 0x28, 0xFE, 0x84, 0x80, -0x83, 0x93, 0x00, 0xCB, 0x97, 0x6E, 0x5E, 0x88, 0x28, 0xFE, 0x84, 0x80, 0x80, 0x81, 0x5E, 0x88, -0x40, 0xBE, 0x84, 0x80, 0x00, 0x48, 0x97, 0x40, 0x5E, 0x88, 0x20, 0xBE, 0x84, 0x80, 0x00, 0x48, -0x98, 0xC0, 0x5E, 0x88, 0x30, 0xFE, 0x84, 0x80, 0x00, 0x48, 0x99, 0x00, 0x5E, 0x88, 0x38, 0x3E, -0x84, 0x80, 0x00, 0x48, 0x9A, 0x00, 0x5E, 0x88, 0x9B, 0x40, 0x5E, 0x88, 0x48, 0xFE, 0x84, 0x80, -0x00, 0x48, 0x9C, 0x00, 0x95, 0x94, 0x95, 0x94, 0x95, 0x94, 0x95, 0x94, 0x95, 0x50, 0xDE, 0x0A, -0x69, 0x2E, 0x95, 0x41, 0x96, 0x41, 0x97, 0x81, 0x98, 0x01, 0x99, 0x41, 0x9A, 0x41, 0x9B, 0x81, -0x9C, 0x41, 0x9E, 0x81, 0xDE, 0xC1, 0x08, 0xF0, 0x5E, 0x82, 0x03, 0x18, 0xC1, 0xEE, 0x5E, 0x88, -0x30, 0xFE, 0x84, 0x80, 0x80, 0x81, 0x5E, 0x88, 0x38, 0x3E, 0x84, 0x80, 0x80, 0x81, 0x5E, 0x88, -0x48, 0xFE, 0x84, 0x80, 0x80, 0x81, 0x5E, 0x88, 0x20, 0xBE, 0x84, 0x80, 0x80, 0x81, 0x5E, 0x88, -0x40, 0xBE, 0x84, 0x80, 0x80, 0x81, 0x5E, 0x88, 0x28, 0xFE, 0x84, 0x80, 0x80, 0x81, 0xDE, 0x0A, -0xA3, 0x2E, 0x83, 0x96, 0xA5, 0x41, 0x83, 0x52, 0x5C, 0x50, 0xDC, 0x90, 0x5C, 0x91, 0x83, 0x96, -0xA8, 0x01, 0xA0, 0xC1, 0xA1, 0x01, 0xA2, 0x01, 0xA3, 0x41, 0x83, 0x52, 0x97, 0x81, 0x98, 0x01, -0x99, 0x41, 0x9A, 0x41, 0x9B, 0x81, 0x9C, 0x41, 0x83, 0x96, 0xA6, 0x41, 0xA7, 0x81, 0xA8, 0x01, -0xA4, 0x01, 0x83, 0x52, 0xDD, 0xC1, 0xDE, 0xC1, 0x83, 0x96, 0xA5, 0x41, 0x83, 0x52, 0x02, 0xF0, -0x5C, 0x50, 0xDC, 0x90, 0x5C, 0x91, 0xD0, 0xC0, 0x03, 0x30, 0xD1, 0x00, 0xD2, 0x00, 0x04, 0xF0, -0xD3, 0x40, 0x05, 0x30, 0xD4, 0x00, 0x06, 0x30, 0xD5, 0x40, 0x07, 0x70, 0xD6, 0x40, 0x08, 0x40, -0x5C, 0x91, 0xDE, 0xC1, 0x08, 0xF0, 0x5E, 0x82, 0x03, 0x18, 0xA2, 0x2F, 0x0A, 0x30, 0x83, 0x96, -0x28, 0xC2, 0x83, 0x52, 0x03, 0x5C, 0x5C, 0xD5, 0x83, 0x96, 0x27, 0x48, 0xA1, 0xC0, 0xA0, 0xC1, -0x26, 0x08, 0xA0, 0x47, 0x03, 0x18, 0xA1, 0x4A, 0x83, 0x52, 0x5E, 0x88, 0x30, 0xFE, 0x84, 0x80, -0x83, 0x93, 0x00, 0x48, 0xD9, 0x40, 0x5E, 0x88, 0x38, 0x3E, 0x84, 0x80, 0x00, 0x48, 0x83, 0x96, -0xA3, 0x00, 0x83, 0x52, 0x59, 0x48, 0x83, 0x96, 0xA2, 0xC0, 0x01, 0xF0, 0x83, 0x52, 0xD9, 0x40, -0x5E, 0xCA, 0x1C, 0x2F, 0x03, 0xD0, 0xD9, 0x0D, 0xFF, 0x7E, 0x03, 0x9D, 0x1A, 0x2F, 0x59, 0x48, -0x13, 0x45, 0x03, 0x9D, 0x28, 0xEF, 0x5E, 0x88, 0x28, 0xFE, 0x84, 0x80, 0x00, 0xCB, 0x9C, 0x6F, -0x5E, 0x88, 0x40, 0xBE, 0x84, 0x80, 0x00, 0x48, 0x5D, 0xC6, 0x03, 0x9D, 0x9C, 0x6F, 0x5E, 0x88, -0x20, 0xBE, 0x84, 0x80, 0x00, 0x48, 0x83, 0x96, 0x24, 0x06, 0x03, 0x9D, 0x3B, 0xAF, 0x83, 0x52, -0x03, 0x53, 0x5C, 0xD5, 0x9C, 0x6F, 0x83, 0x52, 0x5D, 0x88, 0x4A, 0x3E, 0x84, 0x80, 0x00, 0x48, -0x83, 0x96, 0x22, 0x47, 0x83, 0x52, 0xD9, 0x40, 0x83, 0x96, 0x23, 0x08, 0x03, 0x18, 0x23, 0x4A, -0x83, 0x52, 0xDA, 0x40, 0x80, 0x7A, 0xDB, 0x80, 0x83, 0x96, 0x21, 0xC8, 0x80, 0x7A, 0x83, 0x52, -0x5B, 0x82, 0x03, 0x9D, 0x57, 0xAF, 0x83, 0x96, 0x20, 0x88, 0x83, 0x52, 0x59, 0x42, 0x03, 0x5C, -0x9C, 0x6F, 0x83, 0x52, 0x03, 0x53, 0x5D, 0x88, 0x4A, 0x3E, 0x84, 0x80, 0x83, 0x96, 0x23, 0x08, -0x83, 0x52, 0xDA, 0x40, 0x83, 0x93, 0x00, 0x48, 0x83, 0x96, 0x22, 0xC2, 0x83, 0x52, 0xD9, 0x40, -0x03, 0x5C, 0xDA, 0xC3, 0x83, 0x96, 0x21, 0xC8, 0x80, 0x7A, 0x83, 0x52, 0xDB, 0x80, 0x5A, 0x48, -0x80, 0x7A, 0x5B, 0x82, 0x03, 0x9D, 0x77, 0xEF, 0x59, 0x48, 0x83, 0x96, 0x20, 0x82, 0x03, 0x5C, -0x9C, 0x6F, 0x83, 0x52, 0x03, 0x53, 0x5E, 0x88, 0x48, 0xFE, 0x84, 0x80, 0x83, 0x93, 0x00, 0x48, -0x02, 0xBE, 0xD9, 0x40, 0x00, 0xB0, 0x03, 0x18, 0x01, 0xF0, 0xDA, 0x40, 0x80, 0x7A, 0xDB, 0x80, -0x80, 0xF0, 0x5B, 0x82, 0x03, 0x9D, 0x90, 0xEF, 0x83, 0x96, 0x28, 0xC8, 0x83, 0x52, 0x59, 0x42, -0x03, 0x18, 0x37, 0xAF, 0x83, 0x52, 0x03, 0x53, 0x5E, 0x88, 0x28, 0xFE, 0x84, 0x80, 0x83, 0x93, -0x80, 0x81, 0x5E, 0x88, 0xE8, 0x27, 0x8A, 0x51, 0x83, 0x52, 0x03, 0x53, 0x5C, 0xD9, 0xA2, 0x2F, -0xDE, 0x0A, 0xF2, 0x6E, 0x5C, 0xD9, 0x08, 0x40, 0xDE, 0xC1, 0x08, 0xF0, 0x5E, 0x82, 0x03, 0x18, -0x08, 0x40, 0x01, 0xF0, 0xD9, 0x40, 0x5E, 0xCA, 0xAF, 0xEF, 0x03, 0xD0, 0xD9, 0x0D, 0xFF, 0x7E, -0x03, 0x9D, 0xAD, 0xAF, 0x59, 0x48, 0x13, 0x45, 0x03, 0x9D, 0xE6, 0xAF, 0x5E, 0x88, 0x28, 0xFE, -0x84, 0x80, 0x83, 0x93, 0x80, 0x88, 0x03, 0x9D, 0xE6, 0xAF, 0x5E, 0x88, 0x30, 0xFE, 0x84, 0x80, -0x83, 0x96, 0x26, 0x08, 0x80, 0x40, 0x83, 0x52, 0x5E, 0x88, 0x38, 0x3E, 0x84, 0x80, 0x83, 0x96, -0x27, 0x48, 0x80, 0x40, 0x83, 0x52, 0x5E, 0x88, 0x48, 0xFE, 0x84, 0x80, 0x83, 0x96, 0x28, 0xC8, -0x80, 0x40, 0x83, 0x52, 0x5E, 0x88, 0x20, 0xBE, 0x84, 0x80, 0x83, 0x96, 0x24, 0xC8, 0x80, 0x40, -0x83, 0x52, 0x5E, 0x88, 0x40, 0xBE, 0x84, 0x80, 0x5D, 0x88, 0x80, 0x40, 0x5E, 0x88, 0x28, 0xFE, -0x84, 0x80, 0x80, 0x81, 0x80, 0xCA, 0x9E, 0xCA, 0x5C, 0xD5, 0x08, 0x40, 0xDE, 0x0A, 0xA5, 0x6F, -0xD8, 0x00, 0x9B, 0x40, 0x15, 0x95, 0x15, 0x95, 0x15, 0x95, 0x15, 0x95, 0x15, 0x95, 0x15, 0x95, -0x15, 0x95, 0x15, 0x51, 0x01, 0xF0, 0xD7, 0x80, 0x58, 0x4A, 0xF8, 0xAF, 0x03, 0xD0, 0xD7, 0x4D, -0xFF, 0x7E, 0x03, 0x9D, 0xF6, 0xEF, 0x57, 0x88, 0x13, 0x45, 0x03, 0x59, 0x08, 0x40, 0xF2, 0xAF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, -0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF -}; diff --git a/loragw_hal/src/loragw_aux.c b/loragw_hal/src/loragw_aux.c deleted file mode 100644 index 1c7e354..0000000 --- a/loragw_hal/src/loragw_aux.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - / _____) _ | | -( (____ _____ ____ _| |_ _____ ____| |__ - \____ \| ___ | (_ _) ___ |/ ___) _ \ - _____) ) ____| | | || |_| ____( (___| | | | -(______/|_____)_|_|_| \__)_____)\____)_| |_| - ©2013 Semtech-Cycleo - -Description: - Lora gateway auxiliary functions -*/ - - -/* -------------------------------------------------------------------------- */ -/* --- DEPENDANCIES --------------------------------------------------------- */ - -#include /* printf fprintf */ -#include /* clock_nanosleep */ - -/* -------------------------------------------------------------------------- */ -/* --- PRIVATE MACROS ------------------------------------------------------- */ - -#if DEBUG_AUX == 1 - #define DEBUG_MSG(str) fprintf(stderr, str) - #define DEBUG_PRINTF(fmt, args...) fprintf(stderr,"%s:%d: "fmt, __FUNCTION__, __LINE__, args) -#else - #define DEBUG_MSG(str) - #define DEBUG_PRINTF(fmt, args...) -#endif - -/* -------------------------------------------------------------------------- */ -/* --- PUBLIC FUNCTIONS DEFINITION ------------------------------------------ */ - -/* This implementation is POSIX-pecific and require a fix to be compatible with C99 */ -void wait_ms(unsigned long a) { - struct timespec dly; - struct timespec rem; - - dly.tv_sec = a / 1000; - dly.tv_nsec = ((long)a % 1000) * 1000000; - - DEBUG_PRINTF("NOTE dly: %ld sec %ld ns\n", dly.tv_sec, dly.tv_nsec); - - if((dly.tv_sec > 0) || ((dly.tv_sec == 0) && (dly.tv_nsec > 100000))) { - clock_nanosleep(CLOCK_MONOTONIC, 0, &dly, &rem); - DEBUG_PRINTF("NOTE remain: %ld sec %ld ns\n", rem.tv_sec, rem.tv_nsec); - } - return; -} - -/* --- EOF ------------------------------------------------------------------ */ diff --git a/loragw_hal/src/loragw_hal.c b/loragw_hal/src/loragw_hal.c deleted file mode 100644 index 5b261f2..0000000 --- a/loragw_hal/src/loragw_hal.c +++ /dev/null @@ -1,1033 +0,0 @@ -/* - / _____) _ | | -( (____ _____ ____ _| |_ _____ ____| |__ - \____ \| ___ | (_ _) ___ |/ ___) _ \ - _____) ) ____| | | || |_| ____( (___| | | | -(______/|_____)_|_|_| \__)_____)\____)_| |_| - ©2013 Semtech-Cycleo - -Description: - Lora gateway Hardware Abstraction Layer -*/ - - -/* -------------------------------------------------------------------------- */ -/* --- DEPENDANCIES --------------------------------------------------------- */ - -#include /* C99 types */ -#include /* malloc & free */ -#include /* bool type */ -#include /* printf fprintf */ -#include /* NaN */ -#include /* memcpy */ - -#include "loragw_reg.h" -#include "loragw_hal.h" -#include "loragw_aux.h" - -/* -------------------------------------------------------------------------- */ -/* --- PRIVATE MACROS ------------------------------------------------------- */ - -#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) -#if DEBUG_HAL == 1 - #define DEBUG_MSG(str) fprintf(stderr, str) - #define DEBUG_PRINTF(fmt, args...) fprintf(stderr,"%s:%d: "fmt, __FUNCTION__, __LINE__, args) - #define DEBUG_ARRAY(a,b,c) for(a=0;a 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 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) */ - -/* -------------------------------------------------------------------------- */ -/* --- PRIVATE FUNCTIONS DECLARATION ---------------------------------------- */ - -int load_firmware(uint8_t target, uint8_t *firmware, uint16_t size); - -void sx125x_write(uint8_t rf_chain, uint8_t addr, uint8_t data); - -uint8_t sx125x_read(uint8_t rf_chain, uint8_t addr); - -int setup_sx1257(uint8_t rf_chain, uint32_t freq_hz); - -void lgw_constant_adjust(void); - -/* -------------------------------------------------------------------------- */ -/* --- PRIVATE FUNCTIONS DEFINITION ----------------------------------------- */ - -/* size is the firmware size in bytes (not 14b words) */ -int load_firmware(uint8_t target, uint8_t *firmware, uint16_t size) { - int32_t read_value; - int reg_rst; - int reg_sel; - - /* check parameters */ - CHECK_NULL(firmware); - if (target == MCU_ARB) { - if (size != MCU_ARB_FW_BYTE) { - DEBUG_MSG("ERROR: NOT A VALID SIZE FOR MCU ARG FIRMWARE\n"); - return -1; - } - reg_rst = LGW_MCU_RST_0; - reg_sel = LGW_MCU_SELECT_MUX_0; - }else if (target == MCU_AGC) { - if (size != MCU_AGC_FW_BYTE) { - DEBUG_MSG("ERROR: NOT A VALID SIZE FOR MCU AGC FIRMWARE\n"); - return -1; - } - reg_rst = LGW_MCU_RST_1; - reg_sel = LGW_MCU_SELECT_MUX_1; - } else { - DEBUG_MSG("ERROR: NOT A VALID TARGET FOR LOADING FIRMWARE\n"); - return -1; - } - - /* reset the targeted MCU */ - lgw_reg_w(reg_rst, 1); - - /* set mux to access MCU program RAM and set address to 0 */ - lgw_reg_w(reg_sel, 0); - lgw_reg_w(LGW_MCU_PROM_ADDR, 0); - - /* write the program in one burst */ - lgw_reg_wb(LGW_MCU_PROM_DATA, firmware, size); - - /* give back control of the MCU program ram to the MCU */ - lgw_reg_w(reg_sel, 1); - - return 0; -} - -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ - -void sx125x_write(uint8_t channel, uint8_t addr, uint8_t data) { - int reg_add, reg_dat, reg_cs; - - /* checking input parameters */ - if (channel >= LGW_RF_CHAIN_NB) { - DEBUG_MSG("ERROR: INVALID RF_CHAIN\n"); - return; - } - if (addr >= 0x7F) { - DEBUG_MSG("ERROR: ADDRESS OUT OF RANGE\n"); - return; - } - - /* selecting the target radio */ - switch (channel) { - case 0: - reg_add = LGW_SPI_RADIO_A__ADDR; - reg_dat = LGW_SPI_RADIO_A__DATA; - reg_cs = LGW_SPI_RADIO_A__CS; - break; - - case 1: - reg_add = LGW_SPI_RADIO_B__ADDR; - reg_dat = LGW_SPI_RADIO_B__DATA; - reg_cs = LGW_SPI_RADIO_B__CS; - break; - - default: - DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", channel); - return; - } - - /* SPI master data write procedure */ - lgw_reg_w(reg_cs, 0); - lgw_reg_w(reg_add, 0x80 | addr); /* MSB at 1 for write operation */ - lgw_reg_w(reg_dat, data); - lgw_reg_w(reg_cs, 1); - lgw_reg_w(reg_cs, 0); - - return; -} - -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ - -uint8_t sx125x_read(uint8_t channel, uint8_t addr) { - int reg_add, reg_dat, reg_cs, reg_rb; - int32_t read_value; - - /* checking input parameters */ - if (channel >= LGW_RF_CHAIN_NB) { - DEBUG_MSG("ERROR: INVALID RF_CHAIN\n"); - return 0; - } - if (addr >= 0x7F) { - DEBUG_MSG("ERROR: ADDRESS OUT OF RANGE\n"); - return 0; - } - - /* selecting the target radio */ - switch (channel) { - case 0: - reg_add = LGW_SPI_RADIO_A__ADDR; - reg_dat = LGW_SPI_RADIO_A__DATA; - reg_cs = LGW_SPI_RADIO_A__CS; - reg_rb = LGW_SPI_RADIO_A__DATA_READBACK; - break; - - case 1: - reg_add = LGW_SPI_RADIO_B__ADDR; - reg_dat = LGW_SPI_RADIO_B__DATA; - reg_cs = LGW_SPI_RADIO_B__CS; - reg_rb = LGW_SPI_RADIO_B__DATA_READBACK; - break; - - default: - DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", channel); - return 0; - } - - /* SPI master data read procedure */ - lgw_reg_w(reg_cs, 0); - lgw_reg_w(reg_add, addr); /* MSB at 0 for read operation */ - lgw_reg_w(reg_dat, 0); - lgw_reg_w(reg_cs, 1); - lgw_reg_w(reg_cs, 0); - lgw_reg_r(reg_rb, &read_value); - - return (uint8_t)read_value; -} - -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ - -int setup_sx1257(uint8_t rf_chain, uint32_t freq_hz) { - uint32_t part_int; - uint32_t part_frac; - int cpt_attempts = 0; - - if (rf_chain >= LGW_RF_CHAIN_NB) { - DEBUG_MSG("ERROR: INVALID RF_CHAIN\n"); - return -1; - } - - /* misc */ - sx125x_write(rf_chain, 0x10, SX1257_TX_DAC_CLK_SEL + SX1257_CLK_OUT*2); - - /* Tx gain and trim */ - sx125x_write(rf_chain, 0x08, SX1257_TX_MIX_GAIN + SX1257_TX_DAC_GAIN*16); - sx125x_write(rf_chain, 0x0A, SX1257_TX_ANA_BW + SX1257_TX_PLL_BW*32); - sx125x_write(rf_chain, 0x0B, SX1257_TX_DAC_BW); - - /* Rx gain and trim */ - sx125x_write(rf_chain, 0x0C, 0 + SX1257_RX_BB_GAIN*2 + SX1257_RX_LNA_GAIN*32); - 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 */ - 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 */ - - /* start and PLL lock */ - do { - if (cpt_attempts >= PLL_LOCK_MAX_ATTEMPTS) { - DEBUG_MSG("ERROR: FAIL TO LOCK PLL\n"); - return -1; - } - sx125x_write(rf_chain, 0x00, 1); /* enable Xtal oscillator */ - sx125x_write(rf_chain, 0x00, 3); /* Enable RX (PLL+FE) */ - ++cpt_attempts; - DEBUG_PRINTF("Note: SX1257 #%d PLL start (attempt %d)\n", rf_chain, cpt_attempts); - wait_ms(1); - } while(sx125x_read(rf_chain, 0x11) & 0x02 == 0); - - return 0; -} - -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ - -void lgw_constant_adjust(void) { - - /* I/Q path setup */ - // lgw_reg_w(LGW_RX_INVERT_IQ,0); /* default 0 */ - // lgw_reg_w(LGW_MODEM_INVERT_IQ,1); /* default 1 */ - // lgw_reg_w(LGW_CHIRP_INVERT_RX,1); /* default 1 */ - // lgw_reg_w(LGW_RX_EDGE_SELECT,0); /* default 0 */ - // lgw_reg_w(LGW_MBWSSF_MODEM_INVERT_IQ,0); /* default 0 */ - // lgw_reg_w(LGW_DC_NOTCH_EN,1); /* default 1 */ - lgw_reg_w(LGW_RSSI_BB_FILTER_ALPHA,9); /* default 7 */ - lgw_reg_w(LGW_RSSI_DEC_FILTER_ALPHA,7); /* default 5 */ - lgw_reg_w(LGW_RSSI_CHANN_FILTER_ALPHA,7); /* default 8 */ - // lgw_reg_w(LGW_RSSI_BB_DEFAULT_VALUE,32); /* default 32 */ - lgw_reg_w(LGW_RSSI_CHANN_DEFAULT_VALUE,90); /* default 100 */ - lgw_reg_w(LGW_RSSI_DEC_DEFAULT_VALUE,90); /* default 100 */ - // lgw_reg_w(LGW_DEC_GAIN_OFFSET, 8); /* default 8 */ - // lgw_reg_w(LGW_CHAN_GAIN_OFFSET, 7); /* default 7 */ - - /* Correlator setup */ - // lgw_reg_w(LGW_CORR_DETECT_EN,126); /* default 126 */ - // lgw_reg_w(LGW_CORR_NUM_SAME_PEAK,4); /* default 4 */ - // lgw_reg_w(LGW_CORR_MAC_GAIN,5); /* default 5 */ - // lgw_reg_w(LGW_CORR_SAME_PEAKS_OPTION_SF6,0); /* default 0 */ - // lgw_reg_w(LGW_CORR_SAME_PEAKS_OPTION_SF7,1); /* default 1 */ - // lgw_reg_w(LGW_CORR_SAME_PEAKS_OPTION_SF8,1); /* default 1 */ - // lgw_reg_w(LGW_CORR_SAME_PEAKS_OPTION_SF9,1); /* default 1 */ - // lgw_reg_w(LGW_CORR_SAME_PEAKS_OPTION_SF10,1); /* default 1 */ - // lgw_reg_w(LGW_CORR_SAME_PEAKS_OPTION_SF11,1); /* default 1 */ - // lgw_reg_w(LGW_CORR_SAME_PEAKS_OPTION_SF12,1); /* default 1 */ - // lgw_reg_w(LGW_CORR_SIG_NOISE_RATIO_SF6,4); /* default 4 */ - // lgw_reg_w(LGW_CORR_SIG_NOISE_RATIO_SF7,4); /* default 4 */ - // lgw_reg_w(LGW_CORR_SIG_NOISE_RATIO_SF8,4); /* default 4 */ - // lgw_reg_w(LGW_CORR_SIG_NOISE_RATIO_SF9,4); /* default 4 */ - // lgw_reg_w(LGW_CORR_SIG_NOISE_RATIO_SF10,4); /* default 4 */ - // 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 */ - 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 */ - // lgw_reg_w(LGW_FRAME_SYNCH_GAIN,1); /* default 1 */ - // lgw_reg_w(LGW_SYNCH_DETECT_TH,1); /* default 1 */ - // lgw_reg_w(LGW_ZERO_PAD,0); /* default 0 */ - lgw_reg_w(LGW_SNR_AVG_CST,3); /* default 2 */ - // lgw_reg_w(LGW_FRAME_SYNCH_PEAK1_POS,1); /* default 1 */ - // lgw_reg_w(LGW_FRAME_SYNCH_PEAK2_POS,2); /* default 2 */ - // lgw_reg_w(LGW_PREAMBLE_FINE_TIMING_GAIN,1); /* default 1 */ - // lgw_reg_w(LGW_ONLY_CRC_EN,1); /* default 1 */ - // lgw_reg_w(LGW_PAYLOAD_FINE_TIMING_GAIN,2); /* default 2 */ - // lgw_reg_w(LGW_TRACKING_INTEGRAL,0); /* default 0 */ - // lgw_reg_w(LGW_ADJUST_MODEM_START_OFFSET_RDX8,0); /* default 0 */ - // 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 */ - // 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 */ - // lgw_reg_w(LGW_MBWSSF_FREQ_TO_TIME_INVERT,29); /* default 29 */ - // lgw_reg_w(LGW_MBWSSF_FRAME_SYNCH_GAIN,1); /* default 1 */ - // lgw_reg_w(LGW_MBWSSF_SYNCH_DETECT_TH,1); /* default 1 */ - // lgw_reg_w(LGW_MBWSSF_ZERO_PAD,0); /* default 0 */ - // lgw_reg_w(LGW_MBWSSF_FRAME_SYNCH_PEAK1_POS,1); /* default 1 */ - // lgw_reg_w(LGW_MBWSSF_FRAME_SYNCH_PEAK2_POS,2); /* default 2 */ - // lgw_reg_w(LGW_MBWSSF_ONLY_CRC_EN,1); /* default 1 */ - // lgw_reg_w(LGW_MBWSSF_PAYLOAD_FINE_TIMING_GAIN,2); /* default 2 */ - // lgw_reg_w(LGW_MBWSSF_PREAMBLE_FINE_TIMING_GAIN,1); /* default 1 */ - // lgw_reg_w(LGW_MBWSSF_TRACKING_INTEGRAL,0); /* default 0 */ - // lgw_reg_w(LGW_MBWSSF_AGC_FREEZE_ON_DETECT,1); /* default 1 */ - - /* FSK datapath */ - 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 */ - 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_ERROR_OSR_TOL,10); /* default 0 */ - lgw_reg_w(LGW_FSK_MODEM_INVERT_IQ,1); /* default 0 */ - // 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) */ - - /* 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 */ - // 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 */ - - return; -} - -/* -------------------------------------------------------------------------- */ -/* --- PUBLIC FUNCTIONS DEFINITION ------------------------------------------ */ - -int lgw_rxrf_setconf(uint8_t rf_chain, struct lgw_conf_rxrf_s conf) { - - /* check if the gateway is running */ - if (lgw_is_started == true) { - DEBUG_MSG("ERROR: GATEWAY IS RUNNING, STOP IT BEFORE TOUCHING CONFIGURATION\n"); - return LGW_HAL_ERROR; - } - - /* check input parameters */ - if (rf_chain > LGW_RF_CHAIN_NB) { - DEBUG_MSG("ERROR: NOT A VALID RF_CHAIN NUMBER\n"); - return LGW_HAL_ERROR; - } - if (conf.freq_hz > rf_rx_upfreq[rf_chain]) { - DEBUG_MSG("ERROR: FREQUENCY TOO HIGH FOR THAT RF_CHAIN\n"); - return LGW_HAL_ERROR; - } else if (conf.freq_hz < rf_rx_lowfreq[rf_chain]) { - DEBUG_MSG("ERROR: FREQUENCY TOO LOW FOR THAT RF_CHAIN\n"); - return LGW_HAL_ERROR; - } - - /* set internal config according to parameters */ - rf_enable[rf_chain] = conf.enable; - rf_rx_freq[rf_chain] = conf.freq_hz; - - return LGW_HAL_SUCCESS; -} - -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ - -int lgw_rxif_setconf(uint8_t if_chain, struct lgw_conf_rxif_s conf) { - /* check if the gateway is running */ - if (lgw_is_started == true) { - DEBUG_MSG("ERROR: GATEWAY IS RUNNING, STOP IT BEFORE TOUCHING CONFIGURATION\n"); - return LGW_HAL_ERROR; - } - - /* if chain is disabled, don't care about most parameters */ - if (conf.enable == false) { - if_enable[if_chain] = false; - if_freq[if_chain] = 0; - DEBUG_PRINTF("Note: if_chain %d disabled\n", if_chain); - return LGW_HAL_SUCCESS; - } - - /* check 'general' parameters */ - if (if_chain > LGW_IF_CHAIN_NB) { - DEBUG_PRINTF("ERROR: %d NOT A VALID IF_CHAIN NUMBER\n", if_chain); - return LGW_HAL_ERROR; - } - if (ifmod_config[if_chain] == IF_UNDEFINED) { - DEBUG_PRINTF("ERROR: IF CHAIN %d NOT CONFIGURABLE\n", if_chain); - } - if (conf.rf_chain >= LGW_RF_CHAIN_NB) { - DEBUG_MSG("ERROR: INVALID RF_CHAIN TO ASSOCIATE WITH A LORA_STD IF CHAIN\n"); - return LGW_HAL_ERROR; - } - if ((conf.freq_hz + LGW_REF_BW/2) > ((int32_t)rf_rx_bandwidth[conf.rf_chain] / 2)) { - DEBUG_PRINTF("ERROR: IF FREQUENCY %d TOO HIGH\n", conf.freq_hz); - return LGW_HAL_ERROR; - } else if ((conf.freq_hz - LGW_REF_BW/2) < -((int32_t)rf_rx_bandwidth[conf.rf_chain] / 2)) { - DEBUG_PRINTF("ERROR: IF FREQUENCY %d TOO LOW\n", conf.freq_hz); - return LGW_HAL_ERROR; - } - /* WARNING: if the channel is 250 or 500kHz wide, that check is insufficient */ - - /* check parameters according to the type of IF chain + modem, - fill default if necessary, and commit configuration if everything is OK */ - switch (ifmod_config[if_chain]) { - case IF_LORA_STD: - /* fill default parameters if needed */ - if (conf.bandwidth == 0) { - conf.bandwidth = BW_250KHZ; - } - if (conf.datarate == 0) { - conf.datarate = DR_LORA_SF9; - } - /* check BW & DR */ - if (!IS_LORA_BW(conf.bandwidth)) { - DEBUG_MSG("ERROR: BANDWIDTH NOT SUPPORTED BY LORA_STD IF CHAIN\n"); - return LGW_HAL_ERROR; - } - if (!IS_LORA_STD_DR(conf.datarate)) { - DEBUG_MSG("ERROR: DATARATE NOT SUPPORTED BY LORA_STD IF CHAIN\n"); - return LGW_HAL_ERROR; - } - /* set internal configuration */ - if_enable[if_chain] = conf.enable; - if_freq[if_chain] = conf.freq_hz; - lora_rx_bw = conf.bandwidth; - lora_rx_sf = conf.datarate; - if (SET_PPM_ON(conf.bandwidth, conf.datarate)) { - lora_rx_ppm_offset = 1; - } else { - lora_rx_ppm_offset = 0; - } - - DEBUG_PRINTF("Note: Lora 'std' if_chain %d configured; en:%d freq:%d bw:%d dr:%d\n", if_chain, if_enable[if_chain], if_freq[if_chain], lora_rx_bw, lora_rx_sf); - break; - - case IF_LORA_MULTI: - /* fill default parameters if needed */ - if (conf.datarate == 0) { - conf.datarate = DR_LORA_MULTI; - } - /* check BW & DR */ - if ((conf.bandwidth != BW_125KHZ) && (conf.bandwidth != 0)) { /* 0 is for default */ - DEBUG_MSG("ERROR: BANDWIDTH NOT SUPPORTED BY LORA_MULTI IF CHAIN\n"); - return LGW_HAL_ERROR; - } - if (!IS_LORA_MULTI_DR(conf.datarate)) { - DEBUG_MSG("ERROR: DATARATE(S) NOT SUPPORTED BY LORA_MULTI IF CHAIN\n"); - return LGW_HAL_ERROR; - } - /* 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_freq[if_chain] = conf.freq_hz; - lora_multi_sfmask[if_chain] = (uint8_t)(0x007F & conf.datarate); - 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 - - default: - DEBUG_PRINTF("ERROR: IF CHAIN %d TYPE NOT SUPPORTED\n", if_chain); - return LGW_HAL_ERROR; - } - - return LGW_HAL_SUCCESS; -} - -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ - -int lgw_start(void) { - int reg_stat; - int32_t read_value; - - if (lgw_is_started == true) { - DEBUG_MSG("Note: Lora Gateway already started, restarting it now\n"); - } - - reg_stat = lgw_connect(); - if (reg_stat == LGW_REG_ERROR) { - DEBUG_MSG("ERROR: FAIL TO CONNECT BOARD\n"); - return LGW_HAL_ERROR; - } - - /* reset the registers (also shuts the radios down) */ - lgw_soft_reset(); - - /* 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 */ - lgw_reg_w(LGW_RADIO_B_EN,1); /* radio B *must* be started because they share the same XTAL I/O is clamped to ground when off */ - wait_ms(500); - lgw_reg_w(LGW_RADIO_RST,1); - wait_ms(5); - lgw_reg_w(LGW_RADIO_RST,0); - - /* setup the radios */ - if (rf_enable[0] == 1) { - setup_sx1257(0, rf_rx_freq[0]); - } - if (rf_enable[1] == 1) { - setup_sx1257(1, rf_rx_freq[1]); - } - - /* gives the AGC MCU control over radio, RF front-end and filter gain */ - lgw_reg_w(LGW_FORCE_HOST_RADIO_CTRL,0); - lgw_reg_w(LGW_FORCE_HOST_FE_CTRL,0); - lgw_reg_w(LGW_FORCE_DEC_FILTER_GAIN,0); - - /* TODO load the calibration firmware and wait for calibration to end */ - - /* in the absence of calibration firmware, do a "manual" calibration */ - lgw_reg_w(LGW_TX_OFFSET_I,10); - lgw_reg_w(LGW_TX_OFFSET_Q,5); - lgw_reg_w(LGW_IQ_MISMATCH_A_AMP_COEFF,63); - lgw_reg_w(LGW_IQ_MISMATCH_A_PHI_COEFF,9); - lgw_reg_w(LGW_IQ_MISMATCH_B_AMP_COEFF,0); - lgw_reg_w(LGW_IQ_MISMATCH_B_PHI_COEFF,0); - - /* 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) */ - - 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 */ - lgw_reg_w(LGW_IF_FREQ_2, IF_HZ_TO_REG(if_freq[2])); /* default 128 */ - lgw_reg_w(LGW_IF_FREQ_3, IF_HZ_TO_REG(if_freq[3])); /* default 384 */ - - lgw_reg_w(LGW_CORR0_DETECT_EN, (if_enable[0] == true) ? lora_multi_sfmask[0] : 0); /* default 0 */ - lgw_reg_w(LGW_CORR1_DETECT_EN, (if_enable[1] == true) ? lora_multi_sfmask[1] : 0); /* default 0 */ - lgw_reg_w(LGW_CORR2_DETECT_EN, (if_enable[2] == true) ? lora_multi_sfmask[2] : 0); /* default 0 */ - lgw_reg_w(LGW_CORR3_DETECT_EN, (if_enable[3] == true) ? lora_multi_sfmask[3] : 0); /* default 0 */ - - lgw_reg_w(LGW_PPM_OFFSET, 0x60); /* as the threshold is 16ms, use 0x60 to enable ppm_offset for SF12 and SF11 @125kHz*/ - - lgw_reg_w(LGW_CONCENTRATOR_MODEM_ENABLE,1); /* default 0 */ - - /* configure Lora 'stand-alone' modem */ - lgw_reg_w(LGW_IF_FREQ_8, IF_HZ_TO_REG(if_freq[8])); /* MBWSSF modem (default 0) */ - if (if_enable[8] == true) { - 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; - case BW_500KHZ: lgw_reg_w(LGW_MBWSSF_MODEM_BW,2); break; - default: DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", lora_rx_bw); return LGW_HAL_ERROR; - } - switch(lora_rx_sf) { - case DR_LORA_SF7: lgw_reg_w(LGW_MBWSSF_RATE_SF,7); break; - case DR_LORA_SF8: lgw_reg_w(LGW_MBWSSF_RATE_SF,8); break; - case DR_LORA_SF9: lgw_reg_w(LGW_MBWSSF_RATE_SF,9); break; - case DR_LORA_SF10: lgw_reg_w(LGW_MBWSSF_RATE_SF,10); break; - case DR_LORA_SF11: lgw_reg_w(LGW_MBWSSF_RATE_SF,11); break; - case DR_LORA_SF12: lgw_reg_w(LGW_MBWSSF_RATE_SF,12); break; - default: DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", lora_rx_sf); return LGW_HAL_ERROR; - } - lgw_reg_w(LGW_MBWSSF_PPM_OFFSET, lora_rx_ppm_offset); /* default 0 */ - lgw_reg_w(LGW_MBWSSF_MODEM_ENABLE, 1); /* default 0 */ - } else { - 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) */ - - /* Load firmware */ - load_firmware(MCU_ARB, arb_firmware, MCU_ARB_FW_BYTE); - load_firmware(MCU_AGC, agc_firmware, MCU_AGC_FW_BYTE); - - /* Get MCUs out of reset */ - lgw_reg_w(LGW_MCU_RST_0, 0); - lgw_reg_w(LGW_MCU_RST_1, 0); - - lgw_is_started = true; - return LGW_HAL_SUCCESS; -} - -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ - -int lgw_stop(void) { - lgw_soft_reset(); - lgw_disconnect(); - - lgw_is_started = false; - return LGW_HAL_SUCCESS; -} - -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ - -int lgw_receive(uint8_t max_pkt, struct lgw_pkt_rx_s *pkt_data) { - int nb_pkt_fetch; /* loop variable and return value */ - struct lgw_pkt_rx_s *p; /* pointer to the current structure in the struct array */ - uint8_t buff[255+RX_METADATA_NB]; /* buffer to store the result of SPI read bursts */ - uint16_t data_addr; /* address read from the FIFO and programmed before the data buffer read operation */ - int s; /* size of the payload, uses to address metadata */ - int ifmod; /* type of if_chain/modem a packet was received by */ - int stat_fifo; /* the packet status as indicated in the FIFO */ - - /* check if the gateway is running */ - if (lgw_is_started == false) { - DEBUG_MSG("ERROR: GATEWAY IS NOT RUNNING, START IT BEFORE RECEIVING\n"); - return LGW_HAL_ERROR; - } - - /* check input variables */ - if (max_pkt <= 0) { - DEBUG_PRINTF("ERROR: %d = INVALID MAX NUMBER OF PACKETS TO FETCH\n", max_pkt); - return LGW_HAL_ERROR; - } - CHECK_NULL(pkt_data); - - /* iterate max_pkt times at most */ - for (nb_pkt_fetch = 0; nb_pkt_fetch < max_pkt; ++nb_pkt_fetch) { - - /* point to the proper struct in the struct array */ - p = &pkt_data[nb_pkt_fetch]; - - /* fetch all the RX FIFO data */ - lgw_reg_rb(LGW_RX_PACKET_DATA_FIFO_NUM_STORED, buff, 5); - - /* how many packets are in the RX buffer ? Break if zero */ - if (buff[0] == 0) { - DEBUG_MSG("Note: RX packet buffer empty, receive function returning nothing\n"); - break; /* no more packets to fetch, exit out of FOR loop */ - } - - DEBUG_PRINTF("FIFO content: %x %x %x %x %x\n",buff[0],buff[1],buff[2],buff[3],buff[4]); - - p->size = buff[4]; - 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); - - /* process metadata */ - p->if_chain = buff[s+0]; - ifmod = ifmod_config[p->if_chain]; - DEBUG_PRINTF("[%d %d]\n", p->if_chain, ifmod); - - if ((ifmod == IF_LORA_MULTI) || (ifmod == IF_LORA_STD)) { - DEBUG_MSG("Note: Lora packet\n"); - 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_LORA; - p->snr = ((float)((int8_t)buff[s+2]))/4; - p->snr_min = ((float)((int8_t)buff[s+3]))/4; - p->snr_max = ((float)((int8_t)buff[s+4]))/4; - if (ifmod == IF_LORA_MULTI) { - p->rssi = RSSI_OFFSET_LORA_MULTI + (float)buff[s+5]; - p->bandwidth = BW_125KHZ; /* fixed in hardware */ - } else { - p->rssi = RSSI_OFFSET_LORA_STD + (float)buff[s+5]; - p->bandwidth = lora_rx_bw; /* get the parameter from the config variable */ - } - switch ((buff[s+1] >> 4) & 0x0F) { - case 7: p->datarate = DR_LORA_SF7; break; - case 8: p->datarate = DR_LORA_SF8; break; - case 9: p->datarate = DR_LORA_SF9; break; - case 10: p->datarate = DR_LORA_SF10; break; - case 11: p->datarate = DR_LORA_SF11; break; - case 12: p->datarate = DR_LORA_SF12; break; - default: p->datarate = DR_UNDEFINED; - } - switch ((buff[s+1] >> 1) & 0x07) { - case 1: p->coderate = CR_LORA_4_5; break; - case 2: p->coderate = CR_LORA_4_6; break; - case 3: p->coderate = CR_LORA_4_7; break; - case 4: p->coderate = CR_LORA_4_8; break; - 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; - p->modulation = MOD_FSK; - p->rssi = NAN; - p->snr = NAN; - p->snr_min = NAN; - p->snr_max = NAN; - p->bandwidth = BW_UNDEFINED; - p->datarate = DR_UNDEFINED; - p->coderate = CR_UNDEFINED; - } else { - DEBUG_MSG("ERROR: UNEXPECTED PACKET ORIGIN\n"); - p->status = STAT_UNDEFINED; - p->modulation = MOD_UNDEFINED; - p->rssi = NAN; - p->snr = NAN; - p->snr_min = NAN; - p->snr_max = NAN; - p->bandwidth = BW_UNDEFINED; - p->datarate = DR_UNDEFINED; - p->coderate = CR_UNDEFINED; - } - - p->count_us = (uint32_t)buff[s+6] + ((uint32_t)buff[s+7] << 8) + ((uint32_t)buff[s+8] << 16) + ((uint32_t)buff[s+9] << 24); - p->crc = (uint16_t)buff[s+10] + ((uint16_t)buff[s+11] << 8); - - /* advance packet FIFO */ - lgw_reg_w(LGW_RX_PACKET_DATA_FIFO_NUM_STORED, 0); - } - - return nb_pkt_fetch; -} - -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ - -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 */ - uint32_t part_int; /* integer part for PLL register value calculation */ - uint32_t part_frac; /* fractional part for PLL register value calculation */ - int i; - - /* check if the gateway is running */ - if (lgw_is_started == false) { - DEBUG_MSG("ERROR: GATEWAY IS NOT RUNNING, START IT BEFORE SENDING\n"); - return LGW_HAL_ERROR; - } - - /* 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; - } - if (rf_enable[pkt_data.rf_chain] == false) { - DEBUG_MSG("ERROR: SELECTED RF_CHAIN IS DISABLED\n"); - return LGW_HAL_ERROR; - } - if (pkt_data.freq_hz > rf_tx_upfreq[pkt_data.rf_chain]) { - DEBUG_PRINTF("ERROR: FREQUENCY %d HIGHER THAN UPPER LIMIT %d OF RF_CHAIN %d\n", pkt_data.freq_hz, rf_tx_upfreq[pkt_data.rf_chain], pkt_data.rf_chain); - return LGW_HAL_ERROR; - } else if (pkt_data.freq_hz < rf_tx_lowfreq[pkt_data.rf_chain]) { - DEBUG_PRINTF("ERROR: FREQUENCY %d LOWER THAN LOWER LIMIT %d OF RF_CHAIN %d\n", pkt_data.freq_hz, rf_tx_lowfreq[pkt_data.rf_chain], pkt_data.rf_chain); - return LGW_HAL_ERROR; - } - if (!IS_TX_MODE(pkt_data.tx_mode)) { - DEBUG_MSG("ERROR: TX_MODE NOT SUPPORTED\n"); - return LGW_HAL_ERROR; - } - if (pkt_data.modulation == MOD_LORA) { - if (!IS_LORA_BW(pkt_data.bandwidth)) { - DEBUG_MSG("ERROR: BANDWIDTH NOT SUPPORTED BY LORA TX\n"); - return LGW_HAL_ERROR; - } - if (!IS_LORA_STD_DR(pkt_data.datarate)) { - DEBUG_MSG("ERROR: DATARATE NOT SUPPORTED BY LORA TX\n"); - return LGW_HAL_ERROR; - } - if (!IS_LORA_CR(pkt_data.coderate)) { - DEBUG_MSG("ERROR: CODERATE NOT SUPPORTED BY LORA TX\n"); - return LGW_HAL_ERROR; - } - if (pkt_data.size > 255) { - 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 { - DEBUG_MSG("ERROR: INVALID TX MODULATION\n"); - return LGW_HAL_ERROR; - } - - /* reset TX command flags */ - lgw_reg_w(LGW_TX_TRIG_IMMEDIATE, 0); - lgw_reg_w(LGW_TX_TRIG_DELAYED, 0); - lgw_reg_w(LGW_TX_TRIG_GPS, 0); - - /* 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 */ - buff[0] = 0xFF & (part_int >> 8); /* Most Significant Byte */ - buff[1] = 0xFF & part_int; /* middle byte */ - buff[2] = 0xFF & part_frac; /* Least Significant Byte */ - - /* metadata 3 to 6, timestamp trigger value */ - buff[3] = 0xFF & (pkt_data.count_us >> 24); - buff[4] = 0xFF & (pkt_data.count_us >> 16); - buff[5] = 0xFF & (pkt_data.count_us >> 8); - buff[6] = 0xFF & pkt_data.count_us; - - /* parameters depending on modulation */ - if (pkt_data.modulation == MOD_LORA) { - /* metadata 7, modulation type, radio chain selection and TX power */ - buff[7] = (0x20 & (pkt_data.rf_chain << 5)) | (0x0F & pkt_data.rf_power); /* bit 4 is 0 -> Lora 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, CRC, Lora CR & SF */ - switch (pkt_data.datarate) { - case DR_LORA_SF7: buff[9] = 7; break; - case DR_LORA_SF8: buff[9] = 8; break; - case DR_LORA_SF9: buff[9] = 9; break; - case DR_LORA_SF10: buff[9] = 10; break; - case DR_LORA_SF11: buff[9] = 11; break; - case DR_LORA_SF12: buff[9] = 12; break; - default: DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", pkt_data.datarate); - } - switch (pkt_data.coderate) { - case CR_LORA_4_5: buff[9] |= 1 << 4; break; - case CR_LORA_4_6: buff[9] |= 2 << 4; break; - case CR_LORA_4_7: buff[9] |= 3 << 4; break; - case CR_LORA_4_8: buff[9] |= 4 << 4; break; - default: DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", pkt_data.coderate); - } - if (pkt_data.no_crc == false) { - buff[9] |= 0x80; /* set 'CRC enable' bit */ - } - - /* metadata 10, payload size */ - buff[10] = pkt_data.size; - - /* metadata 11, implicit header, modulation bandwidth, PPM offset & polarity */ - switch (pkt_data.bandwidth) { - case BW_125KHZ: buff[11] = 0; break; - case BW_250KHZ: buff[11] = 1; break; - case BW_500KHZ: buff[11] = 2; break; - default: DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", pkt_data.bandwidth); - } - if (pkt_data.no_header == true) { - buff[11] |= 0x04; /* set 'implicit header' bit */ - } - if (SET_PPM_ON(pkt_data.bandwidth,pkt_data.datarate)) { - buff[11] |= 0x08; /* set 'PPM offset' bit at 1 */ - } - if (pkt_data.invert_pol == true) { - buff[11] |= 0x10; /* set 'TX polarity' bit at 1 */ - } - - /* metadata 12 & 13, Lora preamble size */ - if (pkt_data.preamble < MIN_LORA_PREAMBLE) { /* enforce minimum preamble size */ - pkt_data.preamble = MIN_LORA_PREAMBLE; - DEBUG_MSG("Note: preamble length adjusted to respect minimum Lora preamble size\n"); - } - buff[12] = 0xFF & (pkt_data.preamble >> 8); - buff[13] = 0xFF & pkt_data.preamble; - - /* metadata 14 & 15, not used */ - buff[14] = 0; - buff[15] = 0; - - } else { - DEBUG_MSG("ERROR: ONLY LORA TX SUPPORTED FOR NOW\n"); - return LGW_HAL_ERROR; - } - - /* copy payload */ - memcpy((void *)(buff + TX_METADATA_NB), 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); - - /* send data */ - switch(pkt_data.tx_mode) { - case IMMEDIATE: - lgw_reg_w(LGW_TX_TRIG_IMMEDIATE, 1); - break; - - case TIMESTAMPED: - lgw_reg_w(LGW_TX_TRIG_DELAYED, 1); - break; - - case ON_GPS: - lgw_reg_w(LGW_TX_TRIG_GPS, 1); - break; - - default: - DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", pkt_data.tx_mode); - return LGW_HAL_ERROR; - } - - return LGW_HAL_SUCCESS; -} - -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ - -int lgw_status(uint8_t select, uint8_t *code) { - int32_t read_value; - - /* check input variables */ - CHECK_NULL(code); - - if (select == TX_STATUS) { - lgw_reg_r(LGW_TX_STATUS, &read_value); - if (lgw_is_started == false) { - *code = TX_OFF; - } else if ((read_value & 0x10) == 0) { /* bit 4 @1: TX programmed */ - *code = TX_FREE; - } else if ((read_value & 0x60) != 0) { /* bit 5 or 6 @1: TX sequence */ - *code = TX_EMITTING; - } else { - *code = TX_SCHEDULED; - } - return LGW_HAL_SUCCESS; - - } else if (select == RX_STATUS) { - *code = RX_STATUS_UNKNOWN; /* todo */ - return LGW_HAL_SUCCESS; - - } else { - DEBUG_MSG("ERROR: SELECTION INVALID, NO STATUS TO RETURN\n"); - return LGW_HAL_ERROR; - } - -} - - -/* --- EOF ------------------------------------------------------------------ */ diff --git a/loragw_hal/src/loragw_reg.c b/loragw_hal/src/loragw_reg.c deleted file mode 100644 index a9122d2..0000000 --- a/loragw_hal/src/loragw_reg.c +++ /dev/null @@ -1,756 +0,0 @@ -/* - / _____) _ | | -( (____ _____ ____ _| |_ _____ ____| |__ - \____ \| ___ | (_ _) ___ |/ ___) _ \ - _____) ) ____| | | || |_| ____( (___| | | | -(______/|_____)_|_|_| \__)_____)\____)_| |_| - ©2013 Semtech-Cycleo - -Description: - Functions used to handle a single Lora gateway. - Registers are addressed by name. - Multi-bytes registers are handled automatically. - Read-modify-write is handled automatically. -*/ - - -/* -------------------------------------------------------------------------- */ -/* --- DEPENDANCIES --------------------------------------------------------- */ - -#include /* C99 types */ -#include /* bool type */ -#include /* printf fprintf */ - -#include "loragw_spi.h" -#include "loragw_reg.h" - -/* -------------------------------------------------------------------------- */ -/* --- PRIVATE MACROS ------------------------------------------------------- */ - -#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) -#if DEBUG_REG == 1 - #define DEBUG_MSG(str) fprintf(stderr, str) - #define DEBUG_PRINTF(fmt, args...) fprintf(stderr,"%s:%d: "fmt, __FUNCTION__, __LINE__, args) - #define CHECK_NULL(a) if(a==NULL){fprintf(stderr,"%s:%d: ERROR: NULL POINTER AS ARGUMENT\n", __FUNCTION__, __LINE__);return LGW_REG_ERROR;} -#else - #define DEBUG_MSG(str) - #define DEBUG_PRINTF(fmt, args...) - #define CHECK_NULL(a) if(a==NULL){return LGW_REG_ERROR;} -#endif - -/* -------------------------------------------------------------------------- */ -/* --- PRIVATE TYPES -------------------------------------------------------- */ - -struct lgw_reg_s { - int8_t page; /*!< page containing the register (-1 for all pages) */ - uint8_t addr; /*!< base address of the register (7 bit) */ - uint8_t offs; /*!< position of the register LSB (between 0 to 7) */ - bool sign; /*!< 1 indicates the register is signed (2 complem.) */ - uint8_t leng; /*!< number of bits in the register */ - bool rdon; /*!< 1 indicates a read-only register */ - int32_t dflt; /*!< register default value */ -}; - -/* -------------------------------------------------------------------------- */ -/* --- PRIVATE CONSTANTS ---------------------------------------------------- */ - -#define PAGE_ADDR 0x00 -#define PAGE_MASK 0x03 - -/* -auto generated register mapping for C code : 11-Jul-2013 13:20:40 -this file contains autogenerated C struct used to access the Lora register from the Primer firmware -this file is autogenerated from registers description -293 registers are defined -*/ -const struct lgw_reg_s loregs[LGW_TOTALREGS] = { - {-1,0,0,0,2,0,0}, /* PAGE_REG */ - {-1,0,7,0,1,0,0}, /* SOFT_RESET */ - {-1,1,0,0,8,1,103}, /* VERSION */ - {-1,2,0,0,16,0,0}, /* RX_DATA_BUF_ADDR */ - {-1,4,0,0,8,0,0}, /* RX_DATA_BUF_DATA */ - {-1,5,0,0,8,0,0}, /* TX_DATA_BUF_ADDR */ - {-1,6,0,0,8,0,0}, /* TX_DATA_BUF_DATA */ - {-1,7,0,0,8,0,0}, /* CAPTURE_RAM_ADDR */ - {-1,8,0,0,8,1,0}, /* CAPTURE_RAM_DATA */ - {-1,9,0,0,8,0,0}, /* MCU_PROM_ADDR */ - {-1,10,0,0,8,0,0}, /* MCU_PROM_DATA */ - {-1,11,0,0,8,0,0}, /* RX_PACKET_DATA_FIFO_NUM_STORED */ - {-1,12,0,0,16,1,0}, /* RX_PACKET_DATA_FIFO_ADDR_POINTER */ - {-1,14,0,0,8,1,0}, /* RX_PACKET_DATA_FIFO_STATUS */ - {-1,15,0,0,8,1,0}, /* RX_PACKET_DATA_FIFO_PAYLOAD_SIZE */ - {-1,16,0,0,1,0,0}, /* MBWSSF_MODEM_ENABLE */ - {-1,16,1,0,1,0,0}, /* CONCENTRATOR_MODEM_ENABLE */ - {-1,16,2,0,1,0,0}, /* FSK_MODEM_ENABLE */ - {-1,16,3,0,1,0,0}, /* GLOBAL_EN */ - {-1,17,0,0,1,0,1}, /* CLK32M_EN */ - {-1,17,1,0,1,0,1}, /* CLKHS_EN */ - {-1,18,0,0,1,0,0}, /* START_BIST0 */ - {-1,18,1,0,1,0,0}, /* START_BIST1 */ - {-1,18,2,0,1,0,0}, /* CLEAR_BIST0 */ - {-1,18,3,0,1,0,0}, /* CLEAR_BIST1 */ - {-1,19,0,0,1,1,0}, /* BIST0_FINISHED */ - {-1,19,1,0,1,1,0}, /* BIST1_FINISHED */ - {-1,20,0,0,1,1,0}, /* MCU_AGC_PROG_RAM_BIST_STATUS */ - {-1,20,1,0,1,1,0}, /* MCU_ARB_PROG_RAM_BIST_STATUS */ - {-1,20,2,0,1,1,0}, /* CAPTURE_RAM_BIST_STATUS */ - {-1,20,3,0,1,1,0}, /* CHAN_FIR_RAM0_BIST_STATUS */ - {-1,20,4,0,1,1,0}, /* CHAN_FIR_RAM1_BIST_STATUS */ - {-1,21,0,0,1,1,0}, /* CORR0_RAM_BIST_STATUS */ - {-1,21,1,0,1,1,0}, /* CORR1_RAM_BIST_STATUS */ - {-1,21,2,0,1,1,0}, /* CORR2_RAM_BIST_STATUS */ - {-1,21,3,0,1,1,0}, /* CORR3_RAM_BIST_STATUS */ - {-1,21,4,0,1,1,0}, /* CORR4_RAM_BIST_STATUS */ - {-1,21,5,0,1,1,0}, /* CORR5_RAM_BIST_STATUS */ - {-1,21,6,0,1,1,0}, /* CORR6_RAM_BIST_STATUS */ - {-1,21,7,0,1,1,0}, /* CORR7_RAM_BIST_STATUS */ - {-1,22,0,0,1,1,0}, /* MODEM0_RAM0_BIST_STATUS */ - {-1,22,1,0,1,1,0}, /* MODEM1_RAM0_BIST_STATUS */ - {-1,22,2,0,1,1,0}, /* MODEM2_RAM0_BIST_STATUS */ - {-1,22,3,0,1,1,0}, /* MODEM3_RAM0_BIST_STATUS */ - {-1,22,4,0,1,1,0}, /* MODEM4_RAM0_BIST_STATUS */ - {-1,22,5,0,1,1,0}, /* MODEM5_RAM0_BIST_STATUS */ - {-1,22,6,0,1,1,0}, /* MODEM6_RAM0_BIST_STATUS */ - {-1,22,7,0,1,1,0}, /* MODEM7_RAM0_BIST_STATUS */ - {-1,23,0,0,1,1,0}, /* MODEM0_RAM1_BIST_STATUS */ - {-1,23,1,0,1,1,0}, /* MODEM1_RAM1_BIST_STATUS */ - {-1,23,2,0,1,1,0}, /* MODEM2_RAM1_BIST_STATUS */ - {-1,23,3,0,1,1,0}, /* MODEM3_RAM1_BIST_STATUS */ - {-1,23,4,0,1,1,0}, /* MODEM4_RAM1_BIST_STATUS */ - {-1,23,5,0,1,1,0}, /* MODEM5_RAM1_BIST_STATUS */ - {-1,23,6,0,1,1,0}, /* MODEM6_RAM1_BIST_STATUS */ - {-1,23,7,0,1,1,0}, /* MODEM7_RAM1_BIST_STATUS */ - {-1,24,0,0,1,1,0}, /* MODEM0_RAM2_BIST_STATUS */ - {-1,24,1,0,1,1,0}, /* MODEM1_RAM2_BIST_STATUS */ - {-1,24,2,0,1,1,0}, /* MODEM2_RAM2_BIST_STATUS */ - {-1,24,3,0,1,1,0}, /* MODEM3_RAM2_BIST_STATUS */ - {-1,24,4,0,1,1,0}, /* MODEM4_RAM2_BIST_STATUS */ - {-1,24,5,0,1,1,0}, /* MODEM5_RAM2_BIST_STATUS */ - {-1,24,6,0,1,1,0}, /* MODEM6_RAM2_BIST_STATUS */ - {-1,24,7,0,1,1,0}, /* MODEM7_RAM2_BIST_STATUS */ - {-1,25,0,0,1,1,0}, /* MODEM_MBWSSF_RAM0_BIST_STATUS */ - {-1,25,1,0,1,1,0}, /* MODEM_MBWSSF_RAM1_BIST_STATUS */ - {-1,25,2,0,1,1,0}, /* MODEM_MBWSSF_RAM2_BIST_STATUS */ - {-1,26,0,0,1,1,0}, /* MCU_AGC_DATA_RAM_BIST0_STATUS */ - {-1,26,1,0,1,1,0}, /* MCU_AGC_DATA_RAM_BIST1_STATUS */ - {-1,26,2,0,1,1,0}, /* MCU_ARB_DATA_RAM_BIST0_STATUS */ - {-1,26,3,0,1,1,0}, /* MCU_ARB_DATA_RAM_BIST1_STATUS */ - {-1,26,4,0,1,1,0}, /* TX_TOP_RAM_BIST0_STATUS */ - {-1,26,5,0,1,1,0}, /* TX_TOP_RAM_BIST1_STATUS */ - {-1,26,6,0,1,1,0}, /* DATA_MNGT_RAM_BIST0_STATUS */ - {-1,26,7,0,1,1,0}, /* DATA_MNGT_RAM_BIST1_STATUS */ - {-1,27,0,0,4,0,0}, /* GPIO_SELECT_INPUT */ - {-1,28,0,0,4,0,0}, /* GPIO_SELECT_OUTPUT */ - {-1,29,0,0,5,0,0}, /* GPIO_MODE */ - {-1,30,0,0,5,1,0}, /* GPIO_PIN_REG_IN */ - {-1,31,0,0,5,0,0}, /* GPIO_PIN_REG_OUT */ - {-1,32,0,0,8,1,0}, /* MCU_AGC_STATUS */ - {-1,125,0,0,8,1,0}, /* MCU_ARB_STATUS */ - {-1,126,0,0,8,1,1}, /* CHIP_ID */ - {-1,127,0,0,1,0,1}, /* EMERGENCY_FORCE_HOST_CTRL */ - {0,33,0,0,1,0,0}, /* RX_INVERT_IQ */ - {0,33,1,0,1,0,1}, /* MODEM_INVERT_IQ */ - {0,33,2,0,1,0,0}, /* MBWSSF_MODEM_INVERT_IQ */ - {0,33,3,0,1,0,0}, /* RX_EDGE_SELECT */ - {0,33,4,0,1,0,0}, /* MISC_RADIO_EN */ - {0,33,5,0,1,0,0}, /* FSK_MODEM_INVERT_IQ */ - {0,34,0,0,4,0,7}, /* FILTER_GAIN */ - {0,35,0,0,8,0,240}, /* RADIO_SELECT */ - {0,36,0,1,13,0,-384}, /* IF_FREQ_0 */ - {0,38,0,1,13,0,-128}, /* IF_FREQ_1 */ - {0,40,0,1,13,0,128}, /* IF_FREQ_2 */ - {0,42,0,1,13,0,384}, /* IF_FREQ_3 */ - {0,44,0,1,13,0,-384}, /* IF_FREQ_4 */ - {0,46,0,1,13,0,-128}, /* IF_FREQ_5 */ - {0,48,0,1,13,0,128}, /* IF_FREQ_6 */ - {0,50,0,1,13,0,384}, /* IF_FREQ_7 */ - {0,52,0,1,13,0,0}, /* IF_FREQ_8 */ - {0,54,0,1,13,0,0}, /* IF_FREQ_9 */ - {0,64,0,0,1,0,0}, /* CHANN_OVERRIDE_AGC_GAIN */ - {0,64,1,0,4,0,7}, /* CHANN_AGC_GAIN */ - {0,65,0,0,7,0,0}, /* CORR0_DETECT_EN */ - {0,66,0,0,7,0,0}, /* CORR1_DETECT_EN */ - {0,67,0,0,7,0,0}, /* CORR2_DETECT_EN */ - {0,68,0,0,7,0,0}, /* CORR3_DETECT_EN */ - {0,69,0,0,7,0,0}, /* CORR4_DETECT_EN */ - {0,70,0,0,7,0,0}, /* CORR5_DETECT_EN */ - {0,71,0,0,7,0,0}, /* CORR6_DETECT_EN */ - {0,72,0,0,7,0,0}, /* CORR7_DETECT_EN */ - {0,73,0,0,1,0,0}, /* CORR_SAME_PEAKS_OPTION_SF6 */ - {0,73,1,0,1,0,1}, /* CORR_SAME_PEAKS_OPTION_SF7 */ - {0,73,2,0,1,0,1}, /* CORR_SAME_PEAKS_OPTION_SF8 */ - {0,73,3,0,1,0,1}, /* CORR_SAME_PEAKS_OPTION_SF9 */ - {0,73,4,0,1,0,1}, /* CORR_SAME_PEAKS_OPTION_SF10 */ - {0,73,5,0,1,0,1}, /* CORR_SAME_PEAKS_OPTION_SF11 */ - {0,73,6,0,1,0,1}, /* CORR_SAME_PEAKS_OPTION_SF12 */ - {0,74,0,0,4,0,4}, /* CORR_SIG_NOISE_RATIO_SF6 */ - {0,74,4,0,4,0,4}, /* CORR_SIG_NOISE_RATIO_SF7 */ - {0,75,0,0,4,0,4}, /* CORR_SIG_NOISE_RATIO_SF8 */ - {0,75,4,0,4,0,4}, /* CORR_SIG_NOISE_RATIO_SF9 */ - {0,76,0,0,4,0,4}, /* CORR_SIG_NOISE_RATIO_SF10 */ - {0,76,4,0,4,0,4}, /* CORR_SIG_NOISE_RATIO_SF11 */ - {0,77,0,0,4,0,4}, /* CORR_SIG_NOISE_RATIO_SF12 */ - {0,78,0,0,4,0,4}, /* CORR_NUM_SAME_PEAK */ - {0,78,4,0,3,0,5}, /* CORR_MAC_GAIN */ - {0,81,0,0,12,0,0}, /* ADJUST_MODEM_START_OFFSET_RDX4 */ - {0,83,0,0,12,0,4092}, /* ADJUST_MODEM_START_OFFSET_SF12_RDX4 */ - {0,85,0,0,8,0,7}, /* DBG_CORR_SELECT_SF */ - {0,86,0,0,8,0,0}, /* DBG_CORR_SELECT_CHANNEL */ - {0,87,0,0,8,1,0}, /* DBG_DETECT_CPT */ - {0,88,0,0,8,1,0}, /* DBG_SYMB_CPT */ - {0,89,0,0,1,0,1}, /* CHIRP_INVERT_RX */ - {0,89,1,0,1,0,1}, /* DC_NOTCH_EN */ - {0,90,0,0,1,0,0}, /* IMPLICIT_CRC_EN */ - {0,90,1,0,3,0,0}, /* IMPLICIT_CODING_RATE */ - {0,91,0,0,8,0,0}, /* IMPLICIT_PAYLOAD_LENGHT */ - {0,92,0,0,8,0,29}, /* FREQ_TO_TIME_INVERT */ - {0,93,0,0,6,0,9}, /* FREQ_TO_TIME_DRIFT */ - {0,94,0,0,2,0,2}, /* PAYLOAD_FINE_TIMING_GAIN */ - {0,94,2,0,2,0,1}, /* PREAMBLE_FINE_TIMING_GAIN */ - {0,94,4,0,2,0,0}, /* TRACKING_INTEGRAL */ - {0,95,0,0,4,0,1}, /* FRAME_SYNCH_PEAK1_POS */ - {0,95,4,0,4,0,2}, /* FRAME_SYNCH_PEAK2_POS */ - {0,96,0,0,16,0,10}, /* PREAMBLE_SYMB1_NB */ - {0,98,0,0,1,0,1}, /* FRAME_SYNCH_GAIN */ - {0,98,1,0,1,0,1}, /* SYNCH_DETECT_TH */ - {0,99,0,0,4,0,8}, /* LLR_SCALE */ - {0,99,4,0,2,0,2}, /* SNR_AVG_CST */ - {0,100,0,0,7,0,0}, /* PPM_OFFSET */ - {0,101,0,0,8,0,255}, /* MAX_PAYLOAD_LEN */ - {0,102,0,0,1,0,1}, /* ONLY_CRC_EN */ - {0,103,0,0,8,0,0}, /* ZERO_PAD */ - {0,104,0,0,4,0,8}, /* DEC_GAIN_OFFSET */ - {0,104,4,0,4,0,7}, /* CHAN_GAIN_OFFSET */ - {0,105,1,0,1,0,1}, /* FORCE_HOST_RADIO_CTRL */ - {0,105,2,0,1,0,1}, /* FORCE_HOST_FE_CTRL */ - {0,105,3,0,1,0,1}, /* FORCE_DEC_FILTER_GAIN */ - {0,106,0,0,1,0,1}, /* MCU_RST_0 */ - {0,106,1,0,1,0,1}, /* MCU_RST_1 */ - {0,106,2,0,1,0,0}, /* MCU_SELECT_MUX_0 */ - {0,106,3,0,1,0,0}, /* MCU_SELECT_MUX_1 */ - {0,106,4,0,1,1,0}, /* MCU_CORRUPTION_DETECTED_0 */ - {0,106,5,0,1,1,0}, /* MCU_CORRUPTION_DETECTED_1 */ - {0,106,6,0,1,0,0}, /* MCU_SELECT_EDGE_0 */ - {0,106,7,0,1,0,0}, /* MCU_SELECT_EDGE_1 */ - {0,107,0,0,8,0,1}, /* CHANN_SELECT_RSSI */ - {0,108,0,0,8,0,32}, /* RSSI_BB_DEFAULT_VALUE */ - {0,109,0,0,8,0,100}, /* RSSI_DEC_DEFAULT_VALUE */ - {0,110,0,0,8,0,100}, /* RSSI_CHANN_DEFAULT_VALUE */ - {0,111,0,0,5,0,7}, /* RSSI_BB_FILTER_ALPHA */ - {0,112,0,0,5,0,5}, /* RSSI_DEC_FILTER_ALPHA */ - {0,113,0,0,5,0,8}, /* RSSI_CHANN_FILTER_ALPHA */ - {0,114,0,0,6,0,0}, /* IQ_MISMATCH_A_AMP_COEFF */ - {0,115,0,0,6,0,0}, /* IQ_MISMATCH_A_PHI_COEFF */ - {0,116,0,0,6,0,0}, /* IQ_MISMATCH_B_AMP_COEFF */ - {0,116,6,0,1,0,0}, /* IQ_MISMATCH_B_SEL_I */ - {0,117,0,0,6,0,0}, /* IQ_MISMATCH_B_PHI_COEFF */ - {1,33,0,0,1,0,0}, /* TX_TRIG_IMMEDIATE */ - {1,33,1,0,1,0,0}, /* TX_TRIG_DELAYED */ - {1,33,2,0,1,0,0}, /* TX_TRIG_GPS */ - {1,34,0,0,16,0,0}, /* TX_START_DELAY */ - {1,36,0,0,4,0,1}, /* TX_FRAME_SYNCH_PEAK1_POS */ - {1,36,4,0,4,0,2}, /* TX_FRAME_SYNCH_PEAK2_POS */ - {1,37,0,0,3,0,0}, /* TX_RAMP_DURATION */ - {1,39,0,1,8,0,0}, /* TX_OFFSET_I */ - {1,40,0,1,8,0,0}, /* TX_OFFSET_Q */ - {1,41,0,0,1,0,0}, /* TX_MODE */ - {1,41,1,0,4,0,0}, /* TX_ZERO_PAD */ - {1,41,5,0,1,0,0}, /* TX_EDGE_SELECT */ - {1,41,6,0,1,0,0}, /* TX_EDGE_SELECT_TOP */ - {1,42,0,0,2,0,0}, /* TX_GAIN */ - {1,42,2,0,3,0,5}, /* TX_CHIRP_LOW_PASS */ - {1,42,5,0,2,0,0}, /* TX_FCC_WIDEBAND */ - {1,42,7,0,1,0,1}, /* TX_SWAP_IQ */ - {1,43,0,0,1,0,0}, /* MBWSSF_IMPLICIT_HEADER */ - {1,43,1,0,1,0,0}, /* MBWSSF_IMPLICIT_CRC_EN */ - {1,43,2,0,3,0,0}, /* MBWSSF_IMPLICIT_CODING_RATE */ - {1,44,0,0,8,0,0}, /* MBWSSF_IMPLICIT_PAYLOAD_LENGHT */ - {1,45,0,0,1,0,1}, /* MBWSSF_AGC_FREEZE_ON_DETECT */ - {1,46,0,0,4,0,1}, /* MBWSSF_FRAME_SYNCH_PEAK1_POS */ - {1,46,4,0,4,0,2}, /* MBWSSF_FRAME_SYNCH_PEAK2_POS */ - {1,47,0,0,16,0,10}, /* MBWSSF_PREAMBLE_SYMB1_NB */ - {1,49,0,0,1,0,1}, /* MBWSSF_FRAME_SYNCH_GAIN */ - {1,49,1,0,1,0,1}, /* MBWSSF_SYNCH_DETECT_TH */ - {1,50,0,0,8,0,10}, /* MBWSSF_DETECT_MIN_SINGLE_PEAK */ - {1,51,0,0,3,0,3}, /* MBWSSF_DETECT_TRIG_SAME_PEAK_NB */ - {1,52,0,0,8,0,29}, /* MBWSSF_FREQ_TO_TIME_INVERT */ - {1,53,0,0,6,0,36}, /* MBWSSF_FREQ_TO_TIME_DRIFT */ - {1,54,0,0,12,0,0}, /* MBWSSF_PPM_CORRECTION */ - {1,56,0,0,2,0,2}, /* MBWSSF_PAYLOAD_FINE_TIMING_GAIN */ - {1,56,2,0,2,0,1}, /* MBWSSF_PREAMBLE_FINE_TIMING_GAIN */ - {1,56,4,0,2,0,0}, /* MBWSSF_TRACKING_INTEGRAL */ - {1,57,0,0,8,0,0}, /* MBWSSF_ZERO_PAD */ - {1,58,0,0,2,0,0}, /* MBWSSF_MODEM_BW */ - {1,58,2,0,1,0,0}, /* MBWSSF_RADIO_SELECT */ - {1,58,3,0,1,0,1}, /* MBWSSF_RX_CHIRP_INVERT */ - {1,59,0,0,4,0,8}, /* MBWSSF_LLR_SCALE */ - {1,59,4,0,2,0,3}, /* MBWSSF_SNR_AVG_CST */ - {1,59,6,0,1,0,0}, /* MBWSSF_PPM_OFFSET */ - {1,60,0,0,4,0,7}, /* MBWSSF_RATE_SF */ - {1,60,4,0,1,0,1}, /* MBWSSF_ONLY_CRC_EN */ - {1,61,0,0,8,0,255}, /* MBWSSF_MAX_PAYLOAD_LEN */ - {1,62,0,0,8,1,128}, /* TX_STATUS */ - {1,63,0,0,3,0,0}, /* FSK_CH_BW_EXPO */ - {1,63,3,0,3,0,0}, /* FSK_RSSI_LENGTH */ - {1,63,6,0,1,0,0}, /* FSK_RX_INVERT */ - {1,63,7,0,1,0,0}, /* FSK_PKT_MODE */ - {1,64,0,0,3,0,0}, /* FSK_PSIZE */ - {1,64,3,0,1,0,0}, /* FSK_CRC_EN */ - {1,64,4,0,2,0,0}, /* FSK_DCFREE_ENC */ - {1,64,6,0,1,0,0}, /* FSK_CRC_IBM */ - {1,65,0,0,5,0,0}, /* FSK_ERROR_OSR_TOL */ - {1,65,7,0,1,0,0}, /* FSK_RADIO_SELECT */ - {1,66,0,0,16,0,0}, /* FSK_BR_RATIO */ - {1,68,0,0,32,0,0}, /* FSK_REF_PATTERN_LSB */ - {1,72,0,0,32,0,0}, /* FSK_REF_PATTERN_MSB */ - {1,76,0,0,8,0,0}, /* FSK_PKT_LENGTH */ - {1,77,0,0,1,0,1}, /* FSK_TX_GAUSSIAN_EN */ - {1,77,1,0,2,0,0}, /* FSK_TX_GAUSSIAN_SELECT_BT */ - {1,77,3,0,1,0,1}, /* FSK_TX_PATTERN_EN */ - {1,77,4,0,1,0,0}, /* FSK_TX_PREAMBLE_SEQ */ - {1,77,5,0,3,0,0}, /* FSK_TX_PSIZE */ - {1,80,0,0,8,0,0}, /* FSK_NODE_ADRS */ - {1,81,0,0,8,0,0}, /* FSK_BROADCAST */ - {1,82,0,0,1,0,1}, /* FSK_AUTO_AFC_ON */ - {1,83,0,0,10,0,0}, /* FSK_PATTERN_TIMEOUT_CFG */ - {2,33,0,0,8,0,0}, /* SPI_RADIO_A__DATA */ - {2,34,0,0,8,1,0}, /* SPI_RADIO_A__DATA_READBACK */ - {2,35,0,0,8,0,0}, /* SPI_RADIO_A__ADDR */ - {2,37,0,0,1,0,0}, /* SPI_RADIO_A__CS */ - {2,38,0,0,8,0,0}, /* SPI_RADIO_B__DATA */ - {2,39,0,0,8,1,0}, /* SPI_RADIO_B__DATA_READBACK */ - {2,40,0,0,8,0,0}, /* SPI_RADIO_B__ADDR */ - {2,42,0,0,1,0,0}, /* SPI_RADIO_B__CS */ - {2,43,0,0,1,0,0}, /* RADIO_A_EN */ - {2,43,1,0,1,0,0}, /* RADIO_B_EN */ - {2,43,2,0,1,0,1}, /* RADIO_RST */ - {2,43,3,0,1,0,0}, /* LNA_A_EN */ - {2,43,4,0,1,0,0}, /* PA_A_EN */ - {2,43,5,0,1,0,0}, /* LNA_B_EN */ - {2,43,6,0,1,0,0}, /* PA_B_EN */ - {2,44,0,0,2,0,0}, /* PA_GAIN */ - {2,45,0,0,4,0,2}, /* LNA_A_CTRL_LUT */ - {2,45,4,0,4,0,4}, /* PA_A_CTRL_LUT */ - {2,46,0,0,4,0,2}, /* LNA_B_CTRL_LUT */ - {2,46,4,0,4,0,4}, /* PA_B_CTRL_LUT */ - {2,47,0,0,5,0,0}, /* CAPTURE_SOURCE */ - {2,47,5,0,1,0,0}, /* CAPTURE_START */ - {2,47,6,0,1,0,0}, /* CAPTURE_FORCE_TRIGGER */ - {2,47,7,0,1,0,0}, /* CAPTURE_WRAP */ - {2,48,0,0,16,0,0}, /* CAPTURE_PERIOD */ - {2,51,0,0,8,1,0}, /* MODEM_STATUS */ - {2,52,0,0,8,1,0}, /* VALID_HEADER_COUNTER_0 */ - {2,54,0,0,8,1,0}, /* VALID_PACKET_COUNTER_0 */ - {2,56,0,0,8,1,0}, /* VALID_HEADER_COUNTER_MBWSSF */ - {2,57,0,0,8,1,0}, /* VALID_HEADER_COUNTER_FSK */ - {2,58,0,0,8,1,0}, /* VALID_PACKET_COUNTER_MBWSSF */ - {2,59,0,0,8,1,0}, /* VALID_PACKET_COUNTER_FSK */ - {2,60,0,0,8,1,0}, /* CHANN_RSSI */ - {2,61,0,0,8,1,0}, /* BB_RSSI */ - {2,62,0,0,8,1,0}, /* DEC_RSSI */ - {2,63,0,0,8,1,0}, /* DBG_MCU_DATA */ - {2,64,0,0,8,1,0}, /* DBG_ARB_MCU_RAM_DATA */ - {2,65,0,0,8,1,0}, /* DBG_AGC_MCU_RAM_DATA */ - {2,66,0,0,16,1,0}, /* NEXT_PACKET_CNT */ - {2,68,0,0,16,1,0}, /* ADDR_CAPTURE_COUNT */ - {2,70,0,0,32,1,0}, /* TIMESTAMP */ - {2,74,0,0,4,1,0}, /* DBG_CHANN0_GAIN */ - {2,74,4,0,4,1,0}, /* DBG_CHANN1_GAIN */ - {2,75,0,0,4,1,0}, /* DBG_CHANN2_GAIN */ - {2,75,4,0,4,1,0}, /* DBG_CHANN3_GAIN */ - {2,76,0,0,4,1,0}, /* DBG_CHANN4_GAIN */ - {2,76,4,0,4,1,0}, /* DBG_CHANN5_GAIN */ - {2,77,0,0,4,1,0}, /* DBG_CHANN6_GAIN */ - {2,77,4,0,4,1,0}, /* DBG_CHANN7_GAIN */ - {2,78,0,0,4,1,0}, /* DBG_DEC_FILT_GAIN */ - {2,79,0,0,3,1,0}, /* SPI_DATA_FIFO_PTR */ - {2,79,3,0,3,1,0}, /* PACKET_DATA_FIFO_PTR */ - {2,80,0,0,8,0,0}, /* DBG_ARB_MCU_RAM_ADDR */ - {2,81,0,0,8,0,0}, /* DBG_AGC_MCU_RAM_ADDR */ - {2,82,0,0,1,0,0}, /* SPI_MASTER_CHIP_SELECT_POLARITY */ - {2,82,1,0,1,0,0}, /* SPI_MASTER_CPOL */ - {2,82,2,0,1,0,0}, /* SPI_MASTER_CPHA */ - {2,83,0,0,1,0,0}, /* SIG_GEN_ANALYSER_MUX_SEL */ - {2,84,0,0,1,0,0}, /* SIG_GEN_EN */ - {2,84,1,0,1,0,0}, /* SIG_ANALYSER_EN */ - {2,84,2,0,2,0,0}, /* SIG_ANALYSER_AVG_LEN */ - {2,84,4,0,3,0,0}, /* SIG_ANALYSER_PRECISION */ - {2,84,7,0,1,1,0}, /* SIG_ANALYSER_VALID_OUT */ - {2,85,0,0,8,0,0}, /* SIG_GEN_FREQ */ - {2,86,0,0,8,0,0}, /* SIG_ANALYSER_FREQ */ - {2,87,0,0,8,1,0}, /* SIG_ANALYSER_I_OUT */ - {2,88,0,0,8,1,0}, /* SIG_ANALYSER_Q_OUT */ - {2,89,0,0,1,0,0}, /* GPS_EN */ - {2,89,1,0,1,0,1}, /* GPS_POL */ - {2,90,0,1,8,0,0}, /* SW_TEST_REG1 */ - {2,91,2,1,6,0,0}, /* SW_TEST_REG2 */ - {2,92,0,1,16,0,0}, /* SW_TEST_REG3 */ - {2,94,0,0,4,1,0}, /* DATA_MNGT_STATUS */ - {2,95,0,0,5,1,0}, /* DATA_MNGT_CPT_FRAME_ALLOCATED */ - {2,96,0,0,5,1,0}, /* DATA_MNGT_CPT_FRAME_FINISHED */ - {2,97,0,0,5,1,0} /* DATA_MNGT_CPT_FRAME_READEN */ -}; - -/* -------------------------------------------------------------------------- */ -/* --- PRIVATE VARIABLES ---------------------------------------------------- */ - -void *lgw_spi_target = NULL; /*! generic pointer to the SPI device */ -static int lgw_regpage = -1; /*! keep the value of the register page selected */ - -/* -------------------------------------------------------------------------- */ -/* --- PRIVATE FUNCTIONS ---------------------------------------------------- */ - -int page_switch(uint8_t target) { - lgw_regpage = PAGE_MASK & target; - lgw_spi_w(lgw_spi_target, PAGE_ADDR, (uint8_t)lgw_regpage); - return LGW_REG_SUCCESS; -} - -/* -------------------------------------------------------------------------- */ -/* --- PUBLIC FUNCTIONS DEFINITION ------------------------------------------ */ - -/* Gateway connect */ -int lgw_connect(void) { - int spi_stat = LGW_SPI_SUCCESS; - uint8_t u = 0; - - if (lgw_spi_target != NULL) { - DEBUG_MSG("WARNING: gateway was already connected\n"); - lgw_spi_close(lgw_spi_target); - } - /* open the SPI link */ - spi_stat = lgw_spi_open(&lgw_spi_target); - if (spi_stat != LGW_SPI_SUCCESS) { - DEBUG_MSG("ERROR CONNECTING GATEWAY\n"); - return LGW_REG_ERROR; - } - /* write 0 to the page/reset register */ - spi_stat = lgw_spi_w(lgw_spi_target, loregs[LGW_PAGE_REG].addr, 0); - if (spi_stat != LGW_SPI_SUCCESS) { - DEBUG_MSG("ERROR WRITING PAGE REGISTER\n"); - return LGW_REG_ERROR; - } else { - lgw_regpage = 0; - } - /* 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"); - return LGW_REG_ERROR; - } else if (u != loregs[LGW_VERSION].dflt) { - DEBUG_MSG("ERROR: MISMATCH BETWEEN EXPECTED REG VERSION AND READ REG VERSION\n"); - return LGW_REG_ERROR; - } - DEBUG_MSG("Note: success connecting the gateway\n"); - return LGW_REG_SUCCESS; -} - -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ - -/* Gateway disconnect */ -int lgw_disconnect(void) { - if (lgw_spi_target != NULL) { - lgw_spi_close(lgw_spi_target); - lgw_spi_target = NULL; - DEBUG_MSG("Note: success disconnecting the gateway\n"); - return LGW_REG_SUCCESS; - } else { - DEBUG_MSG("WARNING: gateway was already disconnected\n"); - return LGW_REG_ERROR; - } -} - -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ - -/* soft-reset function */ -int lgw_soft_reset(void) { - int32_t read_value; - /* check if SPI is initialised */ - if ((lgw_spi_target == NULL) || (lgw_regpage < 0)) { - DEBUG_MSG("ERROR: GATEWAY UNCONNECTED\n"); - return LGW_REG_ERROR; - } - lgw_spi_w(lgw_spi_target, 0, 0x80); /* 1 -> SOFT_RESET bit */ - lgw_regpage = 0; /* reset the paging static variable */ - return LGW_REG_SUCCESS; -} - -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ - -/* register verification */ -int lgw_reg_check(FILE *f) { - struct lgw_reg_s r; - int32_t read_value; - char ok_msg[] = "+++MATCH+++"; - char notok_msg[] = "###MISMATCH###"; - char *ptr; - int i; - - /* check if SPI is initialised */ - if ((lgw_spi_target == NULL) || (lgw_regpage < 0)) { - DEBUG_MSG("ERROR: GATEWAY UNCONNECTED\n"); - fprintf(f, "ERROR: GATEWAY UNCONNECTED\n"); - return LGW_REG_ERROR; - } - - fprintf(f, "Start of register verification\n"); - for (i=0; i= LGW_TOTALREGS) { - DEBUG_MSG("ERROR: REGISTER NUMBER OUT OF DEFINED RANGE\n"); - return LGW_REG_ERROR; - } - - /* check if SPI is initialised */ - if ((lgw_spi_target == NULL) || (lgw_regpage < 0)) { - DEBUG_MSG("ERROR: GATEWAY UNCONNECTED\n"); - return LGW_REG_ERROR; - } - - /* intercept direct access to PAGE_REG & SOFT_RESET */ - if (register_id == LGW_PAGE_REG) { - page_switch(reg_value); - return LGW_REG_SUCCESS; - } else if (register_id == LGW_SOFT_RESET) { - /* only reset if lsb is 1 */ - if ((reg_value & 0x01) != 0) - lgw_soft_reset(); - return LGW_REG_SUCCESS; - } - - /* get register struct from the struct array */ - r = loregs[register_id]; - - /* reject write to read-only registers */ - if (r.rdon == 1){ - DEBUG_MSG("ERROR: TRYING TO WRITE A READ-ONLY REGISTER\n"); - return LGW_REG_ERROR; - } - - /* select proper register page if needed */ - if ((r.page != -1) && (r.page != lgw_regpage)) { - spi_stat += page_switch(r.page); - } - - if ((r.leng == 8) && (r.offs == 0)) { - /* direct write */ - spi_stat += lgw_spi_w(lgw_spi_target, r.addr, (uint8_t)reg_value); - } else if ((r.offs + r.leng) <= 8) { - /* single-byte read-modify-write, offs:[0-7], leng:[1-7] */ - spi_stat += lgw_spi_r(lgw_spi_target, r.addr, &buf[0]); - buf[1] = ((1 << r.leng) - 1) << r.offs; /* bit mask */ - buf[2] = ((uint8_t)reg_value) << r.offs; /* new data offsetted */ - buf[3] = (~buf[1] & buf[0]) | (buf[1] & buf[2]); /* mixing old & new data */ - spi_stat += lgw_spi_w(lgw_spi_target, r.addr, buf[3]); - } else if ((r.offs == 0) && (r.leng > 0) && (r.leng <= 32)) { - /* multi-byte direct write routine */ - size_byte = (r.leng + 7) / 8; /* add a byte if it's not an exact multiple of 8 */ - for (i=0; i> 8); - } - spi_stat += lgw_spi_wb(lgw_spi_target, r.addr, buf, size_byte); /* write the register in one burst */ - } else { - /* register spanning multiple memory bytes but with an offset */ - DEBUG_MSG("ERROR: REGISTER SIZE AND OFFSET ARE NOT SUPPORTED\n"); - return LGW_REG_ERROR; - } - - if (spi_stat != LGW_SPI_SUCCESS) { - DEBUG_MSG("ERROR: SPI ERROR DURING REGISTER WRITE\n"); - return LGW_REG_ERROR; - } else { - return LGW_REG_SUCCESS; - } -} - -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ - -/* Read to a register addressed by name */ -int lgw_reg_r(uint16_t register_id, int32_t *reg_value) { - int spi_stat = LGW_SPI_SUCCESS; - struct lgw_reg_s r; - uint8_t bufu[4] = "\x00\x00\x00\x00"; - int8_t *bufs = bufu; - int i, size_byte; - uint32_t u = 0; - - /* check input parameters */ - CHECK_NULL(reg_value); - if (register_id >= LGW_TOTALREGS) { - DEBUG_MSG("ERROR: REGISTER NUMBER OUT OF DEFINED RANGE\n"); - return LGW_REG_ERROR; - } - - /* check if SPI is initialised */ - if ((lgw_spi_target == NULL) || (lgw_regpage < 0)) { - DEBUG_MSG("ERROR: GATEWAY UNCONNECTED\n"); - return LGW_REG_ERROR; - } - - /* get register struct from the struct array */ - r = loregs[register_id]; - - /* select proper register page if needed */ - if ((r.page != -1) && (r.page != lgw_regpage)) { - spi_stat += page_switch(r.page); - } - - if ((r.offs + r.leng) <= 8) { - /* read one byte, then shift and mask bits to get reg value with sign extension if needed */ - spi_stat += lgw_spi_r(lgw_spi_target, r.addr, &bufu[0]); - bufu[1] = bufu[0] << (8 - r.leng - r.offs); /* left-align the data */ - if (r.sign == true) { - bufs[2] = bufs[1] >> (8 - r.leng); /* right align the data with sign extension (ARITHMETIC right shift) */ - *reg_value = (int32_t)bufs[2]; /* signed pointer -> 32b sign extension */ - } else { - bufu[2] = bufu[1] >> (8 - r.leng); /* right align the data, no sign extension */ - *reg_value = (int32_t)bufu[2]; /* unsigned pointer -> no sign extension */ - } - } else if ((r.offs == 0) && (r.leng > 0) && (r.leng <= 32)) { - size_byte = (r.leng + 7) / 8; /* add a byte if it's not an exact multiple of 8 */ - spi_stat += lgw_spi_rb(lgw_spi_target, r.addr, bufu, size_byte); - u = 0; - for (i=(size_byte-1); i>=0; --i) { - u = (uint32_t)bufu[i] + (u << 8); /* transform a 4-byte array into a 32 bit word */ - } - if (r.sign == true) { - u = u << (32 - r.leng); /* left-align the data */ - *reg_value = (int32_t)u >> (32 - r.leng); /* right-align the data with sign extension (ARITHMETIC right shift) */ - } else { - *reg_value = (int32_t)u; /* unsigned value -> return 'as is' */ - } - } else { - /* register spanning multiple memory bytes but with an offset */ - DEBUG_MSG("ERROR: REGISTER SIZE AND OFFSET ARE NOT SUPPORTED\n"); - return LGW_REG_ERROR; - } - - if (spi_stat != LGW_SPI_SUCCESS) { - DEBUG_MSG("ERROR: SPI ERROR DURING REGISTER WRITE\n"); - return LGW_REG_ERROR; - } else { - return LGW_REG_SUCCESS; - } -} - -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ - -/* Point to a register by name and do a burst write */ -int lgw_reg_wb(uint16_t register_id, uint8_t *data, uint16_t size) { - int spi_stat; - struct lgw_reg_s r; - - /* check input parameters */ - CHECK_NULL(data); - if (size == 0) { - DEBUG_MSG("ERROR: BURST OF NULL LENGTH\n"); - return LGW_REG_ERROR; - } - if (register_id >= LGW_TOTALREGS) { - DEBUG_MSG("ERROR: REGISTER NUMBER OUT OF DEFINED RANGE\n"); - return LGW_REG_ERROR; - } - - /* check if SPI is initialised */ - if ((lgw_spi_target == NULL) || (lgw_regpage < 0)) { - DEBUG_MSG("ERROR: GATEWAY UNCONNECTED\n"); - return LGW_REG_ERROR; - } - - /* get register struct from the struct array */ - r = loregs[register_id]; - - /* reject write to read-only registers */ - if (r.rdon == 1){ - DEBUG_MSG("ERROR: TRYING TO BURST WRITE A READ-ONLY REGISTER\n"); - return LGW_REG_ERROR; - } - - /* select proper register page if needed */ - if ((r.page != -1) && (r.page != lgw_regpage)) { - spi_stat += page_switch(r.page); - } - - /* do the burst write */ - spi_stat = lgw_spi_wb(lgw_spi_target, r.addr, data, size); - - if (spi_stat != LGW_SPI_SUCCESS) { - DEBUG_MSG("ERROR: SPI ERROR DURING REGISTER BURST WRITE\n"); - return LGW_REG_ERROR; - } else { - return LGW_REG_SUCCESS; - } -} - -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ - -/* Point to a register by name and do a burst read */ -int lgw_reg_rb(uint16_t register_id, uint8_t *data, uint16_t size) { - int spi_stat; - struct lgw_reg_s r; - - /* check input parameters */ - CHECK_NULL(data); - if (size == 0) { - DEBUG_MSG("ERROR: BURST OF NULL LENGTH\n"); - return LGW_REG_ERROR; - } - if (register_id >= LGW_TOTALREGS) { - DEBUG_MSG("ERROR: REGISTER NUMBER OUT OF DEFINED RANGE\n"); - return LGW_REG_ERROR; - } - - /* check if SPI is initialised */ - if ((lgw_spi_target == NULL) || (lgw_regpage < 0)) { - DEBUG_MSG("ERROR: GATEWAY UNCONNECTED\n"); - return LGW_REG_ERROR; - } - - /* get register struct from the struct array */ - r = loregs[register_id]; - - /* select proper register page if needed */ - if ((r.page != -1) && (r.page != lgw_regpage)) { - spi_stat += page_switch(r.page); - } - - /* do the burst read */ - spi_stat = lgw_spi_rb(lgw_spi_target, r.addr, data, size); - - if (spi_stat != LGW_SPI_SUCCESS) { - DEBUG_MSG("ERROR: SPI ERROR DURING REGISTER BURST READ\n"); - return LGW_REG_ERROR; - } else { - return LGW_REG_SUCCESS; - } -} - -/* --- EOF ------------------------------------------------------------------ */ diff --git a/loragw_hal/src/loragw_spi.ftdi.c b/loragw_hal/src/loragw_spi.ftdi.c deleted file mode 100644 index 7b71901..0000000 --- a/loragw_hal/src/loragw_spi.ftdi.c +++ /dev/null @@ -1,285 +0,0 @@ -/* - / _____) _ | | -( (____ _____ ____ _| |_ _____ ____| |__ - \____ \| ___ | (_ _) ___ |/ ___) _ \ - _____) ) ____| | | || |_| ____( (___| | | | -(______/|_____)_|_|_| \__)_____)\____)_| |_| - ©2013 Semtech-Cycleo - -Description: - Host specific functions to address the LoRa™ gateway registers through a - SPI interface. - Single-byte read/write and burst read/write. - Does not handle pagination. - Could be used with multiple SPI ports in parallel (explicit file descriptor) -*/ - - -/* -------------------------------------------------------------------------- */ -/* --- DEPENDANCIES --------------------------------------------------------- */ - -#include /* C99 types */ -#include /* printf fprintf */ -#include /* malloc free */ -#include /* memcpy */ - -#include - -#include "loragw_spi.h" - -/* -------------------------------------------------------------------------- */ -/* --- PRIVATE MACROS ------------------------------------------------------- */ - -#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) -#if DEBUG_SPI == 1 - #define DEBUG_MSG(str) fprintf(stderr, str) - #define DEBUG_PRINTF(fmt, args...) fprintf(stderr,"%s:%d: "fmt, __FUNCTION__, __LINE__, args) - #define CHECK_NULL(a) if(a==NULL){fprintf(stderr,"%s:%d: ERROR: NULL POINTER AS ARGUMENT\n", __FUNCTION__, __LINE__);return LGW_SPI_ERROR;} -#else - #define DEBUG_MSG(str) - #define DEBUG_PRINTF(fmt, args...) - #define CHECK_NULL(a) if(a==NULL){return LGW_SPI_ERROR;} -#endif - -/* -------------------------------------------------------------------------- */ -/* --- PRIVATE CONSTANTS ---------------------------------------------------- */ - -#define READ_ACCESS 0x00 -#define WRITE_ACCESS 0x80 - -/* parameters for a FT2232H */ -#define VID 0x0403 -#define PID 0x6010 - -/* -------------------------------------------------------------------------- */ -/* --- PUBLIC FUNCTIONS DEFINITION ------------------------------------------ */ - -/* SPI initialization and configuration */ -int lgw_spi_open(void **spi_target_ptr) { - struct mpsse_context *mpsse = NULL; - - /* check input variables */ - CHECK_NULL(spi_target_ptr); /* cannot be null, must point on a void pointer (*spi_target_ptr can be null) */ - - /* try to open the first available FTDI device matching VID/PID parameters */ - mpsse = OpenIndex(VID,PID,SPI0, SIX_MHZ, MSB, IFACE_A, NULL, NULL, 0); - if (mpsse == NULL) { - DEBUG_MSG("ERROR: MPSSE OPEN FUNCTION RETURNED NULL\n"); - return LGW_SPI_ERROR; - } - if (mpsse->open != 1) { - DEBUG_MSG("ERROR: MPSSE OPEN FUNCTION FAILED\n"); - return LGW_SPI_ERROR; - } - - DEBUG_PRINTF("SPI port opened and configured ok\ndesc: %s\nPID: 0x%04X\nVID: 0x%04X\nclock: %d\nLibmpsse version: 0x%02X\n", GetDescription(mpsse), GetPid(mpsse), GetVid(mpsse), GetClock(mpsse), Version()); - *spi_target_ptr = (void *)mpsse; - return LGW_SPI_SUCCESS; -} - -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ - -/* SPI release */ -int lgw_spi_close(void *spi_target) { - struct mpsse_context *mpsse = spi_target; - - /* check input variables */ - CHECK_NULL(spi_target); - - Close(mpsse); - - /* close return no status, assume success (0_o) */ - return LGW_SPI_SUCCESS; -} - -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ - -/* Simple write */ -/* transaction time: .6 to 1 ms typically */ -int lgw_spi_w(void *spi_target, uint8_t address, uint8_t data) { - struct mpsse_context *mpsse = spi_target; - uint8_t out_buf[2]; - int a, b, c; - - /* check input variables */ - CHECK_NULL(spi_target); - if ((address & 0x80) != 0) { - DEBUG_MSG("WARNING: SPI address > 127\n"); - } - - /* prepare frame to be sent */ - out_buf[0] = WRITE_ACCESS | (address & 0x7F); - out_buf[1] = data; - - /* MPSSE transaction */ - a = Start(mpsse); - b = FastWrite(mpsse, (char *)out_buf, 2); - c = Stop(mpsse); - - /* determine return code */ - if ((a != MPSSE_OK) || (b != MPSSE_OK) || (c != MPSSE_OK)) { - DEBUG_MSG("ERROR: SPI WRITE FAILURE\n"); - return LGW_SPI_ERROR; - } else { - DEBUG_MSG("Note: SPI write success\n"); - return LGW_SPI_SUCCESS; - } -} - -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ - -/* Simple read (using Transfer function) */ -/* transaction time: 1.1 to 2 ms typically */ -int lgw_spi_r(void *spi_target, uint8_t address, uint8_t *data) { - struct mpsse_context *mpsse = spi_target; - uint8_t out_buf[2]; - uint8_t *in_buf = NULL; - int a, b; - - /* check input variables */ - CHECK_NULL(spi_target); - if ((address & 0x80) != 0) { - DEBUG_MSG("WARNING: SPI address > 127\n"); - } - CHECK_NULL(data); - - /* prepare frame to be sent */ - out_buf[0] = READ_ACCESS | (address & 0x7F); - out_buf[1] = 0x00; - - /* MPSSE transaction */ - a = Start(mpsse); - in_buf = (uint8_t *)Transfer(mpsse, (char *)out_buf, 2); - b = Stop(mpsse); - - /* determine return code */ - if ((in_buf == NULL) || (a != MPSSE_OK) || (b != MPSSE_OK)) { - DEBUG_MSG("ERROR: SPI READ FAILURE\n"); - if (in_buf != NULL) { - free(in_buf); - } - return LGW_SPI_ERROR; - } else { - DEBUG_MSG("Note: SPI read success\n"); - *data = in_buf[1]; - free(in_buf); - return LGW_SPI_SUCCESS; - } -} - -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ - -/* Burst (multiple-byte) write */ -/* transaction time: 3.7ms for 2500 data bytes @6MHz, 1kB chunks */ -/* transaction time: 0.5ms for 16 data bytes @6MHz, 1kB chunks */ -int lgw_spi_wb(void *spi_target, uint8_t address, uint8_t *data, uint16_t size) { - struct mpsse_context *mpsse = spi_target; - uint8_t command; - uint8_t *out_buf = NULL; - int size_to_do, buf_size, chunk_size, offset; - int a, b, c; - int i; - - /* check input parameters */ - CHECK_NULL(spi_target); - if ((address & 0x80) != 0) { - DEBUG_MSG("WARNING: SPI address > 127\n"); - } - CHECK_NULL(data); - if (size == 0) { - DEBUG_MSG("ERROR: BURST OF NULL LENGTH\n"); - return LGW_SPI_ERROR; - } - - /* prepare command byte */ - command = WRITE_ACCESS | (address & 0x7F); - size_to_do = size + 1; /* add a byte for the address */ - - /* allocate data buffer */ - buf_size = (size_to_do < LGW_BURST_CHUNK) ? size_to_do : LGW_BURST_CHUNK; - out_buf = malloc(buf_size); - if (out_buf == NULL) { - DEBUG_MSG("ERROR: MALLOC FAIL\n"); - return LGW_SPI_ERROR; - } - - /* start MPSSE transaction */ - a = Start(mpsse); - for (i=0; size_to_do > 0; ++i) { - chunk_size = (size_to_do < LGW_BURST_CHUNK) ? size_to_do : LGW_BURST_CHUNK; - if (i == 0) { - /* first chunk, need to append the address */ - out_buf[0] = command; - memcpy(out_buf+1, data, chunk_size-1); - } else { - /* following chunks, just copy the data */ - offset = (i * LGW_BURST_CHUNK) - 1; - memcpy(out_buf, data + offset, chunk_size); - } - b = FastWrite(mpsse, (char *)out_buf, chunk_size); - size_to_do -= chunk_size; /* subtract the quantity of data already transferred */ - } - c = Stop(mpsse); - - /* deallocate data buffer */ - free(out_buf); - - /* determine return code (only the last FastWrite is checked) */ - if ((a != MPSSE_OK) || (b != MPSSE_OK) || (c != MPSSE_OK)) { - DEBUG_MSG("ERROR: SPI BURST WRITE FAILURE\n"); - return LGW_SPI_ERROR; - } else { - DEBUG_MSG("Note: SPI burst write success\n"); - return LGW_SPI_SUCCESS; - } -} - -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ - -/* Burst (multiple-byte) read (using FastWrite & FastRead functions) */ -/* transaction time: 7-12ms for 2500 data bytes @6MHz, 1kB chunks */ -/* transaction time: 2ms for 16 data bytes @6MHz, 1kB chunks */ -int lgw_spi_rb(void *spi_target, uint8_t address, uint8_t *data, uint16_t size) { - struct mpsse_context *mpsse = spi_target; - uint8_t command; - int size_to_do, chunk_size, offset; - int a, b, c, d; - int i; - - /* check input parameters */ - CHECK_NULL(spi_target); - if ((address & 0x80) != 0) { - DEBUG_MSG("WARNING: SPI address > 127\n"); - } - CHECK_NULL(data); - if (size == 0) { - DEBUG_MSG("ERROR: BURST OF NULL LENGTH\n"); - return LGW_SPI_ERROR; - } - - /* prepare command byte */ - command = READ_ACCESS | (address & 0x7F); - size_to_do = size; - - /* start MPSSE transaction */ - a = Start(mpsse); - b = FastWrite(mpsse, (char *)&command, 1); - for (i=0; size_to_do > 0; ++i) { - chunk_size = (size_to_do < LGW_BURST_CHUNK) ? size_to_do : LGW_BURST_CHUNK; - offset = i * LGW_BURST_CHUNK; - c = FastRead(mpsse, (char *)(data + offset), chunk_size); - size_to_do -= chunk_size; /* subtract the quantity of data already transferred */ - } - d = Stop(mpsse); - - /* determine return code (only the last FastRead is checked) */ - if ((a != MPSSE_OK) || (b != MPSSE_OK) || (c != MPSSE_OK) || (d != MPSSE_OK)) { - DEBUG_MSG("ERROR: SPI BURST READ FAILURE\n"); - return LGW_SPI_ERROR; - } else { - DEBUG_MSG("Note: SPI burst read success\n"); - return LGW_SPI_SUCCESS; - } -} - -/* --- EOF ------------------------------------------------------------------ */ diff --git a/loragw_hal/src/loragw_spi.native.c b/loragw_hal/src/loragw_spi.native.c deleted file mode 100644 index f5f0701..0000000 --- a/loragw_hal/src/loragw_spi.native.c +++ /dev/null @@ -1,346 +0,0 @@ -/* - / _____) _ | | -( (____ _____ ____ _| |_ _____ ____| |__ - \____ \| ___ | (_ _) ___ |/ ___) _ \ - _____) ) ____| | | || |_| ____( (___| | | | -(______/|_____)_|_|_| \__)_____)\____)_| |_| - ©2013 Semtech-Cycleo - -Description: - Host specific functions to address the LoRa™ gateway registers through a - SPI interface. - Single-byte read/write and burst read/write. - Does not handle pagination. - Could be used with multiple SPI ports in parallel (explicit file descriptor) -*/ - - -/* -------------------------------------------------------------------------- */ -/* --- DEPENDANCIES --------------------------------------------------------- */ - -#include /* C99 types */ -#include /* printf fprintf */ -#include /* malloc free */ -#include /* lseek, close */ -#include /* open */ -#include /* memset */ - -#include -#include - -#include "loragw_spi.h" - -/* -------------------------------------------------------------------------- */ -/* --- PRIVATE MACROS ------------------------------------------------------- */ - -#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) -#if DEBUG_SPI == 1 - #define DEBUG_MSG(str) fprintf(stderr, str) - #define DEBUG_PRINTF(fmt, args...) fprintf(stderr,"%s:%d: "fmt, __FUNCTION__, __LINE__, args) - #define CHECK_NULL(a) if(a==NULL){fprintf(stderr,"%s:%d: ERROR: NULL POINTER AS ARGUMENT\n", __FUNCTION__, __LINE__);return LGW_SPI_ERROR;} -#else - #define DEBUG_MSG(str) - #define DEBUG_PRINTF(fmt, args...) - #define CHECK_NULL(a) if(a==NULL){return LGW_SPI_ERROR;} -#endif - -/* -------------------------------------------------------------------------- */ -/* --- PRIVATE CONSTANTS ---------------------------------------------------- */ - -#define READ_ACCESS 0x00 -#define WRITE_ACCESS 0x80 -#define SPI_SPEED 8000000 -#define SPI_DEV_PATH "/dev/spidev0.0" - -/* -------------------------------------------------------------------------- */ -/* --- PUBLIC FUNCTIONS DEFINITION ------------------------------------------ */ - -/* SPI initialization and configuration */ -int lgw_spi_open(void **spi_target_ptr) { - int *spi_device = NULL; - int dev; - int a,b,c; - int i; - - /* check input variables */ - CHECK_NULL(spi_target_ptr); /* cannot be null, must point on a void pointer (*spi_target_ptr can be null) */ - - /* allocate memory for the device descriptor */ - spi_device = malloc(sizeof(int)); - if (spi_device == NULL) { - DEBUG_MSG("ERROR: MALLOC FAIL\n"); - return LGW_SPI_ERROR; - } - - /* open SPI device */ - dev = open(SPI_DEV_PATH, O_RDWR); - if (dev < 0) { - DEBUG_MSG("SPI port fail to open\n"); - return LGW_SPI_ERROR; - } - - /* setting SPI mode to 'mode 0' */ - i = SPI_MODE_0; - a = ioctl(dev, SPI_IOC_WR_MODE, &i); - b = ioctl(dev, SPI_IOC_RD_MODE, &i); - if ((a < 0) || (b < 0)) { - DEBUG_MSG("ERROR: SPI PORT FAIL TO SET IN MODE 0\n"); - close(dev); - free(spi_device); - return LGW_SPI_ERROR; - } - - /* setting SPI max clk (in Hz) */ - i = SPI_SPEED; - a = ioctl(dev, SPI_IOC_WR_MAX_SPEED_HZ, &i); - b = ioctl(dev, SPI_IOC_RD_MAX_SPEED_HZ, &i); - if ((a < 0) || (b < 0)) { - DEBUG_MSG("ERROR: SPI PORT FAIL TO SET MAX SPEED\n"); - close(dev); - free(spi_device); - return LGW_SPI_ERROR; - } - - /* setting SPI to MSB first */ - i = 0; - a = ioctl(dev, SPI_IOC_WR_LSB_FIRST, &i); - b = ioctl(dev, SPI_IOC_RD_LSB_FIRST, &i); - if ((a < 0) || (b < 0)) { - DEBUG_MSG("ERROR: SPI PORT FAIL TO SET MSB FIRST\n"); - close(dev); - free(spi_device); - return LGW_SPI_ERROR; - } - - /* setting SPI to 8 bits per word */ - i = 0; - a = ioctl(dev, SPI_IOC_WR_BITS_PER_WORD, &i); - b = ioctl(dev, SPI_IOC_RD_BITS_PER_WORD, &i); - if ((a < 0) || (b < 0)) { - DEBUG_MSG("ERROR: SPI PORT FAIL TO SET 8 BITS-PER-WORD\n"); - close(dev); - return LGW_SPI_ERROR; - } - - *spi_device = dev; - *spi_target_ptr = (void *)spi_device; - DEBUG_MSG("Note: SPI port opened and configured ok\n"); - return LGW_SPI_SUCCESS; -} - -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ - -/* SPI release */ -int lgw_spi_close(void *spi_target) { - int spi_device; - int a; - - /* check input variables */ - CHECK_NULL(spi_target); - - /* close file & deallocate file descriptor */ - spi_device = *(int *)spi_target; /* must check that spi_target is not null beforehand */ - a = close(spi_device); - free(spi_target); - - /* determine return code */ - if (a < 0) { - DEBUG_MSG("ERROR: SPI PORT FAILED TO CLOSE\n"); - return LGW_SPI_ERROR; - } else { - DEBUG_MSG("Note: SPI port closed\n"); - return LGW_SPI_SUCCESS; - } -} - -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ - -/* Simple write */ -int lgw_spi_w(void *spi_target, uint8_t address, uint8_t data) { - int spi_device; - uint8_t out_buf[2]; - struct spi_ioc_transfer k; - int a; - - /* check input variables */ - CHECK_NULL(spi_target); - if ((address & 0x80) != 0) { - DEBUG_MSG("WARNING: SPI address > 127\n"); - } - - spi_device = *(int *)spi_target; /* must check that spi_target is not null beforehand */ - - /* prepare frame to be sent */ - out_buf[0] = WRITE_ACCESS | (address & 0x7F); - out_buf[1] = data; - - /* I/O transaction */ - memset(&k, 0, sizeof(k)); /* clear k */ - k.tx_buf = (unsigned long) out_buf; - k.len = ARRAY_SIZE(out_buf); - k.speed_hz = SPI_SPEED; - k.cs_change = 1; - k.bits_per_word = 8; - a = ioctl(spi_device, SPI_IOC_MESSAGE(1), &k); - - /* determine return code */ - if (a != 2) { - DEBUG_MSG("ERROR: SPI WRITE FAILURE\n"); - return LGW_SPI_ERROR; - } else { - DEBUG_MSG("Note: SPI write success\n"); - return LGW_SPI_SUCCESS; - } -} - -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ - -/* Simple read */ -int lgw_spi_r(void *spi_target, uint8_t address, uint8_t *data) { - int spi_device; - uint8_t out_buf[2]; - uint8_t in_buf[ARRAY_SIZE(out_buf)]; - struct spi_ioc_transfer k; - int a; - - /* check input variables */ - CHECK_NULL(spi_target); - if ((address & 0x80) != 0) { - DEBUG_MSG("WARNING: SPI address > 127\n"); - } - CHECK_NULL(data); - - spi_device = *(int *)spi_target; /* must check that spi_target is not null beforehand */ - - /* prepare frame to be sent */ - out_buf[0] = READ_ACCESS | (address & 0x7F); - out_buf[1] = 0x00; - - /* I/O transaction */ - memset(&k, 0, sizeof(k)); /* clear k */ - k.tx_buf = (unsigned long) out_buf; - k.rx_buf = (unsigned long) in_buf; - k.len = ARRAY_SIZE(out_buf); - k.cs_change = 1; - a = ioctl(spi_device, SPI_IOC_MESSAGE(1), &k); - - /* determine return code */ - if (a != 2) { - DEBUG_MSG("ERROR: SPI READ FAILURE\n"); - return LGW_SPI_ERROR; - } else { - DEBUG_MSG("Note: SPI read success\n"); - *data = in_buf[1]; - return LGW_SPI_SUCCESS; - } -} - -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ - -/* Burst (multiple-byte) write */ -int lgw_spi_wb(void *spi_target, uint8_t address, uint8_t *data, uint16_t size) { - int spi_device; - uint8_t command; - struct spi_ioc_transfer k[2]; - int size_to_do, chunk_size, offset; - int byte_transfered = 0; - int i; - - /* check input parameters */ - CHECK_NULL(spi_target); - if ((address & 0x80) != 0) { - DEBUG_MSG("WARNING: SPI address > 127\n"); - } - CHECK_NULL(data); - if (size == 0) { - DEBUG_MSG("ERROR: BURST OF NULL LENGTH\n"); - return LGW_SPI_ERROR; - } - - spi_device = *(int *)spi_target; /* must check that spi_target is not null beforehand */ - - /* prepare command byte */ - command = WRITE_ACCESS | (address & 0x7F); - size_to_do = size; - - /* I/O transaction */ - memset(&k, 0, sizeof(k)); /* clear k */ - k[0].tx_buf = (unsigned long) &command; - k[0].len = 1; - k[0].cs_change = 0; - k[1].cs_change = 1; - for (i=0; size_to_do > 0; ++i) { - chunk_size = (size_to_do < LGW_BURST_CHUNK) ? size_to_do : LGW_BURST_CHUNK; - offset = i * LGW_BURST_CHUNK; - k[1].tx_buf = (unsigned long)(data + offset); - k[1].len = chunk_size; - byte_transfered += (ioctl(spi_device, SPI_IOC_MESSAGE(2), &k) - 1 ); - DEBUG_PRINTF("BURST WRITE: to trans %d # chunk %d # transferred %d \n", size_to_do, chunk_size, byte_transfered); - size_to_do -= chunk_size; /* subtract the quantity of data already transferred */ - } - - /* determine return code */ - if (byte_transfered != size) { - DEBUG_MSG("ERROR: SPI BURST WRITE FAILURE\n"); - return LGW_SPI_ERROR; - } else { - DEBUG_MSG("Note: SPI burst write success\n"); - return LGW_SPI_SUCCESS; - } -} - -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ - -/* Burst (multiple-byte) read */ -int lgw_spi_rb(void *spi_target, uint8_t address, uint8_t *data, uint16_t size) { - int spi_device; - uint8_t command; - struct spi_ioc_transfer k[2]; - int size_to_do, chunk_size, offset; - int byte_transfered = 0; - int i; - - /* check input parameters */ - CHECK_NULL(spi_target); - if ((address & 0x80) != 0) { - DEBUG_MSG("WARNING: SPI address > 127\n"); - } - CHECK_NULL(data); - if (size == 0) { - DEBUG_MSG("ERROR: BURST OF NULL LENGTH\n"); - return LGW_SPI_ERROR; - } - - spi_device = *(int *)spi_target; /* must check that spi_target is not null beforehand */ - - /* prepare command byte */ - command = READ_ACCESS | (address & 0x7F); - size_to_do = size; - - /* I/O transaction */ - memset(&k, 0, sizeof(k)); /* clear k */ - k[0].tx_buf = (unsigned long) &command; - k[0].len = 1; - k[0].cs_change = 0; - k[1].cs_change = 1; - for (i=0; size_to_do > 0; ++i) { - chunk_size = (size_to_do < LGW_BURST_CHUNK) ? size_to_do : LGW_BURST_CHUNK; - offset = i * LGW_BURST_CHUNK; - k[1].rx_buf = (unsigned long)(data + offset); - k[1].len = chunk_size; - byte_transfered += (ioctl(spi_device, SPI_IOC_MESSAGE(2), &k) - 1 ); - DEBUG_PRINTF("BURST READ: to trans %d # chunk %d # transferred %d \n", size_to_do, chunk_size, byte_transfered); - size_to_do -= chunk_size; /* subtract the quantity of data already transferred */ - } - - /* determine return code */ - if (byte_transfered != size) { - DEBUG_MSG("ERROR: SPI BURST READ FAILURE\n"); - return LGW_SPI_ERROR; - } else { - DEBUG_MSG("Note: SPI burst read success\n"); - return LGW_SPI_SUCCESS; - } -} - -/* --- EOF ------------------------------------------------------------------ */ diff --git a/loragw_hal/test/test_loragw_hal.c b/loragw_hal/test/test_loragw_hal.c deleted file mode 100644 index f23f55c..0000000 --- a/loragw_hal/test/test_loragw_hal.c +++ /dev/null @@ -1,266 +0,0 @@ -/* - / _____) _ | | -( (____ _____ ____ _| |_ _____ ____| |__ - \____ \| ___ | (_ _) ___ |/ ___) _ \ - _____) ) ____| | | || |_| ____( (___| | | | -(______/|_____)_|_|_| \__)_____)\____)_| |_| - ©2013 Semtech-Cycleo - -Description: - Minimum test program for the loragw_hal 'library' -*/ - - -/* -------------------------------------------------------------------------- */ -/* --- DEPENDANCIES --------------------------------------------------------- */ - -/* fix an issue between POSIX and C99 */ -#if __STDC_VERSION__ >= 199901L - #define _XOPEN_SOURCE 600 -#else - #define _XOPEN_SOURCE 500 -#endif - -#include /* C99 types */ -#include /* malloc & free */ -#include /* bool type */ -#include /* printf */ -#include /* memset */ -#include /* sigaction */ - -#include "loragw_hal.h" -#include "loragw_aux.h" - -/* -------------------------------------------------------------------------- */ -/* --- PRIVATE MACROS ------------------------------------------------------- */ - -#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) - -/* -------------------------------------------------------------------------- */ -/* --- PRIVATE VARIABLES ---------------------------------------------------- */ - -static int exit_sig = 0; /* 1 -> application terminates cleanly (shut down hardware, close open files, etc) */ -static int quit_sig = 0; /* 1 -> application terminates without shutting down the hardware */ - -/* -------------------------------------------------------------------------- */ -/* --- PRIVATE FUNCTIONS DECLARATION ---------------------------------------- */ - -static void sig_handler(int sigio); - -/* -------------------------------------------------------------------------- */ -/* --- PRIVATE FUNCTIONS DEFINITION ----------------------------------------- */ - -static void sig_handler(int sigio) { - if (sigio == SIGQUIT) { - quit_sig = 1;; - } else if ((sigio == SIGINT) || (sigio == SIGTERM)) { - exit_sig = 1; - } -} - -/* -------------------------------------------------------------------------- */ -/* --- MAIN FUNCTION -------------------------------------------------------- */ - -int main(int argc, char **argv) -{ - struct sigaction sigact; /* SIGQUIT&SIGINT&SIGTERM signal handling */ - - struct lgw_conf_rxrf_s rfconf; - struct lgw_conf_rxif_s ifconf; - - 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; - int nb_pkt; - uint8_t x; - - uint32_t tx_cnt = 0; - unsigned long loop_cnt = 0; - int tx_path = 0; - struct lgw_pkt_tx_s txs; - uint8_t status_var = 0; - - /* configure signal handling */ - sigemptyset(&sigact.sa_mask); - sigact.sa_flags = 0; - sigact.sa_handler = sig_handler; - sigaction(SIGQUIT, &sigact, NULL); - sigaction(SIGINT, &sigact, NULL); - sigaction(SIGTERM, &sigact, NULL); - - /* beginning of Lora gateway-specific code */ - printf("Beginning of test for loragw_hal.c\n"); - - /* set configuration for RF chains */ - memset(&rfconf, 0, sizeof(rfconf)); - - rfconf.enable = true; - rfconf.freq_hz = 866187500; - lgw_rxrf_setconf(0, rfconf); /* radio A */ - - rfconf.enable = true; - rfconf.freq_hz = 866437500; - lgw_rxrf_setconf(1, rfconf); /* radio B */ - - /* set configuration for Lora multi-SF channels (bandwidth cannot be set) */ - memset(&ifconf, 0, sizeof(ifconf)); - - ifconf.enable = true; - ifconf.rf_chain = 0; - ifconf.freq_hz = -187500; - ifconf.bandwidth = BW_125KHZ; - ifconf.datarate = DR_LORA_MULTI; - lgw_rxif_setconf(0, ifconf); /* chain 0: 1st radio, bleeper channel 1, all SF */ - - ifconf.enable = true; - ifconf.rf_chain = 0; - ifconf.freq_hz = -62500; - 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.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 = -187500; - ifconf.bandwidth = BW_125KHZ; - ifconf.datarate = DR_LORA_MULTI; - lgw_rxif_setconf(3, ifconf); /* chain 3: 2nd radio, bleeper channel 3, all SF */ - - /* set configuration for Lora 'stand alone' channel */ - ifconf.enable = true; - ifconf.rf_chain = 0; - ifconf.freq_hz = 187500; - ifconf.bandwidth = BW_125KHZ; - ifconf.datarate = DR_LORA_SF10; - lgw_rxif_setconf(8, ifconf); /* chain 8: bleeper channel 4, SF10 only */ - - - /* 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.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; - txs.size = 20; - txs.rf_chain = 1; - - /* connect, configure and start the Lora gateway */ - lgw_start(); - - while ((quit_sig != 1) && (exit_sig != 1)) { - loop_cnt++; - - /* fetch N packets */ - nb_pkt = lgw_receive(ARRAY_SIZE(rxpkt), rxpkt); - - 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); - if (p->status == STAT_CRC_OK) { - printf(" if_chain:%2d", p->if_chain); - printf(" tstamp:%010u", p->count_us); - printf(" size:%3u", p->size); - 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) { - case DR_LORA_SF7: printf(" SF7"); break; - case DR_LORA_SF8: printf(" SF8"); break; - case DR_LORA_SF9: printf(" SF9"); break; - case DR_LORA_SF10: printf(" SF10"); break; - case DR_LORA_SF11: printf(" SF11"); break; - case DR_LORA_SF12: printf(" SF12"); break; - default: printf(" datarate?"); - } - switch (p->coderate) { - case CR_LORA_4_5: printf(" CR1(4/5)"); break; - case CR_LORA_4_6: printf(" CR2(2/3)"); break; - case CR_LORA_4_7: printf(" CR3(4/7)"); break; - case CR_LORA_4_8: printf(" CR4(1/2)"); break; - default: printf(" coderate?"); - } - 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]); - } - printf(" #\n"); - } else if (p->status == STAT_CRC_BAD) { - printf(" if_chain:%2d", p->if_chain); - printf(" tstamp:%010u", p->count_us); - printf(" size:%3u\n", p->size); - printf(" CRC error, damaged packet\n\n"); - } else if (p->status == STAT_NO_CRC){ - printf(" if_chain:%2d", p->if_chain); - printf(" tstamp:%010u", p->count_us); - printf(" size:%3u\n", p->size); - printf(" no CRC\n\n"); - } else { - printf(" if_chain:%2d", p->if_chain); - printf(" tstamp:%010u", p->count_us); - printf(" size:%3u\n", p->size); - 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; - 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); - do { - ++j; - wait_ms(100); - lgw_status(TX_STATUS, &status_var); /* get TX status */ - printf("%d:", status_var); - } while ((status_var != TX_FREE) && (j < 100)); - ++tx_cnt; - printf("\nTX finished\n"); - } - } - - if (exit_sig == 1) { - /* clean up before leaving */ - lgw_stop(); - } - - printf("\nEnd of test for loragw_hal.c\n"); - return 0; -} - -/* --- EOF ------------------------------------------------------------------ */ diff --git a/loragw_hal/test/test_loragw_reg.c b/loragw_hal/test/test_loragw_reg.c deleted file mode 100644 index 2b80109..0000000 --- a/loragw_hal/test/test_loragw_reg.c +++ /dev/null @@ -1,131 +0,0 @@ -/* - / _____) _ | | -( (____ _____ ____ _| |_ _____ ____| |__ - \____ \| ___ | (_ _) ___ |/ ___) _ \ - _____) ) ____| | | || |_| ____( (___| | | | -(______/|_____)_|_|_| \__)_____)\____)_| |_| - ©2013 Semtech-Cycleo - -Description: - Minimum test program for the loragw_spi 'library' -*/ - - -/* -------------------------------------------------------------------------- */ -/* --- DEPENDANCIES --------------------------------------------------------- */ - -#include -#include - -#include "loragw_reg.h" - -/* -------------------------------------------------------------------------- */ -/* --- MAIN FUNCTION -------------------------------------------------------- */ - -#define BURST_TEST_LENGTH 8192 - -int main(int argc, char **argv) -{ - int32_t read_value, test_value; - uint16_t lfsr; - uint8_t burst_buffout[BURST_TEST_LENGTH]; - uint8_t burst_buffin[BURST_TEST_LENGTH]; - int i; - - printf("Beginning of test for loragw_reg.c\n"); - - lgw_connect(); - /* 2 SPI transactions: - -> 0x80 0x00 <- 0x00 0x00 forcing page 0 - -> 0x01 0x00 <- 0x00 0x64 checking version - */ - - /* --- READ TEST --- */ - - lgw_reg_w(LGW_SOFT_RESET, 1); - lgw_reg_check(stdout); - - /* --- READ/WRITE COHERENCY TEST --- */ - - /* 8b unsigned */ - test_value = 197; /* 11000101b */ - lgw_reg_w(LGW_IMPLICIT_PAYLOAD_LENGHT, test_value); - lgw_reg_r(LGW_IMPLICIT_PAYLOAD_LENGHT, &read_value); - printf("IMPLICIT_PAYLOAD_LENGHT = %d (should be %d)\n", read_value, test_value); - - /* 8b signed */ - /* NO SUCH REG AVAILABLE */ - // /* RADIO_SELECT is normally unsigned, modify it manually in loragw_reg.c */ - // test_value = -59; /* 11000101b */ - // lgw_reg_w(LGW_RADIO_SELECT, test_value); - // lgw_reg_r(LGW_RADIO_SELECT, &read_value); - // printf("RADIO_SELECT = %d (should be %d)\n", read_value, test_value); - - /* less than 8b, with offset, unsigned */ - test_value = 11; /* 1011b */ - lgw_reg_w(LGW_FRAME_SYNCH_PEAK2_POS, test_value); - lgw_reg_r(LGW_FRAME_SYNCH_PEAK2_POS, &read_value); - printf("FRAME_SYNCH_PEAK2_POS = %d (should be %d)\n", read_value, test_value); - - /* less than 8b, with offset, signed */ - /* NO SUCH REG AVAILABLE */ - // /* MBWSSF_FRAME_SYNCH_PEAK2_POS is normally unsigned, modify it manually in loragw_reg.c */ - // test_value = -5; /* 1011b */ - // lgw_reg_w(LGW_MBWSSF_FRAME_SYNCH_PEAK2_POS, test_value); - // lgw_reg_r(LGW_MBWSSF_FRAME_SYNCH_PEAK2_POS, &read_value); - // printf("MBWSSF_FRAME_SYNCH_PEAK2_POS = %d (should be %d)\n", read_value, test_value); - - /* 16b unsigned */ - test_value = 49253; /* 11000000 01100101b */ - lgw_reg_w(LGW_PREAMBLE_SYMB1_NB, test_value); - lgw_reg_r(LGW_PREAMBLE_SYMB1_NB, &read_value); - printf("PREAMBLE_SYMB1_NB = %d (should be %d)\n", read_value, test_value); - - /* 16b signed */ - /* NO SUCH REG AVAILABLE */ - // /* CAPTURE_PERIOD is normally unsigned, modify it manually in loragw_reg.c */ - // test_value = -16283; /* 11000000 01100101b */ - // lgw_reg_w(LGW_CAPTURE_PERIOD, test_value); - // lgw_reg_r(LGW_CAPTURE_PERIOD, &read_value); - // printf("CAPTURE_PERIOD = %d (should be %d)\n", read_value, test_value); - - /* between 8b and 16b, unsigned */ - test_value = 3173; /* 1100 01100101b */ - lgw_reg_w(LGW_ADJUST_MODEM_START_OFFSET_SF12_RDX4, test_value); - lgw_reg_r(LGW_ADJUST_MODEM_START_OFFSET_SF12_RDX4, &read_value); - printf("ADJUST_MODEM_START_OFFSET_SF12_RDX4 = %d (should be %d)\n", read_value, test_value); - - /* between 8b and 16b, signed */ - test_value = -1947; /* 11000 01100101b */ - lgw_reg_w(LGW_IF_FREQ_1, test_value); - lgw_reg_r(LGW_IF_FREQ_1, &read_value); - printf("IF_FREQ_1 = %d (should be %d)\n", read_value, test_value); - - /* --- BURST WRITE AND READ TEST --- */ - - /* initialize data for SPI test */ - lfsr = 0xFFFF; - for(i=0; i> 4)); - /* printf("%05d # 0x%04x 0x%02x\n", i, lfsr, burst_buffout[i]); */ - lfsr = (lfsr & 1) ? ((lfsr >> 1) ^ 0x8679) : (lfsr >> 1); - } - - lgw_reg_wb(LGW_TX_DATA_BUF_DATA, burst_buffout, 256); - lgw_reg_rb(LGW_RX_DATA_BUF_DATA, burst_buffin, 256); - - /* impossible to check in software, - RX_DATA_BUF_DATA is read-only, - TX_DATA_BUF_DATA is write only, - use a logic analyser */ - - /* --- END OF TEST --- */ - - lgw_disconnect(); - /* no SPI transaction */ - - printf("End of test for loragw_reg.c\n"); - return 0; -} - -/* --- EOF ------------------------------------------------------------------ */ diff --git a/loragw_hal/test/test_loragw_spi.c b/loragw_hal/test/test_loragw_spi.c deleted file mode 100644 index 0eae55d..0000000 --- a/loragw_hal/test/test_loragw_spi.c +++ /dev/null @@ -1,81 +0,0 @@ -/* - / _____) _ | | -( (____ _____ ____ _| |_ _____ ____| |__ - \____ \| ___ | (_ _) ___ |/ ___) _ \ - _____) ) ____| | | || |_| ____( (___| | | | -(______/|_____)_|_|_| \__)_____)\____)_| |_| - ©2013 Semtech-Cycleo - -Description: - Minimum test program for the loragw_spi 'library' - Use logic analyser to check the results. -*/ - - -/* -------------------------------------------------------------------------- */ -/* --- DEPENDANCIES --------------------------------------------------------- */ - -#include -#include - -#include "loragw_spi.h" - -/* -------------------------------------------------------------------------- */ -/* --- PRIVATE MACROS ------------------------------------------------------- */ - -#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) - -/* -------------------------------------------------------------------------- */ -/* --- PRIVATE CONSTANTS ---------------------------------------------------- */ - -#define BURST_TEST_SIZE 2500 /* >> LGW_BURST_CHUNK */ -#define TIMING_REPEAT 1 /* repeat transactions multiple times for timing characterisation */ - -/* -------------------------------------------------------------------------- */ -/* --- MAIN FUNCTION -------------------------------------------------------- */ - -int main(int argc, char **argv) -{ - int i; - void *spi_target = NULL; - uint8_t data = 0; - uint8_t dataout[BURST_TEST_SIZE]; - uint8_t datain[BURST_TEST_SIZE]; - - for (i = 0; i < BURST_TEST_SIZE; ++i) { - dataout[i] = 0x30 + (i % 10); /* ASCCI code for 0 -> 9 */ - datain[i] = 0x23; /* garbage data, to be overwritten by received data */ - } - - printf("Beginning of test for loragw_spi.c\n"); - lgw_spi_open(&spi_target); - - /* normal R/W test */ - for (i = 0; i < TIMING_REPEAT; ++i) - lgw_spi_w(spi_target, 0xAA, 0x96); - for (i = 0; i < TIMING_REPEAT; ++i) - lgw_spi_r(spi_target, 0x55, &data); - - /* burst R/W test, small bursts << LGW_BURST_CHUNK */ - for (i = 0; i < TIMING_REPEAT; ++i) - lgw_spi_wb(spi_target, 0x55, dataout, 16); - for (i = 0; i < TIMING_REPEAT; ++i) - lgw_spi_rb(spi_target, 0x55, datain, 16); - - /* burst R/W test, large bursts >> LGW_BURST_CHUNK */ - for (i = 0; i < TIMING_REPEAT; ++i) - lgw_spi_wb(spi_target, 0x5A, dataout, ARRAY_SIZE(dataout)); - for (i = 0; i < TIMING_REPEAT; ++i) - lgw_spi_rb(spi_target, 0x5A, datain, ARRAY_SIZE(datain)); - - /* last read (blocking), just to be sure no to quit before the FTDI buffer is flushed */ - lgw_spi_r(spi_target, 0x55, &data); - printf("data received (simple read): %d\n",data); - - lgw_spi_close(spi_target); - printf("End of test for loragw_spi.c\n"); - - return 0; -} - -/* --- EOF ------------------------------------------------------------------ */ -- cgit v1.2.3