v1.0.0
* Initial release for SX1302 CoreCell Reference Design.
This commit is contained in:
parent
c7a5171a47
commit
4c61c5d48e
|
@ -0,0 +1,44 @@
|
|||
### Environment constants
|
||||
|
||||
ARCH ?=
|
||||
CROSS_COMPILE ?=
|
||||
export
|
||||
|
||||
### general build targets
|
||||
|
||||
.PHONY: all clean install install_conf libtools libloragw packet_forwarder util_net_downlink util_chip_id
|
||||
|
||||
all: libtools libloragw packet_forwarder util_net_downlink util_chip_id
|
||||
|
||||
libtools:
|
||||
$(MAKE) all -e -C $@
|
||||
|
||||
libloragw: libtools
|
||||
$(MAKE) all -e -C $@
|
||||
|
||||
packet_forwarder: libloragw
|
||||
$(MAKE) all -e -C $@
|
||||
|
||||
util_net_downlink: libtools
|
||||
$(MAKE) all -e -C $@
|
||||
|
||||
util_chip_id: libloragw
|
||||
$(MAKE) all -e -C $@
|
||||
|
||||
clean:
|
||||
$(MAKE) clean -e -C libtools
|
||||
$(MAKE) clean -e -C libloragw
|
||||
$(MAKE) clean -e -C packet_forwarder
|
||||
$(MAKE) clean -e -C util_net_downlink
|
||||
$(MAKE) clean -e -C util_chip_id
|
||||
|
||||
install:
|
||||
$(MAKE) install -e -C libloragw
|
||||
$(MAKE) install -e -C packet_forwarder
|
||||
$(MAKE) install -e -C util_net_downlink
|
||||
$(MAKE) install -e -C util_chip_id
|
||||
|
||||
install_conf:
|
||||
$(MAKE) install_conf -e -C packet_forwarder
|
||||
|
||||
### EOF
|
|
@ -0,0 +1,126 @@
|
|||
### get external defined data
|
||||
|
||||
LIBLORAGW_VERSION := `cat ../VERSION`
|
||||
include library.cfg
|
||||
include ../target.cfg
|
||||
|
||||
### constant symbols
|
||||
|
||||
ARCH ?=
|
||||
CROSS_COMPILE ?=
|
||||
CC := $(CROSS_COMPILE)gcc
|
||||
AR := $(CROSS_COMPILE)ar
|
||||
|
||||
CFLAGS := -O2 -Wall -Wextra -std=c99 -Iinc -I. -I../libtools/inc
|
||||
|
||||
OBJDIR = obj
|
||||
INCLUDES = $(wildcard inc/*.h) $(wildcard ../libtools/inc/*.h)
|
||||
|
||||
### linking options
|
||||
|
||||
LIBS := -lloragw -ltinymt32 -lrt -lm
|
||||
|
||||
### general build targets
|
||||
|
||||
all: libloragw.a test_loragw_spi test_loragw_i2c test_loragw_reg test_loragw_hal_tx test_loragw_hal_rx test_loragw_cal test_loragw_capture_ram test_loragw_spi_sx1250 test_loragw_counter test_loragw_gps
|
||||
|
||||
clean:
|
||||
rm -f libloragw.a
|
||||
rm -f test_loragw_*
|
||||
rm -f $(OBJDIR)/*.o
|
||||
rm -f inc/config.h
|
||||
|
||||
install:
|
||||
ifneq ($(strip $(TARGET_IP)),)
|
||||
ifneq ($(strip $(TARGET_DIR)),)
|
||||
ifneq ($(strip $(TARGET_USR)),)
|
||||
@echo "---- Copying libloragw files to $(TARGET_IP):$(TARGET_DIR)"
|
||||
@ssh $(TARGET_USR)@$(TARGET_IP) "mkdir -p $(TARGET_DIR)"
|
||||
@scp test_loragw_* $(TARGET_USR)@$(TARGET_IP):$(TARGET_DIR)
|
||||
@scp ../tools/reset_lgw.sh $(TARGET_USR)@$(TARGET_IP):$(TARGET_DIR)
|
||||
else
|
||||
@echo "ERROR: TARGET_USR is not configured in target.cfg"
|
||||
endif
|
||||
else
|
||||
@echo "ERROR: TARGET_DIR is not configured in target.cfg"
|
||||
endif
|
||||
else
|
||||
@echo "ERROR: TARGET_IP is not configured in target.cfg"
|
||||
endif
|
||||
|
||||
### transpose library.cfg into a C header file : config.h
|
||||
|
||||
inc/config.h: ../VERSION library.cfg
|
||||
@echo "*** Checking libloragw library configuration ***"
|
||||
@rm -f $@
|
||||
#File initialization
|
||||
@echo "#ifndef _LORAGW_CONFIGURATION_H" >> $@
|
||||
@echo "#define _LORAGW_CONFIGURATION_H" >> $@
|
||||
# Release version
|
||||
@echo "Release version : $(LIBLORAGW_VERSION)"
|
||||
@echo " #define LIBLORAGW_VERSION "\"$(LIBLORAGW_VERSION)\""" >> $@
|
||||
# Debug options
|
||||
@echo " #define DEBUG_AUX $(DEBUG_AUX)" >> $@
|
||||
@echo " #define DEBUG_SPI $(DEBUG_SPI)" >> $@
|
||||
@echo " #define DEBUG_I2C $(DEBUG_SPI)" >> $@
|
||||
@echo " #define DEBUG_REG $(DEBUG_REG)" >> $@
|
||||
@echo " #define DEBUG_HAL $(DEBUG_HAL)" >> $@
|
||||
@echo " #define DEBUG_GPS $(DEBUG_GPS)" >> $@
|
||||
@echo " #define DEBUG_GPIO $(DEBUG_GPIO)" >> $@
|
||||
@echo " #define DEBUG_LBT $(DEBUG_LBT)" >> $@
|
||||
@echo " #define DEBUG_RAD $(DEBUG_RAD)" >> $@
|
||||
@echo " #define DEBUG_CAL $(DEBUG_CAL)" >> $@
|
||||
@echo " #define DEBUG_SX1302 $(DEBUG_SX1302)" >> $@
|
||||
# Configuration options
|
||||
@echo " #define BYPASS_FW_INIT $(BYPASS_FW_INIT)" >> $@
|
||||
@echo " #define FPGA_BOARD_16_CH $(FPGA_BOARD_16_CH)" >> $@
|
||||
# end of file
|
||||
@echo "#endif" >> $@
|
||||
@echo "*** Configuration seems ok ***"
|
||||
|
||||
### library module target
|
||||
|
||||
$(OBJDIR):
|
||||
mkdir -p $(OBJDIR)
|
||||
|
||||
$(OBJDIR)/%.o: src/%.c $(INCLUDES) inc/config.h | $(OBJDIR)
|
||||
$(CC) -c $(CFLAGS) $< -o $@
|
||||
|
||||
### static library
|
||||
|
||||
libloragw.a: $(OBJDIR)/loragw_spi.o $(OBJDIR)/loragw_i2c.o $(OBJDIR)/loragw_aux.o $(OBJDIR)/loragw_reg.o $(OBJDIR)/loragw_sx1250.o $(OBJDIR)/loragw_sx125x.o $(OBJDIR)/loragw_sx1302.o $(OBJDIR)/loragw_cal.o $(OBJDIR)/loragw_debug.o $(OBJDIR)/loragw_hal.o $(OBJDIR)/loragw_stts751.o $(OBJDIR)/loragw_gps.o $(OBJDIR)/loragw_sx1302_timestamp.o $(OBJDIR)/loragw_sx1302_rx.o
|
||||
$(AR) rcs $@ $^
|
||||
|
||||
### test programs
|
||||
|
||||
test_loragw_spi: tst/test_loragw_spi.c libloragw.a
|
||||
$(CC) $(CFLAGS) -L. -L../libtools $< -o $@ $(LIBS)
|
||||
|
||||
test_loragw_i2c: tst/test_loragw_i2c.c libloragw.a
|
||||
$(CC) $(CFLAGS) -L. -L../libtools $< -o $@ $(LIBS)
|
||||
|
||||
test_loragw_reg: tst/test_loragw_reg.c libloragw.a
|
||||
$(CC) $(CFLAGS) -L. -L../libtools $< -o $@ $(LIBS)
|
||||
|
||||
test_loragw_hal_tx: tst/test_loragw_hal_tx.c libloragw.a
|
||||
$(CC) $(CFLAGS) -L. -L../libtools $< -o $@ $(LIBS)
|
||||
|
||||
test_loragw_hal_rx: tst/test_loragw_hal_rx.c libloragw.a
|
||||
$(CC) $(CFLAGS) -L. -L../libtools $< -o $@ $(LIBS)
|
||||
|
||||
test_loragw_capture_ram: tst/test_loragw_capture_ram.c libloragw.a
|
||||
$(CC) $(CFLAGS) -L. -L../libtools $< -o $@ $(LIBS)
|
||||
|
||||
test_loragw_cal: tst/test_loragw_cal.c libloragw.a
|
||||
$(CC) $(CFLAGS) -L. -L../libtools $< -o $@ $(LIBS)
|
||||
|
||||
test_loragw_spi_sx1250: tst/test_loragw_spi_sx1250.c libloragw.a
|
||||
$(CC) $(CFLAGS) -L. -L../libtools $< -o $@ $(LIBS)
|
||||
|
||||
test_loragw_counter: tst/test_loragw_counter.c libloragw.a
|
||||
$(CC) $(CFLAGS) -L. -L../libtools $< -o $@ $(LIBS)
|
||||
|
||||
test_loragw_gps: tst/test_loragw_gps.c libloragw.a
|
||||
$(CC) $(CFLAGS) -L. -L../libtools $< -o $@ $(LIBS)
|
||||
|
||||
### EOF
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2019 Semtech
|
||||
|
||||
Description:
|
||||
SX1302 AGC parameters definition.
|
||||
|
||||
License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _LORAGW_AGC_PARAMS_H
|
||||
#define _LORAGW_AGC_PARAMS_H
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE TYPES -------------------------------------------------------- */
|
||||
|
||||
struct agc_gain_params_s {
|
||||
uint8_t ana_min;
|
||||
uint8_t ana_max;
|
||||
uint8_t ana_thresh_l;
|
||||
uint8_t ana_thresh_h;
|
||||
uint8_t dec_attn_min;
|
||||
uint8_t dec_attn_max;
|
||||
uint8_t dec_thresh_l;
|
||||
uint8_t dec_thresh_h1;
|
||||
uint8_t dec_thresh_h2;
|
||||
uint8_t chan_attn_min;
|
||||
uint8_t chan_attn_max;
|
||||
uint8_t chan_thresh_l;
|
||||
uint8_t chan_thresh_h;
|
||||
uint8_t deviceSel; /* sx1250 only */
|
||||
uint8_t hpMax; /* sx1250 only */
|
||||
uint8_t paDutyCycle; /* sx1250 only */
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE CONSTANTS ---------------------------------------------------- */
|
||||
|
||||
const struct agc_gain_params_s agc_params_sx1250 = {
|
||||
.ana_min = 1,
|
||||
.ana_max = 13,
|
||||
.ana_thresh_l = 3,
|
||||
.ana_thresh_h = 12,
|
||||
.dec_attn_min = 4,
|
||||
.dec_attn_max = 15,
|
||||
.dec_thresh_l = 40,
|
||||
.dec_thresh_h1 = 80,
|
||||
.dec_thresh_h2 = 90,
|
||||
.chan_attn_min = 4,
|
||||
.chan_attn_max = 14,
|
||||
.chan_thresh_l = 52,
|
||||
.chan_thresh_h = 132,
|
||||
.deviceSel = 0,
|
||||
.hpMax = 7,
|
||||
.paDutyCycle = 4
|
||||
};
|
||||
|
||||
const struct agc_gain_params_s agc_params_sx125x = {
|
||||
.ana_min = 0,
|
||||
.ana_max = 9,
|
||||
.ana_thresh_l = 16,
|
||||
.ana_thresh_h = 35,
|
||||
.dec_attn_min = 7,
|
||||
.dec_attn_max = 11,
|
||||
.dec_thresh_l = 45,
|
||||
.dec_thresh_h1 = 100,
|
||||
.dec_thresh_h2 = 115,
|
||||
.chan_attn_min = 4,
|
||||
.chan_attn_max = 14,
|
||||
.chan_thresh_l = 52,
|
||||
.chan_thresh_h = 132,
|
||||
.deviceSel = 0,
|
||||
.hpMax = 0,
|
||||
.paDutyCycle = 0
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2019 Semtech
|
||||
|
||||
Description:
|
||||
LoRa concentrator HAL common auxiliary functions
|
||||
|
||||
License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _LORAGW_AUX_H
|
||||
#define _LORAGW_AUX_H
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- DEPENDANCIES --------------------------------------------------------- */
|
||||
|
||||
#include "config.h" /* library configuration options (dynamically generated) */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PUBLIC MACROS -------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
@brief Get a particular bit value from a byte
|
||||
@param b [in] Any byte from which we want a bit value
|
||||
@param p [in] Position of the bit in the byte [0..7]
|
||||
@param n [in] Number of bits we want to get
|
||||
@return The value corresponding the requested bits
|
||||
*/
|
||||
#define TAKE_N_BITS_FROM(b, p, n) (((b) >> (p)) & ((1 << (n)) - 1))
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- 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 ------------------------------------------------------------------ */
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2019 Semtech
|
||||
|
||||
Description:
|
||||
LoRa concentrator radio calibration functions
|
||||
|
||||
License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _LORAGW_CAL_H
|
||||
#define _LORAGW_CAL_H
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- DEPENDANCIES --------------------------------------------------------- */
|
||||
|
||||
#include <stdint.h> /* C99 types*/
|
||||
|
||||
#include "config.h" /* library configuration options (dynamically generated) */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PUBLIC CONSTANTS ----------------------------------------------------- */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PUBLIC MACROS -------------------------------------------------------- */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PUBLIC TYPES --------------------------------------------------------- */
|
||||
|
||||
struct lgw_sx125x_cal_rx_result_s {
|
||||
int8_t amp;
|
||||
int8_t phi;
|
||||
uint16_t rej;
|
||||
uint16_t rej_init;
|
||||
uint16_t snr;
|
||||
};
|
||||
|
||||
struct lgw_sx125x_cal_tx_result_s {
|
||||
uint8_t dac_gain;
|
||||
uint8_t mix_gain;
|
||||
int8_t offset_i;
|
||||
int8_t offset_q;
|
||||
uint16_t rej;
|
||||
uint16_t sig;
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PUBLIC FUNCTIONS PROTOTYPES ------------------------------------------ */
|
||||
|
||||
int sx1302_cal_start(uint8_t version, struct lgw_conf_rxrf_s * rf_chain_cfg, struct lgw_tx_gain_lut_s * txgain_lut);
|
||||
|
||||
#endif
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2019 Semtech
|
||||
|
||||
Description:
|
||||
LoRa concentrator HAL debug functions
|
||||
|
||||
License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _LORAGW_DBG_H
|
||||
#define _LORAGW_DBG_H
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- DEPENDANCIES --------------------------------------------------------- */
|
||||
|
||||
#include "config.h" /* library configuration options (dynamically generated) */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PUBLIC MACROS -------------------------------------------------------- */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PUBLIC FUNCTIONS PROTOTYPES ------------------------------------------ */
|
||||
|
||||
/**
|
||||
@brief
|
||||
@param
|
||||
*/
|
||||
void dbg_log_buffer_to_file(FILE * file, uint8_t * buffer, uint16_t size);
|
||||
|
||||
/**
|
||||
@brief
|
||||
@param
|
||||
*/
|
||||
void dbg_log_payload_diff_to_file(FILE * file, uint8_t * buffer1, uint8_t * buffer2, uint16_t size);
|
||||
|
||||
/**
|
||||
@brief
|
||||
@param
|
||||
*/
|
||||
void dbg_init_random(void);
|
||||
|
||||
/**
|
||||
@brief
|
||||
@param
|
||||
*/
|
||||
void dbg_generate_random_payload(uint32_t pkt_cnt, uint8_t * buffer_expected, uint8_t size);
|
||||
|
||||
/**
|
||||
@brief
|
||||
@param
|
||||
*/
|
||||
int dbg_check_payload(struct lgw_conf_debug_s * context, FILE * file, uint8_t * payload_received, uint8_t size, uint8_t ref_payload_idx, uint8_t sf);
|
||||
|
||||
/**
|
||||
@brief
|
||||
@param
|
||||
*/
|
||||
void dbg_init_gpio(void);
|
||||
|
||||
/**
|
||||
@brief
|
||||
@param
|
||||
*/
|
||||
void dbg_toggle_gpio(void);
|
||||
|
||||
#endif
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
|
@ -0,0 +1,234 @@
|
|||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2019 Semtech
|
||||
|
||||
Description:
|
||||
Library of functions to manage a GNSS module (typically GPS) for accurate
|
||||
timestamping of packets and synchronisation of gateways.
|
||||
A limited set of module brands/models are supported.
|
||||
|
||||
License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _LORAGW_GPS_H
|
||||
#define _LORAGW_GPS_H
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- DEPENDANCIES --------------------------------------------------------- */
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <stdint.h> /* C99 types */
|
||||
#include <time.h> /* time library */
|
||||
#include <termios.h> /* speed_t */
|
||||
#include <unistd.h> /* ssize_t */
|
||||
|
||||
#include "config.h" /* library configuration options (dynamically generated) */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PUBLIC TYPES --------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
@struct coord_s
|
||||
@brief Time solution required for timestamp to absolute time conversion
|
||||
*/
|
||||
struct tref {
|
||||
time_t systime; /*!> system time when solution was calculated */
|
||||
uint32_t count_us; /*!> reference concentrator internal timestamp */
|
||||
struct timespec utc; /*!> reference UTC time (from GPS/NMEA) */
|
||||
struct timespec gps; /*!> reference GPS time (since 01.Jan.1980) */
|
||||
double xtal_err; /*!> raw clock error (eg. <1 'slow' XTAL) */
|
||||
};
|
||||
|
||||
/**
|
||||
@struct coord_s
|
||||
@brief Geodesic coordinates
|
||||
*/
|
||||
struct coord_s {
|
||||
double lat; /*!> latitude [-90,90] (North +, South -) */
|
||||
double lon; /*!> longitude [-180,180] (East +, West -)*/
|
||||
short alt; /*!> altitude in meters (WGS 84 geoid ref.) */
|
||||
};
|
||||
|
||||
/**
|
||||
@enum gps_msg
|
||||
@brief Type of GPS (and other GNSS) sentences
|
||||
*/
|
||||
enum gps_msg {
|
||||
UNKNOWN, /*!> neutral value */
|
||||
IGNORED, /*!> frame was not parsed by the system */
|
||||
INVALID, /*!> system try to parse frame but failed */
|
||||
INCOMPLETE, /*!> frame parsed was missing bytes */
|
||||
/* NMEA messages of interest */
|
||||
NMEA_RMC, /*!> Recommended Minimum data (time + date) */
|
||||
NMEA_GGA, /*!> Global positioning system fix data (pos + alt) */
|
||||
NMEA_GNS, /*!> GNSS fix data (pos + alt, sat number) */
|
||||
NMEA_ZDA, /*!> Time and Date */
|
||||
/* NMEA message useful for time reference quality assessment */
|
||||
NMEA_GBS, /*!> GNSS Satellite Fault Detection */
|
||||
NMEA_GST, /*!> GNSS Pseudo Range Error Statistics */
|
||||
NMEA_GSA, /*!> GNSS DOP and Active Satellites (sat number) */
|
||||
NMEA_GSV, /*!> GNSS Satellites in View (sat SNR) */
|
||||
/* Misc. NMEA messages */
|
||||
NMEA_GLL, /*!> Latitude and longitude, with time fix and status */
|
||||
NMEA_TXT, /*!> Text Transmission */
|
||||
NMEA_VTG, /*!> Course over ground and Ground speed */
|
||||
/* uBlox proprietary NMEA messages of interest */
|
||||
UBX_NAV_TIMEGPS, /*!> GPS Time Solution */
|
||||
UBX_NAV_TIMEUTC /*!> UTC Time Solution */
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PUBLIC CONSTANTS ----------------------------------------------------- */
|
||||
|
||||
#define LGW_GPS_SUCCESS 0
|
||||
#define LGW_GPS_ERROR -1
|
||||
|
||||
#define LGW_GPS_MIN_MSG_SIZE (8)
|
||||
#define LGW_GPS_UBX_SYNC_CHAR (0xB5)
|
||||
#define LGW_GPS_NMEA_SYNC_CHAR (0x24)
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PUBLIC FUNCTIONS PROTOTYPES ------------------------------------------ */
|
||||
|
||||
/**
|
||||
@brief Configure a GPS module
|
||||
|
||||
@param tty_path path to the TTY connected to the GPS
|
||||
@param gps_familly parameter (eg. ubx6 for uBlox gen.6)
|
||||
@param target_brate target baudrate for communication (0 keeps default target baudrate)
|
||||
@param fd_ptr pointer to a variable to receive file descriptor on GPS tty
|
||||
@return success if the function was able to connect and configure a GPS module
|
||||
*/
|
||||
int lgw_gps_enable(char* tty_path, char* gps_familly, speed_t target_brate, int* fd_ptr);
|
||||
|
||||
/**
|
||||
@brief Restore GPS serial configuration and close serial device
|
||||
|
||||
@param fd file descriptor on GPS tty
|
||||
@return success if the function was able to complete
|
||||
*/
|
||||
int lgw_gps_disable(int fd);
|
||||
|
||||
/**
|
||||
@brief Parse messages coming from the GPS system (or other GNSS)
|
||||
|
||||
@param serial_buff pointer to the string to be parsed
|
||||
@param buff_size maximum string lengths for NMEA parsing (incl. null char)
|
||||
@return type of frame parsed
|
||||
|
||||
The RAW NMEA sentences are parsed to a global set of variables shared with the
|
||||
lgw_gps_get function.
|
||||
If the lgw_parse_nmea and lgw_gps_get are used in different threads, a mutex
|
||||
lock must be acquired before calling either function.
|
||||
*/
|
||||
enum gps_msg lgw_parse_nmea(const char* serial_buff, int buff_size);
|
||||
|
||||
/**
|
||||
@brief Parse Ublox proprietary messages coming from the GPS system
|
||||
|
||||
@param serial_buff pointer to the string to be parsed
|
||||
@param buff_size maximum string lengths for UBX parsing (incl. null char)
|
||||
@param msg_size number of bytes parsed as UBX message if found
|
||||
@return type of frame parsed
|
||||
|
||||
The RAW UBX sentences are parsed to a global set of variables shared with the
|
||||
lgw_gps_get function.
|
||||
If the lgw_parse_ubx and lgw_gps_get are used in different threads, a mutex
|
||||
lock must be acquired before calling either function.
|
||||
*/
|
||||
enum gps_msg lgw_parse_ubx(const char* serial_buff, size_t buff_size, size_t *msg_size);
|
||||
|
||||
/**
|
||||
@brief Get the GPS solution (space & time) for the concentrator
|
||||
|
||||
@param utc pointer to store UTC time, with ns precision (NULL to ignore)
|
||||
@param gps_time pointer to store GPS time, with ns precision (NULL to ignore)
|
||||
@param loc pointer to store coordinates (NULL to ignore)
|
||||
@param err pointer to store coordinates standard deviation (NULL to ignore)
|
||||
@return success if the chosen elements could be returned
|
||||
|
||||
This function read the global variables generated by the NMEA/UBX parsing
|
||||
functions lgw_parse_nmea/lgw_parse_ubx. It returns time and location data in a
|
||||
format that is exploitable by other functions in that library sub-module.
|
||||
If the lgw_parse_nmea/lgw_parse_ubx and lgw_gps_get are used in different
|
||||
threads, a mutex lock must be acquired before calling either function.
|
||||
*/
|
||||
int lgw_gps_get(struct timespec *utc, struct timespec *gps_time, struct coord_s *loc, struct coord_s *err);
|
||||
|
||||
/**
|
||||
@brief Get time and position information from the serial GPS last message received
|
||||
@param utc UTC time, with ns precision (leap seconds are ignored)
|
||||
@param gps_time timestamp of last time pulse from the GPS module converted to the UNIX epoch
|
||||
(leap seconds are ignored)
|
||||
@param loc location information
|
||||
@param err location error estimate if supported
|
||||
@return success if timestamp was read and time reference could be refreshed
|
||||
|
||||
Set systime to 0 in ref to trigger initial synchronization.
|
||||
*/
|
||||
int lgw_gps_sync(struct tref *ref, uint32_t count_us, struct timespec utc, struct timespec gps_time);
|
||||
|
||||
/**
|
||||
@brief Convert concentrator timestamp counter value to UTC time
|
||||
|
||||
@param ref time reference structure required for time conversion
|
||||
@param count_us internal timestamp counter of the LoRa concentrator
|
||||
@param utc pointer to store UTC time, with ns precision (leap seconds ignored)
|
||||
@return success if the function was able to convert timestamp to UTC
|
||||
|
||||
This function is typically used when a packet is received to transform the
|
||||
internal counter-based timestamp in an absolute timestamp with an accuracy in
|
||||
the order of a couple microseconds (ns resolution).
|
||||
*/
|
||||
int lgw_cnt2utc(struct tref ref, uint32_t count_us, struct timespec* utc);
|
||||
|
||||
/**
|
||||
@brief Convert UTC time to concentrator timestamp counter value
|
||||
|
||||
@param ref time reference structure required for time conversion
|
||||
@param utc UTC time, with ns precision (leap seconds are ignored)
|
||||
@param count_us pointer to store internal timestamp counter of LoRa concentrator
|
||||
@return success if the function was able to convert UTC to timestamp
|
||||
|
||||
This function is typically used when a packet must be sent at an accurate time
|
||||
(eg. to send a piggy-back response after receiving a packet from a node) to
|
||||
transform an absolute UTC time into a matching internal concentrator timestamp.
|
||||
*/
|
||||
int lgw_utc2cnt(struct tref ref,struct timespec utc, uint32_t* count_us);
|
||||
|
||||
/**
|
||||
@brief Convert concentrator timestamp counter value to GPS time
|
||||
|
||||
@param ref time reference structure required for time conversion
|
||||
@param count_us internal timestamp counter of the LoRa concentrator
|
||||
@param gps_time pointer to store GPS time, with ns precision (leap seconds ignored)
|
||||
@return success if the function was able to convert timestamp to GPS time
|
||||
|
||||
This function is typically used when a packet is received to transform the
|
||||
internal counter-based timestamp in an absolute timestamp with an accuracy in
|
||||
the order of a millisecond.
|
||||
*/
|
||||
int lgw_cnt2gps(struct tref ref, uint32_t count_us, struct timespec* gps_time);
|
||||
|
||||
/**
|
||||
@brief Convert GPS time to concentrator timestamp counter value
|
||||
|
||||
@param ref time reference structure required for time conversion
|
||||
@param gps_time GPS time, with ns precision (leap seconds are ignored)
|
||||
@param count_us pointer to store internal timestamp counter of LoRa concentrator
|
||||
@return success if the function was able to convert GPS time to timestamp
|
||||
|
||||
This function is typically used when a packet must be sent at an accurate time
|
||||
(eg. to send a piggy-back response after receiving a packet from a node) to
|
||||
transform an absolute GPS time into a matching internal concentrator timestamp.
|
||||
*/
|
||||
int lgw_gps2cnt(struct tref ref, struct timespec gps_time, uint32_t* count_us);
|
||||
|
||||
#endif
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
|
@ -0,0 +1,463 @@
|
|||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2019 Semtech
|
||||
|
||||
Description:
|
||||
LoRa concentrator Hardware Abstraction Layer
|
||||
|
||||
License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _LORAGW_HAL_H
|
||||
#define _LORAGW_HAL_H
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- DEPENDANCIES --------------------------------------------------------- */
|
||||
|
||||
#include <stdint.h> /* C99 types */
|
||||
#include <stdbool.h> /* bool type */
|
||||
|
||||
#include "config.h" /* library configuration options (dynamically generated) */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PUBLIC MACROS -------------------------------------------------------- */
|
||||
|
||||
#define IS_LORA_BW(bw) ((bw == BW_125KHZ) || (bw == BW_250KHZ) || (bw == BW_500KHZ))
|
||||
#define IS_LORA_DR(dr) ((dr == DR_LORA_SF5) || (dr == DR_LORA_SF6) || (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_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
|
||||
#define LGW_LBT_ISSUE 1
|
||||
|
||||
/* radio-specific parameters */
|
||||
#define LGW_XTAL_FREQU 32000000 /* frequency of the RF reference oscillator */
|
||||
#define LGW_RF_CHAIN_NB 2 /* number of RF chains */
|
||||
#define LGW_RF_RX_BANDWIDTH {1000000, 1000000} /* bandwidth of the radios */
|
||||
|
||||
/* concentrator chipset-specific parameters */
|
||||
/* to use array parameters, declare a local const and use 'if_chain' as index */
|
||||
#define LGW_IF_CHAIN_NB 10 /* number of IF+modem RX chains */
|
||||
#define LGW_REF_BW 125000 /* typical bandwidth of data channel */
|
||||
#define LGW_MULTI_NB 8 /* number of LoRa 'multi SF' chains */
|
||||
|
||||
/* values available for the 'modulation' parameters */
|
||||
/* NOTE: arbitrary values */
|
||||
#define MOD_UNDEFINED 0
|
||||
#define MOD_CW 0x08
|
||||
#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 0x06
|
||||
#define BW_250KHZ 0x05
|
||||
#define BW_125KHZ 0x04
|
||||
|
||||
/* 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_SF5 5
|
||||
#define DR_LORA_SF6 6
|
||||
#define DR_LORA_SF7 7
|
||||
#define DR_LORA_SF8 8
|
||||
#define DR_LORA_SF9 9
|
||||
#define DR_LORA_SF10 10
|
||||
#define DR_LORA_SF11 11
|
||||
#define DR_LORA_SF12 12
|
||||
/* NOTE: for FSK directly use baudrate between 500 bauds and 250 kbauds */
|
||||
#define DR_FSK_MIN 500
|
||||
#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
|
||||
|
||||
/* 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 */
|
||||
|
||||
/* Maximum size of Tx gain LUT */
|
||||
#define TX_GAIN_LUT_SIZE_MAX 16
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PUBLIC TYPES --------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
@enum lgw_radio_type_t
|
||||
@brief Radio types that can be found on the LoRa Gateway
|
||||
*/
|
||||
typedef enum {
|
||||
LGW_RADIO_TYPE_NONE,
|
||||
LGW_RADIO_TYPE_SX1255,
|
||||
LGW_RADIO_TYPE_SX1257,
|
||||
LGW_RADIO_TYPE_SX1272,
|
||||
LGW_RADIO_TYPE_SX1276,
|
||||
LGW_RADIO_TYPE_SX1250
|
||||
} lgw_radio_type_t;
|
||||
|
||||
/**
|
||||
@struct lgw_conf_board_s
|
||||
@brief Configuration structure for board specificities
|
||||
*/
|
||||
struct lgw_conf_board_s {
|
||||
bool lorawan_public; /*!> Enable ONLY for *public* networks using the LoRa MAC protocol */
|
||||
uint8_t clksrc; /*!> Index of RF chain which provides clock to concentrator */
|
||||
bool full_duplex; /*!> Indicates if the gateway operates in full duplex mode or not */
|
||||
char spidev_path[64];/*!> Path to access the SPI device to connect to the SX1302 */
|
||||
};
|
||||
|
||||
/**
|
||||
@struct lgw_rssi_tcomp_s
|
||||
@brief Structure containing all coefficients necessary to compute the offset to be applied on RSSI for current temperature
|
||||
*/
|
||||
struct lgw_rssi_tcomp_s {
|
||||
float coeff_a;
|
||||
float coeff_b;
|
||||
float coeff_c;
|
||||
float coeff_d;
|
||||
float coeff_e;
|
||||
};
|
||||
|
||||
/**
|
||||
@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 */
|
||||
float rssi_offset; /*!> Board-specific RSSI correction factor */
|
||||
struct lgw_rssi_tcomp_s rssi_tcomp; /*!> Board-specific RSSI temperature compensation coefficients */
|
||||
lgw_radio_type_t type; /*!> Radio type for that RF chain (SX1255, SX1257....) */
|
||||
bool tx_enable; /*!> enable or disable TX on that RF chain */
|
||||
};
|
||||
|
||||
/**
|
||||
@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 */
|
||||
uint8_t sync_word_size; /*!> size of FSK sync word (number of bytes, 0 for default) */
|
||||
uint64_t sync_word; /*!> FSK sync word (ALIGN RIGHT, eg. 0xC194C1) */
|
||||
bool implicit_hdr; /*!> LoRa Service implicit header */
|
||||
uint8_t implicit_payload_length; /*!> LoRa Service implicit header payload length (number of bytes, 0 for default) */
|
||||
bool implicit_crc_en; /*!> LoRa Service implicit header CRC enable */
|
||||
uint8_t implicit_coderate; /*!> LoRa Service implicit header coding rate */
|
||||
};
|
||||
|
||||
/**
|
||||
@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 {
|
||||
uint32_t freq_hz; /*!> central frequency of the IF chain */
|
||||
int32_t freq_offset;
|
||||
uint8_t if_chain; /*!> by which IF chain was packet received */
|
||||
uint8_t status; /*!> status of the received packet */
|
||||
uint32_t count_us; /*!> internal concentrator counter for timestamping, 1 microsecond resolution */
|
||||
uint8_t rf_chain; /*!> through which RF chain the packet was received */
|
||||
uint8_t modem_id;
|
||||
uint8_t modulation; /*!> modulation used by the packet */
|
||||
uint8_t bandwidth; /*!> modulation bandwidth (LoRa only) */
|
||||
uint32_t datarate; /*!> RX datarate of the packet (SF for LoRa) */
|
||||
uint8_t coderate; /*!> error-correcting code of the packet (LoRa only) */
|
||||
float rssic; /*!> average RSSI of the channel in dB */
|
||||
float rssis; /*!> average RSSI of the signal 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 */
|
||||
int8_t freq_offset; /*!> frequency offset from Radio Tx frequency (CW mode) */
|
||||
uint8_t bandwidth; /*!> modulation bandwidth (LoRa only) */
|
||||
uint32_t datarate; /*!> TX datarate (baudrate for FSK, SF for LoRa) */
|
||||
uint8_t coderate; /*!> error-correcting code of the packet (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 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 */
|
||||
};
|
||||
|
||||
/**
|
||||
@struct lgw_tx_gain_s
|
||||
@brief Structure containing all gains of Tx chain
|
||||
*/
|
||||
struct lgw_tx_gain_s {
|
||||
int8_t rf_power; /*!> measured TX power at the board connector, in dBm */
|
||||
uint8_t dig_gain; /*!> (sx125x) 2 bits: control of the digital gain of SX1302 */
|
||||
uint8_t pa_gain; /*!> (sx125x) 2 bits: control of the external PA (SX1302 I/O)
|
||||
(sx1250) 1 bits: enable/disable the external PA (SX1302 I/O) */
|
||||
uint8_t dac_gain; /*!> (sx125x) 2 bits: control of the radio DAC */
|
||||
uint8_t mix_gain; /*!> (sx125x) 4 bits: control of the radio mixer */
|
||||
int8_t offset_i; /*!> (sx125x) calibrated I offset */
|
||||
int8_t offset_q; /*!> (sx125x) calibrated Q offset */
|
||||
uint8_t pwr_idx; /*!> (sx1250) 6 bits: control the radio power index to be used for configuration */
|
||||
};
|
||||
|
||||
/**
|
||||
@struct lgw_tx_gain_lut_s
|
||||
@brief Structure defining the Tx gain LUT
|
||||
*/
|
||||
struct lgw_tx_gain_lut_s {
|
||||
struct lgw_tx_gain_s lut[TX_GAIN_LUT_SIZE_MAX]; /*!> Array of Tx gain struct */
|
||||
uint8_t size; /*!> Number of LUT indexes */
|
||||
};
|
||||
|
||||
/**
|
||||
@struct lgw_conf_debug_s
|
||||
@brief Configuration structure for debug
|
||||
*/
|
||||
struct conf_ref_payload_s {
|
||||
uint32_t id;
|
||||
uint8_t payload[255];
|
||||
uint32_t prev_cnt;
|
||||
};
|
||||
struct lgw_conf_debug_s {
|
||||
uint8_t nb_ref_payload;
|
||||
struct conf_ref_payload_s ref_payload[16];
|
||||
char log_file_name[128];
|
||||
};
|
||||
|
||||
/**
|
||||
@struct lgw_conf_debug_s
|
||||
@brief Configuration structure for debug
|
||||
*/
|
||||
struct lgw_conf_timestamp_s {
|
||||
bool enable_precision_ts;
|
||||
uint8_t max_ts_metrics;
|
||||
uint8_t nb_symbols;
|
||||
};
|
||||
|
||||
/**
|
||||
@struct lgw_context_s
|
||||
@brief Configuration context shared across modules
|
||||
*/
|
||||
typedef struct lgw_context_s {
|
||||
/* Global context */
|
||||
bool is_started;
|
||||
struct lgw_conf_board_s board_cfg;
|
||||
/* RX context */
|
||||
struct lgw_conf_rxrf_s rf_chain_cfg[LGW_RF_CHAIN_NB];
|
||||
struct lgw_conf_rxif_s if_chain_cfg[LGW_IF_CHAIN_NB];
|
||||
struct lgw_conf_rxif_s lora_service_cfg; /* LoRa service channel config parameters */
|
||||
struct lgw_conf_rxif_s fsk_cfg; /* FSK channel config parameters */
|
||||
/* TX context */
|
||||
struct lgw_tx_gain_lut_s tx_gain_lut[LGW_RF_CHAIN_NB];
|
||||
/* Misc */
|
||||
struct lgw_conf_timestamp_s timestamp_cfg;
|
||||
/* Debug */
|
||||
struct lgw_conf_debug_s debug_cfg;
|
||||
} lgw_context_t;
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PUBLIC FUNCTIONS PROTOTYPES ------------------------------------------ */
|
||||
|
||||
/**
|
||||
@brief Configure the gateway board
|
||||
@param conf structure containing the configuration parameters
|
||||
@return LGW_HAL_ERROR id the operation failed, LGW_HAL_SUCCESS else
|
||||
*/
|
||||
int lgw_board_setconf(struct lgw_conf_board_s * conf);
|
||||
|
||||
/**
|
||||
@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 Configure the Tx gain LUT
|
||||
@param pointer to structure defining the LUT
|
||||
@return LGW_HAL_ERROR id the operation failed, LGW_HAL_SUCCESS else
|
||||
*/
|
||||
int lgw_txgain_setconf(uint8_t rf_chain, struct lgw_tx_gain_lut_s * conf);
|
||||
|
||||
/**
|
||||
@brief Configure the precision timestamp
|
||||
@param pointer to structure defining the config to be applied
|
||||
@return LGW_HAL_ERROR id the operation failed, LGW_HAL_SUCCESS else
|
||||
*/
|
||||
int lgw_timestamp_setconf(struct lgw_conf_timestamp_s * conf);
|
||||
|
||||
/**
|
||||
@brief Configure the debug context
|
||||
@param pointer to structure defining the config to be applied
|
||||
@return LGW_HAL_ERROR id the operation failed, LGW_HAL_SUCCESS else
|
||||
*/
|
||||
int lgw_debug_setconf(struct lgw_conf_debug_s * conf);
|
||||
|
||||
/**
|
||||
@brief Connect to the LoRa concentrator, 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 concentrator 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 concentrator 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
|
||||
|
||||
/!\ When sending a packet, there is a delay (approx 1.5ms) for the analog
|
||||
circuitry to start and be stable. This delay is adjusted by the HAL depending
|
||||
on the board version (lgw_i_tx_start_delay_us).
|
||||
|
||||
In 'timestamp' mode, this is transparent: the modem is started
|
||||
lgw_i_tx_start_delay_us microseconds before the user-set timestamp value is
|
||||
reached, the preamble of the packet start right when the internal timestamp
|
||||
counter reach target value.
|
||||
|
||||
In 'immediate' mode, the packet is emitted as soon as possible: transferring the
|
||||
packet (and its parameters) from the host to the concentrator takes some time,
|
||||
then there is the lgw_i_tx_start_delay_us, then the packet is emitted.
|
||||
|
||||
In 'triggered' mode (aka PPS/GPS mode), the packet, typically a beacon, is
|
||||
emitted lgw_i_tx_start_delay_us microsenconds after a rising edge of the
|
||||
trigger signal. Because there is no way to anticipate the triggering event and
|
||||
start the analog circuitry beforehand, that delay must be taken into account in
|
||||
the protocol.
|
||||
*/
|
||||
int lgw_send(struct lgw_pkt_tx_s * pkt_data);
|
||||
|
||||
/**
|
||||
@brief Give the the status of different part of the LoRa concentrator
|
||||
@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 rf_chain, uint8_t select, uint8_t * code);
|
||||
|
||||
/**
|
||||
@brief Abort a currently scheduled or ongoing TX
|
||||
@return LGW_HAL_ERROR id the operation failed, LGW_HAL_SUCCESS else
|
||||
*/
|
||||
int lgw_abort_tx(uint8_t rf_chain);
|
||||
|
||||
/**
|
||||
@brief Return value of internal counter when latest event (eg GPS pulse) was captured
|
||||
@param trig_cnt_us pointer to receive timestamp value
|
||||
@return LGW_HAL_ERROR id the operation failed, LGW_HAL_SUCCESS else
|
||||
*/
|
||||
int lgw_get_trigcnt(uint32_t * trig_cnt_us);
|
||||
|
||||
/**
|
||||
@brief Return instateneous value of internal counter
|
||||
@param inst_cnt_us pointer to receive timestamp value
|
||||
@return LGW_HAL_ERROR id the operation failed, LGW_HAL_SUCCESS else
|
||||
*/
|
||||
int lgw_get_instcnt(uint32_t * inst_cnt_us);
|
||||
|
||||
/**
|
||||
@brief Return the LoRa concentrator EUI
|
||||
@param eui pointer to receive eui
|
||||
@return LGW_HAL_ERROR id the operation failed, LGW_HAL_SUCCESS else
|
||||
*/
|
||||
int lgw_get_eui(uint64_t * eui);
|
||||
|
||||
/**
|
||||
@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);
|
||||
|
||||
/**
|
||||
@brief Return time on air of given packet, in milliseconds
|
||||
@param packet is a pointer to the packet structure
|
||||
@return the packet time on air in milliseconds
|
||||
*/
|
||||
uint32_t lgw_time_on_air(struct lgw_pkt_tx_s * packet);
|
||||
|
||||
#endif
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2019 Semtech
|
||||
|
||||
Description:
|
||||
Host specific functions to address the LoRa concentrator I2C peripherals.
|
||||
|
||||
License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _LORAGW_I2C_H
|
||||
#define _LORAGW_I2C_H
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- DEPENDANCIES --------------------------------------------------------- */
|
||||
|
||||
#include <stdint.h> /* C99 types*/
|
||||
|
||||
#include "config.h" /* library configuration options (dynamically generated) */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PUBLIC CONSTANTS ----------------------------------------------------- */
|
||||
|
||||
#define LGW_I2C_SUCCESS 0
|
||||
#define LGW_I2C_ERROR -1
|
||||
|
||||
#define I2C_DEVICE "/dev/i2c-1"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PUBLIC FUNCTIONS PROTOTYPES ------------------------------------------ */
|
||||
|
||||
/**
|
||||
@brief Open I2C port
|
||||
@param path Path to the I2C device driver (absolute or relative)
|
||||
@param device_addr Address of the device
|
||||
@param i2c_fd Pointer to receive I2C port file descriptor index
|
||||
@return 0 if I2C port was open successfully, -1 else
|
||||
*/
|
||||
int i2c_linuxdev_open(const char *path, uint8_t device_addr, int *i2c_fd);
|
||||
|
||||
/**
|
||||
@brief Close I2C port
|
||||
@param i2c_fd I2C port file descriptor index
|
||||
@return 0 if I2C port was closed successfully, -1 else
|
||||
*/
|
||||
int i2c_linuxdev_close(int i2c_fd);
|
||||
|
||||
/**
|
||||
@brief Read data from an I2C port
|
||||
@param i2c_fd I2C port file descriptor index
|
||||
@param device_addr I2C device address
|
||||
@param reg_addr Address of the register to be read
|
||||
@param data Pointer to a buffer to store read data
|
||||
@return 0 if I2C data read is successful, -1 else
|
||||
*/
|
||||
int i2c_linuxdev_read(int i2c_fd, uint8_t device_addr, uint8_t reg_addr, uint8_t *data);
|
||||
|
||||
/**
|
||||
@brief Write data to an I2C port
|
||||
@param i2c_fd I2C port file descriptor index
|
||||
@param device_addr I2C device address
|
||||
@param reg_addr Address of the register to write to
|
||||
@param data byte to write in the register
|
||||
@return 0 if I2C data write is successful, -1 else
|
||||
*/
|
||||
int i2c_linuxdev_write(int i2c_fd, uint8_t device_addr, uint8_t reg_addr, uint8_t data);
|
||||
|
||||
#endif
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2019 Semtech
|
||||
|
||||
Description:
|
||||
Host specific functions to address the LoRa concentrator registers through
|
||||
a SPI interface.
|
||||
Single-byte read/write and burst read/write.
|
||||
Could be used with multiple SPI ports in parallel (explicit file descriptor)
|
||||
|
||||
License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _LORAGW_SPI_H
|
||||
#define _LORAGW_SPI_H
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- DEPENDANCIES --------------------------------------------------------- */
|
||||
|
||||
#include <stdint.h> /* C99 types*/
|
||||
|
||||
#include "config.h" /* library configuration options (dynamically generated) */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PUBLIC CONSTANTS ----------------------------------------------------- */
|
||||
|
||||
#define LGW_SPI_SUCCESS 0
|
||||
#define LGW_SPI_ERROR -1
|
||||
#define LGW_BURST_CHUNK 1024
|
||||
|
||||
#define SPI_SPEED 2000000
|
||||
|
||||
#define LGW_SPI_MUX_TARGET_SX1302 0x00
|
||||
#define LGW_SPI_MUX_TARGET_RADIOA 0x01
|
||||
#define LGW_SPI_MUX_TARGET_RADIOB 0x02
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PUBLIC FUNCTIONS PROTOTYPES ------------------------------------------ */
|
||||
|
||||
/**
|
||||
@brief LoRa concentrator SPI setup (configure I/O and peripherals)
|
||||
@param spidev_path path to the SPI device to be used to connect to the SX1302
|
||||
@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(const char * spidev_path, void **spi_target_ptr);
|
||||
|
||||
/**
|
||||
@brief LoRa concentrator 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 concentrator 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 spi_mux_target, uint16_t address, uint8_t data);
|
||||
|
||||
/**
|
||||
@brief LoRa concentrator 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 spi_mux_target, uint16_t address, uint8_t *data);
|
||||
|
||||
/**
|
||||
@brief LoRa concentrator 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 concentrator
|
||||
@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 spi_mux_target, uint16_t address, const uint8_t *data, uint16_t size);
|
||||
|
||||
/**
|
||||
@brief LoRa concentrator 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 concentrator
|
||||
@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 spi_mux_target, uint16_t address, uint8_t *data, uint16_t size);
|
||||
|
||||
#endif
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2019 Semtech
|
||||
|
||||
Description:
|
||||
Basic driver for ST ts751 temperature sensor
|
||||
|
||||
License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _LORAGW_STTS751_H
|
||||
#define _LORAGW_STTS751_H
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- DEPENDANCIES --------------------------------------------------------- */
|
||||
|
||||
#include <stdint.h> /* C99 types */
|
||||
#include <stdbool.h> /* bool type */
|
||||
|
||||
#include "config.h" /* library configuration options (dynamically generated) */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- INTERNAL SHARED TYPES ------------------------------------------------ */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- INTERNAL SHARED FUNCTIONS -------------------------------------------- */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PUBLIC CONSTANTS ----------------------------------------------------- */
|
||||
|
||||
#define I2C_PORT_TEMP_SENSOR 0x39
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PUBLIC FUNCTIONS ----------------------------------------------------- */
|
||||
|
||||
/**
|
||||
@brief TODO
|
||||
@param TODO
|
||||
@return TODO
|
||||
*/
|
||||
int lgw_stts751_configure(void);
|
||||
|
||||
/**
|
||||
@brief TODO
|
||||
@param TODO
|
||||
@return TODO
|
||||
*/
|
||||
int lgw_stts751_get_temperature(float * temperature);
|
||||
|
||||
#endif
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2019 Semtech
|
||||
|
||||
Description:
|
||||
Functions used to handle LoRa concentrator SX1250 radios.
|
||||
|
||||
License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _LORAGW_SX1250_H
|
||||
#define _LORAGW_SX1250_H
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- DEPENDANCIES --------------------------------------------------------- */
|
||||
|
||||
#include <stdint.h> /* C99 types*/
|
||||
|
||||
#include "config.h" /* library configuration options (dynamically generated) */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PUBLIC MACROS -------------------------------------------------------- */
|
||||
|
||||
#define SX1250_FREQ_TO_REG(f) (uint32_t)((uint64_t)f * (1 << 25) / 32000000U)
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PUBLIC CONSTANTS ----------------------------------------------------- */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PUBLIC TYPES --------------------------------------------------------- */
|
||||
|
||||
typedef enum {
|
||||
CALIBRATE_IMAGE = 0x98,
|
||||
CLR_IRQ_STATUS = 0x02,
|
||||
STOP_TIMER_ON_PREAMBLE = 0x9F,
|
||||
SET_RFSWITCHMODE = 0x9D,
|
||||
GET_IRQ_STATUS = 0x12,
|
||||
GET_RX_BUFFER_STATUS = 0x13,
|
||||
GET_PACKET_STATUS = 0x14,
|
||||
READ_BUFFER = 0x1E,
|
||||
READ_REGISTER = 0x1D,
|
||||
SET_DIO_IRQ_PARAMS = 0x08,
|
||||
SET_MODULATION_PARAMS = 0x8B,
|
||||
SET_PA_CONFIG = 0x95,
|
||||
SET_PACKET_PARAMS = 0x8C,
|
||||
SET_PACKET_TYPE = 0x8A,
|
||||
SET_RF_FREQUENCY = 0x86,
|
||||
SET_BUFFER_BASE_ADDRESS = 0x8F,
|
||||
SET_SLEEP = 0x84,
|
||||
SET_STANDBY = 0x80,
|
||||
SET_RX = 0x82,
|
||||
SET_TX = 0x83,
|
||||
SET_TX_PARAMS = 0x8E,
|
||||
WRITE_BUFFER = 0x0E,
|
||||
WRITE_REGISTER = 0x0D,
|
||||
SET_TXCONTINUOUSWAVE = 0xD1,
|
||||
SET_TXCONTINUOUSPREAMBLE= 0xD2,
|
||||
GET_STATUS = 0xC0,
|
||||
SET_REGULATORMODE = 0x96,
|
||||
SET_FS = 0xC1,
|
||||
GET_DEVICE_ERRORS = 0x17
|
||||
} sx1250_op_code_t;
|
||||
|
||||
typedef enum {
|
||||
STDBY_RC = 0x00,
|
||||
STDBY_XOSC = 0x01
|
||||
} sx1250_standby_modes_t;
|
||||
|
||||
typedef enum {
|
||||
PACKET_TYPE_GFSK = 0x00,
|
||||
PACKET_TYPE_LORA = 0x01
|
||||
} sx1250_packet_type_t;
|
||||
|
||||
typedef enum {
|
||||
SET_RAMP_10U = 0x00,
|
||||
SET_RAMP_20U = 0x01,
|
||||
SET_RAMP_40U = 0x02,
|
||||
SET_RAMP_80U = 0x03,
|
||||
SET_RAMP_200U = 0x04,
|
||||
SET_RAMP_800U = 0x05,
|
||||
SET_RAMP_1700U = 0x06,
|
||||
SET_RAMP_3400U = 0x07
|
||||
} sx1250_ramp_time_t;
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PUBLIC FUNCTIONS PROTOTYPES ------------------------------------------ */
|
||||
|
||||
int sx1250_write_command(uint8_t rf_chain, sx1250_op_code_t op_code, uint8_t *data, uint16_t size);
|
||||
int sx1250_read_command(uint8_t rf_chain, sx1250_op_code_t op_code, uint8_t *data, uint16_t size);
|
||||
|
||||
int sx1250_calibrate(uint8_t rf_chain, uint32_t freq_hz);
|
||||
int sx1250_setup(uint8_t rf_chain, uint32_t freq_hz);
|
||||
|
||||
#endif
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2019 Semtech
|
||||
|
||||
Description:
|
||||
Functions used to handle LoRa concentrator SX1255/SX1257 radios.
|
||||
|
||||
License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*/
|
||||
|
||||
#ifndef _LORAGW_SX125X_H
|
||||
#define _LORAGW_SX125X_H
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- DEPENDANCIES --------------------------------------------------------- */
|
||||
|
||||
#include <stdint.h> /* C99 types */
|
||||
#include <stdbool.h> /* bool type */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- INTERNAL SHARED TYPES ------------------------------------------------ */
|
||||
|
||||
struct radio_reg_s
|
||||
{
|
||||
uint8_t addr; /* base address of the register */
|
||||
uint8_t offs; /* position of the register LSB (between 0 to 7) */
|
||||
uint8_t leng; /* number of bits in the register */
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PUBLIC MACROS -------------------------------------------------------- */
|
||||
|
||||
#define SX1257_FREQ_TO_REG(f) (uint32_t)((uint64_t)f * (1 << 19) / 32000000U)
|
||||
#define SX1255_FREQ_TO_REG(f) (uint32_t)((uint64_t)f * (1 << 20) / 32000000U)
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PUBLIC CONSTANTS ----------------------------------------------------- */
|
||||
|
||||
#define LGW_REG_SUCCESS 0
|
||||
#define LGW_REG_ERROR -1
|
||||
|
||||
#define SX125x_32MHz_FRAC 15625 /* irreductible fraction for PLL register caculation */
|
||||
|
||||
#define SX125x_TX_DAC_CLK_SEL 0 /* 0:int, 1:ext */
|
||||
#define SX125x_TX_DAC_GAIN 2 /* 3:0, 2:-3, 1:-6, 0:-9 dBFS (default 2) */
|
||||
#define SX125x_TX_MIX_GAIN 14 /* -38 + 2*TxMixGain dB (default 14) */
|
||||
#define SX125x_TX_PLL_BW 1 /* 0:75, 1:150, 2:225, 3:300 kHz (default 3) */
|
||||
#define SX125x_TX_ANA_BW 0 /* 17.5 / 2*(41-TxAnaBw) MHz (default 0) */
|
||||
#define SX125x_TX_DAC_BW 5 /* 24 + 8*TxDacBw Nb FIR taps (default 2) */
|
||||
#define SX125x_RX_LNA_GAIN 1 /* 1 to 6, 1 highest gain */
|
||||
#define SX125x_RX_BB_GAIN 15 /* 0 to 15 , 15 highest gain */
|
||||
#define SX125x_LNA_ZIN 0 /* 0:50, 1:200 Ohms (default 1) */
|
||||
#define SX125x_RX_ADC_BW 7 /* 0 to 7, 2:100<BW<200, 5:200<BW<400,7:400<BW kHz SSB (default 7) */
|
||||
#define SX125x_RX_ADC_TRIM 6 /* 0 to 7, 6 for 32MHz ref, 5 for 36MHz ref */
|
||||
#define SX125x_RX_BB_BW 0 /* 0:750, 1:500, 2:375; 3:250 kHz SSB (default 1, max 3) */
|
||||
#define SX125x_RX_PLL_BW 0 /* 0:75, 1:150, 2:225, 3:300 kHz (default 3, max 3) */
|
||||
#define SX125x_ADC_TEMP 0 /* ADC temperature measurement mode (default 0) */
|
||||
#define SX125x_XOSC_GM_STARTUP 13 /* (default 13) */
|
||||
#define SX125x_XOSC_DISABLE 2 /* Disable of Xtal Oscillator blocks bit0:regulator, bit1:core(gm), bit2:amplifier */
|
||||
|
||||
typedef enum {
|
||||
SX125x_REG_MODE = 0,
|
||||
SX125x_REG_MODE__PA_DRIVER_EN = 1,
|
||||
SX125x_REG_MODE__TX_EN = 2,
|
||||
SX125x_REG_MODE__RX_EN = 3,
|
||||
SX125x_REG_MODE__STANDBY_EN = 4,
|
||||
SX125x_REG_FRF_RX_MSB = 5,
|
||||
SX125x_REG_FRF_RX_MID = 6,
|
||||
SX125x_REG_FRF_RX_LSB = 7,
|
||||
SX125x_REG_FRF_TX_MSB = 8,
|
||||
SX125x_REG_FRF_TX_MID = 9,
|
||||
SX125x_REG_FRF_TX_LSB = 10,
|
||||
SX125x_REG_VERSION = 11,
|
||||
SX125x_REG_TX_GAIN = 12,
|
||||
SX125x_REG_TX_GAIN__DAC_GAIN = 13,
|
||||
SX125x_REG_TX_GAIN__MIX_GAIN = 14,
|
||||
SX125x_REG_TX_BW = 15,
|
||||
SX125x_REG_TX_BW__PLL_BW = 16,
|
||||
SX125x_REG_TX_BW__ANA_BW = 17,
|
||||
SX125x_REG_TX_DAC_BW = 18,
|
||||
SX125x_REG_RX_ANA_GAIN = 19,
|
||||
SX125x_REG_RX_ANA_GAIN__LNA_GAIN = 20,
|
||||
SX125x_REG_RX_ANA_GAIN__BB_GAIN = 21,
|
||||
SX125x_REG_RX_ANA_GAIN__LNA_ZIN = 22,
|
||||
SX125x_REG_RX_BW = 23,
|
||||
SX125x_REG_RX_BW__ADC_BW = 24,
|
||||
SX125x_REG_RX_BW__ADC_TRIM = 25,
|
||||
SX125x_REG_RX_BW__BB_BW = 26,
|
||||
SX125x_REG_RX_PLL_BW = 27,
|
||||
SX125x_REG_RX_PLL_BW__PLL_BW = 28,
|
||||
SX125x_REG_RX_PLL_BW__ADC_TEMP_EN = 29,
|
||||
SX125x_REG_DIO_MAPPING = 30,
|
||||
SX125x_REG_DIO_MAPPING__DIO_0_MAPPING = 31,
|
||||
SX125x_REG_DIO_MAPPING__DIO_1_MAPPING = 32,
|
||||
SX125x_REG_DIO_MAPPING__DIO_2_MAPPING = 33,
|
||||
SX125x_REG_DIO_MAPPING__DIO_3_MAPPING = 34,
|
||||
SX125x_REG_CLK_SELECT = 35,
|
||||
SX125x_REG_CLK_SELECT__DIG_LOOPBACK_EN = 36,
|
||||
SX125x_REG_CLK_SELECT__RF_LOOPBACK_EN = 37,
|
||||
SX125x_REG_CLK_SELECT__CLK_OUT = 38,
|
||||
SX125x_REG_CLK_SELECT__DAC_CLK_SELECT = 39,
|
||||
SX125x_REG_MODE_STATUS = 40,
|
||||
SX125x_REG_MODE_STATUS__LOW_BAT_EN = 41,
|
||||
SX125x_REG_MODE_STATUS__RX_PLL_LOCKED = 42,
|
||||
SX125x_REG_MODE_STATUS__TX_PLL_LOCKED = 43,
|
||||
SX125x_REG_LOW_BAT_THRESH = 44,
|
||||
SX125x_REG_SX1257_XOSC_TEST = 45,
|
||||
SX125x_REG_SX1257_XOSC_TEST__DISABLE = 46,
|
||||
SX125x_REG_SX1257_XOSC_TEST__GM_STARTUP = 47,
|
||||
SX125x_REG_SX1255_XOSC_TEST = 48,
|
||||
SX125x_REG_SX1255_XOSC_TEST__DISABLE = 49,
|
||||
SX125x_REG_SX1255_XOSC_TEST__GM_STARTUP = 50
|
||||
}
|
||||
radio_reg_t;
|
||||
|
||||
#define RADIO_TOTALREGS 51
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PUBLIC CONSTANTS ----------------------------------------------------- */
|
||||
/*
|
||||
|
||||
SX1257 frequency setting :
|
||||
F_register(24bit) = F_rf (Hz) / F_step(Hz)
|
||||
= F_rf (Hz) * 2^19 / F_xtal(Hz)
|
||||
= F_rf (Hz) * 2^19 / 32e6
|
||||
= F_rf (Hz) * 256/15625
|
||||
|
||||
SX1255 frequency setting :
|
||||
F_register(24bit) = F_rf (Hz) / F_step(Hz)
|
||||
= F_rf (Hz) * 2^20 / F_xtal(Hz)
|
||||
= F_rf (Hz) * 2^20 / 32e6
|
||||
= F_rf (Hz) * 512/15625
|
||||
*/
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PUBLIC FUNCTIONS PROTOTYPES ------------------------------------------ */
|
||||
|
||||
int sx125x_setup(uint8_t rf_chain, uint8_t rf_clkout, bool rf_enable, uint8_t rf_radio_type, uint32_t freq_hz);
|
||||
|
||||
int lgw_sx125x_reg_w(radio_reg_t idx, uint8_t data, uint8_t rf_chain);
|
||||
int lgw_sx125x_reg_r(radio_reg_t idx, uint8_t *data, uint8_t rf_chain);
|
||||
|
||||
#endif
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
|
@ -0,0 +1,437 @@
|
|||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2019 Semtech
|
||||
|
||||
Description:
|
||||
SX1302 Hardware Abstraction Layer entry functions.
|
||||
|
||||
License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*/
|
||||
|
||||
#ifndef _LORAGW_SX1302_H
|
||||
#define _LORAGW_SX1302_H
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- DEPENDANCIES --------------------------------------------------------- */
|
||||
|
||||
#include <stdint.h> /* C99 types*/
|
||||
|
||||
#include "config.h" /* library configuration options (dynamically generated) */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PUBLIC CONSTANTS ----------------------------------------------------- */
|
||||
|
||||
/* Default values */
|
||||
#define SX1302_AGC_RADIO_GAIN_AUTO 0xFF
|
||||
#define TX_START_DELAY_DEFAULT 1500 /* Calibrated value for 500KHz BW */
|
||||
|
||||
/* 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 */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PUBLIC MACROS -------------------------------------------------------- */
|
||||
|
||||
#define REG_SELECT(rf_chain, a, b) ((rf_chain == 0) ? a : b)
|
||||
|
||||
#define SET_PPM_ON(bw,dr) (((bw == BW_125KHZ) && ((dr == DR_LORA_SF11) || (dr == DR_LORA_SF12))) || ((bw == BW_250KHZ) && (dr == DR_LORA_SF12)))
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PUBLIC TYPES --------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
@struct sx1302_if_cfg_t
|
||||
@brief TODO
|
||||
*/
|
||||
typedef struct {
|
||||
bool if_enable;
|
||||
bool if_rf_chain; /* for each IF, 0 -> radio A, 1 -> radio B */
|
||||
int32_t if_freq; /* relative to radio frequency, +/- in Hz */
|
||||
} sx1302_if_cfg_t;
|
||||
|
||||
/**
|
||||
@struct sx1302_lora_service_cfg_t
|
||||
@brief TODO
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t lora_rx_bw; /* bandwidth setting for LoRa standalone modem */
|
||||
uint8_t lora_rx_sf; /* spreading factor setting for LoRa standalone modem */
|
||||
bool lora_rx_implicit_hdr; /* implicit header setting for LoRa standalone modem */
|
||||
uint8_t lora_rx_implicit_length; /* implicit header payload length setting for LoRa standalone modem */
|
||||
bool lora_rx_implicit_crc_en; /* implicit header payload crc enable setting for LoRa standalone modem */
|
||||
uint8_t lora_rx_implicit_coderate; /* implicit header payload coderate setting for LoRa standalone modem */
|
||||
} sx1302_lora_service_cfg_t;
|
||||
|
||||
/**
|
||||
@struct sx1302_fsk_cfg_t
|
||||
@brief TODO
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t fsk_rx_bw; /* bandwidth setting of FSK modem */
|
||||
uint32_t fsk_rx_dr; /* FSK modem datarate in bauds */
|
||||
uint8_t fsk_sync_word_size; /* default number of bytes for FSK sync word */
|
||||
uint64_t fsk_sync_word; /* default FSK sync word (ALIGNED RIGHT, MSbit first) */
|
||||
} sx1302_fsk_cfg_t;
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PUBLIC FUNCTIONS PROTOTYPES ------------------------------------------ */
|
||||
|
||||
/**
|
||||
@brief TODO
|
||||
@param TODO
|
||||
@return TODO
|
||||
*/
|
||||
void sx1302_init(struct lgw_conf_timestamp_s *conf);
|
||||
|
||||
/**
|
||||
@brief Get the SX1302 unique identifier
|
||||
@param eui pointerto the memory holding the concentrator EUI
|
||||
@return LGW_REG_SUCCESS if no error, LGW_REG_ERROR otherwise
|
||||
*/
|
||||
int sx1302_get_eui(uint64_t * eui);
|
||||
|
||||
/**
|
||||
@brief Check AGC & ARB MCUs parity error, and update timestamp counter wraping status
|
||||
@brief This function needs to be called regularly (every few seconds) by the upper layer
|
||||
@param N/A
|
||||
@return LGW_REG_SUCCESS if no error, LGW_REG_ERROR otherwise
|
||||
*/
|
||||
int sx1302_update(void);
|
||||
|
||||
/**
|
||||
@brief Select the clock source radio
|
||||
@param rf_chain The RF chain index from which to get the clock source
|
||||
@return LGW_REG_SUCCESS if success, LGW_REG_ERROR otherwise
|
||||
*/
|
||||
int sx1302_radio_clock_select(uint8_t rf_chain);
|
||||
|
||||
/**
|
||||
@brief Apply the radio reset sequence to the required RF chain index
|
||||
@param rf_chain The RF chain index of the radio to be reset
|
||||
@param type The type of radio to be reset
|
||||
@return LGW_REG_SUCCESS if success, LGW_REG_ERROR otherwise
|
||||
*/
|
||||
int sx1302_radio_reset(uint8_t rf_chain, lgw_radio_type_t type);
|
||||
|
||||
/**
|
||||
@brief Configure the radio type for the given RF chain
|
||||
@param rf_chain The RF chain index to be configured
|
||||
@param type The type of radio to be set for the given RF chain
|
||||
@return LGW_REG_SUCCESS if success, LGW_REG_ERROR otherwise
|
||||
*/
|
||||
int sx1302_radio_set_mode(uint8_t rf_chain, lgw_radio_type_t type);
|
||||
|
||||
/**
|
||||
@brief Give/Release control over the radios to/from the Host
|
||||
@param host_ctrl Set to true to give control to the host, false otherwise
|
||||
@return LGW_REG_SUCCESS if success, LGW_REG_ERROR otherwise
|
||||
*/
|
||||
int sx1302_radio_host_ctrl(bool host_ctrl);
|
||||
|
||||
/**
|
||||
@brief Perform the radio calibration sequence and fill the TX gain LUT with calibration offsets
|
||||
@param context_rf_chain The RF chains array from which to get RF chains current configuration
|
||||
@param clksrc The RF chain index which provides the clock source
|
||||
@param txgain_lut A pointer to the TX gain LUT to be filled
|
||||
@return LGW_REG_SUCCESS if success, LGW_REG_ERROR otherwise
|
||||
*/
|
||||
int sx1302_radio_calibrate(struct lgw_conf_rxrf_s * context_rf_chain, uint8_t clksrc, struct lgw_tx_gain_lut_s * txgain_lut);
|
||||
|
||||
/**
|
||||
@brief Configure the PA and LNA LUTs
|
||||
@param N/A
|
||||
@return LGW_REG_SUCCESS if success, LGW_REG_ERROR otherwise
|
||||
*/
|
||||
int sx1302_pa_lna_lut_configure(void);
|
||||
|
||||
/**
|
||||
@brief Configure the Radio Front-End stage of the SX1302
|
||||
@param N/A
|
||||
@return LGW_REG_SUCCESS if success, LGW_REG_ERROR otherwise
|
||||
*/
|
||||
int sx1302_radio_fe_configure(void);
|
||||
|
||||
/**
|
||||
@brief TODO
|
||||
@param TODO
|
||||
@return TODO
|
||||
*/
|
||||
uint8_t sx1302_get_ifmod_config(uint8_t if_chain);
|
||||
|
||||
/**
|
||||
@brief Configure the channelizer stage of the SX1302
|
||||
@param if_cfg A pointer to the channels configuration
|
||||
@param fix_gain Set to true to force the channelizer to a fixed gain, false to let the AGC controlling it
|
||||
@return LGW_REG_SUCCESS if success, LGW_REG_ERROR otherwise
|
||||
*/
|
||||
int sx1302_channelizer_configure(struct lgw_conf_rxif_s * if_cfg, bool fix_gain);
|
||||
|
||||
/**
|
||||
@brief Configure the correlator stage of the SX1302 LoRa multi-SF modems
|
||||
@param N/A
|
||||
@return LGW_REG_SUCCESS if success, LGW_REG_ERROR otherwise
|
||||
*/
|
||||
int sx1302_lora_correlator_configure(void);
|
||||
|
||||
/**
|
||||
@brief Configure the correlator stage of the SX1302 LoRa single-SF modem
|
||||
@param cfg A pointer to the channel configuration
|
||||
@return LGW_REG_SUCCESS if success, LGW_REG_ERROR otherwise
|
||||
*/
|
||||
int sx1302_lora_service_correlator_configure(struct lgw_conf_rxif_s * cfg);
|
||||
|
||||
/**
|
||||
@brief Configure the syncword to be used by LoRa modems (public:0x34, private:0x12)
|
||||
@param public Set to true to use the "public" syncword, false to use the private one
|
||||
@param lora_service_sf The spreading factor configured for the single-SF LoRa modem
|
||||
@return LGW_REG_SUCCESS if success, LGW_REG_ERROR otherwise
|
||||
*/
|
||||
int sx1302_lora_syncword(bool public, uint8_t lora_service_sf);
|
||||
|
||||
/**
|
||||
@brief Configure the LoRa multi-SF modems
|
||||
@param radio_freq_hz The center frequency of the RF chain (0 or 1)
|
||||
@return LGW_REG_SUCCESS if success, LGW_REG_ERROR otherwise
|
||||
*/
|
||||
int sx1302_lora_modem_configure(uint32_t radio_freq_hz);
|
||||
|
||||
/**
|
||||
@brief Configure the LoRa single-SF modem
|
||||
@param cfg A pointer to the channel configuration
|
||||
@param radio_freq_hz The center frequency of the RF chain (0 or 1)
|
||||
@return LGW_REG_SUCCESS if success, LGW_REG_ERROR otherwise
|
||||
*/
|
||||
int sx1302_lora_service_modem_configure(struct lgw_conf_rxif_s * cfg, uint32_t radio_freq_hz);
|
||||
|
||||
/**
|
||||
@brief Configure the FSK modem
|
||||
@param cfg A pointer to the channel configuration
|
||||
@return LGW_REG_SUCCESS if success, LGW_REG_ERROR otherwise
|
||||
*/
|
||||
int sx1302_fsk_configure(struct lgw_conf_rxif_s * cfg);
|
||||
|
||||
/**
|
||||
@brief Enable the modems
|
||||
@param N/A
|
||||
@return LGW_REG_SUCCESS if success, LGW_REG_ERROR otherwise
|
||||
*/
|
||||
int sx1302_modem_enable(void);
|
||||
|
||||
/**
|
||||
@brief Enable/Disable the GPS to allow PPS trigger and counter sampling
|
||||
@param enbale Set to true to enable, false otherwise
|
||||
@return LGW_REG_SUCCESS if success, LGW_REG_ERROR otherwise
|
||||
*/
|
||||
int sx1302_gps_enable(bool enable);
|
||||
|
||||
/**
|
||||
@brief Get the current SX1302 internal counter value
|
||||
@param pps True for getting the counter value at last PPS
|
||||
@return the counter value in mciroseconds (32-bits)
|
||||
*/
|
||||
uint32_t sx1302_timestamp_counter(bool pps);
|
||||
|
||||
/**
|
||||
@brief TODO
|
||||
@param TODO
|
||||
@return TODO
|
||||
*/
|
||||
int sx1302_agc_load_firmware(const uint8_t *firmware);
|
||||
|
||||
/**
|
||||
@brief TODO
|
||||
@param TODO
|
||||
@return TODO
|
||||
*/
|
||||
int sx1302_agc_status(uint8_t* status);
|
||||
|
||||
/**
|
||||
@brief TODO
|
||||
@param TODO
|
||||
@return TODO
|
||||
*/
|
||||
int sx1302_agc_wait_status(uint8_t status);
|
||||
|
||||
/**
|
||||
@brief TODO
|
||||
@param TODO
|
||||
@return TODO
|
||||
*/
|
||||
int sx1302_agc_mailbox_read(uint8_t mailbox, uint8_t* value);
|
||||
|
||||
/**
|
||||
@brief TODO
|
||||
@param TODO
|
||||
@return TODO
|
||||
*/
|
||||
int sx1302_agc_mailbox_write(uint8_t mailbox, uint8_t value);
|
||||
|
||||
/**
|
||||
@brief TODO
|
||||
@param TODO
|
||||
@return TODO
|
||||
*/
|
||||
int sx1302_agc_start(uint8_t version, lgw_radio_type_t radio_type, uint8_t ana_gain, uint8_t dec_gain, uint8_t fdd_mode);
|
||||
|
||||
/**
|
||||
@brief TODO
|
||||
@param TODO
|
||||
@return TODO
|
||||
*/
|
||||
int sx1302_arb_load_firmware(const uint8_t *firmware);
|
||||
|
||||
/**
|
||||
@brief TODO
|
||||
@param TODO
|
||||
@return TODO
|
||||
*/
|
||||
int sx1302_arb_status(uint8_t* status);
|
||||
|
||||
/**
|
||||
@brief TODO
|
||||
@param TODO
|
||||
@return TODO
|
||||
*/
|
||||
int sx1302_arb_wait_status(uint8_t status);
|
||||
|
||||
/**
|
||||
@brief TODO
|
||||
@param TODO
|
||||
@return TODO
|
||||
*/
|
||||
int sx1302_arb_debug_read(uint8_t reg_id, uint8_t* value);
|
||||
|
||||
/**
|
||||
@brief TODO
|
||||
@param TODO
|
||||
@return TODO
|
||||
*/
|
||||
int sx1302_arb_debug_write(uint8_t reg_id, uint8_t value);
|
||||
|
||||
/**
|
||||
@brief TODO
|
||||
@param TODO
|
||||
@return TODO
|
||||
*/
|
||||
int sx1302_arb_start(uint8_t version);
|
||||
|
||||
/**
|
||||
@brief TODO
|
||||
@param TODO
|
||||
@return TODO
|
||||
*/
|
||||
uint8_t sx1302_arb_get_debug_stats_detect(uint8_t channel);
|
||||
|
||||
/**
|
||||
@brief TODO
|
||||
@param TODO
|
||||
@return TODO
|
||||
*/
|
||||
uint8_t sx1302_arb_get_debug_stats_alloc(uint8_t channel);
|
||||
|
||||
/**
|
||||
@brief TODO
|
||||
@param TODO
|
||||
@return TODO
|
||||
*/
|
||||
void sx1302_arb_print_debug_stats(void);
|
||||
|
||||
/**
|
||||
@brief TODO
|
||||
@param TODO
|
||||
@return TODO
|
||||
*/
|
||||
uint16_t sx1302_lora_payload_crc(const uint8_t * data, uint8_t size);
|
||||
|
||||
/**
|
||||
@brief TODO
|
||||
@param TODO
|
||||
@return TODO
|
||||
*/
|
||||
uint16_t sx1302_rx_buffer_read_ptr_addr(void);
|
||||
|
||||
/**
|
||||
@brief TODO
|
||||
@param TODO
|
||||
@return TODO
|
||||
*/
|
||||
uint16_t sx1302_rx_buffer_write_ptr_addr(void);
|
||||
|
||||
/**
|
||||
@brief Check if any data to be fetched from the SX1302 RX buffer and fetch it if any.
|
||||
@param nb_bytes A pointer to allocated memory to hold the number of bytes fetched
|
||||
@return LGW_REG_SUCCESS if success, LGW_REG_ERROR otherwise
|
||||
*/
|
||||
int sx1302_fetch(uint16_t * nb_bytes);
|
||||
|
||||
/**
|
||||
@brief Parse and return the next packet available in the fetched RX buffer.
|
||||
@param context Gateway configuration context
|
||||
@param p The structure to get the packet parsed
|
||||
@return LGW_REG_SUCCESS if a packet could be parsed, LGW_REG_ERROR otherwise
|
||||
*/
|
||||
int sx1302_parse(lgw_context_t * context, struct lgw_pkt_rx_s * p);
|
||||
|
||||
/**
|
||||
@brief Configure the delay to be applied by the SX1302 for TX to start
|
||||
@param rf_chain The RF chain index to be configured
|
||||
@param radio_type The type of radio for this RF chain
|
||||
@param modulation The modulation used for the TX
|
||||
@param bandwidth The bandwidth used for the TX
|
||||
@return LGW_REG_SUCCESS if success, LGW_REG_ERROR otherwise
|
||||
*/
|
||||
int sx1302_tx_set_start_delay(uint8_t rf_chain, lgw_radio_type_t radio_type, uint8_t modulation, uint8_t bandwidth);
|
||||
|
||||
/**
|
||||
@brief Compute the offset to be applied on RSSI for temperature compensation
|
||||
@param context a pointer to the memory that holds the current temp comp context
|
||||
@param temperature the temperature for which to compute the offset to be applied
|
||||
@return the offset to be applied to RSSI
|
||||
*/
|
||||
float sx1302_rssi_get_temperature_offset(struct lgw_rssi_tcomp_s * context, float temperature);
|
||||
|
||||
/**
|
||||
@brief Get current TX status of the SX1302
|
||||
@param rf_chain the TX chain we want to get the status from
|
||||
@return current status
|
||||
*/
|
||||
uint8_t sx1302_tx_status(uint8_t rf_chain);
|
||||
|
||||
/**
|
||||
@brief Get current RX status of the SX1302
|
||||
@param rf_chain the RX chain we want to get the status from
|
||||
@return current status
|
||||
@note NOT IMPLEMENTED
|
||||
*/
|
||||
uint8_t sx1302_rx_status(uint8_t rf_chain);
|
||||
|
||||
/**
|
||||
@brief Abort current transmit
|
||||
@param rf_chain the TX chain on which we want to abort transmit
|
||||
@return LGW_REG_SUCCESS if success, LGW_REG_ERROR otherwise
|
||||
*/
|
||||
int sx1302_tx_abort(uint8_t rf_chain);
|
||||
|
||||
/**
|
||||
@brief TODO
|
||||
@param TODO
|
||||
@return TODO
|
||||
*/
|
||||
int sx1302_tx_configure(lgw_radio_type_t radio_type);
|
||||
|
||||
/**
|
||||
@brief TODO
|
||||
@param TODO
|
||||
@return TODO
|
||||
*/
|
||||
int sx1302_send(lgw_radio_type_t radio_type, struct lgw_tx_gain_lut_s * tx_lut, bool lwan_public, struct lgw_conf_rxif_s * context_fsk, struct lgw_pkt_tx_s * pkt_data);
|
||||
|
||||
#endif
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2019 Semtech
|
||||
|
||||
Description:
|
||||
SX1302 RX buffer Hardware Abstraction Layer
|
||||
|
||||
License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _LORAGW_SX1302_RX_H
|
||||
#define _LORAGW_SX1302_RX_H
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- DEPENDANCIES --------------------------------------------------------- */
|
||||
|
||||
#include <stdint.h> /* C99 types*/
|
||||
|
||||
#include "config.h" /* library configuration options (dynamically generated) */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PUBLIC CONSTANTS ----------------------------------------------------- */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PUBLIC MACROS -------------------------------------------------------- */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PUBLIC TYPES --------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
@struct rx_packet_s
|
||||
@brief packet structure as contained in the sx1302 RX packet engine
|
||||
*/
|
||||
typedef struct rx_packet_s {
|
||||
uint8_t rxbytenb_modem;
|
||||
uint8_t rx_channel_in;
|
||||
bool crc_en;
|
||||
uint8_t coding_rate; /* LoRa only */
|
||||
uint8_t rx_rate_sf; /* LoRa only */
|
||||
uint8_t modem_id;
|
||||
int32_t frequency_offset_error; /* LoRa only */
|
||||
uint8_t payload[255];
|
||||
bool payload_crc_error;
|
||||
bool sync_error; /* LoRa only */
|
||||
bool header_error; /* LoRa only */
|
||||
bool timing_set; /* LoRa only */
|
||||
int8_t snr_average; /* LoRa only */
|
||||
uint8_t rssi_chan_avg;
|
||||
uint8_t rssi_signal_avg; /* LoRa only */
|
||||
uint8_t rssi_chan_max_neg_delta;
|
||||
uint8_t rssi_chan_max_pos_delta;
|
||||
uint8_t rssi_sig_max_neg_delta; /* LoRa only */
|
||||
uint8_t rssi_sig_max_pos_delta; /* LoRa only */
|
||||
uint32_t timestamp_cnt;
|
||||
uint16_t rx_crc16_value; /* LoRa only */
|
||||
uint8_t num_ts_metrics_stored; /* LoRa only */
|
||||
uint8_t timestamp_avg[255]; /* LoRa only */
|
||||
uint8_t timestamp_stddev[255]; /* LoRa only */
|
||||
uint8_t packet_checksum;
|
||||
} rx_packet_t;
|
||||
|
||||
/**
|
||||
@struct rx_buffer_s
|
||||
@brief buffer to hold the data fetched from the sx1302 RX buffer
|
||||
*/
|
||||
typedef struct rx_buffer_s {
|
||||
uint8_t buffer[4096]; /*!> byte array to hald the data fetched from the RX buffer */
|
||||
uint16_t buffer_size; /*!> The number of bytes currently stored in the buffer */
|
||||
int buffer_index; /*!> Current parsing index in the buffer */
|
||||
} rx_buffer_t;
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PUBLIC FUNCTIONS PROTOTYPES ------------------------------------------ */
|
||||
|
||||
/**
|
||||
@brief TODO
|
||||
@param TODO
|
||||
@return TODO
|
||||
*/
|
||||
int rx_buffer_new(rx_buffer_t * self);
|
||||
|
||||
/**
|
||||
@brief TODO
|
||||
@param TODO
|
||||
@return TODO
|
||||
*/
|
||||
int rx_buffer_del(rx_buffer_t * self);
|
||||
|
||||
/**
|
||||
@brief TODO
|
||||
@param TODO
|
||||
@return TODO
|
||||
*/
|
||||
int rx_buffer_fetch(rx_buffer_t * self);
|
||||
|
||||
/**
|
||||
@brief TODO
|
||||
@param TODO
|
||||
@return TODO
|
||||
*/
|
||||
int rx_buffer_pop(rx_buffer_t * self, rx_packet_t * pkt);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- DEBUG FUNCTIONS PROTOTYPES ------------------------------------------- */
|
||||
|
||||
/**
|
||||
@brief TODO
|
||||
@param TODO
|
||||
@return TODO
|
||||
*/
|
||||
uint16_t rx_buffer_read_ptr_addr(void);
|
||||
|
||||
/**
|
||||
@brief TODO
|
||||
@param TODO
|
||||
@return TODO
|
||||
*/
|
||||
uint16_t rx_buffer_write_ptr_addr(void);
|
||||
|
||||
/**
|
||||
@brief TODO
|
||||
@param TODO
|
||||
@return TODO
|
||||
*/
|
||||
void rx_buffer_dump(FILE * file, uint16_t start_addr, uint16_t end_addr);
|
||||
|
||||
#endif
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2019 Semtech
|
||||
|
||||
Description:
|
||||
SX1302 timestamp counter Hardware Abstraction Layer
|
||||
Handles the conversion of a 32-bits 32MHz counter into a 32-bits 1 MHz counter.
|
||||
This modules MUST be called regularly by the application to maintain counter
|
||||
wrapping handling for conversion in 1MHz counter.
|
||||
Provides function to compute the correction to be applied to the received
|
||||
timestamp for demodulation processing time.
|
||||
|
||||
License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _LORAGW_SX1302_TIMESTAMP_H
|
||||
#define _LORAGW_SX1302_TIMESTAMP_H
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- DEPENDANCIES --------------------------------------------------------- */
|
||||
|
||||
#include <stdint.h> /* C99 types*/
|
||||
#include <stdbool.h> /* boolean type */
|
||||
|
||||
|
||||
#include "config.h" /* library configuration options (dynamically generated) */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PUBLIC CONSTANTS ----------------------------------------------------- */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PUBLIC MACROS -------------------------------------------------------- */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PUBLIC TYPES --------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
@struct timestamp_counter_s
|
||||
@brief context to maintain the internal counters (inst and pps trig) wrapping
|
||||
*/
|
||||
typedef struct timestamp_counter_s {
|
||||
uint32_t counter_us_raw_27bits_inst_prev;
|
||||
uint32_t counter_us_raw_27bits_pps_prev;
|
||||
uint8_t counter_us_raw_27bits_inst_wrap;
|
||||
uint8_t counter_us_raw_27bits_pps_wrap;
|
||||
} timestamp_counter_t;
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PUBLIC FUNCTIONS ----------------------------------------------------- */
|
||||
|
||||
/**
|
||||
@brief TODO
|
||||
@param TODO
|
||||
@return TODO
|
||||
*/
|
||||
void timestamp_counter_new(timestamp_counter_t * self);
|
||||
|
||||
/**
|
||||
@brief TODO
|
||||
@param TODO
|
||||
@return TODO
|
||||
*/
|
||||
void timestamp_counter_delete(timestamp_counter_t * self);
|
||||
|
||||
/**
|
||||
@brief Update the counter wrapping status based on given current counter
|
||||
@param self Pointer to the counter handler
|
||||
@param pps Set to true to update the PPS trig counter status
|
||||
@param cnt Current value of the counter to be used for the update
|
||||
@return N/A
|
||||
*/
|
||||
void timestamp_counter_update(timestamp_counter_t * self, bool pps, uint32_t cnt);
|
||||
|
||||
/**
|
||||
@brief Convert the 27-bits counter given by the SX1302 to a 32-bits counter which wraps on a uint32_t.
|
||||
@param self Pointer to the counter handler
|
||||
@param pps Set to true to expand the counter based on the PPS trig wrapping status
|
||||
@param cnt_us The 27-bits counter to be expanded
|
||||
@return the 32-bits counter
|
||||
*/
|
||||
uint32_t timestamp_counter_expand(timestamp_counter_t * self, bool pps, uint32_t cnt_us);
|
||||
|
||||
/**
|
||||
@brief Reads the SX1302 internal counter register, and return the 32-bits 1 MHz counter
|
||||
@param self Pointer to the counter handler
|
||||
@param pps Set to true to expand the counter based on the PPS trig wrapping status
|
||||
@return the current 32-bits counter
|
||||
*/
|
||||
uint32_t timestamp_counter_get(timestamp_counter_t * self, bool pps);
|
||||
|
||||
/**
|
||||
@brief Get the timestamp correction to applied to the packet timestamp
|
||||
@param ifmod modem type
|
||||
@param bandwidth modulation bandwidth
|
||||
@param datarate modulation datarate
|
||||
@param coderate modulation coding rate
|
||||
@param crc_en indicates if CRC is enabled or disabled
|
||||
@param payload_length payload length
|
||||
@return The correction to be applied to the packet timestamp, in microseconds
|
||||
*/
|
||||
uint32_t timestamp_counter_correction(int ifmod, uint8_t bandwidth, uint8_t datarate, uint8_t coderate, uint32_t crc_en, uint16_t payload_length);
|
||||
|
||||
/**
|
||||
@brief TODO
|
||||
@param TODO
|
||||
@return TODO
|
||||
*/
|
||||
int timestamp_counter_mode(bool enable_precision_ts, uint8_t max_ts_metrics, uint8_t nb_symbols);
|
||||
|
||||
#endif
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
|
@ -0,0 +1,19 @@
|
|||
# That file will be included in the Makefile files that have hardware dependencies
|
||||
|
||||
### Debug options ###
|
||||
# Set the DEBUG_* to 1 to activate debug mode in individual modules.
|
||||
# Warning: that makes the module *very verbose*, do not use for production
|
||||
|
||||
DEBUG_AUX= 0
|
||||
DEBUG_SPI= 0
|
||||
DEBUG_REG= 0
|
||||
DEBUG_HAL= 0
|
||||
DEBUG_LBT= 0
|
||||
DEBUG_GPS= 0
|
||||
DEBUG_RAD= 0
|
||||
DEBUG_CAL= 0
|
||||
DEBUG_SX1302= 0
|
||||
|
||||
### Configuration options ###
|
||||
BYPASS_FW_INIT = 0
|
||||
FPGA_BOARD_16_CH = 1
|
|
@ -0,0 +1,393 @@
|
|||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2019 Semtech
|
||||
|
||||
LoRa concentrator HAL user manual
|
||||
=================================
|
||||
|
||||
## 1. Introduction
|
||||
|
||||
The LoRa concentrator Hardware Abstraction Layer is a C library that allow you
|
||||
to use a Semtech concentrator chip through a reduced number of high level C
|
||||
functions to configure the hardware, send and receive packets.
|
||||
|
||||
The Semtech LoRa concentrator 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 the following modules:
|
||||
|
||||
* loragw_hal
|
||||
* loragw_reg
|
||||
* loragw_spi
|
||||
* loragw_i2c
|
||||
* loragw_aux
|
||||
* loragw_gps
|
||||
* loragw_sx125x
|
||||
* loragw_sx1250
|
||||
* loragw_sx1302
|
||||
* loragw_sx1302_rx
|
||||
* loragw_sx1302_timestamp
|
||||
* loragw_stts751
|
||||
|
||||
The library also contains basic test programs 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 concentrator:
|
||||
|
||||
* lgw_board_setconf, to set the configuration of the concentrator
|
||||
* lgw_rxrf_setconf, to set the configuration of the radio channels
|
||||
* lgw_rxif_setconf, to set the configuration of the IF+modem channels
|
||||
* lgw_txgain_setconf, to set the configuration of the concentrator gain table
|
||||
* 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.
|
||||
|
||||
/!\ When sending a packet, there is a delay (approx 1.5ms) for the analog
|
||||
circuitry to start and be stable. This delay is adjusted by the HAL depending
|
||||
on the board version (lgw_i_tx_start_delay_us).
|
||||
|
||||
In 'timestamp' mode, this is transparent: the modem is started
|
||||
lgw_i_tx_start_delay_us microseconds before the user-set timestamp value is
|
||||
reached, the preamble of the packet start right when the internal timestamp
|
||||
counter reach target value.
|
||||
|
||||
In 'immediate' mode, the packet is emitted as soon as possible: transferring the
|
||||
packet (and its parameters) from the host to the concentrator takes some time,
|
||||
then there is the lgw_i_tx_start_delay_us, then the packet is emitted.
|
||||
|
||||
In 'triggered' mode (aka PPS/GPS mode), the packet, typically a beacon, is
|
||||
emitted lgw_i_tx_start_delay_us microsenconds after a rising edge of the
|
||||
trigger signal. Because there is no way to anticipate the triggering event and
|
||||
start the analog circuitry beforehand, that delay must be taken into account in
|
||||
the protocol.
|
||||
|
||||
### 2.2. loragw_reg
|
||||
|
||||
This module is used to access to the LoRa concentrator 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_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 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
|
||||
concentrator inner working before accessing the internal registers directly.
|
||||
|
||||
### 2.3. loragw_spi
|
||||
|
||||
This module contains the functions to access the LoRa concentrator 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 concentrator 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 concentrator 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 does not 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.
|
||||
|
||||
### 2.5. loragw_gps
|
||||
|
||||
This module contains functions to synchronize the concentrator internal
|
||||
counter with an absolute time reference, in our case a GPS satellite receiver.
|
||||
|
||||
The internal concentrator counter is used to timestamp incoming packets and to
|
||||
triggers outgoing packets with a microsecond accuracy.
|
||||
In some cases, it might be useful to be able to transform that internal
|
||||
timestamp (that is independent for each concentrator running in a typical
|
||||
networked system) into an absolute GPS time.
|
||||
|
||||
In a typical implementation a GPS specific thread will be called, doing the
|
||||
following things after opening the serial port:
|
||||
|
||||
* blocking reads on the serial port (using system read() function)
|
||||
* parse UBX messages (using lgw_parse_ubx) to get actual native GPS time
|
||||
* parse NMEA sentences (using lgw_parse_nmea) to get location and UTC time
|
||||
Note: the RMC sentence gives UTC time, not native GPS time.
|
||||
|
||||
And each time an NAV-TIMEGPS UBX message has been received:
|
||||
|
||||
* get the concentrator timestamp (using lgw_get_trigcnt, mutex needed to
|
||||
protect access to the concentrator)
|
||||
* get the GPS time contained in the UBX message (using lgw_gps_get)
|
||||
* call the lgw_gps_sync function (use mutex to protect the time reference that
|
||||
should be a global shared variable).
|
||||
|
||||
Then, in other threads, you can simply used that continuously adjusted time
|
||||
reference to convert internal timestamps to GPS time (using lgw_cnt2gps) or
|
||||
the other way around (using lgw_gps2cnt). Inernal concentrator timestamp can
|
||||
also be converted to/from UTC time using lgw_cnt2utc/lgw_utc2cnt functions.
|
||||
|
||||
### 2.6. loragw_sx125x
|
||||
|
||||
This module contains functions to handle the configuration of SX1255 and
|
||||
SX1257 radios.
|
||||
|
||||
### 2.7. loragw_sx1250
|
||||
|
||||
This module contains functions to handle the configuration of SX1250 radios.
|
||||
|
||||
### 2.8. loragw_sx1302
|
||||
|
||||
This module contains functions to abstract SX1302 concentrator capabilities.
|
||||
|
||||
### 2.9. loragw_sx1302_rx
|
||||
|
||||
This module is a sub-module of the loragw_sx1302 module focusing on abstracting
|
||||
the RX buffer of the SX1302.
|
||||
|
||||
### 2.10. loragw_sx1302_timestamp
|
||||
|
||||
This module is a sub-module of the loragw_sx1302 module focusing on abstracting
|
||||
the timestamp counter of the SX1302.
|
||||
It converts the 32-bits 32MHz internal counter of the SX1302 to a 32-bits 1MHz
|
||||
counter.
|
||||
This module needs to be called regularly by upper layers to maintain counter
|
||||
wrapping when converting from 32MHz to 1MHz.
|
||||
It also provides function to add correction to the timestamp counter to take
|
||||
into account the LoRa demodulation processing time.
|
||||
|
||||
### 2.11. loragw_stts751
|
||||
|
||||
This module contains a very basic driver for the STmicroelectronics ST751
|
||||
temeprature sensor which is on the CoreCell reference design.
|
||||
|
||||
### 2.12. loragw_i2c
|
||||
|
||||
This module provides basic function to communicate with I2C devices on the board.
|
||||
It is used in this project for accessing the temperature sensor.
|
||||
|
||||
## 3. Software build process
|
||||
|
||||
### 3.1. Details of the software
|
||||
|
||||
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 timers.
|
||||
|
||||
### 3.2. Building options
|
||||
|
||||
All modules use a fprintf(stderr,...) function to display debug diagnostic
|
||||
messages if the DEBUG_xxx is set to 1 in library.cfg
|
||||
|
||||
### 3.3. Building procedures
|
||||
|
||||
For cross-compilation set the ARCH and CROSS_COMPILE variables in the Makefile,
|
||||
or in your shell environment, with the correct toolchain name and path.
|
||||
ex:
|
||||
export PATH=/home/foo/rpi-toolchain/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin:$PATH
|
||||
export ARCH=arm
|
||||
export CROSS_COMPILE=arm-linux-gnueabihf-
|
||||
|
||||
The Makefile in the libloragw directory will parse the library.cfg file and
|
||||
generate a config.h C header file containing #define options.
|
||||
Those options enables and disables sections of code in the loragw_xxx.h files
|
||||
and the *.c source files.
|
||||
|
||||
The library.cfg is also used directly to select the proper set of dynamic
|
||||
libraries to be linked with.
|
||||
|
||||
### 3.4. Export
|
||||
|
||||
Once build, to use that library on another system, you need to export the
|
||||
following files :
|
||||
|
||||
* libloragw/library.cfg -> root configuration file
|
||||
* libloragw/libloragw.a -> static library, to be linked with a program
|
||||
* libloragw/readme.md -> required for license compliance
|
||||
* libloragw/inc/config.h -> C configuration flags, derived from library.cfg
|
||||
* libloragw/inc/loragw_*.h -> take only the ones you need (eg. _hal and _gps)
|
||||
|
||||
After statically linking the library to your application, only the license
|
||||
is required to be kept or copied inside your program documentation.
|
||||
|
||||
## 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).
|
||||
|
||||
This code has been written for:
|
||||
|
||||
* Semtech SX1302 chip
|
||||
* Semtech SX1250, SX1257 or SX1255 I/Q transceivers
|
||||
|
||||
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 (not provided)
|
||||
* native SPI using a microcontroller peripheral (not provided)
|
||||
|
||||
You can use the test program test_loragw_spi to check with a logic analyser
|
||||
that the SPI communication is working
|
||||
|
||||
### 4.3. GPS receiver (or other GNSS system)
|
||||
|
||||
To use the GPS module of the library, the host must be connected to a GPS
|
||||
receiver via a serial link (or an equivalent receiver using a different
|
||||
satellite constellation).
|
||||
The serial link must appear as a "tty" device in the /dev/ directory, and the
|
||||
user launching the program must have the proper system rights to read and
|
||||
write on that device.
|
||||
Use `chmod a+rw` to allow all users to access that specific tty device, or use
|
||||
sudo to run all your programs (eg. `sudo ./test_loragw_gps`).
|
||||
|
||||
In the current revision, the library only reads data from the serial port,
|
||||
expecting to receive NMEA frames that are generally sent by GPS receivers as
|
||||
soon as they are powered up, and UBX messages which are proprietary to u-blox
|
||||
modules.
|
||||
|
||||
The GPS receiver **MUST** send UBX messages shortly after sending a PPS pulse
|
||||
on to allow internal concentrator timestamps to be converted to absolute GPS time.
|
||||
If the GPS receiver sends a GGA NMEA sentence, the gateway 3D position will
|
||||
also be available.
|
||||
|
||||
## 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)
|
||||
|
||||
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 concentrator is started
|
||||
* you cannot send packets until one (or +) radio is enabled AND the concentrator
|
||||
is started
|
||||
* you must stop the concentrator before changing the configuration
|
||||
|
||||
A typical application flow for using the HAL is the following:
|
||||
|
||||
<configure the radios and IF+modems>
|
||||
<start the LoRa concentrator>
|
||||
loop {
|
||||
<fetch packets that were received by the concentrator>
|
||||
<process, store and/or forward received packets>
|
||||
<send packets through the concentrator>
|
||||
}
|
||||
<stop the concentrator>
|
||||
|
||||
**/!\ Warning** The lgw_send function is non-blocking and returns while the
|
||||
LoRa concentrator 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*.
|
||||
|
||||
## 6. License
|
||||
|
||||
Copyright (c) 2019, SEMTECH S.A.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the Semtech corporation nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL SEMTECH S.A. BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*EOF*
|
|
@ -0,0 +1,514 @@
|
|||
static uint8_t agc_firmware_sx1250[8192] = {
|
||||
0x8A, 0x51, 0xF0, 0x6F, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 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,
|
||||
0x12, 0x28, 0xE5, 0x40, 0xCA, 0x00, 0x61, 0x08, 0xCB, 0x40, 0x62, 0x08, 0xCC, 0x00, 0x63, 0x48,
|
||||
0xCD, 0x40, 0x4A, 0x70, 0xDC, 0x40, 0x64, 0x08, 0xDD, 0x80, 0x04, 0xF0, 0x32, 0x2F, 0x1D, 0xB0,
|
||||
0xCA, 0x00, 0x08, 0xF0, 0xCB, 0x40, 0x8B, 0xB0, 0xCC, 0x00, 0x4A, 0x70, 0xCD, 0x81, 0xCE, 0x81,
|
||||
0xCF, 0xC1, 0xD0, 0x01, 0xD1, 0x41, 0xDC, 0x40, 0x08, 0xF0, 0xDD, 0xC1, 0x6B, 0x67, 0x8A, 0x51,
|
||||
0x4D, 0x48, 0x83, 0x96, 0xBA, 0x40, 0x83, 0x52, 0x4C, 0x08, 0x83, 0x96, 0xB9, 0x40, 0x83, 0x52,
|
||||
0x4B, 0x48, 0x83, 0x96, 0xB8, 0x00, 0x83, 0x52, 0x4A, 0x08, 0x83, 0x96, 0xB7, 0x80, 0x1D, 0xB0,
|
||||
0x83, 0x52, 0xCA, 0x00, 0x08, 0xF0, 0xCB, 0x40, 0x8B, 0xB0, 0xCC, 0x00, 0x4A, 0x70, 0xCD, 0x81,
|
||||
0xCE, 0x81, 0xCF, 0xC1, 0xD0, 0x01, 0xD1, 0x41, 0xDC, 0x40, 0x08, 0xF0, 0xDD, 0xC1, 0xDD, 0x0A,
|
||||
0x6B, 0x67, 0x4D, 0x48, 0x83, 0x96, 0xBE, 0x80, 0x83, 0x52, 0x4C, 0x08, 0x83, 0x96, 0xBD, 0x80,
|
||||
0x83, 0x52, 0x4B, 0x48, 0x83, 0x96, 0xBC, 0x40, 0x83, 0x52, 0x4A, 0x08, 0x83, 0x96, 0xBB, 0x80,
|
||||
0x08, 0x40, 0xE3, 0x40, 0xC1, 0x70, 0xCA, 0x00, 0x4A, 0x70, 0xDC, 0x40, 0x63, 0x48, 0xDD, 0x80,
|
||||
0x01, 0xF0, 0x32, 0xE7, 0x8A, 0x51, 0x07, 0x70, 0xE2, 0x00, 0x3A, 0xB0, 0xE1, 0x00, 0xE1, 0xCB,
|
||||
0x77, 0x28, 0xE2, 0xCB, 0x77, 0x28, 0x00, 0x00, 0x0D, 0x70, 0x83, 0x52, 0x03, 0x53, 0xCA, 0x00,
|
||||
0x05, 0x30, 0xCB, 0x40, 0x84, 0x30, 0xCC, 0x00, 0x4A, 0x70, 0xCD, 0x81, 0xDC, 0x40, 0x63, 0x48,
|
||||
0xDD, 0x80, 0x04, 0xF0, 0x32, 0xE7, 0x8A, 0x51, 0x0D, 0x70, 0xCA, 0x00, 0x05, 0x30, 0xCB, 0x40,
|
||||
0x85, 0x70, 0xCC, 0x00, 0x4A, 0x70, 0xCD, 0x81, 0xDC, 0x40, 0x63, 0x48, 0xDD, 0x80, 0x04, 0xF0,
|
||||
0x32, 0xE7, 0x8A, 0x51, 0x0D, 0x70, 0xCA, 0x00, 0x05, 0x30, 0xCB, 0x40, 0x82, 0x30, 0xCC, 0x00,
|
||||
0x4A, 0x70, 0xCD, 0x81, 0xDC, 0x40, 0x63, 0x48, 0xDD, 0x80, 0x04, 0xF0, 0x32, 0xE7, 0x8A, 0x51,
|
||||
0x0D, 0x70, 0xCA, 0x00, 0x05, 0x30, 0xCB, 0x40, 0x80, 0xF0, 0xCC, 0x00, 0x4A, 0x70, 0xCD, 0x81,
|
||||
0xDC, 0x40, 0x63, 0x48, 0xDD, 0x80, 0x04, 0xF0, 0x32, 0xE7, 0x8A, 0x51, 0x0D, 0x70, 0xCA, 0x00,
|
||||
0x05, 0x30, 0xCB, 0x40, 0x83, 0x70, 0xCC, 0x00, 0x4A, 0x70, 0xCD, 0x81, 0xDC, 0x40, 0x63, 0x48,
|
||||
0xDD, 0x80, 0x04, 0xF0, 0x32, 0xE7, 0x8A, 0x51, 0x63, 0x83, 0x03, 0x9D, 0xC9, 0xA8, 0x9C, 0x91,
|
||||
0xCA, 0xA8, 0x1C, 0x51, 0x05, 0x30, 0xE1, 0x00, 0xE1, 0xCB, 0xCC, 0xA8, 0x0D, 0x70, 0x83, 0x52,
|
||||
0x03, 0x53, 0xCA, 0x00, 0x05, 0x30, 0xCB, 0x40, 0x87, 0xB0, 0xCC, 0x00, 0x0B, 0x70, 0xCD, 0x40,
|
||||
0x4A, 0x70, 0xDC, 0x40, 0x63, 0x48, 0xDD, 0x80, 0x04, 0xF0, 0x32, 0xE7, 0x8A, 0x51, 0x00, 0xB0,
|
||||
0xE3, 0x88, 0x03, 0x9D, 0xE8, 0xA8, 0x2A, 0xE7, 0x8A, 0x51, 0xC9, 0x00, 0xF3, 0x30, 0xEC, 0xE8,
|
||||
0x2A, 0xE7, 0x8A, 0x51, 0xC9, 0x00, 0x3F, 0x30, 0xC9, 0x85, 0x49, 0x08, 0xDC, 0x40, 0x00, 0xB0,
|
||||
0x22, 0xA7, 0x8A, 0x51, 0x63, 0x98, 0xFB, 0x68, 0x00, 0xB0, 0x2A, 0xE7, 0x8A, 0x51, 0xC9, 0x00,
|
||||
0xFE, 0xF9, 0x01, 0x38, 0x01, 0x29, 0x00, 0xB0, 0x2A, 0xE7, 0x8A, 0x51, 0xC9, 0x00, 0xEF, 0xF9,
|
||||
0x10, 0x38, 0xC9, 0x00, 0xDC, 0x40, 0x00, 0xB0, 0x22, 0xA7, 0x8A, 0x51, 0x00, 0xB0, 0x2A, 0xE7,
|
||||
0x8A, 0x51, 0xC9, 0x00, 0xC9, 0x50, 0x49, 0x08, 0xDC, 0x40, 0x00, 0xB0, 0x22, 0xA7, 0x8A, 0x51,
|
||||
0x00, 0xB0, 0x2A, 0xE7, 0x8A, 0x51, 0xC9, 0x00, 0xC9, 0x92, 0x49, 0x08, 0xDC, 0x40, 0x00, 0xB0,
|
||||
0x22, 0xA7, 0x8A, 0x51, 0x86, 0x70, 0xCA, 0x00, 0xE3, 0x88, 0x03, 0x9D, 0x2E, 0xE9, 0x83, 0x96,
|
||||
0x3A, 0x48, 0x83, 0x52, 0xCB, 0x40, 0x83, 0x96, 0x39, 0x48, 0x83, 0x52, 0xCC, 0x00, 0x83, 0x96,
|
||||
0x38, 0x08, 0x83, 0x52, 0xCD, 0x40, 0x83, 0x96, 0x37, 0x88, 0x3C, 0xE9, 0x83, 0x96, 0x3E, 0x88,
|
||||
0x83, 0x52, 0xCB, 0x40, 0x83, 0x96, 0x3D, 0x88, 0x83, 0x52, 0xCC, 0x00, 0x83, 0x96, 0x3C, 0x48,
|
||||
0x83, 0x52, 0xCD, 0x40, 0x83, 0x96, 0x3B, 0x88, 0x83, 0x52, 0xCE, 0x40, 0x4A, 0x70, 0xDC, 0x40,
|
||||
0x63, 0x48, 0xDD, 0x80, 0x05, 0x30, 0x32, 0xE7, 0x8A, 0x51, 0x0D, 0x70, 0xCA, 0x00, 0x08, 0xF0,
|
||||
0xCB, 0x40, 0x8F, 0xF0, 0xCC, 0x00, 0x4A, 0x70, 0xCD, 0x81, 0xCE, 0x81, 0xCF, 0xC1, 0xDC, 0x40,
|
||||
0x63, 0x48, 0xDD, 0x80, 0x06, 0x30, 0x32, 0xE7, 0x8A, 0x51, 0x82, 0x30, 0xCA, 0x00, 0xFF, 0xB0,
|
||||
0xCB, 0x40, 0xCC, 0x00, 0xCD, 0x40, 0x4A, 0x70, 0xDC, 0x40, 0x63, 0x48, 0xDD, 0x80, 0x04, 0xF0,
|
||||
0x32, 0xE7, 0x8A, 0x51, 0xC7, 0xF0, 0xE1, 0x00, 0x00, 0x00, 0xE1, 0xCB, 0x64, 0xA9, 0x68, 0xA9,
|
||||
0x00, 0x00, 0x08, 0x40, 0xEC, 0x40, 0xC1, 0x70, 0xCA, 0x00, 0x4A, 0x70, 0xDC, 0x40, 0x6C, 0x48,
|
||||
0xDD, 0x80, 0x01, 0xF0, 0x32, 0xE7, 0x8A, 0x51, 0x9F, 0x30, 0xE1, 0x00, 0xE1, 0xCB, 0x76, 0x29,
|
||||
0x79, 0x29, 0x95, 0xB0, 0x83, 0x52, 0x03, 0x53, 0xCA, 0x00, 0x42, 0xC8, 0xCB, 0x40, 0x41, 0xC8,
|
||||
0xCC, 0x00, 0x40, 0x88, 0xCD, 0x40, 0x4A, 0x70, 0xCE, 0x81, 0xCE, 0xCA, 0xDC, 0x40, 0x6C, 0x48,
|
||||
0xDD, 0x80, 0x05, 0x30, 0x32, 0xE7, 0x8A, 0x51, 0xEC, 0x88, 0x03, 0x9D, 0x91, 0xA9, 0x25, 0x70,
|
||||
0x92, 0xA9, 0x2A, 0x70, 0x2A, 0xE7, 0x8A, 0x51, 0xEB, 0x80, 0xEA, 0x40, 0x3F, 0x30, 0xEA, 0xC5,
|
||||
0x8E, 0xB0, 0xCA, 0x00, 0x6A, 0x48, 0xCB, 0x40, 0x02, 0xF0, 0xCC, 0x00, 0x4A, 0x70, 0xDC, 0x40,
|
||||
0x6C, 0x48, 0xDD, 0x80, 0x03, 0x30, 0x32, 0xE7, 0x8A, 0x51, 0x6B, 0x88, 0xE1, 0x00, 0x06, 0x30,
|
||||
0x03, 0xD0, 0xE1, 0x8C, 0xFF, 0x7E, 0x03, 0x9D, 0xA8, 0xA9, 0x61, 0x08, 0xEA, 0x40, 0x03, 0x30,
|
||||
0xEA, 0xC5, 0x00, 0xB0, 0xEC, 0x88, 0x03, 0x9D, 0xC1, 0xA9, 0x2A, 0xE7, 0x8A, 0x51, 0xC9, 0x00,
|
||||
0x6A, 0x48, 0xE1, 0x00, 0x03, 0xD0, 0xE1, 0xCD, 0x03, 0xD0, 0xE1, 0xCD, 0x49, 0x08, 0xF3, 0xB9,
|
||||
0xCE, 0x29, 0x2A, 0xE7, 0x8A, 0x51, 0xC9, 0x00, 0x6A, 0x48, 0xE1, 0x00, 0x06, 0x30, 0x03, 0xD0,
|
||||
0xE1, 0xCD, 0xFF, 0x7E, 0x03, 0x9D, 0xC7, 0x29, 0x49, 0x08, 0x3F, 0xB9, 0x61, 0x04, 0xC9, 0x00,
|
||||
0xDC, 0x40, 0x00, 0xB0, 0x22, 0xA7, 0x8A, 0x51, 0xEC, 0x88, 0x03, 0x9D, 0xE1, 0xE9, 0x27, 0xB0,
|
||||
0x2A, 0xE7, 0x8A, 0x51, 0xEA, 0x40, 0x28, 0x30, 0x2A, 0xE7, 0x8A, 0x51, 0xEB, 0x80, 0x29, 0x70,
|
||||
0xEA, 0x29, 0x2C, 0x70, 0x2A, 0xE7, 0x8A, 0x51, 0xEA, 0x40, 0x2D, 0xB0, 0x2A, 0xE7, 0x8A, 0x51,
|
||||
0xEB, 0x80, 0x2E, 0xB0, 0x2A, 0xE7, 0x8A, 0x51, 0xE3, 0x40, 0x86, 0x70, 0xCA, 0x00, 0x03, 0xD0,
|
||||
0x6A, 0x8C, 0xCB, 0x40, 0x6B, 0x88, 0xE1, 0x00, 0x03, 0xD0, 0xE1, 0x8C, 0x6A, 0x48, 0xE2, 0x00,
|
||||
0x06, 0x30, 0x03, 0xD0, 0xE2, 0xCD, 0xFF, 0x7E, 0x03, 0xD0, 0x03, 0x9D, 0xFA, 0x69, 0x62, 0x8D,
|
||||
0x61, 0x04, 0xCC, 0x00, 0x63, 0x48, 0xE1, 0x00, 0x03, 0xD0, 0xE1, 0x8C, 0x6B, 0x88, 0xE2, 0x00,
|
||||
0x06, 0x30, 0x03, 0xD0, 0xE2, 0xCD, 0xFF, 0x7E, 0x03, 0xD0, 0x03, 0x9D, 0x0A, 0x6A, 0x62, 0x8D,
|
||||
0x61, 0x04, 0xCD, 0x40, 0x63, 0x48, 0xE1, 0x00, 0x06, 0x30, 0x03, 0xD0, 0xE1, 0xCD, 0xFF, 0x7E,
|
||||
0x03, 0xD0, 0x03, 0x9D, 0x16, 0xAA, 0x61, 0x8D, 0xCE, 0x40, 0x4A, 0x70, 0xDC, 0x40, 0x6C, 0x48,
|
||||
0xDD, 0x80, 0x05, 0x30, 0x32, 0xE7, 0x8A, 0x51, 0xE6, 0x81, 0x02, 0xF0, 0x66, 0x42, 0x03, 0x18,
|
||||
0x45, 0xAA, 0xC7, 0xF0, 0xE1, 0x00, 0x00, 0x00, 0xE1, 0xCB, 0x2B, 0xEA, 0x2F, 0x2A, 0x00, 0x00,
|
||||
0x1D, 0xB0, 0x83, 0x52, 0x03, 0x53, 0xCA, 0x00, 0x08, 0xF0, 0xCB, 0x40, 0xC8, 0x70, 0xCC, 0x00,
|
||||
0x4A, 0x70, 0xCD, 0x81, 0xCE, 0x81, 0xDC, 0x40, 0x6C, 0x48, 0xDD, 0x80, 0x05, 0x30, 0x6B, 0x67,
|
||||
0x8A, 0x51, 0xCA, 0xDA, 0x45, 0xAA, 0xE6, 0xCA, 0x25, 0xAA, 0x4A, 0x08, 0x20, 0x79, 0x66, 0x44,
|
||||
0xDC, 0x40, 0x1C, 0x70, 0x22, 0xA7, 0x8A, 0x51, 0x1D, 0xB0, 0xCA, 0x00, 0x08, 0xF0, 0xCB, 0x40,
|
||||
0xDD, 0x30, 0xCC, 0x00, 0x4A, 0x70, 0xCD, 0x81, 0xCE, 0x81, 0xDC, 0x40, 0x6C, 0x48, 0xDD, 0x80,
|
||||
0x05, 0x30, 0x6B, 0x67, 0x8A, 0x51, 0x4A, 0x08, 0xDC, 0x40, 0x1B, 0xB0, 0x22, 0xA7, 0x8A, 0x51,
|
||||
0x4A, 0x08, 0xE9, 0x40, 0x07, 0x70, 0xE9, 0xC5, 0x04, 0xF0, 0x69, 0x42, 0x03, 0x5C, 0x6A, 0xEA,
|
||||
0x04, 0xF0, 0xE9, 0x40, 0xEC, 0x88, 0x03, 0x9D, 0x74, 0xEA, 0x69, 0x48, 0xDC, 0x40, 0x1D, 0xB0,
|
||||
0x22, 0xA7, 0x8A, 0x51, 0x26, 0x70, 0x7B, 0x6A, 0x69, 0xCE, 0xF0, 0x39, 0xDC, 0x40, 0x1D, 0xB0,
|
||||
0x22, 0xA7, 0x8A, 0x51, 0x2B, 0xB0, 0x2A, 0xE7, 0x8A, 0x51, 0xEA, 0x40, 0xEA, 0x9F, 0x39, 0x2B,
|
||||
0x3D, 0xF0, 0x2A, 0xE7, 0x8A, 0x51, 0xEB, 0x80, 0x3E, 0xF0, 0x2A, 0xE7, 0x8A, 0x51, 0xEA, 0x40,
|
||||
0x06, 0x30, 0xDC, 0x40, 0x69, 0x48, 0xC6, 0x27, 0x01, 0xBE, 0x84, 0x80, 0x8A, 0x95, 0x00, 0x60,
|
||||
0x8A, 0x51, 0xE8, 0x00, 0x06, 0x30, 0xDC, 0x40, 0x69, 0x48, 0xC6, 0x27, 0x02, 0xBE, 0x84, 0x80,
|
||||
0x8A, 0x95, 0x00, 0x60, 0x8A, 0x51, 0xE7, 0x80, 0x6B, 0x88, 0x68, 0x02, 0x03, 0x5C, 0xA8, 0xAA,
|
||||
0x6B, 0x88, 0x68, 0x46, 0x03, 0x9D, 0xCD, 0x2A, 0x6A, 0x48, 0x67, 0x82, 0x03, 0x18, 0xCD, 0x2A,
|
||||
0x01, 0xF0, 0x9E, 0x40, 0x1D, 0xB0, 0xCA, 0x00, 0x08, 0xF0, 0xCB, 0x40, 0xC1, 0x70, 0xCC, 0x00,
|
||||
0x4A, 0x70, 0xCD, 0x81, 0xCE, 0x81, 0xDC, 0x40, 0x6C, 0x48, 0xDD, 0x80, 0x05, 0x30, 0x6B, 0x67,
|
||||
0x8A, 0x51, 0x4A, 0x08, 0xEB, 0x80, 0x1F, 0x79, 0xE0, 0xB8, 0xEB, 0x80, 0x0D, 0x70, 0xCA, 0x00,
|
||||
0x08, 0xF0, 0xCB, 0x40, 0xC1, 0x70, 0xCC, 0x00, 0x6B, 0x88, 0xCD, 0x40, 0x4A, 0x70, 0xDC, 0x40,
|
||||
0x6C, 0x48, 0xDD, 0x80, 0x04, 0xF0, 0x32, 0xE7, 0x8A, 0x51, 0x06, 0x30, 0xDC, 0x40, 0x69, 0x48,
|
||||
0xC6, 0x27, 0x03, 0xFE, 0x84, 0x80, 0x8A, 0x95, 0x00, 0x60, 0x8A, 0x51, 0xE8, 0x00, 0x06, 0x30,
|
||||
0xDC, 0x40, 0x69, 0x48, 0xC6, 0x27, 0x04, 0xBE, 0x84, 0x80, 0x8A, 0x95, 0x00, 0x60, 0x8A, 0x51,
|
||||
0xE7, 0x80, 0x6B, 0x88, 0x68, 0x02, 0x03, 0x5C, 0xED, 0x6A, 0x6B, 0x88, 0x68, 0x46, 0x03, 0x9D,
|
||||
0xFF, 0x2B, 0x6A, 0x48, 0x67, 0x82, 0x03, 0x18, 0xFF, 0x2B, 0x06, 0x30, 0xDC, 0x40, 0x69, 0x48,
|
||||
0xC6, 0x27, 0x05, 0xFE, 0x84, 0x80, 0x8A, 0x95, 0x00, 0x60, 0x8A, 0x51, 0xE8, 0x00, 0x06, 0x30,
|
||||
0xDC, 0x40, 0x69, 0x48, 0xC6, 0x27, 0x06, 0xFE, 0x84, 0x80, 0x8A, 0x95, 0x00, 0x60, 0x8A, 0x51,
|
||||
0xE7, 0x80, 0x6B, 0x88, 0x68, 0x02, 0x03, 0x5C, 0x0D, 0xEB, 0x6B, 0x88, 0x68, 0x46, 0x03, 0x9D,
|
||||
0x23, 0xEB, 0x6A, 0x48, 0x67, 0x82, 0x03, 0x18, 0x23, 0xEB, 0x03, 0x30, 0x9E, 0x40, 0x1D, 0xB0,
|
||||
0xCA, 0x00, 0x08, 0xF0, 0xCB, 0x40, 0xC2, 0x70, 0xCC, 0x00, 0x4A, 0x70, 0xCD, 0x81, 0xCE, 0x81,
|
||||
0xDC, 0x40, 0x6C, 0x48, 0xDD, 0x80, 0x05, 0x30, 0x6B, 0x67, 0x8A, 0x51, 0x4A, 0x08, 0xEB, 0x80,
|
||||
0xE1, 0x39, 0x0E, 0xB8, 0xEF, 0xEB, 0x02, 0xF0, 0x9E, 0x40, 0x1D, 0xB0, 0xCA, 0x00, 0x08, 0xF0,
|
||||
0xCB, 0x40, 0xC2, 0x70, 0xCC, 0x00, 0x4A, 0x70, 0xCD, 0x81, 0xCE, 0x81, 0xDC, 0x40, 0x6C, 0x48,
|
||||
0xDD, 0x80, 0x05, 0x30, 0x6B, 0x67, 0x8A, 0x51, 0x4A, 0x08, 0xEB, 0x80, 0xE1, 0x39, 0x06, 0x78,
|
||||
0xEF, 0xEB, 0x07, 0x70, 0xEA, 0xC5, 0x05, 0x30, 0x6A, 0x42, 0x03, 0x18, 0x49, 0xEB, 0x69, 0x48,
|
||||
0x3C, 0x7E, 0x84, 0x80, 0x8A, 0x95, 0x00, 0x60, 0x8A, 0x51, 0xE4, 0x00, 0x69, 0x48, 0x2D, 0x7E,
|
||||
0x64, 0xEB, 0x6A, 0x48, 0x05, 0xBA, 0x03, 0x9D, 0x57, 0x6B, 0x69, 0x48, 0x41, 0xFE, 0x84, 0x80,
|
||||
0x8A, 0x95, 0x00, 0x60, 0x8A, 0x51, 0xE4, 0x00, 0x69, 0x48, 0x32, 0x3E, 0x64, 0xEB, 0x06, 0x30,
|
||||
0x6A, 0x42, 0x03, 0x5C, 0x69, 0x2B, 0x69, 0x48, 0x46, 0x3E, 0x84, 0x80, 0x8A, 0x95, 0x00, 0x60,
|
||||
0x8A, 0x51, 0xE4, 0x00, 0x69, 0x48, 0x37, 0xBE, 0x84, 0x80, 0x8A, 0x95, 0x00, 0x60, 0x8A, 0x51,
|
||||
0xE5, 0x40, 0x0D, 0x70, 0xCA, 0x00, 0x08, 0xF0, 0xCB, 0x40, 0x89, 0x70, 0xCC, 0x00, 0x06, 0x30,
|
||||
0x6A, 0x42, 0x03, 0x5C, 0x75, 0x6B, 0x09, 0x30, 0x76, 0x6B, 0x0D, 0x70, 0xCD, 0x40, 0x4A, 0x70,
|
||||
0xDC, 0x40, 0x6C, 0x48, 0xDD, 0x80, 0x04, 0xF0, 0x32, 0xE7, 0x8A, 0x51, 0x06, 0x30, 0x6A, 0x42,
|
||||
0x03, 0x5C, 0xA5, 0x2B, 0x1D, 0xB0, 0xCA, 0x00, 0x08, 0xF0, 0xCB, 0x40, 0xC2, 0x70, 0xCC, 0x00,
|
||||
0x4A, 0x70, 0xCD, 0x81, 0xCE, 0x81, 0xDC, 0x40, 0x6C, 0x48, 0xDD, 0x80, 0x05, 0x30, 0x6B, 0x67,
|
||||
0x8A, 0x51, 0x4A, 0x08, 0xEB, 0x80, 0x9F, 0xB9, 0x20, 0x38, 0xEB, 0x80, 0x0D, 0x70, 0xCA, 0x00,
|
||||
0x08, 0xF0, 0xCB, 0x40, 0xC2, 0x70, 0xCC, 0x00, 0x6B, 0x88, 0xCD, 0x40, 0x4A, 0x70, 0xDC, 0x40,
|
||||
0x6C, 0x48, 0xDD, 0x80, 0x04, 0xF0, 0x32, 0xE7, 0x8A, 0x51, 0x64, 0x08, 0x03, 0x59, 0xD4, 0x2B,
|
||||
0x1D, 0xB0, 0xCA, 0x00, 0x08, 0xF0, 0xCB, 0x40, 0xC1, 0x70, 0xCC, 0x00, 0x4A, 0x70, 0xCD, 0x81,
|
||||
0xCE, 0x81, 0xDC, 0x40, 0x6C, 0x48, 0xDD, 0x80, 0x05, 0x30, 0x6B, 0x67, 0x8A, 0x51, 0x4A, 0x08,
|
||||
0xEB, 0x80, 0x64, 0x08, 0xE1, 0x00, 0x05, 0x30, 0x03, 0xD0, 0xE1, 0xCD, 0xFF, 0x7E, 0x03, 0x9D,
|
||||
0xBC, 0x6B, 0x6B, 0x88, 0x1F, 0x79, 0x61, 0x04, 0xEB, 0x80, 0x0D, 0x70, 0xCA, 0x00, 0x08, 0xF0,
|
||||
0xCB, 0x40, 0xC1, 0x70, 0xCC, 0x00, 0x6B, 0x88, 0xCD, 0x40, 0x4A, 0x70, 0xDC, 0x40, 0x6C, 0x48,
|
||||
0xDD, 0x80, 0x04, 0xF0, 0x32, 0xE7, 0x8A, 0x51, 0x65, 0x48, 0x03, 0x59, 0xFF, 0x2B, 0x1D, 0xB0,
|
||||
0xCA, 0x00, 0x08, 0xF0, 0xCB, 0x40, 0xC2, 0x70, 0xCC, 0x00, 0x4A, 0x70, 0xCD, 0x81, 0xCE, 0x81,
|
||||
0xDC, 0x40, 0x6C, 0x48, 0xDD, 0x80, 0x05, 0x30, 0x6B, 0x67, 0x8A, 0x51, 0x4A, 0x08, 0xEB, 0x80,
|
||||
0x65, 0x48, 0xE1, 0x00, 0x03, 0xD0, 0xE1, 0xCD, 0x6B, 0x88, 0xE1, 0x39, 0x61, 0x04, 0xEB, 0x80,
|
||||
0x0D, 0x70, 0xCA, 0x00, 0x08, 0xF0, 0xCB, 0x40, 0xC2, 0x70, 0xCC, 0x00, 0x6B, 0x88, 0xCD, 0x40,
|
||||
0x4A, 0x70, 0xDC, 0x40, 0x6C, 0x48, 0xDD, 0x80, 0x04, 0xF0, 0x32, 0xE7, 0x8A, 0x51, 0x6C, 0xCB,
|
||||
0x07, 0xAC, 0x00, 0xB0, 0x2A, 0xE7, 0x8A, 0x51, 0xC9, 0x00, 0x49, 0x52, 0x0C, 0x6C, 0x00, 0xB0,
|
||||
0x2A, 0xE7, 0x8A, 0x51, 0xC9, 0x00, 0x49, 0x10, 0x49, 0x08, 0xDC, 0x40, 0x00, 0xB0, 0x22, 0xA7,
|
||||
0x8A, 0x51, 0x05, 0x30, 0xE1, 0x00, 0xE1, 0xCB, 0x13, 0xAC, 0x00, 0xB0, 0x2A, 0xE7, 0x8A, 0x51,
|
||||
0xC9, 0x00, 0xFD, 0xF9, 0x02, 0x38, 0xC9, 0x00, 0xDC, 0x40, 0x00, 0xB0, 0x22, 0xA7, 0x8A, 0x51,
|
||||
0x00, 0xB0, 0x2A, 0xE7, 0x8A, 0x51, 0xC9, 0x00, 0xDF, 0xF9, 0x20, 0x38, 0xC9, 0x00, 0x49, 0x08,
|
||||
0xDC, 0x40, 0x00, 0xB0, 0x22, 0xA7, 0x8A, 0x51, 0x15, 0x70, 0xE2, 0x00, 0xC6, 0xB0, 0xE1, 0x00,
|
||||
0xE1, 0xCB, 0x30, 0x6C, 0xE2, 0xCB, 0x30, 0x6C, 0x00, 0x00, 0x0D, 0x70, 0x83, 0x52, 0x03, 0x53,
|
||||
0xCA, 0x00, 0x05, 0x30, 0xCB, 0x40, 0x84, 0x30, 0xCC, 0x00, 0x4A, 0x70, 0xCD, 0x81, 0xDC, 0x40,
|
||||
0x6C, 0x48, 0xDD, 0x80, 0x04, 0xF0, 0x32, 0xE7, 0x8A, 0x51, 0x0D, 0x70, 0xCA, 0x00, 0x05, 0x30,
|
||||
0xCB, 0x40, 0x85, 0x70, 0xCC, 0x00, 0x4A, 0x70, 0xCD, 0x81, 0xDC, 0x40, 0x6C, 0x48, 0xDD, 0x80,
|
||||
0x04, 0xF0, 0x32, 0xE7, 0x8A, 0x51, 0x0D, 0x70, 0xCA, 0x00, 0x05, 0x30, 0xCB, 0x40, 0x82, 0x30,
|
||||
0xCC, 0x00, 0x3F, 0x30, 0xCD, 0x40, 0x4A, 0x70, 0xDC, 0x40, 0x6C, 0x48, 0xDD, 0x80, 0x04, 0xF0,
|
||||
0x32, 0xE7, 0x8A, 0x51, 0x0D, 0x70, 0xCA, 0x00, 0x05, 0x30, 0xCB, 0x40, 0x80, 0xF0, 0xCC, 0x00,
|
||||
0x3E, 0xF0, 0xCD, 0x40, 0x4A, 0x70, 0xDC, 0x40, 0x6C, 0x48, 0xDD, 0x80, 0x04, 0xF0, 0x32, 0xE7,
|
||||
0x8A, 0x51, 0x0D, 0x70, 0xCA, 0x00, 0x05, 0x30, 0xCB, 0x40, 0x83, 0x70, 0xCC, 0x00, 0x3E, 0xF0,
|
||||
0xCD, 0x40, 0x4A, 0x70, 0xDC, 0x40, 0x6C, 0x48, 0xDD, 0x80, 0x04, 0xF0, 0x32, 0xE7, 0x8A, 0x51,
|
||||
0x6C, 0x83, 0x03, 0x9D, 0x85, 0xAC, 0x9C, 0xD5, 0x86, 0xAC, 0x1C, 0x95, 0x05, 0x30, 0xE1, 0x00,
|
||||
0xE1, 0xCB, 0x88, 0x6C, 0x0D, 0x70, 0x83, 0x52, 0x03, 0x53, 0xCA, 0x00, 0x05, 0x30, 0xCB, 0x40,
|
||||
0x87, 0xB0, 0xCC, 0x00, 0x09, 0x30, 0xCD, 0x40, 0x4A, 0x70, 0xDC, 0x40, 0x6C, 0x48, 0xDD, 0x80,
|
||||
0x04, 0xF0, 0x32, 0xE7, 0x8A, 0x51, 0xD1, 0xB0, 0xCA, 0x00, 0x4A, 0x70, 0xDC, 0x40, 0x6C, 0x48,
|
||||
0xDD, 0x80, 0x01, 0xF0, 0x32, 0xE7, 0x8A, 0x51, 0x04, 0xF0, 0xE2, 0x00, 0x1C, 0x70, 0xE1, 0x00,
|
||||
0xE1, 0xCB, 0xA8, 0xAC, 0xE2, 0xCB, 0xA8, 0xAC, 0x00, 0x00, 0x08, 0x40, 0x55, 0xB0, 0x83, 0x52,
|
||||
0x9B, 0x40, 0xC8, 0x01, 0x02, 0xF0, 0x48, 0xC2, 0x03, 0x18, 0x72, 0x2D, 0x48, 0xC8, 0x01, 0xBE,
|
||||
0x9B, 0x40, 0x48, 0xC8, 0xB2, 0x7E, 0x84, 0x80, 0x83, 0x93, 0x80, 0x81, 0x48, 0xC8, 0xB2, 0x7E,
|
||||
0x84, 0x80, 0x80, 0x88, 0x03, 0x9D, 0xEA, 0x2C, 0x3C, 0xB0, 0x2A, 0xE7, 0x8A, 0x51, 0xC9, 0x00,
|
||||
0x48, 0x18, 0xD6, 0x2C, 0x48, 0xC8, 0xB2, 0x7E, 0x84, 0x80, 0x49, 0x08, 0xDE, 0x80, 0x07, 0x70,
|
||||
0x03, 0xD0, 0xDE, 0x0C, 0xFF, 0x7E, 0x03, 0x9D, 0xD0, 0xAC, 0xE1, 0xEC, 0x48, 0xC8, 0xB2, 0x7E,
|
||||
0x84, 0x80, 0x49, 0x08, 0xDE, 0x80, 0x05, 0x30, 0x03, 0xD0, 0xDE, 0x0C, 0xFF, 0x7E, 0x03, 0x9D,
|
||||
0xDC, 0x2C, 0x5E, 0x88, 0x83, 0x93, 0x80, 0x40, 0x48, 0xC8, 0xB2, 0x7E, 0x84, 0x80, 0x01, 0xF0,
|
||||
0x80, 0xC5, 0xBE, 0x6C, 0x3E, 0xF0, 0x2A, 0xE7, 0x8A, 0x51, 0xC9, 0x00, 0x49, 0x08, 0x03, 0x59,
|
||||
0x0A, 0xAD, 0x10, 0xF0, 0x49, 0x02, 0x03, 0x18, 0x0A, 0xAD, 0x48, 0xC8, 0xAE, 0xBE, 0x84, 0x80,
|
||||
0x49, 0x08, 0x83, 0x93, 0x80, 0x40, 0x48, 0xC8, 0xAE, 0xBE, 0x84, 0x80, 0x00, 0x48, 0xDC, 0x40,
|
||||
0x1B, 0xB0, 0x22, 0xA7, 0x8A, 0x51, 0x48, 0xC8, 0xAC, 0x7E, 0x84, 0x80, 0x83, 0x93, 0x80, 0x81,
|
||||
0x80, 0xCA, 0x29, 0xED, 0x49, 0x08, 0xFF, 0x3A, 0x03, 0x9D, 0x16, 0xED, 0x48, 0xC8, 0xAE, 0xBE,
|
||||
0x84, 0x80, 0x04, 0xF0, 0x83, 0x93, 0x80, 0x40, 0xFF, 0xB0, 0x20, 0x6D, 0x48, 0xC8, 0xAE, 0xBE,
|
||||
0x84, 0x80, 0x04, 0xF0, 0x83, 0x93, 0x80, 0x40, 0x48, 0xC8, 0xAE, 0xBE, 0x84, 0x80, 0x00, 0x48,
|
||||
0xDC, 0x40, 0x1B, 0xB0, 0x22, 0xA7, 0x8A, 0x51, 0x48, 0xC8, 0xAC, 0x7E, 0x84, 0x80, 0x83, 0x93,
|
||||
0x80, 0x81, 0x3F, 0x30, 0x2A, 0xE7, 0x8A, 0x51, 0xC9, 0x00, 0x49, 0x08, 0x03, 0x59, 0x49, 0xED,
|
||||
0x0E, 0x70, 0x49, 0x02, 0x03, 0x18, 0x49, 0xED, 0x48, 0xC8, 0xA8, 0x3E, 0x84, 0x80, 0x49, 0x08,
|
||||
0x83, 0x93, 0x80, 0x40, 0x48, 0xC8, 0xA8, 0x3E, 0x84, 0x80, 0x00, 0x48, 0xDC, 0x40, 0x1C, 0x70,
|
||||
0x22, 0xA7, 0x8A, 0x51, 0x48, 0xC8, 0x23, 0x3E, 0x84, 0x80, 0x83, 0x93, 0x80, 0x81, 0x80, 0xCA,
|
||||
0x68, 0xED, 0x49, 0x08, 0xFF, 0x3A, 0x03, 0x9D, 0x55, 0x2D, 0x48, 0xC8, 0xA8, 0x3E, 0x84, 0x80,
|
||||
0x0D, 0x70, 0x83, 0x93, 0x80, 0x40, 0xFF, 0xB0, 0x5F, 0xAD, 0x48, 0xC8, 0xA8, 0x3E, 0x84, 0x80,
|
||||
0x0D, 0x70, 0x83, 0x93, 0x80, 0x40, 0x48, 0xC8, 0xA8, 0x3E, 0x84, 0x80, 0x00, 0x48, 0xDC, 0x40,
|
||||
0x1C, 0x70, 0x22, 0xA7, 0x8A, 0x51, 0x48, 0xC8, 0x23, 0x3E, 0x84, 0x80, 0x83, 0x93, 0x80, 0x81,
|
||||
0x48, 0xC8, 0xB0, 0x3E, 0x84, 0x80, 0x00, 0x48, 0xDC, 0x40, 0x1A, 0x70, 0x22, 0xA7, 0x8A, 0x51,
|
||||
0xC8, 0x4A, 0xB2, 0xEC, 0x03, 0x30, 0x9B, 0x40, 0x3C, 0xB0, 0x2A, 0xE7, 0x8A, 0x51, 0xC9, 0x00,
|
||||
0x03, 0xBA, 0x03, 0x9D, 0x74, 0x2D, 0x3E, 0xF0, 0x2A, 0xE7, 0x8A, 0x51, 0xAA, 0x00, 0x3F, 0x30,
|
||||
0x2A, 0xE7, 0x8A, 0x51, 0xAC, 0x00, 0x2A, 0x02, 0x03, 0x5C, 0x9C, 0x2D, 0x0E, 0x70, 0x2A, 0x02,
|
||||
0x03, 0x18, 0x9C, 0x2D, 0x2C, 0x08, 0x03, 0x59, 0x9C, 0x2D, 0x2A, 0x08, 0xDC, 0x40, 0x1B, 0xB0,
|
||||
0x22, 0xA7, 0x8A, 0x51, 0x2C, 0x08, 0xDC, 0x40, 0x1C, 0x70, 0x22, 0xA7, 0x8A, 0x51, 0x2A, 0x08,
|
||||
0xA9, 0x00, 0x2C, 0x08, 0xAB, 0x40, 0xAA, 0x2D, 0x0D, 0x70, 0xDC, 0x40, 0x1B, 0xB0, 0x22, 0xA7,
|
||||
0x8A, 0x51, 0x1C, 0x70, 0xDC, 0x81, 0xDC, 0xCA, 0x22, 0xA7, 0x8A, 0x51, 0x0D, 0x70, 0xA9, 0x00,
|
||||
0xAB, 0x81, 0xAB, 0xCA, 0x04, 0xF0, 0x9B, 0x40, 0x3C, 0xB0, 0x2A, 0xE7, 0x8A, 0x51, 0xC9, 0x00,
|
||||
0x04, 0x7A, 0x03, 0x9D, 0xAC, 0x2D, 0x3E, 0xF0, 0x2A, 0xE7, 0x8A, 0x51, 0xAE, 0x40, 0x3F, 0x30,
|
||||
0x2A, 0xE7, 0x8A, 0x51, 0xB0, 0xC0, 0x2E, 0x42, 0x03, 0x5C, 0xD0, 0xED, 0x02, 0xF0, 0x30, 0xC2,
|
||||
0x03, 0x5C, 0xD0, 0xED, 0x2E, 0x48, 0xDC, 0x40, 0x1B, 0xB0, 0x22, 0xA7, 0x8A, 0x51, 0x30, 0xC8,
|
||||
0xDC, 0x40, 0x1C, 0x70, 0x22, 0xA7, 0x8A, 0x51, 0x2E, 0x48, 0xAD, 0x40, 0x30, 0xC8, 0xDD, 0xAD,
|
||||
0x0C, 0x30, 0xDC, 0x40, 0x1B, 0xB0, 0x22, 0xA7, 0x8A, 0x51, 0x03, 0x30, 0xDC, 0x40, 0x1C, 0x70,
|
||||
0x22, 0xA7, 0x8A, 0x51, 0x0C, 0x30, 0xAD, 0x40, 0x03, 0x30, 0xAF, 0x80, 0x05, 0x30, 0x9B, 0x40,
|
||||
0x3C, 0xB0, 0x2A, 0xE7, 0x8A, 0x51, 0xC9, 0x00, 0x05, 0xBA, 0x03, 0x9D, 0xE0, 0xED, 0x3E, 0xF0,
|
||||
0x2A, 0xE7, 0x8A, 0x51, 0xB7, 0x80, 0x3F, 0x30, 0x2A, 0xE7, 0x8A, 0x51, 0xB9, 0x40, 0x37, 0x82,
|
||||
0x03, 0x5C, 0x07, 0xEE, 0x10, 0xF0, 0x37, 0x82, 0x03, 0x18, 0x07, 0xEE, 0x39, 0x48, 0x03, 0x59,
|
||||
0x07, 0xEE, 0x37, 0x88, 0xDC, 0x40, 0x1B, 0xB0, 0x22, 0xA7, 0x8A, 0x51, 0x39, 0x48, 0xDC, 0x40,
|
||||
0x1C, 0x70, 0x22, 0xA7, 0x8A, 0x51, 0x37, 0x88, 0xB6, 0x40, 0x39, 0x48, 0x14, 0xAE, 0x0F, 0xB0,
|
||||
0xDC, 0x40, 0x1B, 0xB0, 0x22, 0xA7, 0x8A, 0x51, 0x04, 0xF0, 0xDC, 0x40, 0x1C, 0x70, 0x22, 0xA7,
|
||||
0x8A, 0x51, 0x0F, 0xB0, 0xB6, 0x40, 0x04, 0xF0, 0xB8, 0x00, 0x06, 0x30, 0x9B, 0x40, 0x3C, 0xB0,
|
||||
0x2A, 0xE7, 0x8A, 0x51, 0xC9, 0x00, 0x06, 0xBA, 0x03, 0x9D, 0x17, 0x2E, 0x3D, 0xF0, 0x2A, 0xE7,
|
||||
0x8A, 0x51, 0xBD, 0x80, 0x3E, 0xF0, 0x2A, 0xE7, 0x8A, 0x51, 0xBB, 0x80, 0x3F, 0x30, 0x2A, 0xE7,
|
||||
0x8A, 0x51, 0xBF, 0xC0, 0x3B, 0x88, 0x3D, 0x82, 0x03, 0x5C, 0x4A, 0xEE, 0x3F, 0xC8, 0x3B, 0x82,
|
||||
0x03, 0x5C, 0x4A, 0xEE, 0x3F, 0xC8, 0x03, 0x59, 0x4A, 0xEE, 0x3D, 0x88, 0xDC, 0x40, 0x1A, 0x70,
|
||||
0x22, 0xA7, 0x8A, 0x51, 0x3B, 0x88, 0xDC, 0x40, 0x1B, 0xB0, 0x22, 0xA7, 0x8A, 0x51, 0x3F, 0xC8,
|
||||
0xDC, 0x40, 0x1C, 0x70, 0x22, 0xA7, 0x8A, 0x51, 0x3D, 0x88, 0xBC, 0x40, 0x3B, 0x88, 0xBA, 0x40,
|
||||
0x3F, 0xC8, 0x5E, 0x6E, 0x5A, 0xB0, 0xDC, 0x40, 0x1A, 0x70, 0x22, 0xA7, 0x8A, 0x51, 0x50, 0x30,
|
||||
0xDC, 0x40, 0x1B, 0xB0, 0x22, 0xA7, 0x8A, 0x51, 0x28, 0x30, 0xDC, 0x40, 0x1C, 0x70, 0x22, 0xA7,
|
||||
0x8A, 0x51, 0x5A, 0xB0, 0xBC, 0x40, 0x50, 0x30, 0xBA, 0x40, 0x28, 0x30, 0xBE, 0x80, 0x07, 0x70,
|
||||
0x9B, 0x40, 0x3C, 0xB0, 0x2A, 0xE7, 0x8A, 0x51, 0xC9, 0x00, 0x07, 0xFA, 0x03, 0x9D, 0x61, 0xEE,
|
||||
0x3E, 0xF0, 0x2A, 0xE7, 0x8A, 0x51, 0xB1, 0x00, 0x3F, 0x30, 0x2A, 0xE7, 0x8A, 0x51, 0xB3, 0x40,
|
||||
0x31, 0x02, 0x03, 0x5C, 0x8A, 0xEE, 0x10, 0xF0, 0x31, 0x02, 0x03, 0x18, 0x8A, 0xEE, 0x33, 0x48,
|
||||
0x03, 0x59, 0x8A, 0xEE, 0x31, 0x08, 0xDC, 0x40, 0x1B, 0xB0, 0x22, 0xA7, 0x8A, 0x51, 0x33, 0x48,
|
||||
0xDC, 0x40, 0x1C, 0x70, 0x22, 0xA7, 0x8A, 0x51, 0x31, 0x08, 0x83, 0x96, 0xB4, 0x00, 0x83, 0x52,
|
||||
0x33, 0x48, 0x99, 0x2E, 0x0E, 0x70, 0xDC, 0x40, 0x1B, 0xB0, 0x22, 0xA7, 0x8A, 0x51, 0x04, 0xF0,
|
||||
0xDC, 0x40, 0x1C, 0x70, 0x22, 0xA7, 0x8A, 0x51, 0x0E, 0x70, 0x83, 0x96, 0xB4, 0x00, 0x04, 0xF0,
|
||||
0x83, 0x52, 0xB2, 0x00, 0x08, 0xF0, 0x9B, 0x40, 0x3C, 0xB0, 0x2A, 0xE7, 0x8A, 0x51, 0xC9, 0x00,
|
||||
0x08, 0x7A, 0x03, 0x9D, 0x9C, 0x2E, 0x3E, 0xF0, 0x2A, 0xE7, 0x8A, 0x51, 0xB4, 0x00, 0x3F, 0x30,
|
||||
0x2A, 0xE7, 0x8A, 0x51, 0xB5, 0x40, 0x34, 0x08, 0x35, 0x42, 0x03, 0x18, 0xC4, 0xEE, 0x02, 0xF0,
|
||||
0x35, 0x42, 0x03, 0x5C, 0xC4, 0xEE, 0x34, 0x08, 0xDC, 0x40, 0x1B, 0xB0, 0x22, 0xA7, 0x8A, 0x51,
|
||||
0x35, 0x48, 0xDC, 0x40, 0x1C, 0x70, 0x22, 0xA7, 0x8A, 0x51, 0x34, 0x08, 0x83, 0x96, 0xB5, 0x40,
|
||||
0x83, 0x52, 0x35, 0x48, 0x83, 0x96, 0xD2, 0x2E, 0x84, 0x30, 0xDC, 0x40, 0x1B, 0xB0, 0x22, 0xA7,
|
||||
0x8A, 0x51, 0x34, 0x70, 0xDC, 0x40, 0x1C, 0x70, 0x22, 0xA7, 0x8A, 0x51, 0x84, 0x30, 0x83, 0x96,
|
||||
0xB5, 0x40, 0x34, 0x70, 0xB6, 0x40, 0x09, 0x30, 0x83, 0x52, 0x9B, 0x40, 0x3C, 0xB0, 0x2A, 0xE7,
|
||||
0x8A, 0x51, 0xC9, 0x00, 0x09, 0xBA, 0x03, 0x9D, 0xD6, 0x6E, 0x3D, 0xF0, 0x2A, 0xE7, 0x8A, 0x51,
|
||||
0xC2, 0xC0, 0x3E, 0xF0, 0x2A, 0xE7, 0x8A, 0x51, 0xC1, 0xC0, 0x3F, 0x30, 0x2A, 0xE7, 0x8A, 0x51,
|
||||
0xC0, 0x80, 0x07, 0x70, 0x42, 0xC2, 0x03, 0x18, 0x05, 0xEF, 0x08, 0xF0, 0x41, 0xC2, 0x03, 0x18,
|
||||
0x05, 0xEF, 0x02, 0xF0, 0x40, 0x82, 0x03, 0x18, 0x05, 0xEF, 0x42, 0xC8, 0xDC, 0x40, 0x1A, 0x70,
|
||||
0x22, 0xA7, 0x8A, 0x51, 0x41, 0xC8, 0xDC, 0x40, 0x1B, 0xB0, 0x22, 0xA7, 0x8A, 0x51, 0x40, 0x88,
|
||||
0xDC, 0x40, 0x1C, 0x70, 0x22, 0xA7, 0x8A, 0x51, 0x18, 0xEF, 0x1A, 0x70, 0xDC, 0x81, 0xDC, 0xCA,
|
||||
0x22, 0xA7, 0x8A, 0x51, 0x02, 0xF0, 0xDC, 0x40, 0x1B, 0xB0, 0x22, 0xA7, 0x8A, 0x51, 0x1C, 0x70,
|
||||
0xDC, 0x81, 0x22, 0xA7, 0x8A, 0x51, 0x02, 0xF0, 0xC2, 0x01, 0xC2, 0x4A, 0xC1, 0xC0, 0xC0, 0xC1,
|
||||
0x0A, 0x30, 0x9B, 0x40, 0x3C, 0xB0, 0x2A, 0xE7, 0x8A, 0x51, 0xC9, 0x00, 0x0A, 0xBA, 0x03, 0x59,
|
||||
0x08, 0x40, 0x1A, 0x2F, 0xDD, 0x80, 0x5C, 0x48, 0x96, 0x00, 0x5D, 0x88, 0x95, 0x00, 0x17, 0x94,
|
||||
0x17, 0x50, 0x08, 0x40, 0x83, 0x52, 0x03, 0x53, 0xDC, 0x40, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90,
|
||||
0x0D, 0x08, 0x08, 0x40, 0xDF, 0xC0, 0x5D, 0xD8, 0x50, 0xEF, 0xE0, 0x01, 0x5F, 0xC8, 0x60, 0xC2,
|
||||
0x03, 0x18, 0x45, 0x2F, 0x60, 0xC8, 0x5C, 0xC7, 0xDE, 0x80, 0x84, 0x80, 0x83, 0x93, 0x00, 0x48,
|
||||
0x99, 0x00, 0x18, 0x14, 0x18, 0xD0, 0xE0, 0x4A, 0x36, 0x6F, 0x18, 0x55, 0x18, 0x11, 0x83, 0x52,
|
||||
0x03, 0x53, 0x11, 0x5C, 0x08, 0x40, 0x05, 0x30, 0xDE, 0x80, 0xDE, 0x4B, 0x4D, 0x6F, 0x47, 0x6F,
|
||||
0xE0, 0x01, 0x5F, 0xC8, 0x60, 0xC2, 0x03, 0x18, 0x60, 0xEF, 0x60, 0xC8, 0x5C, 0xC7, 0xDE, 0x80,
|
||||
0x84, 0x80, 0x83, 0x93, 0x00, 0x48, 0x9A, 0x00, 0x98, 0x95, 0x98, 0x51, 0xE0, 0x4A, 0x51, 0x2F,
|
||||
0x98, 0x96, 0x98, 0x52, 0x83, 0x52, 0x03, 0x53, 0x91, 0x9C, 0x08, 0x40, 0x05, 0x30, 0xDE, 0x80,
|
||||
0xDE, 0x4B, 0x68, 0x2F, 0x62, 0x2F, 0xDF, 0xC0, 0x5D, 0xD8, 0x9A, 0x6F, 0xE0, 0x01, 0x5F, 0xC8,
|
||||
0x60, 0xC2, 0x03, 0x18, 0x7E, 0xEF, 0x60, 0xC8, 0x5C, 0xC7, 0xDE, 0x80, 0x84, 0x80, 0x83, 0x93,
|
||||
0x00, 0x48, 0x99, 0x00, 0x18, 0x14, 0x18, 0xD0, 0xE0, 0x4A, 0x6F, 0xEF, 0x18, 0x55, 0x18, 0x11,
|
||||
0x83, 0x52, 0x03, 0x53, 0x11, 0x5C, 0x8A, 0x2F, 0x2A, 0x70, 0xDE, 0x80, 0xDE, 0x4B, 0x86, 0x2F,
|
||||
0x00, 0x00, 0x80, 0xAF, 0xE0, 0x01, 0x5F, 0xC8, 0x60, 0xC2, 0x03, 0x18, 0x08, 0x40, 0x60, 0xC8,
|
||||
0x5C, 0xC7, 0xDE, 0x80, 0x84, 0x80, 0x0F, 0x48, 0x83, 0x93, 0x80, 0x40, 0x98, 0x54, 0x98, 0x10,
|
||||
0xE0, 0x4A, 0x8B, 0x6F, 0xE0, 0x01, 0x5F, 0xC8, 0x60, 0xC2, 0x03, 0x18, 0xAA, 0x6F, 0x60, 0xC8,
|
||||
0x5C, 0xC7, 0xDE, 0x80, 0x84, 0x80, 0x83, 0x93, 0x00, 0x48, 0x9A, 0x00, 0x98, 0x95, 0x98, 0x51,
|
||||
0xE0, 0x4A, 0x9B, 0xAF, 0x98, 0x96, 0x98, 0x52, 0x83, 0x52, 0x03, 0x53, 0x91, 0x9C, 0xB6, 0xAF,
|
||||
0x2A, 0x70, 0xDE, 0x80, 0xDE, 0x4B, 0xB2, 0x6F, 0x00, 0x00, 0xAC, 0x6F, 0xE0, 0x01, 0x5F, 0xC8,
|
||||
0x60, 0xC2, 0x03, 0x18, 0x08, 0x40, 0x60, 0xC8, 0x5C, 0xC7, 0xDE, 0x80, 0x84, 0x80, 0x10, 0x88,
|
||||
0x83, 0x93, 0x80, 0x40, 0x18, 0x56, 0x18, 0x12, 0xE0, 0x4A, 0xB7, 0xEF, 0xDE, 0x80, 0xDD, 0xC1,
|
||||
0x5C, 0x48, 0x5E, 0xD8, 0xDD, 0x47, 0x03, 0xD0, 0xDC, 0x0D, 0x5C, 0x48, 0xDE, 0x18, 0xDD, 0x47,
|
||||
0x03, 0xD0, 0xDC, 0x0D, 0x5C, 0x48, 0x5E, 0x19, 0xDD, 0x47, 0x03, 0xD0, 0xDC, 0x0D, 0x5C, 0x48,
|
||||
0xDE, 0x59, 0xDD, 0x47, 0x03, 0xD0, 0xDC, 0x0D, 0x5C, 0x48, 0x5E, 0x1A, 0xDD, 0x47, 0x03, 0xD0,
|
||||
0xDC, 0x0D, 0x5C, 0x48, 0xDE, 0x5A, 0xDD, 0x47, 0x03, 0xD0, 0xDC, 0x0D, 0x5C, 0x48, 0x5E, 0x5B,
|
||||
0xDD, 0x47, 0x03, 0xD0, 0xDC, 0x0D, 0x5C, 0x48, 0xDE, 0x9B, 0xDD, 0x47, 0x5D, 0x88, 0x08, 0x40,
|
||||
0xEF, 0x01, 0x83, 0x93, 0x21, 0x30, 0x84, 0x80, 0x5C, 0xB0, 0x8A, 0x51, 0x11, 0xE0, 0x8A, 0x51,
|
||||
0xA0, 0x30, 0x84, 0x80, 0xC2, 0x70, 0x8A, 0x51, 0x11, 0xE0, 0x83, 0x01, 0x8A, 0x95, 0x5F, 0xAB,
|
||||
0x08, 0xF0, 0x8A, 0xC0, 0x04, 0x88, 0x84, 0x0A, 0x82, 0x47, 0x00, 0xF4, 0x01, 0x34, 0x48, 0x74,
|
||||
0x02, 0x34, 0x3D, 0x34, 0x03, 0x74, 0x33, 0xF4, 0x00, 0xF4, 0xA4, 0xB4, 0x00, 0xF4, 0xF6, 0x74,
|
||||
0x03, 0x74, 0x33, 0xF4, 0x00, 0xF4, 0x52, 0xB4, 0x00, 0xF4, 0x52, 0xB4, 0x00, 0xF4, 0xCD, 0x34,
|
||||
0x00, 0xF4, 0x29, 0xB4, 0x00, 0xF4, 0x29, 0xB4, 0x00, 0xF4, 0x66, 0xF4, 0x00, 0xF4, 0x15, 0xB4,
|
||||
0x00, 0xF4, 0x15, 0xB4, 0x00, 0xF4, 0x29, 0xB4, 0x7F, 0xB4, 0x34, 0xB4, 0x2F, 0x34, 0x2A, 0xB4,
|
||||
0x26, 0xB4, 0x21, 0x74, 0x1A, 0xB4, 0x16, 0xB4, 0x0F, 0xF4, 0x09, 0x74, 0x04, 0x34, 0x02, 0x34,
|
||||
0x01, 0x34, 0x00, 0xF4, 0x00, 0xF4, 0x00, 0xF4, 0x00, 0xF4, 0x03, 0x74, 0x03, 0x74, 0x00, 0xF4,
|
||||
0x00, 0xF4, 0x03, 0x74, 0x03, 0x74, 0x07, 0xB4, 0x01, 0x34, 0x01, 0x34, 0x01, 0x34, 0x07, 0xB4,
|
||||
0x07, 0xB4, 0x00, 0xF4, 0x00, 0xF4, 0x07, 0xB4, 0x07, 0xB4, 0x07, 0xB4, 0x00, 0xF4, 0x07, 0xB4,
|
||||
0x07, 0xB4, 0x07, 0xB4, 0x07, 0xB4, 0x07, 0xB4, 0x07, 0xB4, 0x07, 0xB4, 0x07, 0xB4, 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, 0xC8, 0x01, 0x02, 0xF0, 0x48, 0xC2,
|
||||
0x03, 0x18, 0x3D, 0x6B, 0x48, 0xC8, 0xB0, 0x3E, 0x84, 0x80, 0x83, 0x93, 0x80, 0x81, 0x48, 0xC8,
|
||||
0xAE, 0xBE, 0x84, 0x80, 0x80, 0x81, 0x48, 0xC8, 0xA8, 0x3E, 0x84, 0x80, 0x80, 0x81, 0x48, 0xC8,
|
||||
0xB2, 0x7E, 0x84, 0x80, 0x80, 0x81, 0x48, 0xC8, 0x23, 0x3E, 0x84, 0x80, 0x80, 0x81, 0x48, 0xC8,
|
||||
0xAC, 0x7E, 0x84, 0x80, 0x80, 0x81, 0xC8, 0x4A, 0x1E, 0x2B, 0x0D, 0x70, 0xAB, 0x81, 0xAB, 0xCA,
|
||||
0xA9, 0x00, 0x03, 0x30, 0xAF, 0x80, 0x0C, 0x30, 0xAD, 0x40, 0x04, 0xF0, 0xB8, 0x00, 0x0F, 0xB0,
|
||||
0xB6, 0x40, 0x28, 0x30, 0xBE, 0x80, 0x50, 0x30, 0xBA, 0x40, 0x5A, 0xB0, 0xBC, 0x40, 0x04, 0xF0,
|
||||
0xB2, 0x00, 0x0E, 0x70, 0x83, 0x96, 0xB4, 0x00, 0x34, 0x70, 0xB6, 0x40, 0x84, 0x30, 0xB5, 0x40,
|
||||
0x83, 0x52, 0x02, 0xF0, 0xC2, 0x01, 0xC2, 0x4A, 0xC1, 0xC0, 0xC0, 0xC1, 0x08, 0x40, 0x9B, 0x81,
|
||||
0x01, 0xF0, 0xA0, 0x80, 0x95, 0x41, 0x96, 0x41, 0x97, 0x81, 0x98, 0x01, 0x99, 0x41, 0x9A, 0x41,
|
||||
0x9B, 0x81, 0x9C, 0x41, 0x9E, 0x81, 0x55, 0xB0, 0x9E, 0x40, 0x9B, 0x81, 0x1C, 0x70, 0xDC, 0x81,
|
||||
0xDC, 0xCA, 0x8A, 0x51, 0x22, 0xA7, 0x8A, 0x95, 0x8A, 0x95, 0x1D, 0xE3, 0x8A, 0x95, 0x3D, 0xF0,
|
||||
0x8A, 0x51, 0x2A, 0xE7, 0x8A, 0x95, 0xC9, 0x00, 0xF7, 0xFA, 0x03, 0x9D, 0x82, 0xAB, 0x83, 0x96,
|
||||
0xBF, 0x01, 0x85, 0xEB, 0x83, 0x96, 0xBF, 0x01, 0xBF, 0x4A, 0x3F, 0xC8, 0x03, 0x59, 0x8C, 0xEB,
|
||||
0x8A, 0x51, 0xAE, 0xE4, 0x8A, 0x95, 0x8F, 0x6B, 0x01, 0xF0, 0x83, 0x52, 0x9B, 0x40, 0x8A, 0x51,
|
||||
0x27, 0x60, 0x8A, 0x95, 0x00, 0xB0, 0x8A, 0x51, 0x2A, 0xE7, 0x8A, 0x95, 0xC9, 0x00, 0xFE, 0xF9,
|
||||
0x01, 0x38, 0xC9, 0x00, 0xDC, 0x40, 0x00, 0xB0, 0x8A, 0x51, 0x22, 0xA7, 0x8A, 0x95, 0x00, 0xB0,
|
||||
0x8A, 0x51, 0x2A, 0xE7, 0x8A, 0x95, 0xC9, 0x00, 0xEF, 0xF9, 0x10, 0x38, 0xC9, 0x00, 0x49, 0x08,
|
||||
0xDC, 0x40, 0x00, 0xB0, 0x8A, 0x51, 0x22, 0xA7, 0x8A, 0x95, 0x1C, 0x54, 0x9C, 0x94, 0x9C, 0xD6,
|
||||
0x35, 0xB0, 0xED, 0x80, 0xED, 0x4B, 0xB2, 0x2B, 0x83, 0x52, 0x03, 0x53, 0x9C, 0x92, 0x9C, 0x17,
|
||||
0x35, 0xB0, 0xED, 0x80, 0xED, 0x4B, 0xBA, 0x6B, 0x83, 0x52, 0x03, 0x53, 0x9C, 0xD3, 0xC8, 0x01,
|
||||
0x02, 0xF0, 0x48, 0xC2, 0x03, 0x18, 0x8D, 0xEC, 0x08, 0xF0, 0xE1, 0x00, 0xAC, 0xB0, 0xE2, 0x00,
|
||||
0x03, 0x30, 0xE3, 0x40, 0x48, 0xC8, 0xE4, 0x00, 0x0D, 0x70, 0x8A, 0x51, 0x19, 0x20, 0x8A, 0x95,
|
||||
0x48, 0xC8, 0x23, 0x3E, 0x84, 0x80, 0x83, 0x93, 0x00, 0xCB, 0xE0, 0xEB, 0x48, 0xC8, 0xA8, 0x3E,
|
||||
0x84, 0x80, 0x00, 0x48, 0xED, 0x80, 0x48, 0xC8, 0x21, 0xFE, 0x84, 0x80, 0x6D, 0x88, 0xE4, 0x2B,
|
||||
0x48, 0xC8, 0x21, 0xFE, 0x84, 0x80, 0x29, 0x08, 0x80, 0x40, 0x48, 0xC8, 0x21, 0xFE, 0x84, 0x80,
|
||||
0x00, 0x48, 0x1F, 0xBE, 0x84, 0x80, 0x8A, 0x95, 0x00, 0x60, 0x8A, 0x95, 0xED, 0x80, 0x48, 0xC8,
|
||||
0x27, 0x7E, 0x84, 0x80, 0x6D, 0x88, 0x80, 0x40, 0x08, 0xF0, 0xE1, 0x00, 0xB6, 0xF0, 0xE2, 0x00,
|
||||
0x48, 0xC8, 0x21, 0xFE, 0x84, 0x80, 0x00, 0x48, 0x20, 0x38, 0xE3, 0x40, 0x48, 0xC8, 0xE4, 0x00,
|
||||
0x0D, 0x70, 0x8A, 0x51, 0x19, 0x20, 0x8A, 0x95, 0x48, 0xC8, 0xAC, 0x7E, 0x84, 0x80, 0x83, 0x93,
|
||||
0x00, 0xCB, 0x14, 0x6C, 0x48, 0xC8, 0xAE, 0xBE, 0x84, 0x80, 0x00, 0x48, 0xED, 0x80, 0x48, 0xC8,
|
||||
0x5A, 0x7E, 0x84, 0x80, 0x6D, 0x88, 0x18, 0x6C, 0x48, 0xC8, 0x5A, 0x7E, 0x84, 0x80, 0x38, 0x08,
|
||||
0x80, 0x40, 0x06, 0x30, 0xDC, 0x40, 0x48, 0xC8, 0x5A, 0x7E, 0x84, 0x80, 0x38, 0x08, 0x00, 0x42,
|
||||
0x8A, 0x51, 0xC6, 0x27, 0x8A, 0x95, 0xED, 0x80, 0x48, 0xC8, 0xAA, 0x7E, 0x84, 0x80, 0x6D, 0x88,
|
||||
0x83, 0x93, 0x80, 0x40, 0x48, 0xC8, 0xAA, 0x7E, 0x84, 0x80, 0x00, 0x48, 0xED, 0x80, 0x48, 0xC8,
|
||||
0x27, 0x7E, 0x84, 0x80, 0x00, 0x48, 0x6D, 0x07, 0xEE, 0x80, 0x48, 0xC8, 0x25, 0x3E, 0x84, 0x80,
|
||||
0x6E, 0x88, 0x80, 0x40, 0x48, 0xC8, 0x25, 0x3E, 0x84, 0x80, 0x7F, 0x70, 0x00, 0x42, 0x03, 0x5C,
|
||||
0x46, 0xAC, 0x48, 0xC8, 0x25, 0x3E, 0x84, 0x80, 0x7F, 0x70, 0x80, 0x40, 0x48, 0x18, 0x4F, 0x2C,
|
||||
0x48, 0xC8, 0x25, 0x3E, 0x84, 0x80, 0x00, 0x48, 0xDC, 0x40, 0x03, 0x30, 0x55, 0xEC, 0x48, 0xC8,
|
||||
0x25, 0x3E, 0x84, 0x80, 0x00, 0x48, 0xDC, 0x40, 0x04, 0xF0, 0x8A, 0x51, 0x22, 0xA7, 0x8A, 0x95,
|
||||
0x48, 0x18, 0x71, 0xEC, 0x48, 0xC8, 0x5A, 0x7E, 0x84, 0x80, 0x83, 0x93, 0x00, 0x48, 0xED, 0x80,
|
||||
0x01, 0xF0, 0x03, 0xD0, 0xED, 0x4D, 0xFF, 0x7E, 0x03, 0xD0, 0x03, 0x9D, 0x62, 0xAC, 0x6D, 0x0D,
|
||||
0x02, 0xBE, 0xC9, 0x00, 0xDC, 0x40, 0x01, 0xF0, 0x8A, 0x51, 0x22, 0xA7, 0x8A, 0x95, 0x01, 0xF0,
|
||||
0x87, 0xEC, 0x48, 0xC8, 0x5A, 0x7E, 0x84, 0x80, 0x83, 0x93, 0x00, 0x48, 0xED, 0x80, 0x01, 0xF0,
|
||||
0x03, 0xD0, 0xED, 0x4D, 0xFF, 0x7E, 0x03, 0xD0, 0x03, 0x9D, 0x79, 0x2C, 0x6D, 0x0D, 0x02, 0xBE,
|
||||
0xC9, 0x00, 0xDC, 0x40, 0x02, 0xF0, 0x8A, 0x51, 0x22, 0xA7, 0x8A, 0x95, 0x02, 0xF0, 0xDC, 0x81,
|
||||
0x8A, 0x51, 0x22, 0xA7, 0x8A, 0x95, 0xC8, 0x4A, 0xC0, 0xAB, 0xC4, 0x01, 0x08, 0xF0, 0x44, 0xC2,
|
||||
0x03, 0x18, 0xB0, 0xAC, 0x44, 0xC8, 0xDC, 0x40, 0x05, 0x30, 0x8A, 0x51, 0x22, 0xA7, 0x8A, 0x95,
|
||||
0x44, 0xC8, 0xA0, 0xFE, 0x84, 0x80, 0x32, 0x08, 0x83, 0x93, 0x80, 0x40, 0x44, 0xC8, 0xA0, 0xFE,
|
||||
0x84, 0x80, 0x03, 0x14, 0x00, 0xCD, 0xC9, 0x00, 0xDC, 0x40, 0x06, 0x30, 0x8A, 0x51, 0x22, 0xA7,
|
||||
0x8A, 0x95, 0x06, 0x30, 0xDC, 0x81, 0x8A, 0x51, 0x22, 0xA7, 0x8A, 0x95, 0xC4, 0x4A, 0x8E, 0xEC,
|
||||
0x34, 0x70, 0x9E, 0x40, 0x83, 0x52, 0x12, 0x18, 0x1C, 0x9C, 0xBC, 0x2C, 0x1C, 0x10, 0x9B, 0xD4,
|
||||
0x00, 0xB0, 0x8A, 0x51, 0x6A, 0xA1, 0x8A, 0x95, 0x83, 0x52, 0x03, 0x53, 0x12, 0x5C, 0x1C, 0x58,
|
||||
0xC9, 0xEC, 0x00, 0xB0, 0x8A, 0x51, 0x69, 0x60, 0x8A, 0x95, 0x83, 0x52, 0x03, 0x53, 0x1C, 0x54,
|
||||
0x9B, 0x90, 0x92, 0x58, 0x9C, 0xDC, 0xD2, 0xEC, 0x9C, 0x50, 0x9B, 0xD4, 0x01, 0xF0, 0x8A, 0x51,
|
||||
0x6A, 0xA1, 0x8A, 0x95, 0x83, 0x52, 0x03, 0x53, 0x92, 0x9C, 0x9C, 0x98, 0xDF, 0xAC, 0x01, 0xF0,
|
||||
0x8A, 0x51, 0x69, 0x60, 0x8A, 0x95, 0x83, 0x52, 0x03, 0x53, 0x9C, 0x94, 0x9B, 0x90, 0xC4, 0x01,
|
||||
0x08, 0xF0, 0x44, 0xC2, 0x03, 0x18, 0x2E, 0x2D, 0x44, 0xC8, 0xDC, 0x40, 0x05, 0x30, 0x8A, 0x51,
|
||||
0x22, 0xA7, 0x8A, 0x95, 0x24, 0x30, 0x8A, 0x51, 0x2A, 0xE7, 0x8A, 0x95, 0xC5, 0x00, 0x83, 0x96,
|
||||
0x35, 0x42, 0x03, 0x18, 0x04, 0x6D, 0x83, 0x52, 0x44, 0xC8, 0xA0, 0xFE, 0x84, 0x80, 0x83, 0x96,
|
||||
0x34, 0x08, 0x83, 0x93, 0x00, 0x42, 0x03, 0x18, 0x04, 0x6D, 0x83, 0x52, 0x44, 0xC8, 0xA0, 0xFE,
|
||||
0x84, 0x80, 0x00, 0x48, 0x01, 0xBE, 0x16, 0xED, 0x36, 0x48, 0x83, 0x52, 0x45, 0x02, 0x03, 0x18,
|
||||
0x2C, 0xED, 0x44, 0xC8, 0xA0, 0xFE, 0x84, 0x80, 0x83, 0x93, 0x00, 0x48, 0x32, 0x02, 0x03, 0x18,
|
||||
0x2C, 0xED, 0x44, 0xC8, 0xA0, 0xFE, 0x84, 0x80, 0x00, 0x48, 0xFF, 0x7E, 0xED, 0x80, 0x44, 0xC8,
|
||||
0xA0, 0xFE, 0x84, 0x80, 0x6D, 0x88, 0x80, 0x40, 0x44, 0xC8, 0xA0, 0xFE, 0x84, 0x80, 0x03, 0x14,
|
||||
0x00, 0xCD, 0xC9, 0x00, 0xDC, 0x40, 0x06, 0x30, 0x8A, 0x51, 0x22, 0xA7, 0x8A, 0x95, 0x06, 0x30,
|
||||
0xDC, 0x81, 0x8A, 0x51, 0x22, 0xA7, 0x8A, 0x95, 0xC4, 0x4A, 0xE0, 0xAC, 0x00, 0xB0, 0x14, 0x59,
|
||||
0x80, 0xF0, 0x94, 0x99, 0x40, 0x38, 0x14, 0x18, 0x20, 0x38, 0x94, 0x58, 0x10, 0x38, 0x21, 0xC4,
|
||||
0x9E, 0x40, 0x83, 0x96, 0xC0, 0xC1, 0x83, 0x52, 0x21, 0x30, 0xC8, 0x01, 0x8A, 0x51, 0x2A, 0xE7,
|
||||
0x8A, 0x95, 0xC6, 0x00, 0x20, 0xF0, 0x8A, 0x51, 0x2A, 0xE7, 0x8A, 0x95, 0xC3, 0x00, 0x94, 0x9C,
|
||||
0x9B, 0x6D, 0x48, 0xC8, 0x23, 0x3E, 0x84, 0x80, 0x83, 0x93, 0x80, 0x88, 0x03, 0x9D, 0x90, 0xAD,
|
||||
0x48, 0xC8, 0x21, 0xFE, 0x84, 0x80, 0x00, 0x48, 0x2B, 0x42, 0x03, 0x18, 0x90, 0xAD, 0x48, 0xC8,
|
||||
0x21, 0xFE, 0x84, 0x80, 0x00, 0x48, 0xFF, 0x7E, 0xED, 0x80, 0x48, 0xC8, 0x21, 0xFE, 0x84, 0x80,
|
||||
0x6D, 0x88, 0x80, 0x40, 0x08, 0xF0, 0xE1, 0x00, 0xB6, 0xF0, 0xE2, 0x00, 0x48, 0xC8, 0x21, 0xFE,
|
||||
0x84, 0x80, 0x00, 0x48, 0x20, 0x38, 0xE3, 0x40, 0x48, 0xC8, 0xE4, 0x00, 0x0D, 0x70, 0x8A, 0x51,
|
||||
0x19, 0x20, 0x8A, 0x95, 0x01, 0xF0, 0xDC, 0x81, 0xDC, 0xCA, 0x8A, 0x51, 0x22, 0xA7, 0x8A, 0x95,
|
||||
0x01, 0xF0, 0xDC, 0x81, 0x8A, 0x51, 0x22, 0xA7, 0x8A, 0x95, 0x48, 0xC8, 0x21, 0xFE, 0x84, 0x80,
|
||||
0x83, 0x93, 0x00, 0x48, 0x1F, 0xBE, 0x84, 0x80, 0x8A, 0x95, 0x00, 0x60, 0x8A, 0x95, 0xED, 0x80,
|
||||
0x48, 0xC8, 0x27, 0x7E, 0x84, 0x80, 0x6D, 0x88, 0x80, 0x40, 0x83, 0x96, 0xC0, 0xC1, 0xC0, 0x0A,
|
||||
0x83, 0x52, 0x9C, 0x92, 0x1C, 0x96, 0x05, 0x30, 0xED, 0x80, 0xED, 0x4B, 0x95, 0x2D, 0x83, 0x52,
|
||||
0x03, 0x53, 0x1C, 0x52, 0x71, 0x2E, 0x48, 0xC8, 0xAC, 0x7E, 0x84, 0x80, 0x83, 0x93, 0x80, 0x88,
|
||||
0x03, 0x9D, 0x15, 0xEE, 0x48, 0xC8, 0x21, 0xFE, 0x84, 0x80, 0x00, 0x48, 0x29, 0x46, 0x03, 0x9D,
|
||||
0xAB, 0x6D, 0x3A, 0x48, 0xAC, 0x2D, 0x3C, 0x48, 0xC7, 0x40, 0x46, 0x08, 0x47, 0x42, 0x03, 0x18,
|
||||
0xD0, 0xED, 0x48, 0xC8, 0x5A, 0x7E, 0x84, 0x80, 0x36, 0x48, 0x00, 0x42, 0x03, 0x18, 0xD0, 0xED,
|
||||
0x48, 0xC8, 0x5A, 0x7E, 0x84, 0x80, 0x00, 0x48, 0x01, 0xBE, 0xED, 0x80, 0x48, 0xC8, 0x5A, 0x7E,
|
||||
0x84, 0x80, 0x6D, 0x88, 0x80, 0x40, 0x48, 0xC8, 0x5A, 0x7E, 0x84, 0x80, 0x00, 0x48, 0xED, 0x80,
|
||||
0x01, 0xF0, 0x03, 0xD0, 0xED, 0x4D, 0xFF, 0x7E, 0x03, 0xD0, 0x03, 0x9D, 0xCA, 0x2D, 0xF2, 0x6D,
|
||||
0x3E, 0x88, 0x46, 0x02, 0x48, 0xC8, 0x03, 0x18, 0x16, 0xEE, 0x5A, 0x7E, 0x84, 0x80, 0x00, 0x48,
|
||||
0x38, 0x02, 0x48, 0xC8, 0x03, 0x18, 0x16, 0xEE, 0x5A, 0x7E, 0x84, 0x80, 0x00, 0x48, 0xFF, 0x7E,
|
||||
0xED, 0x80, 0x48, 0xC8, 0x5A, 0x7E, 0x84, 0x80, 0x6D, 0x88, 0x80, 0x40, 0x48, 0xC8, 0x5A, 0x7E,
|
||||
0x84, 0x80, 0x00, 0x48, 0xED, 0x80, 0x01, 0xF0, 0x03, 0xD0, 0xED, 0x4D, 0xFF, 0x7E, 0x03, 0xD0,
|
||||
0x03, 0x9D, 0xED, 0xAD, 0x6D, 0x0D, 0x02, 0xBE, 0xC9, 0x00, 0xDC, 0x40, 0x01, 0xF0, 0x8A, 0x51,
|
||||
0x22, 0xA7, 0x8A, 0x95, 0x01, 0xF0, 0xDC, 0x81, 0x8A, 0x51, 0x22, 0xA7, 0x8A, 0x95, 0x83, 0x96,
|
||||
0x06, 0x30, 0xC0, 0xC1, 0xC0, 0x0A, 0x83, 0x52, 0xDC, 0x40, 0x48, 0xC8, 0x5A, 0x7E, 0x84, 0x80,
|
||||
0x38, 0x08, 0x83, 0x93, 0x00, 0x42, 0x8A, 0x51, 0xC6, 0x27, 0x8A, 0x95, 0xED, 0x80, 0x48, 0xC8,
|
||||
0xAA, 0x7E, 0x84, 0x80, 0x6D, 0x88, 0x83, 0x93, 0x80, 0x40, 0x48, 0xC8, 0x23, 0x3E, 0x84, 0x80,
|
||||
0x80, 0x88, 0x03, 0x9D, 0x71, 0x2E, 0x43, 0x08, 0x2D, 0x42, 0x03, 0x18, 0x2C, 0xEE, 0x48, 0xC8,
|
||||
0x21, 0xFE, 0x84, 0x80, 0x00, 0x48, 0x2B, 0x42, 0x03, 0x18, 0x2C, 0xEE, 0x48, 0xC8, 0x21, 0xFE,
|
||||
0x84, 0x80, 0x00, 0x48, 0xFF, 0x7E, 0x3C, 0x2E, 0x2F, 0x88, 0x43, 0x02, 0x03, 0x18, 0x71, 0x2E,
|
||||
0x48, 0xC8, 0x21, 0xFE, 0x84, 0x80, 0x29, 0x08, 0x00, 0x42, 0x03, 0x18, 0x71, 0x2E, 0x48, 0xC8,
|
||||
0x21, 0xFE, 0x84, 0x80, 0x00, 0x48, 0x01, 0xBE, 0xED, 0x80, 0x48, 0xC8, 0x21, 0xFE, 0x84, 0x80,
|
||||
0x6D, 0x88, 0x80, 0x40, 0x08, 0xF0, 0xE1, 0x00, 0xB6, 0xF0, 0xE2, 0x00, 0x48, 0xC8, 0x21, 0xFE,
|
||||
0x84, 0x80, 0x00, 0x48, 0x20, 0x38, 0xE3, 0x40, 0x48, 0xC8, 0xE4, 0x00, 0x0D, 0x70, 0x8A, 0x51,
|
||||
0x19, 0x20, 0x8A, 0x95, 0x01, 0xF0, 0xDC, 0x81, 0xDC, 0xCA, 0x8A, 0x51, 0x22, 0xA7, 0x8A, 0x95,
|
||||
0x01, 0xF0, 0xDC, 0x81, 0x8A, 0x51, 0x22, 0xA7, 0x8A, 0x95, 0x83, 0x96, 0xC0, 0xC1, 0xC0, 0x0A,
|
||||
0x83, 0x52, 0x48, 0xC8, 0x21, 0xFE, 0x84, 0x80, 0x83, 0x93, 0x00, 0x48, 0x1F, 0xBE, 0x84, 0x80,
|
||||
0x8A, 0x95, 0x00, 0x60, 0x8A, 0x95, 0xED, 0x80, 0x48, 0xC8, 0x27, 0x7E, 0x84, 0x80, 0x6D, 0x88,
|
||||
0x80, 0x40, 0x83, 0x96, 0x40, 0x0B, 0x9B, 0x6E, 0x83, 0x52, 0x48, 0xC8, 0xAA, 0x7E, 0x84, 0x80,
|
||||
0x83, 0x93, 0x00, 0x48, 0xED, 0x80, 0x48, 0xC8, 0x27, 0x7E, 0x84, 0x80, 0x00, 0x48, 0x6D, 0x07,
|
||||
0xEE, 0x80, 0x48, 0xC8, 0x25, 0x3E, 0x84, 0x80, 0x6E, 0x88, 0x80, 0x40, 0x48, 0xC8, 0x25, 0x3E,
|
||||
0x84, 0x80, 0x7F, 0x70, 0x00, 0x42, 0x48, 0xC8, 0x03, 0x5C, 0x93, 0x2E, 0x25, 0x3E, 0x84, 0x80,
|
||||
0x7F, 0x70, 0x80, 0x40, 0x48, 0xC8, 0x25, 0x3E, 0x84, 0x80, 0x00, 0x48, 0xDC, 0x40, 0x03, 0x30,
|
||||
0x8A, 0x51, 0x22, 0xA7, 0x8A, 0x95, 0x83, 0x52, 0x23, 0x70, 0xC8, 0x01, 0xC8, 0x4A, 0x8A, 0x51,
|
||||
0x2A, 0xE7, 0x8A, 0x95, 0xC6, 0x00, 0x22, 0x30, 0x8A, 0x51, 0x2A, 0xE7, 0x8A, 0x95, 0xC3, 0x00,
|
||||
0x83, 0x96, 0xC1, 0x01, 0x83, 0x52, 0x94, 0xDD, 0xFF, 0x2E, 0x48, 0xC8, 0x23, 0x3E, 0x84, 0x80,
|
||||
0x83, 0x93, 0x80, 0x88, 0x03, 0x9D, 0xF4, 0x6E, 0x48, 0xC8, 0x21, 0xFE, 0x84, 0x80, 0x00, 0x48,
|
||||
0x2B, 0x42, 0x03, 0x18, 0xF4, 0x6E, 0x48, 0xC8, 0x21, 0xFE, 0x84, 0x80, 0x00, 0x48, 0xFF, 0x7E,
|
||||
0xED, 0x80, 0x48, 0xC8, 0x21, 0xFE, 0x84, 0x80, 0x6D, 0x88, 0x80, 0x40, 0x08, 0xF0, 0xE1, 0x00,
|
||||
0xB6, 0xF0, 0xE2, 0x00, 0x48, 0xC8, 0x21, 0xFE, 0x84, 0x80, 0x00, 0x48, 0x20, 0x38, 0xE3, 0x40,
|
||||
0x48, 0xC8, 0xE4, 0x00, 0x0D, 0x70, 0x8A, 0x51, 0x19, 0x20, 0x8A, 0x95, 0x02, 0xF0, 0xDC, 0x81,
|
||||
0xDC, 0xCA, 0x8A, 0x51, 0x22, 0xA7, 0x8A, 0x95, 0x02, 0xF0, 0xDC, 0x81, 0x8A, 0x51, 0x22, 0xA7,
|
||||
0x8A, 0x95, 0x48, 0xC8, 0x21, 0xFE, 0x84, 0x80, 0x83, 0x93, 0x00, 0x48, 0x1F, 0xBE, 0x84, 0x80,
|
||||
0x8A, 0x95, 0x00, 0x60, 0x8A, 0x95, 0xED, 0x80, 0x48, 0xC8, 0x27, 0x7E, 0x84, 0x80, 0x6D, 0x88,
|
||||
0x80, 0x40, 0x83, 0x96, 0xC1, 0x01, 0xC1, 0x4A, 0x83, 0x52, 0x9C, 0xD3, 0x1C, 0xD7, 0x05, 0x30,
|
||||
0xED, 0x80, 0xED, 0x4B, 0xF9, 0xAE, 0x83, 0x52, 0x03, 0x53, 0x1C, 0x93, 0xD5, 0xAF, 0x48, 0xC8,
|
||||
0xAC, 0x7E, 0x84, 0x80, 0x83, 0x93, 0x80, 0x88, 0x03, 0x9D, 0x79, 0xAF, 0x48, 0xC8, 0x21, 0xFE,
|
||||
0x84, 0x80, 0x00, 0x48, 0x29, 0x46, 0x03, 0x9D, 0x0F, 0x6F, 0x3A, 0x48, 0x10, 0xAF, 0x3C, 0x48,
|
||||
0xC7, 0x40, 0x46, 0x08, 0x47, 0x42, 0x03, 0x18, 0x34, 0x2F, 0x48, 0xC8, 0x5A, 0x7E, 0x84, 0x80,
|
||||
0x36, 0x48, 0x00, 0x42, 0x03, 0x18, 0x34, 0x2F, 0x48, 0xC8, 0x5A, 0x7E, 0x84, 0x80, 0x00, 0x48,
|
||||
0x01, 0xBE, 0xED, 0x80, 0x48, 0xC8, 0x5A, 0x7E, 0x84, 0x80, 0x6D, 0x88, 0x80, 0x40, 0x48, 0xC8,
|
||||
0x5A, 0x7E, 0x84, 0x80, 0x00, 0x48, 0xED, 0x80, 0x01, 0xF0, 0x03, 0xD0, 0xED, 0x4D, 0xFF, 0x7E,
|
||||
0x03, 0xD0, 0x03, 0x9D, 0x2E, 0x6F, 0x56, 0x6F, 0x3E, 0x88, 0x46, 0x02, 0x48, 0xC8, 0x03, 0x18,
|
||||
0x7A, 0xAF, 0x5A, 0x7E, 0x84, 0x80, 0x00, 0x48, 0x38, 0x02, 0x48, 0xC8, 0x03, 0x18, 0x7A, 0xAF,
|
||||
0x5A, 0x7E, 0x84, 0x80, 0x00, 0x48, 0xFF, 0x7E, 0xED, 0x80, 0x48, 0xC8, 0x5A, 0x7E, 0x84, 0x80,
|
||||
0x6D, 0x88, 0x80, 0x40, 0x48, 0xC8, 0x5A, 0x7E, 0x84, 0x80, 0x00, 0x48, 0xED, 0x80, 0x01, 0xF0,
|
||||
0x03, 0xD0, 0xED, 0x4D, 0xFF, 0x7E, 0x03, 0xD0, 0x03, 0x9D, 0x51, 0x2F, 0x6D, 0x0D, 0x02, 0xBE,
|
||||
0xC9, 0x00, 0xDC, 0x40, 0x02, 0xF0, 0x8A, 0x51, 0x22, 0xA7, 0x8A, 0x95, 0x02, 0xF0, 0xDC, 0x81,
|
||||
0x8A, 0x51, 0x22, 0xA7, 0x8A, 0x95, 0x83, 0x96, 0x06, 0x30, 0xC1, 0x01, 0xC1, 0x4A, 0x83, 0x52,
|
||||
0xDC, 0x40, 0x48, 0xC8, 0x5A, 0x7E, 0x84, 0x80, 0x38, 0x08, 0x83, 0x93, 0x00, 0x42, 0x8A, 0x51,
|
||||
0xC6, 0x27, 0x8A, 0x95, 0xED, 0x80, 0x48, 0xC8, 0xAA, 0x7E, 0x84, 0x80, 0x6D, 0x88, 0x83, 0x93,
|
||||
0x80, 0x40, 0x48, 0xC8, 0x23, 0x3E, 0x84, 0x80, 0x80, 0x88, 0x03, 0x9D, 0xD5, 0xAF, 0x43, 0x08,
|
||||
0x2D, 0x42, 0x03, 0x18, 0x90, 0xEF, 0x48, 0xC8, 0x21, 0xFE, 0x84, 0x80, 0x00, 0x48, 0x2B, 0x42,
|
||||
0x03, 0x18, 0x90, 0xEF, 0x48, 0xC8, 0x21, 0xFE, 0x84, 0x80, 0x00, 0x48, 0xFF, 0x7E, 0xA0, 0xEF,
|
||||
0x2F, 0x88, 0x43, 0x02, 0x03, 0x18, 0xD5, 0xAF, 0x48, 0xC8, 0x21, 0xFE, 0x84, 0x80, 0x29, 0x08,
|
||||
0x00, 0x42, 0x03, 0x18, 0xD5, 0xAF, 0x48, 0xC8, 0x21, 0xFE, 0x84, 0x80, 0x00, 0x48, 0x01, 0xBE,
|
||||
0xED, 0x80, 0x48, 0xC8, 0x21, 0xFE, 0x84, 0x80, 0x6D, 0x88, 0x80, 0x40, 0x08, 0xF0, 0xE1, 0x00,
|
||||
0xB6, 0xF0, 0xE2, 0x00, 0x48, 0xC8, 0x21, 0xFE, 0x84, 0x80, 0x00, 0x48, 0x20, 0x38, 0xE3, 0x40,
|
||||
0x48, 0xC8, 0xE4, 0x00, 0x0D, 0x70, 0x8A, 0x51, 0x19, 0x20, 0x8A, 0x95, 0x02, 0xF0, 0xDC, 0x81,
|
||||
0xDC, 0xCA, 0x8A, 0x51, 0x22, 0xA7, 0x8A, 0x95, 0x02, 0xF0, 0xDC, 0x81, 0x8A, 0x51, 0x22, 0xA7,
|
||||
0x8A, 0x95, 0x83, 0x96, 0xC1, 0x01, 0xC1, 0x4A, 0x83, 0x52, 0x48, 0xC8, 0x21, 0xFE, 0x84, 0x80,
|
||||
0x83, 0x93, 0x00, 0x48, 0x1F, 0xBE, 0x84, 0x80, 0x8A, 0x95, 0x00, 0x60, 0x8A, 0x95, 0xED, 0x80,
|
||||
0x48, 0xC8, 0x27, 0x7E, 0x84, 0x80, 0x6D, 0x88, 0x80, 0x40, 0x83, 0x96, 0x41, 0x4B, 0xB2, 0xEC,
|
||||
0x83, 0x52, 0x48, 0xC8, 0xAA, 0x7E, 0x84, 0x80, 0x83, 0x93, 0x00, 0x48, 0xED, 0x80, 0x48, 0xC8,
|
||||
0x27, 0x7E, 0x84, 0x80, 0x00, 0x48, 0x6D, 0x07, 0xEE, 0x80, 0x48, 0xC8, 0x25, 0x3E, 0x84, 0x80,
|
||||
0x6E, 0x88, 0x80, 0x40, 0x48, 0xC8, 0x25, 0x3E, 0x84, 0x80, 0x7F, 0x70, 0x00, 0x42, 0x48, 0xC8,
|
||||
0x03, 0x5C, 0xF7, 0x2F, 0x25, 0x3E, 0x84, 0x80, 0x7F, 0x70, 0x80, 0x40, 0x48, 0xC8, 0x25, 0x3E,
|
||||
0x84, 0x80, 0x00, 0x48, 0xDC, 0x40, 0x04, 0xF0, 0x8A, 0x51, 0x22, 0xA7, 0x8A, 0x95, 0xB2, 0xEC
|
||||
};
|
|
@ -0,0 +1,515 @@
|
|||
static uint8_t agc_firmware_sx125x[8192] = {
|
||||
0x8A, 0x51, 0xCF, 0xEF, 0x00, 0xB0, 0x8A, 0xC0, 0x04, 0x88, 0x84, 0x0A, 0x82, 0x47, 0x00, 0xF4,
|
||||
0x0F, 0xF4, 0x0C, 0x74, 0x09, 0x74, 0x09, 0x74, 0x09, 0x74, 0x0C, 0x74, 0x0F, 0xF4, 0x0C, 0x74,
|
||||
0x0F, 0xF4, 0x0C, 0x74, 0x00, 0xF4, 0x06, 0x74, 0x0C, 0x74, 0x12, 0x74, 0x18, 0x74, 0x1E, 0xF4,
|
||||
0x24, 0x74, 0x2A, 0xB4, 0x30, 0x74, 0x36, 0xF4, 0x01, 0x34, 0x01, 0x34, 0x01, 0x34, 0x02, 0x34,
|
||||
0x03, 0x74, 0x04, 0x34, 0x05, 0x74, 0x05, 0x74, 0x06, 0x74, 0x06, 0x74, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 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, 0xB6, 0x29, 0xDF, 0xC0, 0xDE, 0xC1, 0x5D, 0x88,
|
||||
0x5F, 0x18, 0xDE, 0x47, 0x03, 0xD0, 0xDD, 0x4D, 0x5D, 0x88, 0xDF, 0x58, 0xDE, 0x47, 0x03, 0xD0,
|
||||
0xDD, 0x4D, 0x5D, 0x88, 0x5F, 0x59, 0xDE, 0x47, 0x03, 0xD0, 0xDD, 0x4D, 0x5D, 0x88, 0xDF, 0x99,
|
||||
0xDE, 0x47, 0x03, 0xD0, 0xDD, 0x4D, 0x5D, 0x88, 0x5F, 0x5A, 0xDE, 0x47, 0x03, 0xD0, 0xDD, 0x4D,
|
||||
0x5D, 0x88, 0xDF, 0x9A, 0xDE, 0x47, 0x03, 0xD0, 0xDD, 0x4D, 0x5D, 0x88, 0x5F, 0x9B, 0xDE, 0x47,
|
||||
0x03, 0xD0, 0xDD, 0x4D, 0x5D, 0x88, 0xDF, 0xDB, 0xDE, 0x47, 0x5E, 0x88, 0x08, 0x40, 0xD7, 0xC1,
|
||||
0x02, 0xF0, 0x57, 0x82, 0x03, 0x18, 0x07, 0xAA, 0x57, 0x88, 0x2D, 0x7E, 0x84, 0x80, 0x83, 0x93,
|
||||
0x80, 0x81, 0x57, 0x88, 0x2B, 0x7E, 0x84, 0x80, 0x80, 0x81, 0x57, 0x88, 0x25, 0x3E, 0x84, 0x80,
|
||||
0x80, 0x81, 0x57, 0x88, 0x33, 0x7E, 0x84, 0x80, 0x80, 0x81, 0x57, 0x88, 0xA8, 0x3E, 0x84, 0x80,
|
||||
0x80, 0x81, 0x57, 0x88, 0x29, 0x3E, 0x84, 0x80, 0x80, 0x81, 0xD7, 0x0A, 0xE8, 0xE9, 0x09, 0x30,
|
||||
0xB7, 0xC1, 0xB5, 0x40, 0x10, 0xF0, 0xBB, 0x80, 0x23, 0x70, 0xB9, 0x40, 0x07, 0x70, 0xC7, 0x40,
|
||||
0x0B, 0x70, 0xC5, 0x00, 0x2D, 0xB0, 0xCD, 0x40, 0x64, 0x70, 0xC9, 0x00, 0x73, 0xF0, 0xCB, 0x40,
|
||||
0x04, 0xF0, 0xBF, 0xC0, 0x0E, 0x70, 0xBD, 0x80, 0x34, 0x70, 0xC3, 0x00, 0x84, 0x30, 0xC1, 0xC0,
|
||||
0x08, 0x40, 0x01, 0xF0, 0xA0, 0x80, 0x95, 0x41, 0x96, 0x41, 0x97, 0x81, 0x98, 0x01, 0x99, 0x41,
|
||||
0x9A, 0x41, 0x9B, 0x81, 0x9C, 0x41, 0x9E, 0x81, 0x00, 0xB0, 0xDD, 0x80, 0x5D, 0x88, 0x95, 0x00,
|
||||
0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xEF, 0xC0, 0x6F, 0xC8, 0xFE, 0xF9, 0x01, 0x38, 0xEF, 0xC0,
|
||||
0x6F, 0xC8, 0xDD, 0x80, 0x00, 0xB0, 0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88, 0x95, 0x00,
|
||||
0x17, 0x94, 0x17, 0x50, 0x00, 0xB0, 0xDD, 0x80, 0x5D, 0x88, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90,
|
||||
0x0D, 0x08, 0xEF, 0xC0, 0x6F, 0xC8, 0xEF, 0xF9, 0x10, 0x38, 0xEF, 0xC0, 0x6F, 0xC8, 0xDD, 0x80,
|
||||
0x00, 0xB0, 0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50,
|
||||
0x1C, 0x54, 0x9C, 0x94, 0x83, 0x96, 0xAC, 0x41, 0xAD, 0x81, 0x83, 0x52, 0xB3, 0x81, 0xB4, 0x41,
|
||||
0x9B, 0x81, 0x1C, 0x70, 0xDD, 0xC1, 0xDD, 0x0A, 0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88,
|
||||
0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x8A, 0x51, 0xE7, 0x21, 0x8A, 0x51, 0x3D, 0xF0, 0xDD, 0x80,
|
||||
0x5D, 0x88, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xEF, 0xC0, 0x6F, 0xC8, 0xF7, 0xFA,
|
||||
0x03, 0x9D, 0x7C, 0x2A, 0xCF, 0xC1, 0x7E, 0x6A, 0xCF, 0xC1, 0xCF, 0x0A, 0x4F, 0x88, 0x03, 0x59,
|
||||
0x85, 0xAA, 0x8A, 0x95, 0xB1, 0xA4, 0x8A, 0x51, 0x87, 0xEA, 0x01, 0xF0, 0x9B, 0x40, 0xD7, 0xC1,
|
||||
0x02, 0xF0, 0x57, 0x82, 0x03, 0x18, 0x94, 0xEB, 0x57, 0x88, 0xA8, 0x3E, 0x84, 0x80, 0x83, 0x93,
|
||||
0x00, 0xCB, 0x9C, 0xEA, 0x57, 0x88, 0x25, 0x3E, 0x84, 0x80, 0x00, 0x48, 0xEB, 0x80, 0x57, 0x88,
|
||||
0x23, 0x3E, 0x84, 0x80, 0x6B, 0x88, 0xA0, 0x6A, 0x57, 0x88, 0x23, 0x3E, 0x84, 0x80, 0x37, 0x88,
|
||||
0x80, 0x40, 0x57, 0x88, 0x23, 0x3E, 0x84, 0x80, 0x00, 0x48, 0x01, 0xBE, 0x84, 0x80, 0x8A, 0x51,
|
||||
0x02, 0xA0, 0x8A, 0x51, 0x0F, 0x39, 0xEB, 0x80, 0x03, 0xD0, 0xEB, 0x4D, 0x57, 0x88, 0x23, 0x3E,
|
||||
0x84, 0x80, 0x00, 0x48, 0x15, 0x3E, 0x84, 0x80, 0x8A, 0x51, 0x02, 0xA0, 0x8A, 0x51, 0x07, 0xF9,
|
||||
0xEC, 0x40, 0x04, 0xF0, 0x03, 0xD0, 0xEC, 0x0D, 0xFF, 0x7E, 0x03, 0xD0, 0x03, 0x9D, 0xBB, 0x6A,
|
||||
0x6C, 0xCD, 0x6B, 0x84, 0x01, 0x38, 0xED, 0x80, 0x57, 0x88, 0x21, 0xFE, 0x84, 0x80, 0x6D, 0x88,
|
||||
0x80, 0x40, 0x8C, 0x70, 0x83, 0x96, 0xB5, 0x40, 0x83, 0x52, 0x57, 0x88, 0x21, 0xFE, 0x84, 0x80,
|
||||
0x00, 0x48, 0x83, 0x96, 0xB6, 0x40, 0xB5, 0xF0, 0x83, 0x52, 0xDD, 0x80, 0x57, 0x88, 0xDE, 0x80,
|
||||
0x02, 0xF0, 0x8A, 0x95, 0x15, 0x64, 0x8A, 0x51, 0x57, 0x88, 0x23, 0x3E, 0x84, 0x80, 0x83, 0x93,
|
||||
0x00, 0x48, 0x0B, 0x3E, 0x84, 0x80, 0x8A, 0x51, 0x02, 0xA0, 0x8A, 0x51, 0xEB, 0x80, 0x57, 0x88,
|
||||
0x31, 0x3E, 0x84, 0x80, 0x6B, 0x88, 0x80, 0x40, 0x57, 0x88, 0x29, 0x3E, 0x84, 0x80, 0x00, 0xCB,
|
||||
0xFB, 0xAA, 0x57, 0x88, 0x2B, 0x7E, 0x84, 0x80, 0x00, 0x48, 0xEB, 0x80, 0x57, 0x88, 0x59, 0x7E,
|
||||
0x84, 0x80, 0x6B, 0x88, 0xFF, 0xEA, 0x57, 0x88, 0x59, 0x7E, 0x84, 0x80, 0x47, 0x48, 0x80, 0x40,
|
||||
0x06, 0x30, 0xDD, 0x80, 0x57, 0x88, 0x59, 0x7E, 0x84, 0x80, 0x47, 0x48, 0x00, 0x42, 0x8A, 0x51,
|
||||
0xBD, 0x21, 0x8A, 0x51, 0xEB, 0x80, 0x57, 0x88, 0x27, 0x7E, 0x84, 0x80, 0x6B, 0x88, 0x80, 0x40,
|
||||
0x57, 0x88, 0x27, 0x7E, 0x84, 0x80, 0x00, 0x48, 0xEB, 0x80, 0x57, 0x88, 0x31, 0x3E, 0x84, 0x80,
|
||||
0x00, 0x48, 0x6B, 0x07, 0xEC, 0x40, 0x57, 0x88, 0x2F, 0xBE, 0x84, 0x80, 0x6C, 0x48, 0x80, 0x40,
|
||||
0x57, 0x88, 0x2F, 0xBE, 0x84, 0x80, 0x7F, 0x70, 0x00, 0x42, 0x03, 0x5C, 0x2C, 0xEB, 0x57, 0x88,
|
||||
0x2F, 0xBE, 0x84, 0x80, 0x7F, 0x70, 0x80, 0x40, 0x57, 0xD8, 0x62, 0xEB, 0x57, 0x88, 0x2F, 0xBE,
|
||||
0x84, 0x80, 0x00, 0x48, 0xDD, 0x80, 0x03, 0x30, 0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88,
|
||||
0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x57, 0xD8, 0x70, 0xEB, 0x57, 0x88, 0x59, 0x7E, 0x84, 0x80,
|
||||
0x83, 0x93, 0x00, 0x48, 0xEB, 0x80, 0x01, 0xF0, 0x03, 0xD0, 0xEB, 0x4D, 0xFF, 0x7E, 0x03, 0xD0,
|
||||
0x03, 0x9D, 0x45, 0xEB, 0x6B, 0x0D, 0x02, 0xBE, 0xEF, 0xC0, 0x6F, 0xC8, 0xDD, 0x80, 0x01, 0xF0,
|
||||
0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x01, 0xF0,
|
||||
0xDD, 0xC1, 0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50,
|
||||
0xD7, 0x0A, 0x88, 0x6A, 0x57, 0x88, 0x2F, 0xBE, 0x84, 0x80, 0x00, 0x48, 0xDD, 0x80, 0x04, 0xF0,
|
||||
0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x3B, 0x6B,
|
||||
0x57, 0x88, 0x59, 0x7E, 0x84, 0x80, 0x83, 0x93, 0x00, 0x48, 0xEB, 0x80, 0x01, 0xF0, 0x03, 0xD0,
|
||||
0xEB, 0x4D, 0xFF, 0x7E, 0x03, 0xD0, 0x03, 0x9D, 0x78, 0x2B, 0x6B, 0x0D, 0x02, 0xBE, 0xEF, 0xC0,
|
||||
0x6F, 0xC8, 0xDD, 0x80, 0x02, 0xF0, 0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88, 0x95, 0x00,
|
||||
0x17, 0x94, 0x17, 0x50, 0x02, 0xF0, 0xDD, 0xC1, 0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88,
|
||||
0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x60, 0xAB, 0xD1, 0x41, 0x51, 0x08, 0xDD, 0x80, 0x05, 0x30,
|
||||
0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x51, 0x08,
|
||||
0xA0, 0xFE, 0x84, 0x80, 0x3F, 0xC8, 0x83, 0x93, 0x80, 0x40, 0x51, 0x08, 0xA0, 0xFE, 0x84, 0x80,
|
||||
0x03, 0x14, 0x00, 0xCD, 0xEF, 0xC0, 0x6F, 0xC8, 0xDD, 0x80, 0x06, 0x30, 0xDE, 0x80, 0x5D, 0x88,
|
||||
0x96, 0x00, 0x5E, 0x88, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x06, 0x30, 0xDD, 0xC1, 0xDE, 0x80,
|
||||
0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x08, 0xF0, 0xD1, 0x8A,
|
||||
0x51, 0x02, 0x03, 0x5C, 0x95, 0x2B, 0x12, 0x18, 0x1C, 0x9C, 0xCC, 0x2B, 0x1C, 0x10, 0x9B, 0xD4,
|
||||
0x00, 0xB0, 0x8A, 0x95, 0x0F, 0xA2, 0x8A, 0x51, 0x12, 0x5C, 0x1C, 0x58, 0xD5, 0x6B, 0x00, 0xB0,
|
||||
0x8A, 0x95, 0x75, 0xE1, 0x8A, 0x51, 0x1C, 0x54, 0x9B, 0x90, 0x92, 0x58, 0x9C, 0xDC, 0xDE, 0xAB,
|
||||
0x9C, 0x50, 0x9B, 0xD4, 0x01, 0xF0, 0x8A, 0x95, 0x0F, 0xA2, 0x8A, 0x51, 0x92, 0x9C, 0x9C, 0x98,
|
||||
0xE7, 0xAB, 0x01, 0xF0, 0x8A, 0x95, 0x75, 0xE1, 0x8A, 0x51, 0x9C, 0x94, 0x9B, 0x90, 0xD1, 0x41,
|
||||
0x51, 0x08, 0xDD, 0x80, 0x05, 0x30, 0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88, 0x95, 0x00,
|
||||
0x17, 0x94, 0x17, 0x50, 0x24, 0x30, 0xDD, 0x80, 0x5D, 0x88, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90,
|
||||
0x0D, 0x08, 0xD2, 0x00, 0x52, 0x08, 0x41, 0xC2, 0x03, 0x18, 0x4D, 0xEC, 0x51, 0x08, 0xA0, 0xFE,
|
||||
0x84, 0x80, 0x3D, 0x88, 0x83, 0x93, 0x00, 0x42, 0x03, 0x18, 0x4D, 0xEC, 0x51, 0x08, 0xA0, 0xFE,
|
||||
0x84, 0x80, 0x00, 0x48, 0x01, 0xBE, 0xEB, 0x80, 0x51, 0x08, 0xA0, 0xFE, 0x84, 0x80, 0x6B, 0x88,
|
||||
0x80, 0x40, 0x51, 0x08, 0xA0, 0xFE, 0x84, 0x80, 0x03, 0x14, 0x00, 0xCD, 0xEF, 0xC0, 0x6F, 0xC8,
|
||||
0xDD, 0x80, 0x06, 0x30, 0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88, 0x95, 0x00, 0x17, 0x94,
|
||||
0x17, 0x50, 0x06, 0x30, 0xDD, 0xC1, 0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88, 0x95, 0x00,
|
||||
0x17, 0x94, 0x17, 0x50, 0x08, 0xF0, 0xD1, 0x8A, 0x51, 0x02, 0x03, 0x5C, 0xE8, 0x2B, 0x59, 0xCE,
|
||||
0xF0, 0x39, 0x23, 0x04, 0x9E, 0x40, 0x21, 0x30, 0xD7, 0xC1, 0xDD, 0x80, 0x5D, 0x88, 0x95, 0x00,
|
||||
0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xD3, 0x40, 0x20, 0xF0, 0xDD, 0x80, 0x5D, 0x88, 0x95, 0x00,
|
||||
0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xD0, 0xC0, 0xD5, 0x81, 0x57, 0x88, 0x29, 0x3E, 0x84, 0x80,
|
||||
0x83, 0x93, 0x80, 0x88, 0x03, 0x59, 0x7E, 0x6C, 0x0D, 0xED, 0x43, 0x08, 0x52, 0x02, 0x03, 0x18,
|
||||
0x2A, 0xAC, 0x51, 0x08, 0xA0, 0xFE, 0x84, 0x80, 0x83, 0x93, 0x00, 0x48, 0x3F, 0xC2, 0x03, 0x18,
|
||||
0x2A, 0xAC, 0x51, 0x08, 0xA0, 0xFE, 0x84, 0x80, 0x00, 0x48, 0xFF, 0x7E, 0xEB, 0x80, 0x51, 0x08,
|
||||
0xA0, 0xFE, 0x84, 0x80, 0x6B, 0x88, 0x80, 0x40, 0x51, 0x08, 0xA0, 0xFE, 0x84, 0x80, 0x03, 0x14,
|
||||
0x00, 0xCD, 0xEF, 0xC0, 0x6F, 0xC8, 0xDD, 0x80, 0x06, 0x30, 0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00,
|
||||
0x5E, 0x88, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x06, 0x30, 0xDD, 0xC1, 0xDE, 0x80, 0x5D, 0x88,
|
||||
0x96, 0x00, 0x5E, 0x88, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x2A, 0xAC, 0x57, 0x88, 0x23, 0x3E,
|
||||
0x84, 0x80, 0x00, 0x48, 0x37, 0xC6, 0x03, 0x9D, 0x87, 0xEC, 0x49, 0x08, 0x88, 0x6C, 0x4B, 0x48,
|
||||
0xD4, 0x00, 0x53, 0x48, 0x54, 0x02, 0x03, 0x18, 0xC2, 0xAC, 0x57, 0x88, 0x59, 0x7E, 0x84, 0x80,
|
||||
0x45, 0x08, 0x00, 0x42, 0x03, 0x18, 0xC2, 0xAC, 0x57, 0x88, 0x59, 0x7E, 0x84, 0x80, 0x00, 0x48,
|
||||
0x01, 0xBE, 0xEB, 0x80, 0x57, 0x88, 0x59, 0x7E, 0x84, 0x80, 0x6B, 0x88, 0x80, 0x40, 0x57, 0x88,
|
||||
0x59, 0x7E, 0x84, 0x80, 0x00, 0x48, 0xEB, 0x80, 0x01, 0xF0, 0x03, 0xD0, 0xEB, 0x4D, 0xFF, 0x7E,
|
||||
0x03, 0xD0, 0x03, 0x9D, 0xA6, 0xEC, 0x6B, 0x0D, 0x02, 0xBE, 0xEF, 0xC0, 0x6F, 0xC8, 0xDD, 0x80,
|
||||
0x01, 0xF0, 0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50,
|
||||
0x01, 0xF0, 0xDD, 0xC1, 0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88, 0x95, 0x00, 0x17, 0x94,
|
||||
0x17, 0x50, 0xFA, 0x6C, 0x4D, 0x48, 0x53, 0x42, 0x57, 0x88, 0x03, 0x18, 0x0E, 0xED, 0x59, 0x7E,
|
||||
0x84, 0x80, 0x00, 0x48, 0x47, 0x42, 0x57, 0x88, 0x03, 0x18, 0x0E, 0xED, 0x59, 0x7E, 0x84, 0x80,
|
||||
0x00, 0x48, 0xFF, 0x7E, 0xEB, 0x80, 0x57, 0x88, 0x59, 0x7E, 0x84, 0x80, 0x6B, 0x88, 0x80, 0x40,
|
||||
0x57, 0x88, 0x59, 0x7E, 0x84, 0x80, 0x00, 0x48, 0xEB, 0x80, 0x01, 0xF0, 0x03, 0xD0, 0xEB, 0x4D,
|
||||
0xFF, 0x7E, 0x03, 0xD0, 0x03, 0x9D, 0xDF, 0xAC, 0x6B, 0x0D, 0x02, 0xBE, 0xEF, 0xC0, 0x6F, 0xC8,
|
||||
0xDD, 0x80, 0x01, 0xF0, 0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88, 0x95, 0x00, 0x17, 0x94,
|
||||
0x17, 0x50, 0x01, 0xF0, 0xDD, 0xC1, 0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88, 0x95, 0x00,
|
||||
0x17, 0x94, 0x17, 0x50, 0x06, 0x30, 0xD5, 0x81, 0xD5, 0xCA, 0xDD, 0x80, 0x57, 0x88, 0x59, 0x7E,
|
||||
0x84, 0x80, 0x47, 0x48, 0x83, 0x93, 0x00, 0x42, 0x8A, 0x51, 0xBD, 0x21, 0x8A, 0x51, 0xEB, 0x80,
|
||||
0x57, 0x88, 0x27, 0x7E, 0x84, 0x80, 0x6B, 0x88, 0x80, 0x40, 0x57, 0x88, 0xA8, 0x3E, 0x84, 0x80,
|
||||
0x80, 0x88, 0x03, 0x9D, 0xEE, 0xAD, 0x50, 0xC8, 0x39, 0x42, 0x03, 0x18, 0x78, 0x2D, 0x57, 0x88,
|
||||
0x23, 0x3E, 0x84, 0x80, 0x35, 0x48, 0x00, 0x42, 0x03, 0x18, 0x78, 0x2D, 0x57, 0x88, 0x23, 0x3E,
|
||||
0x84, 0x80, 0x00, 0x48, 0x01, 0xBE, 0xEB, 0x80, 0x57, 0x88, 0x23, 0x3E, 0x84, 0x80, 0x6B, 0x88,
|
||||
0x80, 0x40, 0x57, 0x88, 0x23, 0x3E, 0x84, 0x80, 0x00, 0x48, 0x01, 0xBE, 0x84, 0x80, 0x8A, 0x51,
|
||||
0x02, 0xA0, 0x8A, 0x51, 0x0F, 0x39, 0xEB, 0x80, 0x03, 0xD0, 0xEB, 0x4D, 0x57, 0x88, 0x23, 0x3E,
|
||||
0x84, 0x80, 0x00, 0x48, 0x15, 0x3E, 0x84, 0x80, 0x8A, 0x51, 0x02, 0xA0, 0x8A, 0x51, 0x07, 0xF9,
|
||||
0xEC, 0x40, 0x04, 0xF0, 0x03, 0xD0, 0xEC, 0x0D, 0xFF, 0x7E, 0x03, 0xD0, 0x03, 0x9D, 0x43, 0xED,
|
||||
0x6C, 0xCD, 0x6B, 0x84, 0x01, 0x38, 0xED, 0x80, 0x57, 0x88, 0x21, 0xFE, 0x84, 0x80, 0x6D, 0x88,
|
||||
0x80, 0x40, 0x8C, 0x70, 0x83, 0x96, 0xB5, 0x40, 0x83, 0x52, 0x57, 0x88, 0x21, 0xFE, 0x84, 0x80,
|
||||
0x00, 0x48, 0x83, 0x96, 0xB6, 0x40, 0xB5, 0xF0, 0x83, 0x52, 0xDD, 0x80, 0x57, 0x88, 0xDE, 0x80,
|
||||
0x02, 0xF0, 0x8A, 0x95, 0x15, 0x64, 0x8A, 0x51, 0x01, 0xF0, 0xDD, 0xC1, 0xDD, 0x0A, 0xDE, 0x80,
|
||||
0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x01, 0xF0, 0xDD, 0xC1,
|
||||
0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0xDC, 0x6D,
|
||||
0x3B, 0x88, 0x50, 0xC2, 0x03, 0x18, 0xEE, 0xAD, 0x57, 0x88, 0x23, 0x3E, 0x84, 0x80, 0x00, 0x48,
|
||||
0x37, 0x82, 0x03, 0x18, 0xEE, 0xAD, 0x57, 0x88, 0x23, 0x3E, 0x84, 0x80, 0x00, 0x48, 0xFF, 0x7E,
|
||||
0xEB, 0x80, 0x57, 0x88, 0x23, 0x3E, 0x84, 0x80, 0x6B, 0x88, 0x80, 0x40, 0x57, 0x88, 0x23, 0x3E,
|
||||
0x84, 0x80, 0x00, 0x48, 0x01, 0xBE, 0x84, 0x80, 0x8A, 0x51, 0x02, 0xA0, 0x8A, 0x51, 0x0F, 0x39,
|
||||
0xEB, 0x80, 0x03, 0xD0, 0xEB, 0x4D, 0x57, 0x88, 0x23, 0x3E, 0x84, 0x80, 0x00, 0x48, 0x15, 0x3E,
|
||||
0x84, 0x80, 0x8A, 0x51, 0x02, 0xA0, 0x8A, 0x51, 0x07, 0xF9, 0xEC, 0x40, 0x04, 0xF0, 0x03, 0xD0,
|
||||
0xEC, 0x0D, 0xFF, 0x7E, 0x03, 0xD0, 0x03, 0x9D, 0xA8, 0xED, 0x6C, 0xCD, 0x6B, 0x84, 0x01, 0x38,
|
||||
0xED, 0x80, 0x57, 0x88, 0x21, 0xFE, 0x84, 0x80, 0x6D, 0x88, 0x80, 0x40, 0x8C, 0x70, 0x83, 0x96,
|
||||
0xB5, 0x40, 0x83, 0x52, 0x57, 0x88, 0x21, 0xFE, 0x84, 0x80, 0x00, 0x48, 0x83, 0x96, 0xB6, 0x40,
|
||||
0xB5, 0xF0, 0x83, 0x52, 0xDD, 0x80, 0x57, 0x88, 0xDE, 0x80, 0x02, 0xF0, 0x8A, 0x95, 0x15, 0x64,
|
||||
0x8A, 0x51, 0x01, 0xF0, 0xDD, 0xC1, 0xDD, 0x0A, 0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88,
|
||||
0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x01, 0xF0, 0xDD, 0xC1, 0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00,
|
||||
0x5E, 0x88, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0xD5, 0x81, 0xD5, 0xCA, 0x57, 0x88, 0x23, 0x3E,
|
||||
0x84, 0x80, 0x83, 0x93, 0x00, 0x48, 0x0B, 0x3E, 0x84, 0x80, 0x8A, 0x51, 0x02, 0xA0, 0x8A, 0x51,
|
||||
0xEB, 0x80, 0x57, 0x88, 0x31, 0x3E, 0x84, 0x80, 0x6B, 0x88, 0x80, 0x40, 0x55, 0xCB, 0x19, 0xEE,
|
||||
0x57, 0x88, 0x27, 0x7E, 0x84, 0x80, 0x00, 0x48, 0xEB, 0x80, 0x57, 0x88, 0x31, 0x3E, 0x84, 0x80,
|
||||
0x00, 0x48, 0x6B, 0x07, 0xEC, 0x40, 0x57, 0x88, 0x2F, 0xBE, 0x84, 0x80, 0x6C, 0x48, 0x80, 0x40,
|
||||
0x57, 0x88, 0x2F, 0xBE, 0x84, 0x80, 0x7F, 0x70, 0x00, 0x42, 0x57, 0x88, 0x03, 0x5C, 0x0D, 0xEE,
|
||||
0x2F, 0xBE, 0x84, 0x80, 0x7F, 0x70, 0x80, 0x40, 0x57, 0x88, 0x2F, 0xBE, 0x84, 0x80, 0x00, 0x48,
|
||||
0xDD, 0x80, 0x03, 0x30, 0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88, 0x95, 0x00, 0x17, 0x94,
|
||||
0x17, 0x50, 0x23, 0x70, 0xD7, 0xC1, 0xD7, 0x0A, 0xDD, 0x80, 0x5D, 0x88, 0x95, 0x00, 0x97, 0xD4,
|
||||
0x97, 0x90, 0x0D, 0x08, 0xD3, 0x40, 0x22, 0x30, 0xDD, 0x80, 0x5D, 0x88, 0x95, 0x00, 0x97, 0xD4,
|
||||
0x97, 0x90, 0x0D, 0x08, 0xD0, 0xC0, 0xD6, 0x81, 0x57, 0x88, 0x29, 0x3E, 0x84, 0x80, 0x83, 0x93,
|
||||
0x80, 0x88, 0x03, 0x9D, 0xC2, 0xEE, 0x57, 0x88, 0x23, 0x3E, 0x84, 0x80, 0x00, 0x48, 0x37, 0xC6,
|
||||
0x03, 0x9D, 0x3C, 0x2E, 0x49, 0x08, 0x3D, 0x6E, 0x4B, 0x48, 0xD4, 0x00, 0x53, 0x48, 0x54, 0x02,
|
||||
0x03, 0x18, 0x77, 0xAE, 0x57, 0x88, 0x59, 0x7E, 0x84, 0x80, 0x45, 0x08, 0x00, 0x42, 0x03, 0x18,
|
||||
0x77, 0xAE, 0x57, 0x88, 0x59, 0x7E, 0x84, 0x80, 0x00, 0x48, 0x01, 0xBE, 0xEB, 0x80, 0x57, 0x88,
|
||||
0x59, 0x7E, 0x84, 0x80, 0x6B, 0x88, 0x80, 0x40, 0x57, 0x88, 0x59, 0x7E, 0x84, 0x80, 0x00, 0x48,
|
||||
0xEB, 0x80, 0x01, 0xF0, 0x03, 0xD0, 0xEB, 0x4D, 0xFF, 0x7E, 0x03, 0xD0, 0x03, 0x9D, 0x5B, 0x6E,
|
||||
0x6B, 0x0D, 0x02, 0xBE, 0xEF, 0xC0, 0x6F, 0xC8, 0xDD, 0x80, 0x02, 0xF0, 0xDE, 0x80, 0x5D, 0x88,
|
||||
0x96, 0x00, 0x5E, 0x88, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x02, 0xF0, 0xDD, 0xC1, 0xDE, 0x80,
|
||||
0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0xAF, 0xAE, 0x4D, 0x48,
|
||||
0x53, 0x42, 0x57, 0x88, 0x03, 0x18, 0xC3, 0x2E, 0x59, 0x7E, 0x84, 0x80, 0x00, 0x48, 0x47, 0x42,
|
||||
0x57, 0x88, 0x03, 0x18, 0xC3, 0x2E, 0x59, 0x7E, 0x84, 0x80, 0x00, 0x48, 0xFF, 0x7E, 0xEB, 0x80,
|
||||
0x57, 0x88, 0x59, 0x7E, 0x84, 0x80, 0x6B, 0x88, 0x80, 0x40, 0x57, 0x88, 0x59, 0x7E, 0x84, 0x80,
|
||||
0x00, 0x48, 0xEB, 0x80, 0x01, 0xF0, 0x03, 0xD0, 0xEB, 0x4D, 0xFF, 0x7E, 0x03, 0xD0, 0x03, 0x9D,
|
||||
0x94, 0xEE, 0x6B, 0x0D, 0x02, 0xBE, 0xEF, 0xC0, 0x6F, 0xC8, 0xDD, 0x80, 0x02, 0xF0, 0xDE, 0x80,
|
||||
0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x02, 0xF0, 0xDD, 0xC1,
|
||||
0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x06, 0x30,
|
||||
0xD6, 0x81, 0xD6, 0xCA, 0xDD, 0x80, 0x57, 0x88, 0x59, 0x7E, 0x84, 0x80, 0x47, 0x48, 0x83, 0x93,
|
||||
0x00, 0x42, 0x8A, 0x51, 0xBD, 0x21, 0x8A, 0x51, 0xEB, 0x80, 0x57, 0x88, 0x27, 0x7E, 0x84, 0x80,
|
||||
0x6B, 0x88, 0x80, 0x40, 0x57, 0x88, 0xA8, 0x3E, 0x84, 0x80, 0x80, 0x88, 0x03, 0x9D, 0xA3, 0x6F,
|
||||
0x50, 0xC8, 0x39, 0x42, 0x03, 0x18, 0x2D, 0x6F, 0x57, 0x88, 0x23, 0x3E, 0x84, 0x80, 0x35, 0x48,
|
||||
0x00, 0x42, 0x03, 0x18, 0x2D, 0x6F, 0x57, 0x88, 0x23, 0x3E, 0x84, 0x80, 0x00, 0x48, 0x01, 0xBE,
|
||||
0xEB, 0x80, 0x57, 0x88, 0x23, 0x3E, 0x84, 0x80, 0x6B, 0x88, 0x80, 0x40, 0x57, 0x88, 0x23, 0x3E,
|
||||
0x84, 0x80, 0x00, 0x48, 0x01, 0xBE, 0x84, 0x80, 0x8A, 0x51, 0x02, 0xA0, 0x8A, 0x51, 0x0F, 0x39,
|
||||
0xEB, 0x80, 0x03, 0xD0, 0xEB, 0x4D, 0x57, 0x88, 0x23, 0x3E, 0x84, 0x80, 0x00, 0x48, 0x15, 0x3E,
|
||||
0x84, 0x80, 0x8A, 0x51, 0x02, 0xA0, 0x8A, 0x51, 0x07, 0xF9, 0xEC, 0x40, 0x04, 0xF0, 0x03, 0xD0,
|
||||
0xEC, 0x0D, 0xFF, 0x7E, 0x03, 0xD0, 0x03, 0x9D, 0xF8, 0x6E, 0x6C, 0xCD, 0x6B, 0x84, 0x01, 0x38,
|
||||
0xED, 0x80, 0x57, 0x88, 0x21, 0xFE, 0x84, 0x80, 0x6D, 0x88, 0x80, 0x40, 0x8C, 0x70, 0x83, 0x96,
|
||||
0xB5, 0x40, 0x83, 0x52, 0x57, 0x88, 0x21, 0xFE, 0x84, 0x80, 0x00, 0x48, 0x83, 0x96, 0xB6, 0x40,
|
||||
0xB5, 0xF0, 0x83, 0x52, 0xDD, 0x80, 0x57, 0x88, 0xDE, 0x80, 0x02, 0xF0, 0x8A, 0x95, 0x15, 0x64,
|
||||
0x8A, 0x51, 0x02, 0xF0, 0xDD, 0xC1, 0xDD, 0x0A, 0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88,
|
||||
0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x02, 0xF0, 0xDD, 0xC1, 0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00,
|
||||
0x5E, 0x88, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x91, 0x2F, 0x3B, 0x88, 0x50, 0xC2, 0x03, 0x18,
|
||||
0xA3, 0x6F, 0x57, 0x88, 0x23, 0x3E, 0x84, 0x80, 0x00, 0x48, 0x37, 0x82, 0x03, 0x18, 0xA3, 0x6F,
|
||||
0x57, 0x88, 0x23, 0x3E, 0x84, 0x80, 0x00, 0x48, 0xFF, 0x7E, 0xEB, 0x80, 0x57, 0x88, 0x23, 0x3E,
|
||||
0x84, 0x80, 0x6B, 0x88, 0x80, 0x40, 0x57, 0x88, 0x23, 0x3E, 0x84, 0x80, 0x00, 0x48, 0x01, 0xBE,
|
||||
0x84, 0x80, 0x8A, 0x51, 0x02, 0xA0, 0x8A, 0x51, 0x0F, 0x39, 0xEB, 0x80, 0x03, 0xD0, 0xEB, 0x4D,
|
||||
0x57, 0x88, 0x23, 0x3E, 0x84, 0x80, 0x00, 0x48, 0x15, 0x3E, 0x84, 0x80, 0x8A, 0x51, 0x02, 0xA0,
|
||||
0x8A, 0x51, 0x07, 0xF9, 0xEC, 0x40, 0x04, 0xF0, 0x03, 0xD0, 0xEC, 0x0D, 0xFF, 0x7E, 0x03, 0xD0,
|
||||
0x03, 0x9D, 0x5D, 0xAF, 0x6C, 0xCD, 0x6B, 0x84, 0x01, 0x38, 0xED, 0x80, 0x57, 0x88, 0x21, 0xFE,
|
||||
0x84, 0x80, 0x6D, 0x88, 0x80, 0x40, 0x8C, 0x70, 0x83, 0x96, 0xB5, 0x40, 0x83, 0x52, 0x57, 0x88,
|
||||
0x21, 0xFE, 0x84, 0x80, 0x00, 0x48, 0x83, 0x96, 0xB6, 0x40, 0xB5, 0xF0, 0x83, 0x52, 0xDD, 0x80,
|
||||
0x57, 0x88, 0xDE, 0x80, 0x02, 0xF0, 0x8A, 0x95, 0x15, 0x64, 0x8A, 0x51, 0x02, 0xF0, 0xDD, 0xC1,
|
||||
0xDD, 0x0A, 0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50,
|
||||
0x02, 0xF0, 0xDD, 0xC1, 0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88, 0x95, 0x00, 0x17, 0x94,
|
||||
0x17, 0x50, 0xD6, 0x81, 0xD6, 0xCA, 0x57, 0x88, 0x23, 0x3E, 0x84, 0x80, 0x83, 0x93, 0x00, 0x48,
|
||||
0x0B, 0x3E, 0x84, 0x80, 0x8A, 0x51, 0x02, 0xA0, 0x8A, 0x51, 0xEB, 0x80, 0x57, 0x88, 0x31, 0x3E,
|
||||
0x84, 0x80, 0x6B, 0x88, 0x80, 0x40, 0x56, 0xCB, 0xC3, 0x2B, 0x57, 0x88, 0x27, 0x7E, 0x84, 0x80,
|
||||
0x00, 0x48, 0xEB, 0x80, 0x57, 0x88, 0x31, 0x3E, 0x84, 0x80, 0x00, 0x48, 0x6B, 0x07, 0xEC, 0x40,
|
||||
0x57, 0x88, 0x2F, 0xBE, 0x84, 0x80, 0x6C, 0x48, 0x80, 0x40, 0x57, 0x88, 0x2F, 0xBE, 0x84, 0x80,
|
||||
0x7F, 0x70, 0x00, 0x42, 0x57, 0x88, 0x03, 0x5C, 0xC2, 0x2F, 0x2F, 0xBE, 0x84, 0x80, 0x7F, 0x70,
|
||||
0x80, 0x40, 0x57, 0x88, 0x2F, 0xBE, 0x84, 0x80, 0x00, 0x48, 0xDD, 0x80, 0x04, 0xF0, 0xDE, 0x80,
|
||||
0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0xC3, 0x2B, 0xEE, 0xC1,
|
||||
0x83, 0x93, 0x23, 0x70, 0x84, 0x80, 0x5D, 0xF0, 0x8A, 0x51, 0xB5, 0xE1, 0x8A, 0x51, 0xA0, 0x30,
|
||||
0x84, 0x80, 0xD5, 0xF0, 0x8A, 0x51, 0xB5, 0xE1, 0x83, 0x96, 0x38, 0x70, 0xD5, 0x40, 0x3A, 0xB0,
|
||||
0xD6, 0x40, 0x3C, 0xB0, 0xD7, 0x80, 0x78, 0xB0, 0xD8, 0x00, 0x7A, 0xF0, 0xD9, 0x40, 0x7C, 0xF0,
|
||||
0xDA, 0x40, 0x7D, 0x30, 0xDB, 0x80, 0x7F, 0x70, 0xDC, 0x40, 0xB9, 0xF0, 0xDD, 0x80, 0xBA, 0xF0,
|
||||
0xDE, 0x80, 0xBB, 0x30, 0xDF, 0xC0, 0xFA, 0x30, 0xE0, 0xC0, 0xFB, 0x70, 0xE1, 0x00, 0xFC, 0x30,
|
||||
0xE2, 0x00, 0xFD, 0x70, 0xE3, 0x40, 0xFF, 0xB0, 0xE4, 0x00, 0x83, 0x01, 0x8A, 0x51, 0x21, 0x6A,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xE4, 0x00, 0x64, 0x9C, 0xDD, 0x69,
|
||||
0x00, 0xB0, 0xDD, 0x80, 0x5D, 0x88, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xEF, 0xC0,
|
||||
0x3F, 0x30, 0xEF, 0x45, 0x6F, 0xC8, 0xDD, 0x80, 0x00, 0xB0, 0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00,
|
||||
0x5E, 0x88, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0xE4, 0xB0, 0xE2, 0x00, 0x8F, 0x29, 0x90, 0x69,
|
||||
0xE2, 0xCB, 0x8E, 0xE9, 0x93, 0xE9, 0x00, 0x00, 0x83, 0x52, 0x03, 0x53, 0x64, 0x9C, 0xF2, 0x29,
|
||||
0x00, 0xB0, 0xDD, 0x80, 0x5D, 0x88, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xEF, 0xC0,
|
||||
0x6F, 0xC8, 0xEF, 0xF9, 0x10, 0x38, 0xEF, 0xC0, 0x6F, 0xC8, 0xDD, 0x80, 0x00, 0xB0, 0xDE, 0x80,
|
||||
0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x80, 0xF0, 0x83, 0x96,
|
||||
0xB5, 0x40, 0x03, 0x30, 0xB6, 0x40, 0xB5, 0xF0, 0x83, 0x52, 0xDD, 0x80, 0x64, 0x08, 0xDE, 0x80,
|
||||
0x02, 0xF0, 0x15, 0x64, 0x8A, 0x95, 0x04, 0xF0, 0xE3, 0x40, 0x1C, 0x70, 0xE2, 0x00, 0xE2, 0xCB,
|
||||
0xBF, 0xA9, 0xE3, 0x0B, 0xBF, 0xA9, 0x00, 0x00, 0x91, 0x70, 0x83, 0x96, 0x03, 0x53, 0xB5, 0x40,
|
||||
0x83, 0x52, 0x64, 0x08, 0xAE, 0xBE, 0x84, 0x80, 0x83, 0x93, 0x00, 0x48, 0x83, 0x96, 0xB6, 0x40,
|
||||
0xB5, 0xF0, 0x83, 0x52, 0xDD, 0x80, 0x64, 0x08, 0xDE, 0x80, 0x02, 0xF0, 0x15, 0x64, 0x8A, 0x95,
|
||||
0x83, 0x96, 0xAE, 0x1C, 0xAF, 0x18, 0x09, 0x6A, 0x0C, 0x6A, 0x00, 0xB0, 0xDD, 0x80, 0x5D, 0x88,
|
||||
0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xEF, 0xC0, 0xF3, 0x30, 0xEF, 0x45, 0x6F, 0xC8,
|
||||
0xDD, 0x80, 0x00, 0xB0, 0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88, 0x95, 0x00, 0x17, 0x94,
|
||||
0x17, 0x50, 0x8C, 0xA9, 0x00, 0xB0, 0xDD, 0x80, 0x5D, 0x88, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90,
|
||||
0x0D, 0x08, 0xEF, 0xC0, 0x6F, 0xC8, 0xFE, 0xF9, 0x01, 0x38, 0xEF, 0xC0, 0x6F, 0xC8, 0xDD, 0x80,
|
||||
0x00, 0xB0, 0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50,
|
||||
0xAE, 0x29, 0x83, 0x52, 0x1B, 0x92, 0x08, 0x40, 0x83, 0x52, 0x1B, 0xD6, 0x08, 0x40, 0xEA, 0x40,
|
||||
0x6A, 0x98, 0x1A, 0xAA, 0x25, 0x70, 0xDD, 0x80, 0x5D, 0x88, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90,
|
||||
0x0D, 0x08, 0x21, 0x6A, 0x2A, 0x70, 0xDD, 0x80, 0x5D, 0x88, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90,
|
||||
0x0D, 0x08, 0xE6, 0x40, 0xE9, 0x40, 0x3F, 0x30, 0xE9, 0xC5, 0x88, 0x30, 0x83, 0x96, 0xB5, 0x40,
|
||||
0x83, 0x52, 0x69, 0x48, 0x83, 0x96, 0xB6, 0x40, 0xB5, 0xF0, 0x83, 0x52, 0xDD, 0x80, 0x6A, 0x48,
|
||||
0xDE, 0x80, 0x02, 0xF0, 0x15, 0x64, 0x8A, 0x95, 0x66, 0x48, 0xE3, 0x40, 0x06, 0x30, 0x03, 0xD0,
|
||||
0xE3, 0xCC, 0xFF, 0x7E, 0x03, 0x9D, 0x37, 0x2A, 0x63, 0x48, 0xE9, 0x40, 0x03, 0x30, 0xE9, 0xC5,
|
||||
0x6A, 0x98, 0x68, 0xAA, 0x00, 0xB0, 0xDD, 0x80, 0x5D, 0x88, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90,
|
||||
0x0D, 0x08, 0xEF, 0xC0, 0x69, 0x48, 0xE3, 0x40, 0x03, 0xD0, 0xE3, 0x0D, 0x03, 0xD0, 0xE3, 0x0D,
|
||||
0x6F, 0xC8, 0xF3, 0xB9, 0x63, 0x44, 0xEF, 0xC0, 0x6F, 0xC8, 0xDD, 0x80, 0x00, 0xB0, 0xDE, 0x80,
|
||||
0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x6A, 0x98, 0x87, 0xEA,
|
||||
0x26, 0x70, 0xDD, 0x80, 0x5D, 0x88, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0x8E, 0xEA,
|
||||
0x00, 0xB0, 0xDD, 0x80, 0x5D, 0x88, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xEF, 0xC0,
|
||||
0x69, 0x48, 0xE3, 0x40, 0x06, 0x30, 0x03, 0xD0, 0xE3, 0x0D, 0xFF, 0x7E, 0x03, 0x9D, 0x73, 0x2A,
|
||||
0x6F, 0xC8, 0x3F, 0xB9, 0x63, 0x44, 0xEF, 0xC0, 0x6F, 0xC8, 0xDD, 0x80, 0x00, 0xB0, 0xDE, 0x80,
|
||||
0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x5E, 0x2A, 0x2B, 0xB0,
|
||||
0xDD, 0x80, 0x5D, 0x88, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xE9, 0x40, 0x07, 0x70,
|
||||
0xE9, 0xC5, 0x06, 0x30, 0x69, 0x42, 0x03, 0x5C, 0xA7, 0x2A, 0x8A, 0x70, 0x83, 0x96, 0xB5, 0x40,
|
||||
0x6A, 0xB0, 0xB6, 0x40, 0xB5, 0xF0, 0x83, 0x52, 0xDD, 0x80, 0x6A, 0x48, 0xDE, 0x80, 0x02, 0xF0,
|
||||
0x15, 0x64, 0x8A, 0x95, 0x8B, 0xB0, 0x83, 0x96, 0xB5, 0x40, 0x04, 0xF0, 0xC0, 0x6A, 0x69, 0x48,
|
||||
0x05, 0xBA, 0x8A, 0x70, 0x03, 0x9D, 0xB1, 0xEA, 0x83, 0x96, 0xB5, 0x40, 0x20, 0xF0, 0xB6, 0x40,
|
||||
0xB4, 0xEA, 0x83, 0x96, 0xB5, 0x40, 0xB6, 0x81, 0xB5, 0xF0, 0x83, 0x52, 0xDD, 0x80, 0x6A, 0x48,
|
||||
0xDE, 0x80, 0x02, 0xF0, 0x15, 0x64, 0x8A, 0x95, 0x8B, 0xB0, 0x83, 0x96, 0xB5, 0x40, 0x05, 0x30,
|
||||
0xB6, 0x40, 0xB5, 0xF0, 0x83, 0x52, 0xDD, 0x80, 0x6A, 0x48, 0xDE, 0x80, 0x02, 0xF0, 0x15, 0x64,
|
||||
0x8A, 0x95, 0x6A, 0x98, 0xE3, 0x2A, 0x27, 0xB0, 0xDD, 0x80, 0x5D, 0x88, 0x95, 0x00, 0x97, 0xD4,
|
||||
0x97, 0x90, 0x0D, 0x08, 0xE5, 0x40, 0x28, 0x30, 0xDD, 0x80, 0x5D, 0x88, 0x95, 0x00, 0x97, 0xD4,
|
||||
0x97, 0x90, 0x0D, 0x08, 0xE9, 0x40, 0x29, 0x70, 0xDD, 0x80, 0x5D, 0x88, 0x95, 0x00, 0x97, 0xD4,
|
||||
0x97, 0x90, 0x0D, 0x08, 0xFA, 0x6A, 0x2C, 0x70, 0xDD, 0x80, 0x5D, 0x88, 0x95, 0x00, 0x97, 0xD4,
|
||||
0x97, 0x90, 0x0D, 0x08, 0xE5, 0x40, 0x2D, 0xB0, 0xDD, 0x80, 0x5D, 0x88, 0x95, 0x00, 0x97, 0xD4,
|
||||
0x97, 0x90, 0x0D, 0x08, 0xE9, 0x40, 0x2E, 0xB0, 0xDD, 0x80, 0x5D, 0x88, 0x95, 0x00, 0x97, 0xD4,
|
||||
0x97, 0x90, 0x0D, 0x08, 0xE7, 0x80, 0x69, 0x48, 0xE3, 0x40, 0x07, 0x70, 0x03, 0xD0, 0xE3, 0xCC,
|
||||
0xFF, 0x7E, 0x03, 0xD0, 0x03, 0x9D, 0xFF, 0xEA, 0x65, 0xCD, 0x63, 0x44, 0xE8, 0x00, 0x84, 0x30,
|
||||
0x83, 0x96, 0xB5, 0x40, 0x83, 0x52, 0x68, 0x08, 0x83, 0x96, 0xB6, 0x40, 0xB5, 0xF0, 0x83, 0x52,
|
||||
0xDD, 0x80, 0x6A, 0x48, 0xDE, 0x80, 0x02, 0xF0, 0x15, 0x64, 0x8A, 0x95, 0x67, 0x88, 0xE3, 0x40,
|
||||
0x07, 0x70, 0x03, 0xD0, 0xE3, 0xCC, 0xFF, 0x7E, 0x03, 0xD0, 0x03, 0x9D, 0x1A, 0xEB, 0x69, 0xCD,
|
||||
0x63, 0x44, 0xE8, 0x00, 0x85, 0x70, 0x83, 0x96, 0xB5, 0x40, 0x83, 0x52, 0x68, 0x08, 0x83, 0x96,
|
||||
0xB6, 0x40, 0xB5, 0xF0, 0x83, 0x52, 0xDD, 0x80, 0x6A, 0x48, 0xDE, 0x80, 0x02, 0xF0, 0x15, 0x64,
|
||||
0x8A, 0x95, 0x03, 0xD0, 0x67, 0x0D, 0xE8, 0x00, 0x86, 0x70, 0x83, 0x96, 0xB5, 0x40, 0x83, 0x52,
|
||||
0x68, 0x08, 0x83, 0x96, 0xB6, 0x40, 0xB5, 0xF0, 0x83, 0x52, 0xDD, 0x80, 0x6A, 0x48, 0xDE, 0x80,
|
||||
0x02, 0xF0, 0x15, 0x64, 0x8A, 0x95, 0x6A, 0x48, 0x2D, 0x7E, 0x84, 0x80, 0x83, 0x93, 0x80, 0x88,
|
||||
0x03, 0x59, 0x4F, 0x6B, 0x6A, 0x48, 0x5B, 0xBE, 0x84, 0x80, 0x03, 0x30, 0x53, 0x2B, 0x6A, 0x48,
|
||||
0x5B, 0xBE, 0x84, 0x80, 0x01, 0xF0, 0x80, 0x40, 0x80, 0xF0, 0x83, 0x96, 0xB5, 0x40, 0x83, 0x52,
|
||||
0x6A, 0x48, 0x5B, 0xBE, 0x84, 0x80, 0x00, 0x48, 0x04, 0x38, 0x83, 0x96, 0xB6, 0x40, 0xB5, 0xF0,
|
||||
0x83, 0x52, 0xDD, 0x80, 0x6A, 0x48, 0xDE, 0x80, 0x02, 0xF0, 0x15, 0x64, 0x8A, 0x95, 0x03, 0x30,
|
||||
0xE4, 0x00, 0x7D, 0x30, 0xE3, 0x40, 0xE3, 0x0B, 0x6B, 0x6B, 0xE4, 0xCB, 0x6B, 0x6B, 0x83, 0x52,
|
||||
0x03, 0x53, 0x6A, 0xDC, 0x87, 0x2B, 0x00, 0xB0, 0xDD, 0x80, 0x5D, 0x88, 0x95, 0x00, 0x97, 0xD4,
|
||||
0x97, 0x90, 0x0D, 0x08, 0xEF, 0xC0, 0x6F, 0x12, 0x6F, 0xC8, 0xDD, 0x80, 0x00, 0xB0, 0xDE, 0x80,
|
||||
0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x9A, 0x2B, 0x00, 0xB0,
|
||||
0xDD, 0x80, 0x5D, 0x88, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xEF, 0xC0, 0x6F, 0xD0,
|
||||
0x6F, 0xC8, 0xDD, 0x80, 0x00, 0xB0, 0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88, 0x95, 0x00,
|
||||
0x17, 0x94, 0x17, 0x50, 0x05, 0x30, 0xE3, 0x40, 0xE3, 0x0B, 0x9C, 0x2B, 0x83, 0x52, 0x03, 0x53,
|
||||
0x6A, 0xDC, 0xFC, 0xAB, 0x00, 0xB0, 0xDD, 0x80, 0x5D, 0x88, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90,
|
||||
0x0D, 0x08, 0xEF, 0xC0, 0x6F, 0xC8, 0xDF, 0xF9, 0x20, 0x38, 0xEF, 0xC0, 0x6F, 0xC8, 0xDD, 0x80,
|
||||
0x00, 0xB0, 0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50,
|
||||
0x15, 0x70, 0xE4, 0x00, 0xC6, 0xB0, 0xE3, 0x40, 0xE3, 0x0B, 0xBC, 0x6B, 0xE4, 0xCB, 0xBC, 0x6B,
|
||||
0x00, 0x00, 0x80, 0xF0, 0x83, 0x96, 0x03, 0x53, 0xB5, 0x40, 0x83, 0x52, 0x6A, 0x48, 0x5B, 0xBE,
|
||||
0x84, 0x80, 0x83, 0x93, 0x00, 0x48, 0x0C, 0x78, 0x83, 0x96, 0xB6, 0x40, 0xB5, 0xF0, 0x83, 0x52,
|
||||
0xDD, 0x80, 0x6A, 0x48, 0xDE, 0x80, 0x02, 0xF0, 0x15, 0x64, 0x8A, 0x95, 0x04, 0xF0, 0xE4, 0x00,
|
||||
0x1C, 0x70, 0xE3, 0x40, 0xE3, 0x0B, 0xDA, 0x6B, 0xE4, 0xCB, 0xDA, 0x6B, 0x00, 0x00, 0x11, 0x30,
|
||||
0x83, 0x96, 0x03, 0x53, 0xB5, 0x40, 0x55, 0xB0, 0xB6, 0x40, 0xB5, 0xF0, 0x83, 0x52, 0xDD, 0x80,
|
||||
0x6A, 0x48, 0xDE, 0x80, 0x02, 0xF0, 0x4E, 0xA4, 0x8A, 0x95, 0x6A, 0x48, 0xAE, 0xBE, 0x84, 0x80,
|
||||
0x83, 0x96, 0x35, 0x48, 0x83, 0x93, 0x80, 0x40, 0x83, 0x52, 0x6A, 0x48, 0xAE, 0xBE, 0x84, 0x80,
|
||||
0x00, 0xDC, 0x13, 0xAC, 0x9B, 0xD2, 0x08, 0x40, 0x00, 0xB0, 0xDD, 0x80, 0x5D, 0x88, 0x95, 0x00,
|
||||
0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xEF, 0xC0, 0x6F, 0xC8, 0xFD, 0xF9, 0x02, 0x38, 0xEF, 0xC0,
|
||||
0x6F, 0xC8, 0xDD, 0x80, 0x00, 0xB0, 0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88, 0x95, 0x00,
|
||||
0x17, 0x94, 0x17, 0x50, 0xB8, 0x2B, 0x9B, 0x16, 0x08, 0x40, 0xE0, 0xC0, 0x5E, 0xD8, 0x33, 0xEC,
|
||||
0xE1, 0x41, 0x60, 0xC8, 0x61, 0x02, 0x03, 0x18, 0x28, 0x6C, 0x61, 0x08, 0x5D, 0x07, 0xDF, 0xC0,
|
||||
0x84, 0x80, 0x83, 0x93, 0x00, 0x48, 0x99, 0x00, 0x18, 0x14, 0x18, 0xD0, 0xE1, 0x8A, 0x19, 0xAC,
|
||||
0x18, 0x55, 0x18, 0x11, 0x83, 0x52, 0x03, 0x53, 0x11, 0x5C, 0x08, 0x40, 0x05, 0x30, 0xDF, 0xC0,
|
||||
0xDF, 0x8B, 0x30, 0x6C, 0x2A, 0xAC, 0xE1, 0x41, 0x60, 0xC8, 0x61, 0x02, 0x03, 0x18, 0x43, 0xAC,
|
||||
0x61, 0x08, 0x5D, 0x07, 0xDF, 0xC0, 0x84, 0x80, 0x83, 0x93, 0x00, 0x48, 0x9A, 0x00, 0x98, 0x95,
|
||||
0x98, 0x51, 0xE1, 0x8A, 0x34, 0xAC, 0x98, 0x96, 0x98, 0x52, 0x83, 0x52, 0x03, 0x53, 0x91, 0x9C,
|
||||
0x08, 0x40, 0x05, 0x30, 0xDF, 0xC0, 0xDF, 0x8B, 0x4B, 0xEC, 0x45, 0xAC, 0xE0, 0xC0, 0x10, 0xF0,
|
||||
0x60, 0xC2, 0x03, 0x5C, 0x55, 0xEC, 0x10, 0xF0, 0x56, 0xEC, 0x60, 0xC8, 0xE1, 0x00, 0x5E, 0xD8,
|
||||
0x85, 0xAC, 0xE2, 0x41, 0x61, 0x08, 0x62, 0x02, 0x03, 0x18, 0x69, 0xEC, 0x62, 0x08, 0x5D, 0x07,
|
||||
0xDF, 0xC0, 0x84, 0x80, 0x83, 0x93, 0x00, 0x48, 0x99, 0x00, 0x18, 0x14, 0x18, 0xD0, 0xE2, 0x8A,
|
||||
0x5A, 0xEC, 0x18, 0x55, 0x18, 0x11, 0x83, 0x52, 0x03, 0x53, 0x11, 0x5C, 0x75, 0x2C, 0x2A, 0x70,
|
||||
0xDF, 0xC0, 0xDF, 0x8B, 0x71, 0xEC, 0x00, 0x00, 0x6B, 0x2C, 0xE2, 0x41, 0x61, 0x08, 0x62, 0x02,
|
||||
0x03, 0x18, 0x08, 0x40, 0x62, 0x08, 0x5D, 0x07, 0xDF, 0xC0, 0x84, 0x80, 0x0F, 0x48, 0x83, 0x93,
|
||||
0x80, 0x40, 0x98, 0x54, 0x98, 0x10, 0xE2, 0x8A, 0x76, 0x2C, 0xE2, 0x41, 0x61, 0x08, 0x62, 0x02,
|
||||
0x03, 0x18, 0x95, 0xEC, 0x62, 0x08, 0x5D, 0x07, 0xDF, 0xC0, 0x84, 0x80, 0x83, 0x93, 0x00, 0x48,
|
||||
0x9A, 0x00, 0x98, 0x95, 0x98, 0x51, 0xE2, 0x8A, 0x86, 0xAC, 0x98, 0x96, 0x98, 0x52, 0x83, 0x52,
|
||||
0x03, 0x53, 0x91, 0x9C, 0xA1, 0xAC, 0x2A, 0x70, 0xDF, 0xC0, 0xDF, 0x8B, 0x9D, 0x2C, 0x00, 0x00,
|
||||
0x97, 0x2C, 0xE2, 0x41, 0x61, 0x08, 0x62, 0x02, 0x03, 0x18, 0x08, 0x40, 0x62, 0x08, 0x5D, 0x07,
|
||||
0xDF, 0xC0, 0x84, 0x80, 0x10, 0x88, 0x83, 0x93, 0x80, 0x40, 0x18, 0x56, 0x18, 0x12, 0xE2, 0x8A,
|
||||
0xA2, 0xAC, 0x55, 0xB0, 0x9B, 0x40, 0xD7, 0xC1, 0x02, 0xF0, 0x57, 0x82, 0x03, 0x18, 0xC9, 0x2D,
|
||||
0x57, 0x88, 0x01, 0xBE, 0x9B, 0x40, 0x57, 0x88, 0x33, 0x7E, 0x84, 0x80, 0x83, 0x93, 0x80, 0x81,
|
||||
0x57, 0x88, 0x33, 0x7E, 0x84, 0x80, 0x80, 0x88, 0x03, 0x9D, 0xEC, 0x2C, 0x3C, 0xB0, 0xDD, 0x80,
|
||||
0x5D, 0x88, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xEF, 0xC0, 0x57, 0xD8, 0xDC, 0x2C,
|
||||
0x57, 0x88, 0x33, 0x7E, 0x84, 0x80, 0x6F, 0xC8, 0xDF, 0xC0, 0x07, 0x70, 0x03, 0xD0, 0xDF, 0x4C,
|
||||
0xFF, 0x7E, 0x03, 0x9D, 0xD6, 0x2C, 0xE7, 0x6C, 0x57, 0x88, 0x33, 0x7E, 0x84, 0x80, 0x6F, 0xC8,
|
||||
0xDF, 0xC0, 0x05, 0x30, 0x03, 0xD0, 0xDF, 0x4C, 0xFF, 0x7E, 0x03, 0x9D, 0xE2, 0xEC, 0x5F, 0xC8,
|
||||
0x01, 0x79, 0x83, 0x93, 0x80, 0x40, 0xC0, 0x6C, 0x3D, 0xF0, 0xDD, 0x80, 0x5D, 0x88, 0x95, 0x00,
|
||||
0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xEF, 0xC0, 0x6F, 0xC8, 0x03, 0x59, 0xF9, 0x6C, 0x6F, 0x4B,
|
||||
0x18, 0xAD, 0x57, 0x88, 0x2D, 0x7E, 0x84, 0x80, 0x6F, 0xC8, 0x83, 0x93, 0x80, 0x40, 0x57, 0x88,
|
||||
0x2D, 0x7E, 0x84, 0x80, 0x00, 0x48, 0xDD, 0x80, 0x1A, 0x70, 0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00,
|
||||
0x5E, 0x88, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x3E, 0xF0, 0xDD, 0x80, 0x5D, 0x88, 0x95, 0x00,
|
||||
0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xEF, 0xC0, 0x6F, 0xC8, 0x03, 0x9D, 0x2B, 0x2D, 0x49, 0xED,
|
||||
0x57, 0x88, 0x2D, 0x7E, 0x84, 0x80, 0x83, 0x93, 0x80, 0x81, 0x57, 0x88, 0x2D, 0x7E, 0x84, 0x80,
|
||||
0x00, 0x48, 0xDD, 0x80, 0x1A, 0x70, 0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88, 0x95, 0x00,
|
||||
0x17, 0x94, 0x17, 0x50, 0x0C, 0xAD, 0x10, 0xF0, 0x6F, 0xC2, 0x03, 0x18, 0x49, 0xED, 0x57, 0x88,
|
||||
0x2B, 0x7E, 0x84, 0x80, 0x6F, 0xC8, 0x83, 0x93, 0x80, 0x40, 0x57, 0x88, 0x2B, 0x7E, 0x84, 0x80,
|
||||
0x00, 0x48, 0xDD, 0x80, 0x1B, 0xB0, 0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88, 0x95, 0x00,
|
||||
0x17, 0x94, 0x17, 0x50, 0x57, 0x88, 0x29, 0x3E, 0x84, 0x80, 0x83, 0x93, 0x80, 0x81, 0x80, 0xCA,
|
||||
0x76, 0x6D, 0x6F, 0xC8, 0xFF, 0x3A, 0x03, 0x9D, 0x5E, 0x6D, 0x57, 0x88, 0x2B, 0x7E, 0x84, 0x80,
|
||||
0x07, 0x70, 0x83, 0x93, 0x80, 0x40, 0xFF, 0xB0, 0xDD, 0x80, 0x1B, 0xB0, 0xDE, 0x80, 0x5D, 0x88,
|
||||
0x96, 0x00, 0x5E, 0x88, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x71, 0x2D, 0x57, 0x88, 0x2B, 0x7E,
|
||||
0x84, 0x80, 0x07, 0x70, 0x83, 0x93, 0x80, 0x40, 0x57, 0x88, 0x2B, 0x7E, 0x84, 0x80, 0x00, 0x48,
|
||||
0xDD, 0x80, 0x1B, 0xB0, 0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88, 0x95, 0x00, 0x17, 0x94,
|
||||
0x17, 0x50, 0x57, 0x88, 0x29, 0x3E, 0x84, 0x80, 0x83, 0x93, 0x80, 0x81, 0x3F, 0x30, 0xDD, 0x80,
|
||||
0x5D, 0x88, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xEF, 0xC0, 0x0A, 0x30, 0x6F, 0xC2,
|
||||
0x03, 0x18, 0x9C, 0x2D, 0x57, 0x88, 0x25, 0x3E, 0x84, 0x80, 0x6F, 0xC8, 0x83, 0x93, 0x80, 0x40,
|
||||
0x57, 0x88, 0x25, 0x3E, 0x84, 0x80, 0x00, 0x48, 0xDD, 0x80, 0x1C, 0x70, 0xDE, 0x80, 0x5D, 0x88,
|
||||
0x96, 0x00, 0x5E, 0x88, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x57, 0x88, 0xA8, 0x3E, 0x84, 0x80,
|
||||
0x83, 0x93, 0x80, 0x81, 0x80, 0xCA, 0xC7, 0x6D, 0x6F, 0xC8, 0xFF, 0x3A, 0x03, 0x9D, 0xB0, 0xED,
|
||||
0x57, 0x88, 0x25, 0x3E, 0x84, 0x80, 0xFF, 0xB0, 0x83, 0x93, 0x80, 0x81, 0xDD, 0x80, 0x1C, 0x70,
|
||||
0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0xC2, 0xED,
|
||||
0x57, 0x88, 0x25, 0x3E, 0x84, 0x80, 0x83, 0x93, 0x80, 0x81, 0x57, 0x88, 0x25, 0x3E, 0x84, 0x80,
|
||||
0x00, 0x48, 0xDD, 0x80, 0x1C, 0x70, 0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88, 0x95, 0x00,
|
||||
0x17, 0x94, 0x17, 0x50, 0x57, 0x88, 0xA8, 0x3E, 0x84, 0x80, 0x83, 0x93, 0x80, 0x81, 0xD7, 0x0A,
|
||||
0xB4, 0xEC, 0x03, 0x30, 0x9B, 0x40, 0x3C, 0xB0, 0xDD, 0x80, 0x5D, 0x88, 0x95, 0x00, 0x97, 0xD4,
|
||||
0x97, 0x90, 0x0D, 0x08, 0xEF, 0xC0, 0x6F, 0xC8, 0x03, 0xBA, 0x03, 0x9D, 0xCB, 0x6D, 0x3E, 0xF0,
|
||||
0xDD, 0x80, 0x5D, 0x88, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xB6, 0x40, 0x3F, 0x30,
|
||||
0xDD, 0x80, 0x5D, 0x88, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xB8, 0x00, 0x36, 0x42,
|
||||
0x03, 0x5C, 0x07, 0xEE, 0x0A, 0x30, 0x36, 0x42, 0x03, 0x18, 0x07, 0xEE, 0x36, 0x48, 0xDD, 0x80,
|
||||
0x1B, 0xB0, 0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50,
|
||||
0x38, 0x08, 0xDD, 0x80, 0x1C, 0x70, 0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88, 0x95, 0x00,
|
||||
0x17, 0x94, 0x17, 0x50, 0x36, 0x48, 0xB5, 0x40, 0x38, 0x08, 0xB7, 0x80, 0x1D, 0x2E, 0x09, 0x30,
|
||||
0xDD, 0x80, 0x1B, 0xB0, 0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88, 0x95, 0x00, 0x17, 0x94,
|
||||
0x17, 0x50, 0x1C, 0x70, 0xDD, 0xC1, 0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88, 0x95, 0x00,
|
||||
0x17, 0x94, 0x17, 0x50, 0x09, 0x30, 0xB5, 0x40, 0xB7, 0xC1, 0x04, 0xF0, 0x9B, 0x40, 0x3C, 0xB0,
|
||||
0xDD, 0x80, 0x5D, 0x88, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xEF, 0xC0, 0x6F, 0xC8,
|
||||
0x04, 0x7A, 0x03, 0x9D, 0x1F, 0x6E, 0x3E, 0xF0, 0xDD, 0x80, 0x5D, 0x88, 0x95, 0x00, 0x97, 0xD4,
|
||||
0x97, 0x90, 0x0D, 0x08, 0xBA, 0x40, 0x3F, 0x30, 0xDD, 0x80, 0x5D, 0x88, 0x95, 0x00, 0x97, 0xD4,
|
||||
0x97, 0x90, 0x0D, 0x08, 0xBC, 0x40, 0x3A, 0x42, 0x03, 0x5C, 0x5A, 0x2E, 0x02, 0xF0, 0x3C, 0x42,
|
||||
0x03, 0x5C, 0x5A, 0x2E, 0x3A, 0x48, 0xDD, 0x80, 0x1B, 0xB0, 0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00,
|
||||
0x5E, 0x88, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x3C, 0x48, 0xDD, 0x80, 0x1C, 0x70, 0xDE, 0x80,
|
||||
0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x3A, 0x48, 0xB9, 0x40,
|
||||
0x3C, 0x48, 0x71, 0x2E, 0x23, 0x70, 0xDD, 0x80, 0x1B, 0xB0, 0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00,
|
||||
0x5E, 0x88, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x10, 0xF0, 0xDD, 0x80, 0x1C, 0x70, 0xDE, 0x80,
|
||||
0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x23, 0x70, 0xB9, 0x40,
|
||||
0x10, 0xF0, 0xBB, 0x80, 0x05, 0x30, 0x9B, 0x40, 0x3C, 0xB0, 0xDD, 0x80, 0x5D, 0x88, 0x95, 0x00,
|
||||
0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xEF, 0xC0, 0x6F, 0xC8, 0x05, 0xBA, 0x03, 0x9D, 0x74, 0x2E,
|
||||
0x3E, 0xF0, 0xDD, 0x80, 0x5D, 0x88, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xC6, 0x00,
|
||||
0x3F, 0x30, 0xDD, 0x80, 0x5D, 0x88, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xC8, 0xC0,
|
||||
0x46, 0x02, 0x03, 0x5C, 0xB2, 0x2E, 0x10, 0xF0, 0x46, 0x02, 0x03, 0x18, 0xB2, 0x2E, 0x48, 0xC8,
|
||||
0x03, 0x59, 0xB2, 0x2E, 0x46, 0x08, 0xDD, 0x80, 0x1B, 0xB0, 0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00,
|
||||
0x5E, 0x88, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x48, 0xC8, 0xDD, 0x80, 0x1C, 0x70, 0xDE, 0x80,
|
||||
0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x46, 0x08, 0xC5, 0x00,
|
||||
0x48, 0xC8, 0xC9, 0x2E, 0x0B, 0x70, 0xDD, 0x80, 0x1B, 0xB0, 0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00,
|
||||
0x5E, 0x88, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x07, 0x70, 0xDD, 0x80, 0x1C, 0x70, 0xDE, 0x80,
|
||||
0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x0B, 0x70, 0xC5, 0x00,
|
||||
0x07, 0x70, 0xC7, 0x40, 0x06, 0x30, 0x9B, 0x40, 0x3C, 0xB0, 0xDD, 0x80, 0x5D, 0x88, 0x95, 0x00,
|
||||
0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xEF, 0xC0, 0x6F, 0xC8, 0x06, 0xBA, 0x03, 0x9D, 0xCC, 0x2E,
|
||||
0x3D, 0xF0, 0xDD, 0x80, 0x5D, 0x88, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xCC, 0x00,
|
||||
0x3E, 0xF0, 0xDD, 0x80, 0x5D, 0x88, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xCA, 0x00,
|
||||
0x3F, 0x30, 0xDD, 0x80, 0x5D, 0x88, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xCE, 0x40,
|
||||
0x4A, 0x08, 0x4C, 0x02, 0x03, 0x5C, 0x1F, 0xAF, 0x4E, 0x48, 0x4A, 0x02, 0x03, 0x5C, 0x1F, 0xAF,
|
||||
0x4E, 0x48, 0x03, 0x59, 0x1F, 0xAF, 0x4C, 0x08, 0xDD, 0x80, 0x1A, 0x70, 0xDE, 0x80, 0x5D, 0x88,
|
||||
0x96, 0x00, 0x5E, 0x88, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x4A, 0x08, 0xDD, 0x80, 0x1B, 0xB0,
|
||||
0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x4E, 0x48,
|
||||
0xDD, 0x80, 0x1C, 0x70, 0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88, 0x95, 0x00, 0x17, 0x94,
|
||||
0x17, 0x50, 0x4C, 0x08, 0xCB, 0x40, 0x4A, 0x08, 0xC9, 0x00, 0x4E, 0x48, 0x42, 0xEF, 0x73, 0xF0,
|
||||
0xDD, 0x80, 0x1A, 0x70, 0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88, 0x95, 0x00, 0x17, 0x94,
|
||||
0x17, 0x50, 0x64, 0x70, 0xDD, 0x80, 0x1B, 0xB0, 0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88,
|
||||
0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x2D, 0xB0, 0xDD, 0x80, 0x1C, 0x70, 0xDE, 0x80, 0x5D, 0x88,
|
||||
0x96, 0x00, 0x5E, 0x88, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x73, 0xF0, 0xCB, 0x40, 0x64, 0x70,
|
||||
0xC9, 0x00, 0x2D, 0xB0, 0xCD, 0x40, 0x07, 0x70, 0x9B, 0x40, 0x3C, 0xB0, 0xDD, 0x80, 0x5D, 0x88,
|
||||
0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xEF, 0xC0, 0x6F, 0xC8, 0x07, 0xFA, 0x03, 0x9D,
|
||||
0x45, 0x2F, 0x3E, 0xF0, 0xDD, 0x80, 0x5D, 0x88, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08,
|
||||
0xBE, 0x80, 0x3F, 0x30, 0xDD, 0x80, 0x5D, 0x88, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08,
|
||||
0xC0, 0x80, 0x3E, 0x82, 0x03, 0x5C, 0x83, 0x2F, 0x10, 0xF0, 0x3E, 0x82, 0x03, 0x18, 0x83, 0x2F,
|
||||
0x40, 0x88, 0x03, 0x59, 0x83, 0x2F, 0x3E, 0x88, 0xDD, 0x80, 0x1B, 0xB0, 0xDE, 0x80, 0x5D, 0x88,
|
||||
0x96, 0x00, 0x5E, 0x88, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x40, 0x88, 0xDD, 0x80, 0x1C, 0x70,
|
||||
0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x3E, 0x88,
|
||||
0xBD, 0x80, 0x40, 0x88, 0x9A, 0x6F, 0x0E, 0x70, 0xDD, 0x80, 0x1B, 0xB0, 0xDE, 0x80, 0x5D, 0x88,
|
||||
0x96, 0x00, 0x5E, 0x88, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x04, 0xF0, 0xDD, 0x80, 0x1C, 0x70,
|
||||
0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x0E, 0x70,
|
||||
0xBD, 0x80, 0x04, 0xF0, 0xBF, 0xC0, 0x08, 0xF0, 0x9B, 0x40, 0x3C, 0xB0, 0xDD, 0x80, 0x5D, 0x88,
|
||||
0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xEF, 0xC0, 0x6F, 0xC8, 0x08, 0x7A, 0x03, 0x9D,
|
||||
0x9D, 0xAF, 0x3E, 0xF0, 0xDD, 0x80, 0x5D, 0x88, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08,
|
||||
0xC2, 0xC0, 0x3F, 0x30, 0xDD, 0x80, 0x5D, 0x88, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08,
|
||||
0xC4, 0xC0, 0x42, 0xC8, 0x44, 0xC2, 0x03, 0x18, 0xD9, 0xAF, 0x02, 0xF0, 0x44, 0xC2, 0x03, 0x5C,
|
||||
0xD9, 0xAF, 0x42, 0xC8, 0xDD, 0x80, 0x1B, 0xB0, 0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88,
|
||||
0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x44, 0xC8, 0xDD, 0x80, 0x1C, 0x70, 0xDE, 0x80, 0x5D, 0x88,
|
||||
0x96, 0x00, 0x5E, 0x88, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x42, 0xC8, 0xC1, 0xC0, 0x44, 0xC8,
|
||||
0xF0, 0x6F, 0x84, 0x30, 0xDD, 0x80, 0x1B, 0xB0, 0xDE, 0x80, 0x5D, 0x88, 0x96, 0x00, 0x5E, 0x88,
|
||||
0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x34, 0x70, 0xDD, 0x80, 0x1C, 0x70, 0xDE, 0x80, 0x5D, 0x88,
|
||||
0x96, 0x00, 0x5E, 0x88, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x84, 0x30, 0xC1, 0xC0, 0x34, 0x70,
|
||||
0xC3, 0x00, 0x09, 0x30, 0x9B, 0x40, 0x3C, 0xB0, 0xDD, 0x80, 0x5D, 0x88, 0x95, 0x00, 0x97, 0xD4,
|
||||
0x97, 0x90, 0x0D, 0x08, 0xEF, 0xC0, 0x6F, 0xC8, 0x09, 0xBA, 0x03, 0x59, 0x08, 0x40, 0xF3, 0xEF
|
||||
};
|
||||
|
|
@ -0,0 +1,515 @@
|
|||
static uint8_t arb_firmware[8192] = {
|
||||
0x8A, 0x51, 0xE9, 0xAF, 0x00, 0xB0, 0x8A, 0xC0, 0x04, 0x88, 0x84, 0x0A, 0x82, 0x47, 0x00, 0xF4,
|
||||
0x01, 0x34, 0x02, 0x34, 0x04, 0x34, 0x08, 0x34, 0x10, 0x34, 0x20, 0x34, 0x40, 0x34, 0x80, 0x34,
|
||||
0x01, 0x34, 0x02, 0x34, 0x04, 0x34, 0x08, 0x34, 0x10, 0x34, 0x20, 0x34, 0x40, 0x34, 0x80, 0x34,
|
||||
0x00, 0xF4, 0x00, 0xF4, 0x00, 0xF4, 0x00, 0xF4, 0x00, 0xF4, 0x01, 0x34, 0x03, 0x74, 0x07, 0xB4,
|
||||
0x0F, 0xF4, 0x1F, 0x34, 0x3F, 0x74, 0x7F, 0xB4, 0xFF, 0xF4, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
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, 0xF5, 0xAB, 0x95, 0x41, 0x96, 0x41, 0x97, 0x81, 0x98, 0x01,
|
||||
0x99, 0x41, 0x9A, 0x41, 0x9B, 0x81, 0x9C, 0x41, 0x9E, 0x81, 0xDC, 0x81, 0x10, 0xF0, 0x5C, 0x42,
|
||||
0x03, 0x18, 0x25, 0xAC, 0x5C, 0x48, 0x22, 0xFE, 0x84, 0x80, 0x80, 0x81, 0x5C, 0x48, 0xB0, 0x3E,
|
||||
0x84, 0x80, 0x80, 0x81, 0x5C, 0x48, 0xD0, 0x3E, 0x84, 0x80, 0x80, 0x81, 0x5C, 0x48, 0xA0, 0xFE,
|
||||
0x84, 0x80, 0x80, 0x81, 0x5C, 0x48, 0xC0, 0xFE, 0x84, 0x80, 0x80, 0x81, 0x5C, 0x48, 0xE0, 0x3E,
|
||||
0x84, 0x80, 0xFF, 0xB0, 0x80, 0x40, 0xDC, 0xCA, 0x06, 0x6C, 0xC6, 0x41, 0xC7, 0x81, 0xC9, 0x41,
|
||||
0xC4, 0x01, 0xC8, 0x01, 0x6C, 0x50, 0xEC, 0x90, 0xA1, 0x01, 0xDC, 0x81, 0x40, 0xF0, 0x5C, 0x42,
|
||||
0x03, 0x18, 0x3A, 0xEC, 0x5C, 0x48, 0xA0, 0xFE, 0x84, 0x80, 0xFF, 0xB0, 0x83, 0xD7, 0x80, 0x40,
|
||||
0xDC, 0xCA, 0x2E, 0xEC, 0xC5, 0x41, 0x08, 0xF0, 0x45, 0x02, 0x03, 0x18, 0x08, 0x40, 0x45, 0x08,
|
||||
0x3A, 0x7E, 0x84, 0x80, 0x83, 0x93, 0x80, 0x81, 0x45, 0x08, 0x32, 0x3E, 0x84, 0x80, 0x80, 0x81,
|
||||
0xC5, 0x8A, 0x3B, 0x2C, 0x01, 0xF0, 0xA0, 0x80, 0x8A, 0x51, 0xFC, 0x63, 0x8A, 0x51, 0x03, 0x30,
|
||||
0x9E, 0x40, 0x02, 0xF0, 0x9E, 0x40, 0x01, 0xF0, 0x9E, 0x40, 0x9E, 0x81, 0x9B, 0x81, 0xE1, 0x41,
|
||||
0xE1, 0x8A, 0xE2, 0x00, 0x61, 0x08, 0x96, 0x00, 0x62, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50,
|
||||
0x2A, 0x70, 0x83, 0x52, 0x03, 0x53, 0xE1, 0x00, 0x61, 0x08, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90,
|
||||
0x0D, 0x08, 0xDF, 0xC0, 0x5F, 0xC8, 0xF7, 0xFA, 0x03, 0x9D, 0x70, 0xAC, 0xEB, 0xC1, 0x72, 0xEC,
|
||||
0xEB, 0xC1, 0xEB, 0x0A, 0x6B, 0x88, 0x03, 0x59, 0xE2, 0xEC, 0x01, 0xF0, 0x9B, 0x40, 0x29, 0x70,
|
||||
0x83, 0x52, 0x03, 0x53, 0xE1, 0x00, 0x61, 0x08, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08,
|
||||
0xDF, 0xC0, 0x5F, 0x4B, 0x77, 0x6C, 0x28, 0x30, 0x83, 0x52, 0x03, 0x53, 0xE1, 0x00, 0x61, 0x08,
|
||||
0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xCA, 0x00, 0x0D, 0x70, 0x4A, 0x02, 0x03, 0x18,
|
||||
0xD6, 0x2C, 0x05, 0x30, 0x4A, 0x02, 0xD5, 0x81, 0x03, 0x5C, 0xD7, 0x6C, 0xD5, 0xCA, 0x4A, 0x08,
|
||||
0xE1, 0x00, 0x01, 0xF0, 0xE2, 0x00, 0x61, 0x08, 0x96, 0x00, 0x62, 0x08, 0x95, 0x00, 0x17, 0x94,
|
||||
0x17, 0x50, 0x2A, 0x70, 0x83, 0x52, 0x03, 0x53, 0xE1, 0x00, 0x61, 0x08, 0x95, 0x00, 0x97, 0xD4,
|
||||
0x97, 0x90, 0x0D, 0x08, 0xD6, 0x40, 0x10, 0xF0, 0x56, 0x42, 0x03, 0x5C, 0xB1, 0xEC, 0x10, 0xF0,
|
||||
0xD6, 0x40, 0xF0, 0xB0, 0xD6, 0x0E, 0xD6, 0xC5, 0x56, 0x48, 0xE1, 0x00, 0x03, 0x30, 0xE2, 0x00,
|
||||
0x61, 0x08, 0x96, 0x00, 0x62, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x2B, 0xB0, 0x83, 0x52,
|
||||
0x03, 0x53, 0xE1, 0x00, 0x61, 0x08, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xE0, 0xC0,
|
||||
0x01, 0xF0, 0xE0, 0x45, 0x60, 0xC8, 0xE1, 0x00, 0x04, 0xF0, 0xE2, 0x00, 0x61, 0x08, 0x96, 0x00,
|
||||
0x62, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x9B, 0x81, 0xEB, 0x6C, 0xD5, 0x81, 0xFF, 0xB0,
|
||||
0xE1, 0x00, 0x01, 0xF0, 0xE2, 0x00, 0x61, 0x08, 0x96, 0x00, 0x62, 0x08, 0x95, 0x00, 0x17, 0x94,
|
||||
0x17, 0x50, 0xA1, 0xAC, 0x07, 0x70, 0xD5, 0x81, 0xD5, 0xCA, 0xCA, 0x00, 0x30, 0x30, 0xD6, 0x40,
|
||||
0x01, 0xF0, 0xE0, 0x01, 0x9B, 0x40, 0x0E, 0x58, 0xEB, 0x6C, 0x25, 0x70, 0x83, 0x52, 0x03, 0x53,
|
||||
0xE1, 0x00, 0x61, 0x08, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xD7, 0x80, 0x07, 0x70,
|
||||
0xD7, 0x05, 0x57, 0x88, 0xC5, 0x00, 0x08, 0xF0, 0x45, 0x02, 0x03, 0x18, 0xEB, 0x6C, 0x45, 0x08,
|
||||
0x8A, 0x51, 0x07, 0xA5, 0x8A, 0x51, 0x0E, 0x58, 0xEB, 0x6C, 0xC5, 0x8A, 0xFB, 0xAC, 0xEA, 0x40,
|
||||
0xE1, 0x00, 0x00, 0xB0, 0xE2, 0x00, 0x61, 0x08, 0x96, 0x00, 0x62, 0x08, 0x95, 0x00, 0x17, 0x94,
|
||||
0x17, 0x50, 0x8E, 0xDC, 0x08, 0x40, 0x18, 0x14, 0x05, 0x30, 0xE8, 0x00, 0xE8, 0xCB, 0x16, 0xED,
|
||||
0x21, 0x30, 0x83, 0x52, 0x03, 0x53, 0xE1, 0x00, 0x61, 0x08, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90,
|
||||
0x0D, 0x08, 0xC6, 0x00, 0x22, 0x30, 0x83, 0x52, 0x03, 0x53, 0xE1, 0x00, 0x61, 0x08, 0x95, 0x00,
|
||||
0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xC7, 0x40, 0x24, 0x30, 0x83, 0x52, 0x03, 0x53, 0xE1, 0x00,
|
||||
0x61, 0x08, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xC9, 0x00, 0x20, 0xF0, 0x83, 0x52,
|
||||
0x03, 0x53, 0xE1, 0x00, 0x61, 0x08, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xC4, 0xC0,
|
||||
0x23, 0x70, 0x83, 0x52, 0x03, 0x53, 0xE1, 0x00, 0x61, 0x08, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90,
|
||||
0x0D, 0x08, 0xC8, 0xC0, 0x18, 0xD0, 0x55, 0xCB, 0x56, 0x2D, 0x48, 0xC8, 0xE8, 0x00, 0xE9, 0x81,
|
||||
0xE8, 0x1B, 0xE9, 0xC3, 0x4A, 0x46, 0x69, 0x44, 0x03, 0x59, 0x60, 0xAD, 0x0A, 0x30, 0x49, 0x02,
|
||||
0x03, 0x5C, 0x8D, 0x2D, 0x44, 0xC8, 0x80, 0x7A, 0x78, 0x7E, 0x03, 0x5C, 0x81, 0xAD, 0x8D, 0x2D,
|
||||
0x44, 0xC8, 0x80, 0x7A, 0x78, 0x7E, 0x03, 0x5C, 0xC4, 0xDB, 0x56, 0x2D, 0x44, 0xC8, 0x3A, 0x7E,
|
||||
0x84, 0x80, 0x83, 0x93, 0x00, 0x48, 0x01, 0xBE, 0xE8, 0x00, 0x44, 0xC8, 0x3A, 0x7E, 0x84, 0x80,
|
||||
0x68, 0x08, 0x80, 0x40, 0x44, 0xC8, 0x3A, 0x7E, 0x84, 0x80, 0x00, 0x48, 0xE1, 0x00, 0x44, 0xC8,
|
||||
0x01, 0xBE, 0xE2, 0x00, 0x61, 0x08, 0x96, 0x00, 0x62, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50,
|
||||
0x56, 0x2D, 0xC4, 0xDB, 0x8D, 0x2D, 0x48, 0xC8, 0x80, 0x7A, 0x73, 0xBE, 0x03, 0x18, 0x8D, 0x2D,
|
||||
0x48, 0xC8, 0x80, 0x7A, 0x7B, 0xFE, 0x03, 0x18, 0x8F, 0x6D, 0x6C, 0xD5, 0x30, 0xAE, 0x6C, 0x91,
|
||||
0x48, 0xC8, 0x11, 0xFE, 0x84, 0x80, 0x8A, 0x51, 0x02, 0xA0, 0x8A, 0x51, 0xC7, 0xC5, 0x48, 0xC8,
|
||||
0xE8, 0x00, 0x03, 0xD0, 0xE8, 0xCD, 0x03, 0xD0, 0xE8, 0xCD, 0x03, 0xD0, 0xE8, 0xCD, 0x44, 0xC8,
|
||||
0x68, 0x87, 0xD8, 0x7E, 0xDE, 0x80, 0xA0, 0xFE, 0x84, 0x80, 0x83, 0xD7, 0x00, 0x48, 0xDC, 0x40,
|
||||
0x3E, 0xF0, 0x83, 0x52, 0x03, 0x53, 0xE1, 0x00, 0x61, 0x08, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90,
|
||||
0x0D, 0x08, 0xC2, 0xC0, 0x3F, 0x30, 0x83, 0x52, 0x03, 0x53, 0xE1, 0x00, 0x61, 0x08, 0x95, 0x00,
|
||||
0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xC3, 0x00, 0x6C, 0x91, 0xDC, 0x81, 0x08, 0xF0, 0x5C, 0x42,
|
||||
0x03, 0x18, 0xF5, 0xAD, 0x5C, 0x48, 0xE0, 0x3E, 0x84, 0x80, 0x83, 0x93, 0x00, 0x48, 0x5E, 0xC6,
|
||||
0x03, 0x9D, 0xF1, 0x6D, 0x5C, 0x48, 0x01, 0xBE, 0x84, 0x80, 0x8A, 0x51, 0x02, 0xA0, 0x8A, 0x51,
|
||||
0x42, 0x05, 0x03, 0x59, 0xF1, 0x6D, 0x46, 0x08, 0xE1, 0x00, 0x5C, 0x48, 0xB0, 0x3E, 0x84, 0x80,
|
||||
0x00, 0x48, 0xE2, 0x00, 0x5C, 0x48, 0x22, 0xFE, 0x84, 0x80, 0x00, 0x48, 0xE3, 0x40, 0x56, 0x48,
|
||||
0xE4, 0x00, 0x48, 0xC8, 0xE5, 0x40, 0x47, 0x48, 0x52, 0xE7, 0x8A, 0x51, 0xE8, 0x00, 0x68, 0x4C,
|
||||
0x03, 0x5C, 0xEE, 0xAD, 0x83, 0x52, 0x03, 0x53, 0x6C, 0xD5, 0xF1, 0x6D, 0x83, 0x52, 0x03, 0x53,
|
||||
0x6C, 0x91, 0x6C, 0xD9, 0xF5, 0xAD, 0xDC, 0xCA, 0xBE, 0xAD, 0x6C, 0xD9, 0x30, 0xAE, 0x08, 0xF0,
|
||||
0xDC, 0x40, 0x10, 0xF0, 0x5C, 0x42, 0x03, 0x18, 0x30, 0xAE, 0x5C, 0x48, 0xE0, 0x3E, 0x84, 0x80,
|
||||
0x83, 0x93, 0x00, 0x48, 0x5E, 0xC6, 0x03, 0x9D, 0x2C, 0xEE, 0x5C, 0x48, 0x01, 0xBE, 0x84, 0x80,
|
||||
0x8A, 0x51, 0x02, 0xA0, 0x8A, 0x51, 0x43, 0x45, 0x03, 0x59, 0x2C, 0xEE, 0x46, 0x08, 0xE1, 0x00,
|
||||
0x5C, 0x48, 0xB0, 0x3E, 0x84, 0x80, 0x00, 0x48, 0xE2, 0x00, 0x5C, 0x48, 0x22, 0xFE, 0x84, 0x80,
|
||||
0x00, 0x48, 0xE3, 0x40, 0x56, 0x48, 0xE4, 0x00, 0x48, 0xC8, 0xE5, 0x40, 0x47, 0x48, 0x52, 0xE7,
|
||||
0x8A, 0x51, 0xE8, 0x00, 0x68, 0x4C, 0x03, 0x5C, 0x29, 0xEE, 0x83, 0x52, 0x03, 0x53, 0x6C, 0xD5,
|
||||
0x2C, 0xEE, 0x83, 0x52, 0x03, 0x53, 0x6C, 0x91, 0x6C, 0xD9, 0x30, 0xAE, 0xDC, 0xCA, 0xF9, 0xAD,
|
||||
0x6C, 0xD9, 0x08, 0x40, 0x48, 0xC8, 0x80, 0x7A, 0x77, 0xFE, 0x03, 0x5C, 0x3B, 0x6E, 0x60, 0xC8,
|
||||
0x01, 0xBE, 0xDD, 0x80, 0x3D, 0x6E, 0xDD, 0xC1, 0xDD, 0x0A, 0xDB, 0xC1, 0x5D, 0x88, 0x5B, 0x82,
|
||||
0x03, 0x18, 0x08, 0x40, 0x11, 0x30, 0xDC, 0x40, 0x3C, 0xB0, 0x83, 0x52, 0x03, 0x53, 0xE1, 0x00,
|
||||
0x61, 0x08, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xD8, 0x00, 0x3D, 0xF0, 0x83, 0x52,
|
||||
0x03, 0x53, 0xE1, 0x00, 0x61, 0x08, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xD9, 0x40,
|
||||
0x48, 0xC8, 0x80, 0x7A, 0x75, 0xBE, 0x03, 0x5C, 0x65, 0x2E, 0x58, 0x08, 0x80, 0x7A, 0x70, 0x3E,
|
||||
0x03, 0x5C, 0xD8, 0x1B, 0x75, 0x6E, 0x58, 0x08, 0x6C, 0x2E, 0x59, 0x48, 0x80, 0x7A, 0x70, 0x3E,
|
||||
0x03, 0x5C, 0xD9, 0x5B, 0x6E, 0x6E, 0x59, 0x48, 0xDC, 0x40, 0x75, 0x6E, 0x58, 0x08, 0x80, 0x7A,
|
||||
0x70, 0x3E, 0x03, 0x18, 0x75, 0x6E, 0xD8, 0x5F, 0x63, 0x2E, 0x10, 0xF0, 0x5C, 0x42, 0x03, 0x18,
|
||||
0x50, 0xEF, 0x5C, 0x48, 0x22, 0xFE, 0x84, 0x80, 0x46, 0x08, 0x83, 0x93, 0x80, 0x40, 0x5C, 0x48,
|
||||
0xB0, 0x3E, 0x84, 0x80, 0x47, 0x48, 0x80, 0x40, 0x5C, 0x48, 0xD0, 0x3E, 0x84, 0x80, 0x49, 0x08,
|
||||
0x80, 0x40, 0x5C, 0x48, 0xA0, 0xFE, 0x84, 0x80, 0x44, 0xC8, 0x80, 0x40, 0x5C, 0x48, 0xC0, 0xFE,
|
||||
0x84, 0x80, 0x48, 0xC8, 0x80, 0x40, 0x5C, 0x48, 0xE0, 0x3E, 0x84, 0x80, 0x5E, 0x88, 0x80, 0x40,
|
||||
0x5E, 0x88, 0xA0, 0xFE, 0x84, 0x80, 0x5C, 0x48, 0x83, 0xD7, 0x80, 0x40, 0x48, 0xC8, 0xE1, 0x00,
|
||||
0x17, 0xB0, 0xE2, 0x00, 0x61, 0x08, 0x96, 0x00, 0x62, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50,
|
||||
0x44, 0xC8, 0xE1, 0x00, 0x18, 0x30, 0xE2, 0x00, 0x61, 0x08, 0x96, 0x00, 0x62, 0x08, 0x95, 0x00,
|
||||
0x17, 0x94, 0x17, 0x50, 0x46, 0x08, 0xE1, 0x00, 0x19, 0x70, 0xE2, 0x00, 0x61, 0x08, 0x96, 0x00,
|
||||
0x62, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x47, 0x48, 0xE1, 0x00, 0x1A, 0x70, 0xE2, 0x00,
|
||||
0x61, 0x08, 0x96, 0x00, 0x62, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x5C, 0x48, 0xE1, 0x00,
|
||||
0x16, 0x70, 0xE2, 0x00, 0x61, 0x08, 0x96, 0x00, 0x62, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50,
|
||||
0x49, 0x08, 0xE1, 0x00, 0x1B, 0xB0, 0xE2, 0x00, 0x61, 0x08, 0x96, 0x00, 0x62, 0x08, 0x95, 0x00,
|
||||
0x17, 0x94, 0x17, 0x50, 0x5B, 0x88, 0xE1, 0x00, 0x11, 0x30, 0xE2, 0x00, 0x61, 0x08, 0x96, 0x00,
|
||||
0x62, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x08, 0xF0, 0x5C, 0x42, 0x5C, 0x48, 0x03, 0x18,
|
||||
0x12, 0xEF, 0x01, 0xBE, 0x84, 0x80, 0x8A, 0x51, 0x02, 0xA0, 0x8A, 0x51, 0xE1, 0x00, 0x12, 0x30,
|
||||
0xE2, 0x00, 0x61, 0x08, 0x96, 0x00, 0x62, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x05, 0x30,
|
||||
0xE8, 0x00, 0xE8, 0xCB, 0xF9, 0xAE, 0x83, 0x52, 0x12, 0x30, 0x03, 0x53, 0xE1, 0x41, 0xE2, 0x00,
|
||||
0x61, 0x08, 0x96, 0x00, 0x62, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x55, 0xCB, 0x50, 0xEF,
|
||||
0x48, 0xC8, 0xE8, 0x00, 0xE9, 0x81, 0xE8, 0x1B, 0xE9, 0xC3, 0x4A, 0x46, 0x69, 0x44, 0x03, 0x59,
|
||||
0x30, 0xEF, 0x50, 0xEF, 0x01, 0xBE, 0x84, 0x80, 0x8A, 0x51, 0x02, 0xA0, 0x8A, 0x51, 0xE1, 0x00,
|
||||
0x13, 0x70, 0xE2, 0x00, 0x61, 0x08, 0x96, 0x00, 0x62, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50,
|
||||
0x05, 0x30, 0xE8, 0x00, 0xE8, 0xCB, 0x22, 0xEF, 0x83, 0x52, 0x13, 0x70, 0x03, 0x53, 0xE1, 0x41,
|
||||
0xE2, 0x00, 0x61, 0x08, 0x96, 0x00, 0x62, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x06, 0xEF,
|
||||
0x44, 0xC8, 0x80, 0x7A, 0x78, 0x7E, 0x03, 0x5C, 0xC4, 0xDB, 0x50, 0xEF, 0x44, 0xC8, 0x32, 0x3E,
|
||||
0x84, 0x80, 0x83, 0x93, 0x00, 0x48, 0x01, 0xBE, 0xE8, 0x00, 0x44, 0xC8, 0x32, 0x3E, 0x84, 0x80,
|
||||
0x68, 0x08, 0x80, 0x40, 0x44, 0xC8, 0x32, 0x3E, 0x84, 0x80, 0x00, 0x48, 0xE1, 0x00, 0x44, 0xC8,
|
||||
0x09, 0xFE, 0xE2, 0x00, 0x61, 0x08, 0x96, 0x00, 0x62, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50,
|
||||
0xDB, 0x0A, 0x3E, 0x6E, 0xE7, 0x80, 0x62, 0x02, 0x62, 0x08, 0x03, 0x18, 0x9D, 0xAF, 0x67, 0x82,
|
||||
0xD0, 0xC0, 0x63, 0x48, 0x61, 0x02, 0x03, 0x5C, 0x61, 0x2F, 0x63, 0x48, 0x61, 0x02, 0xCC, 0x00,
|
||||
0x68, 0x2F, 0x61, 0x08, 0x63, 0x42, 0xCC, 0x00, 0xFF, 0xB0, 0xD0, 0x87, 0xCC, 0x86, 0xCC, 0x8A,
|
||||
0x65, 0x48, 0x11, 0xFE, 0x84, 0x80, 0x8A, 0x51, 0x02, 0xA0, 0x8A, 0x51, 0xE6, 0x40, 0x67, 0x88,
|
||||
0x66, 0x42, 0xD2, 0x00, 0x61, 0x49, 0xCE, 0x40, 0x62, 0x08, 0x52, 0x87, 0xD1, 0x00, 0x4E, 0x89,
|
||||
0xE6, 0x40, 0x63, 0x48, 0x66, 0x42, 0x03, 0x5C, 0x80, 0xAF, 0x63, 0x48, 0x4E, 0xC7, 0x84, 0xEF,
|
||||
0xD1, 0x8A, 0x4E, 0x89, 0xCD, 0x40, 0x63, 0x42, 0xCD, 0x40, 0x50, 0xC8, 0x51, 0x02, 0x03, 0x5C,
|
||||
0xD3, 0xAF, 0x51, 0x08, 0x50, 0xC2, 0x03, 0x5C, 0x91, 0x2F, 0x4D, 0x48, 0x4C, 0x02, 0x03, 0x18,
|
||||
0xD3, 0xAF, 0xDA, 0x81, 0x5A, 0x48, 0x03, 0x59, 0x99, 0x6F, 0x51, 0x08, 0xCF, 0x80, 0x4D, 0x48,
|
||||
0xE0, 0x2F, 0x50, 0xC8, 0xCF, 0x80, 0x4C, 0x08, 0xE0, 0x2F, 0x67, 0x82, 0x03, 0x18, 0xD6, 0xAF,
|
||||
0x67, 0x88, 0x62, 0x02, 0xD0, 0xC0, 0x61, 0x08, 0x63, 0x42, 0x03, 0x5C, 0xAB, 0xAF, 0x61, 0x08,
|
||||
0x63, 0x42, 0xCC, 0x00, 0xB2, 0x6F, 0x63, 0x48, 0x61, 0x02, 0xCC, 0x00, 0xFF, 0xB0, 0xD0, 0x87,
|
||||
0xCC, 0x86, 0xCC, 0x8A, 0x65, 0x48, 0x11, 0xFE, 0x84, 0x80, 0x8A, 0x51, 0x02, 0xA0, 0x8A, 0x51,
|
||||
0xE6, 0x40, 0x62, 0x08, 0x66, 0x42, 0xD2, 0x00, 0x63, 0x89, 0xCE, 0x40, 0x67, 0x88, 0x52, 0x87,
|
||||
0xD1, 0x00, 0x4E, 0x89, 0xE6, 0x40, 0x61, 0x08, 0x66, 0x42, 0x03, 0x5C, 0xCA, 0x6F, 0x61, 0x08,
|
||||
0x4E, 0xC7, 0xCE, 0xAF, 0xD1, 0x8A, 0x4E, 0x89, 0xCD, 0x40, 0x61, 0x02, 0xCD, 0x40, 0x50, 0xC8,
|
||||
0x51, 0x02, 0x03, 0x18, 0x89, 0x2F, 0xDA, 0x81, 0xDA, 0xCA, 0x92, 0x2F, 0xCF, 0xC1, 0x63, 0x48,
|
||||
0x61, 0x02, 0x03, 0x5C, 0xDE, 0xEF, 0x63, 0x48, 0x61, 0x02, 0xE0, 0x2F, 0x61, 0x08, 0x63, 0x42,
|
||||
0xCB, 0x40, 0xCF, 0xC8, 0x03, 0x9D, 0x00, 0xF4, 0x64, 0x08, 0x4B, 0x42, 0x03, 0x5C, 0x01, 0x34,
|
||||
0x00, 0xF4, 0xEC, 0x81, 0x83, 0x93, 0x22, 0x30, 0x84, 0x80, 0x61, 0x70, 0x8A, 0x51, 0xF4, 0x23,
|
||||
0x8A, 0x51, 0xA0, 0x30, 0x84, 0x80, 0xF0, 0xB0, 0x8A, 0x51, 0xF4, 0x23, 0x8A, 0x51, 0x83, 0xD7,
|
||||
0xA0, 0x30, 0x84, 0x80, 0xE0, 0x70, 0x8A, 0x51, 0xF4, 0x23, 0x83, 0x01, 0x8A, 0x51, 0x4A, 0xAC,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF
|
||||
};
|
||||
|
|
@ -0,0 +1,515 @@
|
|||
static uint8_t cal_firmware_sx125x[8192] = {
|
||||
0x8A, 0x51, 0xF0, 0x6F, 0x00, 0xB0, 0x8A, 0xC0, 0x04, 0x88, 0x84, 0x0A, 0x82, 0x47, 0x00, 0xF4,
|
||||
0x40, 0x34, 0x2B, 0xF4, 0x1C, 0xB4, 0x13, 0xB4, 0x0D, 0xB4, 0x08, 0x34, 0x06, 0x74, 0x04, 0x34,
|
||||
0x02, 0x34, 0x10, 0x34, 0x0B, 0xB4, 0x07, 0xB4, 0x05, 0x74, 0x03, 0x74, 0x02, 0x34, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 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, 0x30, 0x69, 0xB1, 0x00,
|
||||
0x04, 0xF0, 0xA2, 0xC0, 0x10, 0xF0, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00,
|
||||
0x17, 0x94, 0x17, 0x50, 0x2A, 0x08, 0xA2, 0xC0, 0x14, 0x30, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00,
|
||||
0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x2B, 0x48, 0xA2, 0xC0, 0x15, 0x70, 0xA3, 0x00,
|
||||
0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x2C, 0x08, 0xA2, 0xC0,
|
||||
0x11, 0x30, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50,
|
||||
0x2D, 0x48, 0xA2, 0xC0, 0x12, 0x30, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00,
|
||||
0x17, 0x94, 0x17, 0x50, 0x29, 0x08, 0xA2, 0xC0, 0x13, 0x70, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00,
|
||||
0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x31, 0x58, 0xB5, 0x29, 0x2E, 0x48, 0xB0, 0xC0,
|
||||
0x01, 0xF0, 0xD7, 0xA7, 0x8A, 0x51, 0x83, 0x52, 0x03, 0x53, 0xA1, 0xC0, 0x21, 0xC8, 0x95, 0x00,
|
||||
0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xC3, 0x39, 0x30, 0xC4, 0xA2, 0xC0, 0x01, 0xF0, 0xA3, 0x00,
|
||||
0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x01, 0xF0, 0x83, 0x52,
|
||||
0x03, 0x53, 0xA1, 0xC0, 0x21, 0xC8, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xD3, 0x67,
|
||||
0x8A, 0x51, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50,
|
||||
0x01, 0xF0, 0x83, 0x52, 0x03, 0x53, 0xA1, 0xC0, 0x21, 0xC8, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90,
|
||||
0x0D, 0x08, 0xA2, 0xC0, 0x01, 0xF0, 0xA2, 0x10, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08,
|
||||
0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0xB4, 0x41, 0x1B, 0xEA, 0x2E, 0x48, 0xB0, 0xC0, 0x02, 0xF0,
|
||||
0xD7, 0xA7, 0x8A, 0x51, 0x83, 0x52, 0x03, 0x53, 0xA1, 0xC0, 0x21, 0xC8, 0x95, 0x00, 0x97, 0xD4,
|
||||
0x97, 0x90, 0x0D, 0x08, 0xC3, 0x39, 0x30, 0xC4, 0xA2, 0xC0, 0x02, 0xF0, 0xA3, 0x00, 0x22, 0xC8,
|
||||
0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x02, 0xF0, 0x83, 0x52, 0x03, 0x53,
|
||||
0xA1, 0xC0, 0x21, 0xC8, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xCF, 0xA7, 0x8A, 0x51,
|
||||
0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x02, 0xF0,
|
||||
0x83, 0x52, 0x03, 0x53, 0xA1, 0xC0, 0x21, 0xC8, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08,
|
||||
0xA2, 0xC0, 0x02, 0xF0, 0xA2, 0x10, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00,
|
||||
0x17, 0x94, 0x17, 0x50, 0xB3, 0x29, 0x2F, 0x88, 0xA4, 0xC0, 0x32, 0x70, 0x2D, 0x27, 0x8A, 0x51,
|
||||
0x32, 0x08, 0xA2, 0xC0, 0x1B, 0xB0, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00,
|
||||
0x17, 0x94, 0x17, 0x50, 0x33, 0x48, 0xA2, 0xC0, 0x1C, 0x70, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00,
|
||||
0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x07, 0x70, 0x9B, 0x40, 0x3C, 0xB0, 0x83, 0x52,
|
||||
0x03, 0x53, 0xA1, 0xC0, 0x21, 0xC8, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xB4, 0x00,
|
||||
0x06, 0xBA, 0x03, 0x59, 0x0E, 0xAA, 0x34, 0x08, 0x07, 0xFA, 0x03, 0x59, 0x2F, 0x2A, 0x06, 0x30,
|
||||
0x9B, 0x40, 0x3C, 0xB0, 0x83, 0x52, 0x03, 0x53, 0xA1, 0xC0, 0x21, 0xC8, 0x95, 0x00, 0x97, 0xD4,
|
||||
0x97, 0x90, 0x0D, 0x08, 0xB4, 0x00, 0x06, 0xBA, 0x03, 0x59, 0xF3, 0x69, 0x21, 0x6A, 0x10, 0xF0,
|
||||
0xA2, 0x01, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50,
|
||||
0x08, 0x40, 0xB3, 0x40, 0x04, 0xF0, 0xA2, 0xC0, 0x10, 0xF0, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00,
|
||||
0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x2D, 0x48, 0xA2, 0xC0, 0x14, 0x30, 0xA3, 0x00,
|
||||
0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x2E, 0x48, 0xA2, 0xC0,
|
||||
0x15, 0x70, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50,
|
||||
0x2C, 0x08, 0xA2, 0xC0, 0x13, 0x70, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00,
|
||||
0x17, 0x94, 0x17, 0x50, 0x30, 0xC8, 0x20, 0x38, 0xD5, 0x40, 0xA2, 0xC0, 0x18, 0x30, 0xA3, 0x00,
|
||||
0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x01, 0xF0, 0xB9, 0x81,
|
||||
0xC2, 0x01, 0x84, 0x80, 0x8A, 0x51, 0x02, 0xA0, 0x8A, 0x51, 0xFF, 0x3A, 0x01, 0xBE, 0xBA, 0x40,
|
||||
0x01, 0xF0, 0x84, 0x80, 0x8A, 0x51, 0x02, 0xA0, 0x8A, 0x51, 0xFF, 0x3A, 0x01, 0xBE, 0xC3, 0x00,
|
||||
0x01, 0xF0, 0x84, 0x80, 0x8A, 0x51, 0x02, 0xA0, 0x8A, 0x51, 0xFF, 0x3A, 0x01, 0xBE, 0xBB, 0x80,
|
||||
0x01, 0xF0, 0x84, 0x80, 0x8A, 0x51, 0x02, 0xA0, 0x8A, 0x51, 0xC4, 0xC0, 0x01, 0xF0, 0x84, 0x80,
|
||||
0x8A, 0x51, 0x02, 0xA0, 0x8A, 0x51, 0xBC, 0x40, 0x01, 0xF0, 0x84, 0x80, 0x8A, 0x51, 0x02, 0xA0,
|
||||
0x8A, 0x51, 0xFF, 0x3A, 0x01, 0xBE, 0xC5, 0x00, 0x01, 0xF0, 0x84, 0x80, 0x8A, 0x51, 0x02, 0xA0,
|
||||
0x8A, 0x51, 0xBD, 0x80, 0x01, 0xF0, 0x84, 0x80, 0x8A, 0x51, 0x02, 0xA0, 0x8A, 0x51, 0xC6, 0x00,
|
||||
0x0B, 0x70, 0xD7, 0x80, 0x57, 0x88, 0xB4, 0x00, 0x33, 0x98, 0x06, 0xAB, 0x57, 0x88, 0xB1, 0x00,
|
||||
0x01, 0xF0, 0xE1, 0x27, 0x8A, 0x51, 0x83, 0x52, 0x03, 0x53, 0xA1, 0xC0, 0x21, 0xC8, 0x95, 0x00,
|
||||
0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xC3, 0x39, 0x31, 0x04, 0xA2, 0xC0, 0x01, 0xF0, 0xA3, 0x00,
|
||||
0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x01, 0xF0, 0x83, 0x52,
|
||||
0x03, 0x53, 0xA1, 0xC0, 0x21, 0xC8, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xD3, 0x67,
|
||||
0x8A, 0x51, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50,
|
||||
0x01, 0xF0, 0x83, 0x52, 0x03, 0x53, 0xA1, 0xC0, 0x21, 0xC8, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90,
|
||||
0x0D, 0x08, 0xA2, 0xC0, 0x01, 0xF0, 0xA2, 0x10, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08,
|
||||
0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x39, 0x48, 0xA2, 0xC0, 0x11, 0x30, 0xA3, 0x00, 0x22, 0xC8,
|
||||
0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x42, 0xC8, 0xA2, 0xC0, 0x12, 0x30,
|
||||
0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x30, 0xC8,
|
||||
0xA4, 0xC0, 0x4B, 0xB0, 0x2D, 0x27, 0x8A, 0x51, 0xD6, 0x81, 0x69, 0x2B, 0x57, 0x88, 0xB1, 0x00,
|
||||
0x02, 0xF0, 0xE1, 0x27, 0x8A, 0x51, 0x83, 0x52, 0x03, 0x53, 0xA1, 0xC0, 0x21, 0xC8, 0x95, 0x00,
|
||||
0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xC3, 0x39, 0x31, 0x04, 0xA2, 0xC0, 0x02, 0xF0, 0xA3, 0x00,
|
||||
0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x02, 0xF0, 0x83, 0x52,
|
||||
0x03, 0x53, 0xA1, 0xC0, 0x21, 0xC8, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xCF, 0xA7,
|
||||
0x8A, 0x51, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50,
|
||||
0x02, 0xF0, 0x83, 0x52, 0x03, 0x53, 0xA1, 0xC0, 0x21, 0xC8, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90,
|
||||
0x0D, 0x08, 0xA2, 0xC0, 0x02, 0xF0, 0xA2, 0x10, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08,
|
||||
0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0xEB, 0x6A, 0x56, 0x48, 0xCA, 0x27, 0x8A, 0x51, 0xA3, 0x00,
|
||||
0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0xB1, 0x27, 0x8A, 0x51,
|
||||
0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x30, 0xC8,
|
||||
0xA4, 0xC0, 0x51, 0x70, 0x2D, 0x27, 0x8A, 0x51, 0x4B, 0xB0, 0xA1, 0xC0, 0x51, 0x70, 0x79, 0x67,
|
||||
0x8A, 0x51, 0xCD, 0x40, 0x4D, 0x48, 0x03, 0x59, 0x69, 0x2B, 0x51, 0x08, 0xCB, 0x40, 0x52, 0x08,
|
||||
0xCC, 0x00, 0x05, 0x30, 0xD6, 0xCA, 0x56, 0x42, 0x03, 0x5C, 0x44, 0xAB, 0x2F, 0x88, 0xD1, 0x00,
|
||||
0x51, 0x70, 0xD2, 0x41, 0xA1, 0xC0, 0x4B, 0xB0, 0x79, 0x67, 0x8A, 0x51, 0xCD, 0x40, 0x4D, 0x48,
|
||||
0x03, 0x9D, 0x7F, 0xEB, 0x07, 0x70, 0xD7, 0x03, 0x57, 0x82, 0x03, 0x18, 0xAA, 0xEA, 0x4B, 0x48,
|
||||
0xB7, 0x80, 0x4C, 0x08, 0xB8, 0x00, 0xD3, 0x81, 0xD4, 0x41, 0xD7, 0xC1, 0x53, 0x48, 0xB9, 0x40,
|
||||
0x54, 0x08, 0xC2, 0xC0, 0x57, 0x88, 0x01, 0xBE, 0x84, 0x80, 0x8A, 0x51, 0x02, 0xA0, 0x8A, 0x51,
|
||||
0xA1, 0xC0, 0x53, 0x48, 0xDD, 0x66, 0x83, 0x52, 0x03, 0x53, 0xBA, 0x40, 0x57, 0x88, 0x01, 0xBE,
|
||||
0x84, 0x80, 0x8A, 0x51, 0x02, 0xA0, 0x8A, 0x51, 0xA1, 0xC0, 0x54, 0x08, 0xDD, 0x66, 0x83, 0x52,
|
||||
0x03, 0x53, 0xC3, 0x00, 0x57, 0x88, 0x01, 0xBE, 0x84, 0x80, 0x8A, 0x51, 0x02, 0xA0, 0x8A, 0x51,
|
||||
0xA1, 0xC0, 0x53, 0x48, 0xDD, 0x66, 0x83, 0x52, 0x03, 0x53, 0xBB, 0x80, 0x57, 0x88, 0x01, 0xBE,
|
||||
0x84, 0x80, 0x8A, 0x51, 0x02, 0xA0, 0x8A, 0x51, 0xEB, 0xA7, 0x8A, 0x51, 0xDD, 0x66, 0x83, 0x52,
|
||||
0x03, 0x53, 0xC4, 0xC0, 0x57, 0x88, 0x01, 0xBE, 0x84, 0x80, 0x8A, 0x51, 0x02, 0xA0, 0x8A, 0x51,
|
||||
0xDC, 0x67, 0x8A, 0x51, 0xDD, 0x66, 0x83, 0x52, 0x03, 0x53, 0xBC, 0x40, 0x57, 0x88, 0x01, 0xBE,
|
||||
0x84, 0x80, 0x8A, 0x51, 0x02, 0xA0, 0x8A, 0x51, 0xA1, 0xC0, 0x54, 0x08, 0xDD, 0x66, 0x83, 0x52,
|
||||
0x03, 0x53, 0xC5, 0x00, 0x57, 0x88, 0x01, 0xBE, 0x84, 0x80, 0x8A, 0x51, 0x02, 0xA0, 0x8A, 0x51,
|
||||
0xDC, 0x67, 0x8A, 0x51, 0xDD, 0x66, 0x83, 0x52, 0x03, 0x53, 0xBD, 0x80, 0x57, 0x88, 0x01, 0xBE,
|
||||
0x84, 0x80, 0x8A, 0x51, 0x02, 0xA0, 0x8A, 0x51, 0xEB, 0xA7, 0x8A, 0x51, 0xDD, 0x66, 0x8A, 0x51,
|
||||
0x83, 0x52, 0x03, 0x53, 0xC6, 0x00, 0x39, 0x48, 0xA2, 0xC0, 0x11, 0x30, 0xA3, 0x00, 0x22, 0xC8,
|
||||
0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x42, 0xC8, 0xA2, 0xC0, 0x12, 0x30,
|
||||
0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x30, 0xC8,
|
||||
0xA4, 0xC0, 0x4F, 0xF0, 0x2D, 0x27, 0x8A, 0x51, 0x05, 0x30, 0xCE, 0x81, 0xA1, 0xC0, 0x57, 0x88,
|
||||
0x96, 0x27, 0x8A, 0x51, 0xA0, 0xFE, 0x84, 0x80, 0x4F, 0x88, 0xE6, 0x67, 0x8A, 0x51, 0x96, 0x27,
|
||||
0x8A, 0x51, 0xA0, 0xFE, 0x84, 0x80, 0x50, 0xC8, 0x83, 0xD7, 0x80, 0x40, 0xD6, 0x81, 0x05, 0x30,
|
||||
0xD6, 0xCA, 0x56, 0x42, 0x03, 0x18, 0x5A, 0xEC, 0x56, 0x48, 0x39, 0x7E, 0x84, 0x80, 0x83, 0x93,
|
||||
0x00, 0x48, 0xA2, 0xC0, 0x11, 0x30, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00,
|
||||
0x17, 0x94, 0x17, 0x50, 0xB1, 0x27, 0x8A, 0x51, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08,
|
||||
0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x30, 0xC8, 0xA4, 0xC0, 0x51, 0x70, 0x2D, 0x27, 0x8A, 0x51,
|
||||
0x51, 0x70, 0xA1, 0xC0, 0x4F, 0xF0, 0x79, 0x67, 0x8A, 0x51, 0xCD, 0x40, 0x4D, 0x48, 0x03, 0x59,
|
||||
0x44, 0x6C, 0x51, 0x08, 0xBE, 0xA7, 0x8A, 0x51, 0x05, 0x30, 0xA1, 0xC0, 0x57, 0x88, 0x96, 0x27,
|
||||
0x8A, 0x51, 0xA0, 0xFE, 0x56, 0xC7, 0xB1, 0x00, 0x84, 0x80, 0x51, 0x08, 0xE6, 0x67, 0x8A, 0x51,
|
||||
0x96, 0x27, 0x8A, 0x51, 0xA0, 0xFE, 0x56, 0xC7, 0xB1, 0x00, 0x84, 0x80, 0x52, 0x08, 0x83, 0xD7,
|
||||
0x80, 0x40, 0x17, 0xEC, 0x57, 0x88, 0xE0, 0x3E, 0x84, 0x80, 0x4E, 0x48, 0x83, 0x93, 0x80, 0x40,
|
||||
0x4E, 0x48, 0x39, 0x7E, 0x84, 0x80, 0x00, 0x48, 0xD3, 0x40, 0xC4, 0xE7, 0x8A, 0x51, 0x09, 0x30,
|
||||
0xD7, 0x0A, 0x57, 0x82, 0x03, 0x5C, 0x86, 0xEB, 0xA1, 0x01, 0xA1, 0x43, 0x53, 0x48, 0xDD, 0x66,
|
||||
0x8A, 0x51, 0x83, 0x52, 0x03, 0x53, 0xB9, 0x40, 0xA1, 0x01, 0xA1, 0x43, 0x54, 0x08, 0xDD, 0x66,
|
||||
0x8A, 0x51, 0x83, 0x52, 0x03, 0x53, 0xC2, 0xC0, 0xA1, 0x01, 0xA1, 0x43, 0x53, 0x48, 0xDD, 0x66,
|
||||
0x8A, 0x51, 0x83, 0x52, 0x03, 0x53, 0xBA, 0x40, 0x54, 0x08, 0xC3, 0x00, 0xA1, 0x01, 0xA1, 0x43,
|
||||
0x53, 0x48, 0xDD, 0x66, 0x8A, 0x51, 0x83, 0x52, 0x03, 0x53, 0xBB, 0x80, 0xA1, 0x01, 0xA1, 0x4A,
|
||||
0x54, 0x08, 0xDD, 0x66, 0x8A, 0x51, 0x83, 0x52, 0x03, 0x53, 0xC4, 0xC0, 0x53, 0x48, 0xBC, 0x40,
|
||||
0xA1, 0x01, 0xA1, 0x43, 0x54, 0x08, 0xDD, 0x66, 0x8A, 0x51, 0x83, 0x52, 0x03, 0x53, 0xC5, 0x00,
|
||||
0x53, 0x48, 0xBD, 0x80, 0x54, 0x08, 0xC6, 0x00, 0x53, 0x48, 0xBE, 0x80, 0xA1, 0x01, 0xA1, 0x4A,
|
||||
0x54, 0x08, 0xDD, 0x66, 0x8A, 0x51, 0x83, 0x52, 0x03, 0x53, 0xC7, 0x40, 0xA1, 0x01, 0xA1, 0x4A,
|
||||
0x53, 0x48, 0xDD, 0x66, 0x8A, 0x51, 0x83, 0x52, 0x03, 0x53, 0xBF, 0xC0, 0xA1, 0x01, 0xA1, 0x43,
|
||||
0x54, 0x08, 0xDD, 0x66, 0x8A, 0x51, 0x83, 0x52, 0x03, 0x53, 0xC8, 0xC0, 0xA1, 0x01, 0xA1, 0x4A,
|
||||
0x53, 0x48, 0xDD, 0x66, 0x8A, 0x51, 0x83, 0x52, 0x03, 0x53, 0xC0, 0x80, 0x54, 0x08, 0xC9, 0x00,
|
||||
0xA1, 0x01, 0xA1, 0x4A, 0x53, 0x48, 0xDD, 0x66, 0x8A, 0x51, 0x83, 0x52, 0x03, 0x53, 0xC1, 0xC0,
|
||||
0xA1, 0x01, 0xA1, 0x4A, 0x54, 0x08, 0xDD, 0x66, 0x8A, 0x51, 0x83, 0x52, 0x03, 0x53, 0xCA, 0x00,
|
||||
0xCE, 0x81, 0x39, 0x48, 0xA2, 0xC0, 0x11, 0x30, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08,
|
||||
0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x42, 0xC8, 0xA2, 0xC0, 0x12, 0x30, 0xA3, 0x00, 0x22, 0xC8,
|
||||
0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x30, 0xC8, 0xA4, 0xC0, 0x4F, 0xF0,
|
||||
0x2D, 0x27, 0x8A, 0x51, 0xD6, 0x81, 0x09, 0x30, 0xD6, 0xCA, 0x56, 0x42, 0x03, 0x18, 0x1D, 0x2D,
|
||||
0x56, 0x48, 0xCA, 0x27, 0x8A, 0x51, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00,
|
||||
0x17, 0x94, 0x17, 0x50, 0xB1, 0x27, 0x8A, 0x51, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08,
|
||||
0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x30, 0xC8, 0xA4, 0xC0, 0x51, 0x70, 0x2D, 0x27, 0x8A, 0x51,
|
||||
0x51, 0x70, 0xA1, 0xC0, 0x4F, 0xF0, 0x79, 0x67, 0x8A, 0x51, 0xCD, 0x40, 0x4D, 0x48, 0x03, 0x59,
|
||||
0xF3, 0x6C, 0x51, 0x08, 0xBE, 0xA7, 0x8A, 0x51, 0xF3, 0x6C, 0x4E, 0x48, 0x39, 0x7E, 0x84, 0x80,
|
||||
0x00, 0x48, 0xD3, 0x40, 0xC4, 0xE7, 0x8A, 0x51, 0x53, 0x48, 0xA2, 0xC0, 0x11, 0x30, 0xA3, 0x00,
|
||||
0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x54, 0x08, 0xA2, 0xC0,
|
||||
0x12, 0x30, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50,
|
||||
0x4F, 0x88, 0xB5, 0x40, 0x50, 0xC8, 0xB6, 0x40, 0x2F, 0x88, 0xA2, 0xC0, 0x19, 0x70, 0xA3, 0x00,
|
||||
0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x34, 0x08, 0xA2, 0xC0,
|
||||
0x1A, 0x70, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50,
|
||||
0x37, 0x88, 0xA2, 0xC0, 0x1B, 0xB0, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00,
|
||||
0x17, 0x94, 0x17, 0x50, 0x38, 0x08, 0xA2, 0xC0, 0x1C, 0x70, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00,
|
||||
0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x06, 0x30, 0x9B, 0x40, 0x3C, 0xB0, 0x83, 0x52,
|
||||
0x03, 0x53, 0xA1, 0xC0, 0x21, 0xC8, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xD5, 0x40,
|
||||
0x9E, 0x40, 0x55, 0x48, 0x06, 0xBA, 0x03, 0x9D, 0x66, 0x2D, 0x35, 0x48, 0xA2, 0xC0, 0x19, 0x70,
|
||||
0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x36, 0x48,
|
||||
0xA2, 0xC0, 0x1A, 0x70, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94,
|
||||
0x17, 0x50, 0x53, 0x48, 0xA2, 0xC0, 0x1B, 0xB0, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08,
|
||||
0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x54, 0x08, 0xA2, 0xC0, 0x1C, 0x70, 0xA3, 0x00, 0x22, 0xC8,
|
||||
0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x07, 0x70, 0x9B, 0x40, 0x3C, 0xB0,
|
||||
0x83, 0x52, 0x03, 0x53, 0xA1, 0xC0, 0x21, 0xC8, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08,
|
||||
0xD5, 0x40, 0x9E, 0x40, 0x55, 0x48, 0x07, 0xFA, 0x03, 0x9D, 0x9F, 0xAD, 0x83, 0x96, 0x60, 0xC8,
|
||||
0x83, 0x52, 0xA2, 0xC0, 0x19, 0x70, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00,
|
||||
0x17, 0x94, 0x17, 0x50, 0x83, 0x96, 0x61, 0x08, 0x83, 0x52, 0xA2, 0xC0, 0x1A, 0x70, 0xA3, 0x00,
|
||||
0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x83, 0x96, 0x62, 0x08,
|
||||
0x83, 0x52, 0xA2, 0xC0, 0x1B, 0xB0, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00,
|
||||
0x17, 0x94, 0x17, 0x50, 0x83, 0x96, 0x63, 0x48, 0x83, 0x52, 0xA2, 0xC0, 0x1C, 0x70, 0xA3, 0x00,
|
||||
0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x08, 0xF0, 0x9B, 0x40,
|
||||
0x3C, 0xB0, 0x83, 0x52, 0x03, 0x53, 0xA1, 0xC0, 0x21, 0xC8, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90,
|
||||
0x0D, 0x08, 0xD5, 0x40, 0x9E, 0x40, 0x55, 0x48, 0x08, 0x7A, 0x03, 0x9D, 0xE0, 0xED, 0x83, 0x96,
|
||||
0x64, 0x08, 0x83, 0x52, 0xA2, 0xC0, 0x19, 0x70, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08,
|
||||
0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x83, 0x96, 0x65, 0x48, 0x83, 0x52, 0xA2, 0xC0, 0x1A, 0x70,
|
||||
0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x83, 0x96,
|
||||
0x66, 0x48, 0x83, 0x52, 0xA2, 0xC0, 0x1B, 0xB0, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08,
|
||||
0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x83, 0x96, 0x67, 0x88, 0x83, 0x52, 0xA2, 0xC0, 0x1C, 0x70,
|
||||
0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x09, 0x30,
|
||||
0x9B, 0x40, 0x3C, 0xB0, 0x83, 0x52, 0x03, 0x53, 0xA1, 0xC0, 0x21, 0xC8, 0x95, 0x00, 0x97, 0xD4,
|
||||
0x97, 0x90, 0x0D, 0x08, 0xD5, 0x40, 0x9E, 0x40, 0x55, 0x48, 0x09, 0xBA, 0x03, 0x9D, 0x21, 0xAE,
|
||||
0x83, 0x96, 0x68, 0x08, 0x83, 0x52, 0xA2, 0xC0, 0x19, 0x70, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00,
|
||||
0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x83, 0x96, 0x69, 0x48, 0x83, 0x52, 0xA2, 0xC0,
|
||||
0x1A, 0x70, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50,
|
||||
0x83, 0x96, 0x6A, 0x48, 0x83, 0x52, 0xA2, 0xC0, 0x1B, 0xB0, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00,
|
||||
0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x83, 0x96, 0x6B, 0x88, 0x83, 0x52, 0xA2, 0xC0,
|
||||
0x1C, 0x70, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50,
|
||||
0x0A, 0x30, 0x9B, 0x40, 0x3C, 0xB0, 0x83, 0x52, 0x03, 0x53, 0xA1, 0xC0, 0x21, 0xC8, 0x95, 0x00,
|
||||
0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xD5, 0x40, 0x9E, 0x40, 0x55, 0x48, 0x0A, 0xBA, 0x03, 0x9D,
|
||||
0x62, 0xEE, 0xD7, 0xC1, 0x03, 0xD0, 0x57, 0x0D, 0xA0, 0xFE, 0x84, 0x80, 0x83, 0x93, 0x00, 0x48,
|
||||
0xA2, 0xC0, 0x19, 0x70, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94,
|
||||
0x17, 0x50, 0x03, 0xD0, 0x57, 0x0D, 0xA0, 0xFE, 0x84, 0x80, 0x83, 0xD7, 0x00, 0x48, 0xA2, 0xC0,
|
||||
0x1A, 0x70, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50,
|
||||
0x03, 0xD0, 0x57, 0x0D, 0xA1, 0x3E, 0x84, 0x80, 0x83, 0x93, 0x00, 0x48, 0xA2, 0xC0, 0x1B, 0xB0,
|
||||
0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x03, 0xD0,
|
||||
0x57, 0x0D, 0xA1, 0x3E, 0x84, 0x80, 0x83, 0xD7, 0x00, 0x48, 0xA2, 0xC0, 0x1C, 0x70, 0xA3, 0x00,
|
||||
0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x57, 0x88, 0x0C, 0xFE,
|
||||
0x9B, 0x40, 0x3C, 0xB0, 0x83, 0x52, 0x03, 0x53, 0xA1, 0xC0, 0x21, 0xC8, 0x95, 0x00, 0x97, 0xD4,
|
||||
0x97, 0x90, 0x0D, 0x08, 0xA4, 0xE7, 0x8A, 0x51, 0x03, 0x9D, 0xB1, 0x2E, 0x14, 0x30, 0xD7, 0x0A,
|
||||
0x57, 0x82, 0x03, 0x5C, 0x73, 0x6E, 0x57, 0x88, 0x0C, 0xFE, 0x9B, 0x40, 0x3C, 0xB0, 0x83, 0x52,
|
||||
0x03, 0x53, 0xA1, 0xC0, 0x21, 0xC8, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xA4, 0xE7,
|
||||
0x8A, 0x51, 0x03, 0x9D, 0xC6, 0x2E, 0x10, 0xF0, 0xA2, 0x01, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00,
|
||||
0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x08, 0x40, 0xAB, 0x40, 0xAB, 0x9F, 0x09, 0xEF,
|
||||
0xA1, 0x1F, 0x04, 0xAF, 0x2B, 0x48, 0xA2, 0xC0, 0xA3, 0x41, 0xA2, 0xDB, 0xA3, 0x83, 0x80, 0xF0,
|
||||
0xA4, 0xC0, 0xFF, 0xB0, 0xA5, 0x00, 0x22, 0xC8, 0x24, 0xC2, 0xA6, 0x00, 0x23, 0x08, 0x03, 0x5C,
|
||||
0x23, 0x4A, 0x25, 0x02, 0xA7, 0x40, 0x21, 0xC8, 0xA8, 0xC0, 0xA9, 0x41, 0xA8, 0xDB, 0xA9, 0x83,
|
||||
0x29, 0x08, 0x80, 0x7A, 0xAA, 0x00, 0x27, 0x48, 0x80, 0x7A, 0x2A, 0x02, 0x03, 0x9D, 0x02, 0xAF,
|
||||
0x26, 0x08, 0x28, 0xC2, 0x03, 0x5C, 0x80, 0x34, 0x83, 0x52, 0x03, 0x53, 0x21, 0xC8, 0x2B, 0xC7,
|
||||
0x08, 0x40, 0x21, 0xC8, 0x80, 0x7A, 0x7F, 0x3E, 0x03, 0x5C, 0x04, 0xAF, 0x21, 0xC8, 0xA2, 0xC0,
|
||||
0xA3, 0x41, 0xA2, 0xDB, 0xA3, 0x83, 0x2B, 0x48, 0xA4, 0xC0, 0xA5, 0x41, 0xA4, 0xDB, 0xA5, 0x83,
|
||||
0x7F, 0x70, 0xA6, 0x00, 0x24, 0xC8, 0x26, 0x02, 0xA7, 0x40, 0x25, 0x49, 0x03, 0x18, 0x01, 0xBE,
|
||||
0xA8, 0xC0, 0x80, 0x7A, 0xA9, 0x00, 0x23, 0x08, 0x80, 0x7A, 0x29, 0x02, 0x03, 0x9D, 0x2A, 0x2F,
|
||||
0x22, 0xC8, 0x27, 0x42, 0x03, 0x5C, 0x7F, 0xB4, 0x04, 0xAF, 0xA8, 0xC0, 0x24, 0xC8, 0x20, 0x38,
|
||||
0xA7, 0x40, 0xA2, 0xC0, 0x18, 0x30, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00,
|
||||
0x17, 0x94, 0x17, 0x50, 0x05, 0x30, 0xA5, 0x00, 0xA5, 0xCB, 0x3C, 0x6F, 0x83, 0x52, 0x03, 0x53,
|
||||
0x24, 0xC8, 0x30, 0x78, 0xA7, 0x40, 0xA2, 0xC0, 0x18, 0x30, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00,
|
||||
0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x05, 0x30, 0xA5, 0x00, 0xA5, 0xCB, 0x4E, 0x6F,
|
||||
0x39, 0xB0, 0x83, 0x52, 0x03, 0x53, 0xA1, 0xC0, 0x21, 0xC8, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90,
|
||||
0x0D, 0x08, 0xA6, 0x00, 0x55, 0xB0, 0x9E, 0x40, 0x26, 0x9C, 0x50, 0xEF, 0x28, 0xC8, 0x84, 0x80,
|
||||
0x3A, 0xB0, 0x83, 0x52, 0x03, 0x53, 0xA1, 0xC0, 0x21, 0xC8, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90,
|
||||
0x0D, 0x08, 0x83, 0x93, 0x80, 0x40, 0x28, 0x0A, 0x84, 0x80, 0x3B, 0xF0, 0x83, 0x52, 0x03, 0x53,
|
||||
0xA1, 0xC0, 0x21, 0xC8, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0x83, 0x93, 0x80, 0x40,
|
||||
0x08, 0x40, 0xA4, 0xC0, 0x84, 0x80, 0x83, 0x93, 0x00, 0x48, 0xA2, 0xC0, 0x21, 0xC8, 0xB8, 0x27,
|
||||
0x8A, 0x51, 0x03, 0x5C, 0x01, 0x34, 0x21, 0xC8, 0x84, 0x80, 0x00, 0x48, 0xA2, 0xC0, 0x24, 0xC8,
|
||||
0xB8, 0x27, 0x8A, 0x51, 0x03, 0x5C, 0x00, 0xF4, 0x24, 0x0A, 0x84, 0x80, 0x00, 0x48, 0xA2, 0xC0,
|
||||
0x21, 0x0A, 0xB8, 0x27, 0x8A, 0x51, 0x03, 0x5C, 0x01, 0x34, 0x00, 0xF4, 0xA3, 0x00, 0xA2, 0x01,
|
||||
0x21, 0xC8, 0x23, 0x58, 0xA2, 0x87, 0x03, 0xD0, 0xA1, 0x8D, 0x03, 0xD0, 0xA3, 0x8C, 0xA3, 0x48,
|
||||
0x03, 0x9D, 0x98, 0x2F, 0x22, 0xC8, 0x08, 0x40, 0xD5, 0x40, 0x9E, 0x40, 0x57, 0x88, 0x0C, 0xFE,
|
||||
0xB1, 0x00, 0x00, 0xB0, 0x03, 0x18, 0x01, 0xF0, 0xB2, 0x00, 0x55, 0x48, 0x31, 0x46, 0x32, 0x04,
|
||||
0x08, 0x40, 0x56, 0x48, 0x42, 0xFE, 0x84, 0x80, 0x83, 0x93, 0x00, 0x48, 0xA2, 0xC0, 0x12, 0x74,
|
||||
0x84, 0x80, 0x00, 0x48, 0xA3, 0x00, 0x22, 0xC8, 0x23, 0x02, 0x08, 0x40, 0xCF, 0x80, 0x52, 0x08,
|
||||
0xD0, 0xC0, 0x56, 0x48, 0xCE, 0x40, 0x08, 0x40, 0x4E, 0x48, 0x42, 0xFE, 0x84, 0x80, 0x00, 0x48,
|
||||
0xD4, 0x00, 0x08, 0x40, 0x39, 0x7E, 0x84, 0x80, 0x00, 0x48, 0xA2, 0xC0, 0x11, 0x74, 0xFD, 0xF9,
|
||||
0x02, 0x38, 0xA2, 0xC0, 0x02, 0x34, 0xFD, 0xF9, 0x02, 0x38, 0xA2, 0xC0, 0x01, 0x34, 0x03, 0xD0,
|
||||
0xB0, 0x8D, 0x03, 0xD0, 0xB0, 0x8D, 0x08, 0x40, 0xFF, 0x3A, 0x01, 0xBE, 0xA1, 0xC0, 0x53, 0x48,
|
||||
0x08, 0x40, 0x03, 0xD0, 0xB1, 0xCD, 0x03, 0xD0, 0xB1, 0xCD, 0x08, 0x40, 0x80, 0x40, 0x05, 0x30,
|
||||
0xA1, 0xC0, 0x57, 0x88, 0x08, 0x40, 0xFF, 0x3A, 0x01, 0xBE, 0xA1, 0xC0, 0x54, 0x08, 0x08, 0x40,
|
||||
0xA0, 0x30, 0x83, 0x93, 0x84, 0x80, 0xF0, 0xB0, 0x8A, 0x51, 0x2F, 0xE1, 0x8A, 0x51, 0xA0, 0x30,
|
||||
0x83, 0xD7, 0x84, 0x80, 0xE0, 0x70, 0x8A, 0x51, 0x2F, 0xE1, 0x83, 0x01, 0x8A, 0x95, 0xD5, 0x2A,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF,
|
||||
0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0xFF, 0xBF, 0x01, 0xF0, 0xA0, 0x80, 0x95, 0x41,
|
||||
0x96, 0x41, 0x97, 0x81, 0x98, 0x01, 0x99, 0x41, 0x9A, 0x41, 0x9B, 0x81, 0x9C, 0x41, 0x9E, 0x81,
|
||||
0x9B, 0x81, 0x1C, 0x70, 0xA2, 0x01, 0xA2, 0x4A, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08,
|
||||
0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x01, 0xF0, 0x9B, 0x40, 0x3C, 0xB0, 0x83, 0x52, 0x03, 0x53,
|
||||
0xA1, 0xC0, 0x21, 0xC8, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xE5, 0x40, 0x65, 0x48,
|
||||
0x03, 0x59, 0xED, 0x6A, 0x9B, 0x81, 0x10, 0xF0, 0xA2, 0x01, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00,
|
||||
0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x3C, 0xB0, 0x83, 0x52, 0x03, 0x53, 0xA1, 0xC0,
|
||||
0x21, 0xC8, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xE5, 0x40, 0x9E, 0x40, 0x65, 0xCB,
|
||||
0x04, 0x6B, 0x3D, 0xF0, 0x83, 0x52, 0x03, 0x53, 0xA1, 0xC0, 0x21, 0xC8, 0x95, 0x00, 0x97, 0xD4,
|
||||
0x97, 0x90, 0x0D, 0x08, 0xE2, 0x00, 0xA2, 0xC0, 0x1A, 0x70, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00,
|
||||
0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x3E, 0xF0, 0x83, 0x52, 0x03, 0x53, 0xA1, 0xC0,
|
||||
0x21, 0xC8, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xE3, 0x40, 0xA2, 0xC0, 0x1B, 0xB0,
|
||||
0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x3F, 0x30,
|
||||
0x83, 0x52, 0x03, 0x53, 0xA1, 0xC0, 0x21, 0xC8, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08,
|
||||
0xE4, 0x00, 0x03, 0x30, 0xE4, 0x85, 0x64, 0x08, 0xA2, 0xC0, 0x1C, 0x70, 0xA3, 0x00, 0x22, 0xC8,
|
||||
0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x01, 0xF0, 0x9E, 0x40, 0x9B, 0x40,
|
||||
0x3C, 0xB0, 0x83, 0x52, 0x03, 0x53, 0xA1, 0xC0, 0x21, 0xC8, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90,
|
||||
0x0D, 0x08, 0xE5, 0x40, 0x9E, 0x40, 0x65, 0x48, 0x02, 0x7A, 0x03, 0x9D, 0x50, 0xAB, 0x3D, 0xF0,
|
||||
0x83, 0x52, 0x03, 0x53, 0xA1, 0xC0, 0x21, 0xC8, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08,
|
||||
0xDF, 0xC0, 0xA2, 0xC0, 0x1A, 0x70, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00,
|
||||
0x17, 0x94, 0x17, 0x50, 0x3E, 0xF0, 0x83, 0x52, 0x03, 0x53, 0xA1, 0xC0, 0x21, 0xC8, 0x95, 0x00,
|
||||
0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xE0, 0xC0, 0xA2, 0xC0, 0x1B, 0xB0, 0xA3, 0x00, 0x22, 0xC8,
|
||||
0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x02, 0xF0, 0x9E, 0x40, 0x9B, 0x40,
|
||||
0x3C, 0xB0, 0x83, 0x52, 0x03, 0x53, 0xA1, 0xC0, 0x21, 0xC8, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90,
|
||||
0x0D, 0x08, 0xE5, 0x40, 0x9E, 0x40, 0x65, 0x48, 0x03, 0xBA, 0x03, 0x9D, 0x88, 0xAB, 0x3D, 0xF0,
|
||||
0x83, 0x52, 0x03, 0x53, 0xA1, 0xC0, 0x21, 0xC8, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08,
|
||||
0xDC, 0x40, 0xA2, 0xC0, 0x1A, 0x70, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00,
|
||||
0x17, 0x94, 0x17, 0x50, 0x3E, 0xF0, 0x83, 0x52, 0x03, 0x53, 0xA1, 0xC0, 0x21, 0xC8, 0x95, 0x00,
|
||||
0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xDD, 0x80, 0xA2, 0xC0, 0x1B, 0xB0, 0xA3, 0x00, 0x22, 0xC8,
|
||||
0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x03, 0x30, 0x9E, 0x40, 0x9B, 0x40,
|
||||
0x3C, 0xB0, 0x83, 0x52, 0x03, 0x53, 0xA1, 0xC0, 0x21, 0xC8, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90,
|
||||
0x0D, 0x08, 0xE5, 0x40, 0x9E, 0x40, 0x65, 0x48, 0x04, 0x7A, 0x03, 0x9D, 0xC0, 0xAB, 0x9E, 0x81,
|
||||
0x9B, 0x81, 0x3D, 0xF0, 0x83, 0x52, 0x03, 0x53, 0xA1, 0xC0, 0x21, 0xC8, 0x95, 0x00, 0x97, 0xD4,
|
||||
0x97, 0x90, 0x0D, 0x08, 0xDE, 0x80, 0xA2, 0xC0, 0x1A, 0x70, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00,
|
||||
0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x3E, 0xF0, 0x83, 0x52, 0x03, 0x53, 0xA1, 0xC0,
|
||||
0x21, 0xC8, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xE1, 0x00, 0xA2, 0xC0, 0x1B, 0xB0,
|
||||
0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0xE2, 0x48,
|
||||
0x03, 0x9D, 0x02, 0x2C, 0x63, 0x48, 0x56, 0xA4, 0x00, 0xB0, 0x8A, 0x95, 0x5C, 0xA4, 0x8A, 0x95,
|
||||
0x11, 0x30, 0x3B, 0x2C, 0x62, 0x8B, 0x0C, 0x6C, 0x63, 0x48, 0x56, 0xA4, 0x01, 0xF0, 0x8A, 0x95,
|
||||
0x5C, 0xA4, 0x8A, 0x95, 0x22, 0x30, 0x3B, 0x2C, 0x62, 0x08, 0x02, 0x7A, 0x03, 0x9D, 0x18, 0x6C,
|
||||
0x63, 0x48, 0x4C, 0x64, 0x00, 0xB0, 0x8A, 0x51, 0x39, 0xA2, 0x8A, 0x95, 0x33, 0xB0, 0x3B, 0x2C,
|
||||
0x62, 0x08, 0x03, 0xBA, 0x03, 0x9D, 0x24, 0x6C, 0x63, 0x48, 0x4C, 0x64, 0x01, 0xF0, 0x8A, 0x51,
|
||||
0x39, 0xA2, 0x8A, 0x95, 0x44, 0x30, 0x3B, 0x2C, 0x62, 0x08, 0x04, 0x7A, 0x03, 0x9D, 0x30, 0x6C,
|
||||
0x63, 0x48, 0x3E, 0xE4, 0x00, 0xB0, 0x8A, 0x51, 0x37, 0xE1, 0x8A, 0x95, 0x55, 0xB0, 0x3B, 0x2C,
|
||||
0x62, 0x08, 0x05, 0xBA, 0x03, 0x9D, 0x04, 0x6B, 0x63, 0x48, 0x3E, 0xE4, 0x01, 0xF0, 0x8A, 0x51,
|
||||
0x37, 0xE1, 0x8A, 0x95, 0x66, 0xB0, 0x9B, 0x40, 0x9E, 0x40, 0x04, 0x6B, 0xA9, 0x00, 0x5F, 0xC8,
|
||||
0xAA, 0x00, 0x60, 0xC8, 0xAB, 0x40, 0x5C, 0x48, 0xAC, 0x00, 0x5D, 0x88, 0xAD, 0x40, 0x5E, 0x88,
|
||||
0xAE, 0x40, 0x64, 0x08, 0xAF, 0x80, 0x08, 0x40, 0xAC, 0x00, 0x5F, 0xC8, 0xAD, 0x40, 0x60, 0xC8,
|
||||
0xAE, 0x40, 0x61, 0x08, 0xAF, 0x80, 0x64, 0x08, 0xB0, 0xC0, 0x08, 0x40, 0xA9, 0x00, 0x61, 0x08,
|
||||
0xAA, 0x00, 0x64, 0x08, 0xAB, 0x40, 0x08, 0x40, 0xB3, 0x40, 0x04, 0xF0, 0xA2, 0xC0, 0x10, 0xF0,
|
||||
0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x29, 0x08,
|
||||
0xA2, 0xC0, 0x13, 0x70, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94,
|
||||
0x17, 0x50, 0x14, 0x30, 0xA2, 0x01, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00,
|
||||
0x17, 0x94, 0x17, 0x50, 0x15, 0x70, 0xA2, 0x01, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08,
|
||||
0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x2A, 0x08, 0xD6, 0x40, 0x0B, 0x70, 0xD7, 0xC1, 0xDB, 0x80,
|
||||
0x5B, 0x88, 0xB4, 0x00, 0x33, 0x98, 0xE0, 0xAC, 0x5B, 0x88, 0xAC, 0x00, 0x01, 0xF0, 0xFB, 0xE7,
|
||||
0x8A, 0x95, 0x83, 0x52, 0x03, 0x53, 0xA1, 0xC0, 0x21, 0xC8, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90,
|
||||
0x0D, 0x08, 0xC3, 0x39, 0x2C, 0x04, 0xA2, 0xC0, 0x01, 0xF0, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00,
|
||||
0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x01, 0xF0, 0x83, 0x52, 0x03, 0x53, 0xA1, 0xC0,
|
||||
0x21, 0xC8, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0x8A, 0x51, 0xD3, 0x67, 0x8A, 0x95,
|
||||
0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x01, 0xF0,
|
||||
0x83, 0x52, 0x03, 0x53, 0xA1, 0xC0, 0x21, 0xC8, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08,
|
||||
0xA2, 0xC0, 0x01, 0xF0, 0xA2, 0x10, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00,
|
||||
0x17, 0x94, 0x17, 0x50, 0x2B, 0x48, 0xA4, 0xC0, 0x53, 0xB0, 0x8A, 0x51, 0x2D, 0x27, 0x8A, 0x95,
|
||||
0x56, 0xB0, 0xA1, 0xC0, 0x53, 0xB0, 0x8A, 0x51, 0x79, 0x67, 0x8A, 0x95, 0xD0, 0xC0, 0x50, 0xC8,
|
||||
0x03, 0x9D, 0x1F, 0x6D, 0x07, 0x70, 0xDB, 0x03, 0x5B, 0x82, 0x03, 0x5C, 0x1F, 0x6D, 0x88, 0x6C,
|
||||
0x5B, 0x88, 0xAC, 0x00, 0x02, 0xF0, 0xFB, 0xE7, 0x8A, 0x95, 0x83, 0x52, 0x03, 0x53, 0xA1, 0xC0,
|
||||
0x21, 0xC8, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xC3, 0x39, 0x2C, 0x04, 0xA2, 0xC0,
|
||||
0x02, 0xF0, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50,
|
||||
0x02, 0xF0, 0x83, 0x52, 0x03, 0x53, 0xA1, 0xC0, 0x21, 0xC8, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90,
|
||||
0x0D, 0x08, 0x8A, 0x51, 0xCF, 0xA7, 0x8A, 0x95, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08,
|
||||
0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x02, 0xF0, 0x83, 0x52, 0x03, 0x53, 0xA1, 0xC0, 0x21, 0xC8,
|
||||
0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xA2, 0xC0, 0x02, 0xF0, 0xA2, 0x10, 0xA3, 0x00,
|
||||
0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0xCA, 0xEC, 0x53, 0x48,
|
||||
0xB5, 0x40, 0x54, 0x08, 0xB6, 0x40, 0xF3, 0xA7, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08,
|
||||
0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x2B, 0x48, 0xA4, 0xC0, 0x56, 0xB0, 0x8A, 0x51, 0x2D, 0x27,
|
||||
0x8A, 0x95, 0x56, 0x48, 0xB9, 0x40, 0x57, 0x88, 0xBA, 0x40, 0x29, 0x08, 0xFE, 0xFC, 0xAD, 0x40,
|
||||
0x29, 0x49, 0xAE, 0x40, 0x29, 0x08, 0x01, 0x7C, 0xAF, 0x80, 0x29, 0x08, 0x02, 0x7C, 0xB0, 0xC0,
|
||||
0x14, 0x30, 0xA2, 0x01, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94,
|
||||
0x17, 0x50, 0x15, 0x70, 0xA2, 0x01, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00,
|
||||
0x17, 0x94, 0x17, 0x50, 0x2D, 0x48, 0xA2, 0xC0, 0x13, 0x70, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00,
|
||||
0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x2B, 0x48, 0xA4, 0xC0, 0x53, 0xB0, 0x8A, 0x51,
|
||||
0x2D, 0x27, 0x8A, 0x95, 0xDB, 0xC1, 0xDB, 0x0A, 0x5B, 0x88, 0x2D, 0x7E, 0x84, 0x80, 0x00, 0x48,
|
||||
0xA2, 0xC0, 0x13, 0x70, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94,
|
||||
0x17, 0x50, 0x2B, 0x48, 0xA4, 0xC0, 0x56, 0xB0, 0x8A, 0x51, 0x2D, 0x27, 0x8A, 0x95, 0x53, 0xB0,
|
||||
0xA1, 0xC0, 0x56, 0xB0, 0x8A, 0x51, 0x79, 0x67, 0x8A, 0x95, 0xD0, 0xC0, 0x50, 0xC8, 0x03, 0x59,
|
||||
0x85, 0xED, 0x56, 0x48, 0xD3, 0x40, 0x57, 0x88, 0xD4, 0x00, 0x04, 0xF0, 0xDB, 0x0A, 0x5B, 0x82,
|
||||
0x03, 0x5C, 0x64, 0xED, 0x53, 0x48, 0xB7, 0x80, 0x54, 0x08, 0xB8, 0x00, 0xF3, 0xA7, 0xA3, 0x00,
|
||||
0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0xD8, 0x41, 0xD9, 0x81,
|
||||
0xDB, 0xC1, 0x58, 0x08, 0xBD, 0x80, 0x59, 0x48, 0xC6, 0x00, 0x5B, 0x88, 0x0A, 0xFE, 0x84, 0x80,
|
||||
0x8A, 0x51, 0x02, 0xA0, 0x8A, 0x95, 0x58, 0x87, 0xBE, 0x80, 0x5B, 0x88, 0x0A, 0xFE, 0x84, 0x80,
|
||||
0x8A, 0x51, 0x02, 0xA0, 0x8A, 0x95, 0x59, 0xC7, 0xC7, 0x40, 0x5B, 0x88, 0x0A, 0xFE, 0x84, 0x80,
|
||||
0x8A, 0x51, 0x02, 0xA0, 0x8A, 0x95, 0x58, 0x87, 0xBF, 0xC0, 0x5B, 0x88, 0x0A, 0xFE, 0x84, 0x80,
|
||||
0x8A, 0x51, 0x02, 0xA0, 0x8A, 0x95, 0x59, 0x42, 0xC8, 0xC0, 0x5B, 0x88, 0x0A, 0xFE, 0x84, 0x80,
|
||||
0x8A, 0x51, 0x02, 0xA0, 0x8A, 0x95, 0x58, 0x02, 0xC0, 0x80, 0x5B, 0x88, 0x0A, 0xFE, 0x84, 0x80,
|
||||
0x8A, 0x51, 0x02, 0xA0, 0x8A, 0x95, 0x59, 0xC7, 0xC9, 0x00, 0x5B, 0x88, 0x0A, 0xFE, 0x84, 0x80,
|
||||
0x8A, 0x51, 0x02, 0xA0, 0x8A, 0x95, 0x58, 0x02, 0xC1, 0xC0, 0x5B, 0x88, 0x0A, 0xFE, 0x84, 0x80,
|
||||
0x8A, 0x51, 0x02, 0xA0, 0x8A, 0x95, 0x59, 0x42, 0xCA, 0x00, 0xE1, 0x27, 0x8A, 0x95, 0x97, 0x67,
|
||||
0x8A, 0x95, 0xDA, 0x67, 0x8A, 0x95, 0x97, 0x67, 0x8A, 0x95, 0xF7, 0xE7, 0xA3, 0x00, 0x22, 0xC8,
|
||||
0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x46, 0x08, 0xA2, 0xC0, 0x15, 0x70,
|
||||
0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x2B, 0x48,
|
||||
0xA4, 0xC0, 0x51, 0x70, 0x8A, 0x51, 0x2D, 0x27, 0x8A, 0x95, 0xCF, 0xC1, 0xDA, 0x81, 0x05, 0x30,
|
||||
0xDA, 0xCA, 0x5A, 0x42, 0x03, 0x18, 0x32, 0xEE, 0x1F, 0xF0, 0xCB, 0x67, 0x8A, 0x95, 0x97, 0x67,
|
||||
0x8A, 0x95, 0xAE, 0x67, 0x8A, 0x95, 0x97, 0x67, 0x8A, 0x95, 0xBE, 0xA7, 0x8A, 0x95, 0xA3, 0x00,
|
||||
0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0xD3, 0x67, 0xA3, 0x00,
|
||||
0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x2B, 0x48, 0xA4, 0xC0,
|
||||
0x56, 0xB0, 0x8A, 0x51, 0x2D, 0x27, 0x8A, 0x95, 0x56, 0xB0, 0xA1, 0xC0, 0x51, 0x70, 0x8A, 0x51,
|
||||
0x79, 0x67, 0x8A, 0x95, 0xD0, 0xC0, 0x50, 0xC8, 0x03, 0x59, 0xFF, 0x2D, 0x56, 0x48, 0xE7, 0xA7,
|
||||
0x8A, 0x95, 0xFF, 0x2D, 0x4F, 0x88, 0x3D, 0xBE, 0x84, 0x80, 0x00, 0x48, 0xD8, 0x00, 0xED, 0xA7,
|
||||
0x8A, 0x95, 0x06, 0x30, 0xDB, 0x0A, 0x5B, 0x82, 0x58, 0x08, 0x03, 0x5C, 0x9A, 0x2D, 0xFF, 0x7E,
|
||||
0xBD, 0x80, 0x59, 0x48, 0xFF, 0x7E, 0xC6, 0x00, 0x58, 0x08, 0xFF, 0x7E, 0xBE, 0x80, 0x59, 0x48,
|
||||
0xC7, 0x40, 0x58, 0x08, 0xFF, 0x7E, 0xBF, 0xC0, 0x59, 0x48, 0x01, 0xBE, 0xC8, 0xC0, 0x58, 0x08,
|
||||
0xC0, 0x80, 0x59, 0x48, 0xFF, 0x7E, 0xC9, 0x00, 0x58, 0x08, 0xC1, 0xC0, 0x59, 0x48, 0xCA, 0x00,
|
||||
0x58, 0x08, 0xC2, 0xC0, 0x59, 0x48, 0x01, 0xBE, 0xCB, 0x40, 0x58, 0x08, 0x01, 0xBE, 0xC3, 0x00,
|
||||
0x59, 0x48, 0xFF, 0x7E, 0xCC, 0x00, 0x58, 0x08, 0x01, 0xBE, 0xC4, 0xC0, 0x59, 0x48, 0xCD, 0x40,
|
||||
0x58, 0x08, 0x01, 0xBE, 0xC5, 0x00, 0x59, 0x48, 0x01, 0xBE, 0xCE, 0x40, 0xE1, 0x27, 0x8A, 0x95,
|
||||
0x97, 0x67, 0x8A, 0x95, 0xDA, 0x67, 0x8A, 0x95, 0x97, 0x67, 0x8A, 0x95, 0xF7, 0xE7, 0xA3, 0x00,
|
||||
0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x46, 0x08, 0xA2, 0xC0,
|
||||
0x15, 0x70, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50,
|
||||
0x2B, 0x48, 0xA4, 0xC0, 0x51, 0x70, 0x8A, 0x51, 0x2D, 0x27, 0x8A, 0x95, 0xCF, 0xC1, 0xDA, 0x81,
|
||||
0x09, 0x30, 0xDA, 0xCA, 0x5A, 0x42, 0x03, 0x18, 0xC3, 0x2E, 0x1F, 0xF0, 0xCB, 0x67, 0x8A, 0x95,
|
||||
0x97, 0x67, 0x8A, 0x95, 0xAE, 0x67, 0x8A, 0x95, 0x97, 0x67, 0x8A, 0x95, 0xBE, 0xA7, 0x8A, 0x95,
|
||||
0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0xD3, 0x67,
|
||||
0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x2B, 0x48,
|
||||
0xA4, 0xC0, 0x56, 0xB0, 0x8A, 0x51, 0x2D, 0x27, 0x8A, 0x95, 0x56, 0xB0, 0xA1, 0xC0, 0x51, 0x70,
|
||||
0x8A, 0x51, 0x79, 0x67, 0x8A, 0x95, 0xD0, 0xC0, 0x50, 0xC8, 0x03, 0x59, 0x90, 0xAE, 0x56, 0x48,
|
||||
0xE7, 0xA7, 0x8A, 0x95, 0x90, 0xAE, 0x4F, 0x88, 0x3D, 0xBE, 0x84, 0x80, 0x00, 0x48, 0xD8, 0x00,
|
||||
0xED, 0xA7, 0x8A, 0x95, 0x51, 0x08, 0xBB, 0x80, 0x52, 0x08, 0xBC, 0x40, 0x58, 0x08, 0xA2, 0xC0,
|
||||
0x14, 0x30, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50,
|
||||
0x59, 0x48, 0xA2, 0xC0, 0x15, 0x70, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00,
|
||||
0x17, 0x94, 0x17, 0x50, 0x2A, 0x08, 0xA2, 0xC0, 0x19, 0x70, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00,
|
||||
0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x34, 0x08, 0xA2, 0xC0, 0x1A, 0x70, 0xA3, 0x00,
|
||||
0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x35, 0x48, 0xA2, 0xC0,
|
||||
0x1B, 0xB0, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50,
|
||||
0x36, 0x48, 0xA2, 0xC0, 0x1C, 0x70, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00,
|
||||
0x17, 0x94, 0x17, 0x50, 0x06, 0x30, 0x9B, 0x40, 0x3C, 0xB0, 0x83, 0x52, 0x03, 0x53, 0xA1, 0xC0,
|
||||
0x21, 0xC8, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xD5, 0x40, 0x9E, 0x40, 0x55, 0x48,
|
||||
0x06, 0xBA, 0x03, 0x9D, 0x0C, 0xEF, 0x39, 0x48, 0xA2, 0xC0, 0x19, 0x70, 0xA3, 0x00, 0x22, 0xC8,
|
||||
0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x3A, 0x48, 0xA2, 0xC0, 0x1A, 0x70,
|
||||
0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x58, 0x08,
|
||||
0xA2, 0xC0, 0x1B, 0xB0, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94,
|
||||
0x17, 0x50, 0x59, 0x48, 0xA2, 0xC0, 0x1C, 0x70, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08,
|
||||
0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x07, 0x70, 0x9B, 0x40, 0x3C, 0xB0, 0x83, 0x52, 0x03, 0x53,
|
||||
0xA1, 0xC0, 0x21, 0xC8, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xD5, 0x40, 0x9E, 0x40,
|
||||
0x55, 0x48, 0x07, 0xFA, 0x03, 0x9D, 0x45, 0x2F, 0x3B, 0x88, 0xA2, 0xC0, 0x19, 0x70, 0xA3, 0x00,
|
||||
0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x3C, 0x48, 0xA2, 0xC0,
|
||||
0x1A, 0x70, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50,
|
||||
0x37, 0x88, 0xA2, 0xC0, 0x1B, 0xB0, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00,
|
||||
0x17, 0x94, 0x17, 0x50, 0x38, 0x08, 0xA2, 0xC0, 0x1C, 0x70, 0xA3, 0x00, 0x22, 0xC8, 0x96, 0x00,
|
||||
0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x08, 0xF0, 0x9B, 0x40, 0x3C, 0xB0, 0x83, 0x52,
|
||||
0x03, 0x53, 0xA1, 0xC0, 0x21, 0xC8, 0x95, 0x00, 0x97, 0xD4, 0x97, 0x90, 0x0D, 0x08, 0xD5, 0x40,
|
||||
0x9E, 0x40, 0x55, 0x48, 0x08, 0x7A, 0x03, 0x9D, 0x7E, 0xEF, 0x10, 0xF0, 0xA2, 0x01, 0xA3, 0x00,
|
||||
0x22, 0xC8, 0x96, 0x00, 0x23, 0x08, 0x95, 0x00, 0x17, 0x94, 0x17, 0x50, 0x08, 0x40, 0xA4, 0xC0,
|
||||
0x21, 0xC8, 0x80, 0x7A, 0xA3, 0x00, 0x24, 0xC8, 0x80, 0x7A, 0xA3, 0x42, 0x03, 0x18, 0xA2, 0x2F,
|
||||
0x21, 0xC8, 0x08, 0x40, 0x24, 0xC8, 0x80, 0x7A, 0xA3, 0x00, 0x22, 0xC8, 0x80, 0x7A, 0xA3, 0x42,
|
||||
0x03, 0x18, 0xAC, 0x6F, 0x22, 0xC8, 0x08, 0x40, 0x24, 0xC8, 0x08, 0x40, 0xAC, 0x00, 0x5A, 0x48,
|
||||
0x3D, 0xBE, 0x84, 0x80, 0x2C, 0x08, 0x83, 0x93, 0x80, 0x40, 0x1F, 0xF0, 0xA1, 0xC0, 0xE0, 0x70,
|
||||
0xA2, 0xC0, 0x5A, 0x48, 0x46, 0x3E, 0x84, 0x80, 0x00, 0x48, 0x08, 0x40, 0xAC, 0x00, 0x5A, 0x48,
|
||||
0x46, 0x3E, 0x84, 0x80, 0x2C, 0x08, 0x83, 0x93, 0x80, 0x40, 0x5A, 0x48, 0x3D, 0xBE, 0x84, 0x80,
|
||||
0x00, 0x48, 0xA2, 0xC0, 0x14, 0x74, 0xA1, 0xC0, 0xE0, 0x70, 0xA2, 0xC0, 0x5A, 0x48, 0x3D, 0xBE,
|
||||
0x84, 0x80, 0x00, 0x48, 0x08, 0x40, 0x5A, 0x48, 0x46, 0x3E, 0x84, 0x80, 0x83, 0x93, 0x00, 0x48,
|
||||
0xA2, 0xC0, 0x15, 0xB4, 0xBD, 0x80, 0x1F, 0xF0, 0xA1, 0xC0, 0xE0, 0x70, 0xA2, 0xC0, 0x46, 0x08,
|
||||
0x08, 0x40, 0x1F, 0xF0, 0xA1, 0xC0, 0xE0, 0x70, 0xA2, 0xC0, 0x3D, 0x88, 0x08, 0x40, 0xD1, 0x00,
|
||||
0x57, 0x88, 0xD2, 0x00, 0x5A, 0x48, 0xCF, 0x80, 0x08, 0x40, 0x4F, 0x88, 0x46, 0x3E, 0x84, 0x80,
|
||||
0x00, 0x48, 0xD9, 0x40, 0x08, 0x40, 0x29, 0x43, 0xFF, 0x3A, 0xA2, 0xC0, 0x13, 0xB4, 0xC6, 0x00,
|
||||
0x3D, 0x88, 0xA2, 0xC0, 0x14, 0x74, 0x03, 0xD0, 0xAC, 0xCD, 0x03, 0xD0, 0xAC, 0xCD, 0x08, 0x40
|
||||
};
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2019 Semtech
|
||||
|
||||
Description:
|
||||
LoRa concentrator HAL auxiliary functions
|
||||
|
||||
License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*/
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- DEPENDANCIES --------------------------------------------------------- */
|
||||
|
||||
/* fix an issue between POSIX and C99 */
|
||||
#if __STDC_VERSION__ >= 199901L
|
||||
#define _XOPEN_SOURCE 600
|
||||
#else
|
||||
#define _XOPEN_SOURCE 500
|
||||
#endif
|
||||
|
||||
#include <stdio.h> /* printf fprintf */
|
||||
#include <time.h> /* 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 ------------------------------------------------------------------ */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,201 @@
|
|||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2019 Semtech
|
||||
|
||||
Description:
|
||||
LoRa concentrator debug functions
|
||||
|
||||
License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*/
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- DEPENDANCIES --------------------------------------------------------- */
|
||||
|
||||
#include <stdint.h> /* C99 types */
|
||||
#include <stdbool.h> /* bool type */
|
||||
#include <stdio.h> /* printf fprintf */
|
||||
#include <string.h> /* memcmp */
|
||||
#include <time.h>
|
||||
|
||||
#include "loragw_aux.h"
|
||||
#include "loragw_reg.h"
|
||||
#include "loragw_hal.h"
|
||||
#include "loragw_debug.h"
|
||||
|
||||
#include "tinymt32.h"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- DEBUG CONSTANTS ------------------------------------------------------ */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE MACROS ------------------------------------------------------- */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE CONSTANTS & TYPES -------------------------------------------- */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE VARIABLES ---------------------------------------------------- */
|
||||
|
||||
static tinymt32_t tinymt;
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE FUNCTIONS DECLARATION ---------------------------------------- */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE FUNCTIONS DEFINITION ----------------------------------------- */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PUBLIC FUNCTIONS DEFINITION ------------------------------------------ */
|
||||
|
||||
void dbg_init_random(void) {
|
||||
tinymt.mat1 = 0x8f7011ee;
|
||||
tinymt.mat2 = 0xfc78ff1f;
|
||||
tinymt.tmat = 0x3793fdff;
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
void dbg_init_gpio(void) {
|
||||
/* Select GPIO_6 to be controlled by HOST */
|
||||
lgw_reg_w(SX1302_REG_GPIO_GPIO_SEL_6_SELECTION, 0);
|
||||
/* Configure it as an OUTPUT */
|
||||
lgw_reg_w(SX1302_REG_GPIO_GPIO_DIR_L_DIRECTION, 0xFF);
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
void dbg_toggle_gpio(void) {
|
||||
/* Set GPIO_6 to high */
|
||||
lgw_reg_w(SX1302_REG_GPIO_GPIO_OUT_L_OUT_VALUE, 64);
|
||||
/* Set GPIO_6 to low */
|
||||
lgw_reg_w(SX1302_REG_GPIO_GPIO_OUT_L_OUT_VALUE, 0);
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
void dbg_log_buffer_to_file(FILE * file, uint8_t * buffer, uint16_t size) {
|
||||
int i;
|
||||
char stat_timestamp[24];
|
||||
time_t t;
|
||||
|
||||
t = time(NULL);
|
||||
strftime(stat_timestamp, sizeof stat_timestamp, "%F %T %Z", gmtime(&t));
|
||||
fprintf(file, "---------(%s)------------\n", stat_timestamp);
|
||||
for (i = 0; i < size; i++) {
|
||||
fprintf(file, "%02X ", buffer[i]);
|
||||
}
|
||||
fprintf(file, "\n");
|
||||
|
||||
fflush(file);
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
void dbg_log_payload_diff_to_file(FILE * file, uint8_t * buffer1, uint8_t * buffer2, uint16_t size) {
|
||||
int i, j;
|
||||
uint16_t nb_bits_diff = 0;
|
||||
uint8_t debug_payload_diff[255];
|
||||
|
||||
fprintf(file, "Diff: ");
|
||||
/* bit comparison of payloads */
|
||||
for (j = 0; j < size; j++) {
|
||||
debug_payload_diff[j] = buffer1[j] ^ buffer2[j];
|
||||
fprintf(file, "%02X ", debug_payload_diff[j]);
|
||||
}
|
||||
fprintf(file, "\n");
|
||||
|
||||
/* count number of bits flipped, and display bit by bit */
|
||||
for (j = 0; j < size; j++) {
|
||||
for (i = 7; i >= 0; i--) {
|
||||
fprintf(file, "%u", TAKE_N_BITS_FROM(debug_payload_diff[j], i, 1));
|
||||
if (TAKE_N_BITS_FROM(debug_payload_diff[j], i, 1) == 1) {
|
||||
nb_bits_diff += 1;
|
||||
}
|
||||
}
|
||||
fprintf(file, " ");
|
||||
}
|
||||
fprintf(file, "\n");
|
||||
fprintf(file, "%u bits flipped\n", nb_bits_diff);
|
||||
|
||||
fflush(file);
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
void dbg_generate_random_payload(uint32_t pkt_cnt, uint8_t * buffer_expected, uint8_t size) {
|
||||
int k;
|
||||
|
||||
/* construct payload we should get for this packet counter */
|
||||
tinymt32_init(&tinymt, (int)pkt_cnt);
|
||||
buffer_expected[4] = (uint8_t)(pkt_cnt >> 24);
|
||||
buffer_expected[5] = (uint8_t)(pkt_cnt >> 16);
|
||||
buffer_expected[6] = (uint8_t)(pkt_cnt >> 8);
|
||||
buffer_expected[7] = (uint8_t)(pkt_cnt >> 0);
|
||||
tinymt32_generate_uint32(&tinymt); /* dummy: for sync with random size generation */
|
||||
for (k = 8; k < (int)size; k++) {
|
||||
buffer_expected[k] = (uint8_t)tinymt32_generate_uint32(&tinymt);
|
||||
}
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
int dbg_check_payload(struct lgw_conf_debug_s * context, FILE * file, uint8_t * payload_received, uint8_t size, uint8_t ref_payload_idx, uint8_t sf) {
|
||||
int k;
|
||||
uint32_t debug_payload_cnt;
|
||||
|
||||
/* If the 4 first bytes of received payload match with the expected ones, go on with comparison */
|
||||
if (memcmp((void*)payload_received, (void*)(context->ref_payload[ref_payload_idx].payload), 4) == 0) {
|
||||
/* get counter to initialize random seed */
|
||||
debug_payload_cnt = (unsigned int)(payload_received[4] << 24) | (unsigned int)(payload_received[5] << 16) | (unsigned int)(payload_received[6] << 8) | (unsigned int)(payload_received[7] << 0);
|
||||
|
||||
/* check if we missed some packets */
|
||||
if (debug_payload_cnt > (context->ref_payload[ref_payload_idx].prev_cnt + 1)) {
|
||||
printf("ERROR: 0x%08X missed %u pkt before %u (SF%u, size:%u)\n", context->ref_payload[ref_payload_idx].id, debug_payload_cnt - context->ref_payload[ref_payload_idx].prev_cnt - 1, debug_payload_cnt, sf, size);
|
||||
if (file != NULL) {
|
||||
fprintf(file, "ERROR: 0x%08X missed %u pkt before %u (SF%u, size:%u)\n", context->ref_payload[ref_payload_idx].id, debug_payload_cnt - context->ref_payload[ref_payload_idx].prev_cnt - 1, debug_payload_cnt, sf, size);
|
||||
fflush(file);
|
||||
}
|
||||
} else if (debug_payload_cnt < context->ref_payload[ref_payload_idx].prev_cnt) {
|
||||
if (file != NULL) {
|
||||
fprintf(file, "INFO: 0x%08X got missing pkt %u (SF%u, size:%u) ?\n", context->ref_payload[ref_payload_idx].id, debug_payload_cnt, sf, size);
|
||||
fflush(file);
|
||||
}
|
||||
} else {
|
||||
#if 0
|
||||
if (file != NULL) {
|
||||
fprintf(file, "0x%08X %u (SF%u, size:%u)\n", context.ref_payload[ref_payload_idx].id, debug_payload_cnt, sf, size);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
context->ref_payload[ref_payload_idx].prev_cnt = debug_payload_cnt;
|
||||
|
||||
/* generate the random payload which is expected for this packet count */
|
||||
dbg_generate_random_payload(debug_payload_cnt, context->ref_payload[ref_payload_idx].payload, size);
|
||||
|
||||
/* compare expected with received */
|
||||
if (memcmp((void *)payload_received, (void *)(context->ref_payload[ref_payload_idx].payload), size) != 0) {
|
||||
if (file != NULL) {
|
||||
fprintf(file, "RECEIVED:");
|
||||
for (k = 0; k < (int)size; k++) {
|
||||
fprintf(file, "%02X ", payload_received[k]);
|
||||
}
|
||||
fprintf(file, "\n");
|
||||
fprintf(file, "EXPECTED:");
|
||||
for (k = 0; k < (int)size; k++) {
|
||||
fprintf(file, "%02X ", context->ref_payload[ref_payload_idx].payload[k]);
|
||||
}
|
||||
fprintf(file, "\n");
|
||||
}
|
||||
return -1;
|
||||
} else {
|
||||
return 1; /* matches */
|
||||
}
|
||||
}
|
||||
|
||||
return 0; /* ignored */
|
||||
}
|
|
@ -0,0 +1,837 @@
|
|||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2019 Semtech
|
||||
|
||||
Description:
|
||||
Library of functions to manage a GNSS module (typically GPS) for accurate
|
||||
timestamping of packets and synchronisation of gateways.
|
||||
A limited set of module brands/models are supported.
|
||||
|
||||
License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*/
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- DEPENDANCIES --------------------------------------------------------- */
|
||||
|
||||
#define _GNU_SOURCE /* needed for qsort_r to be defined */
|
||||
#include <stdint.h> /* C99 types */
|
||||
#include <stdbool.h> /* bool type */
|
||||
#include <stdio.h> /* printf fprintf */
|
||||
#include <string.h> /* memcpy */
|
||||
#include <errno.h>
|
||||
|
||||
#include <time.h> /* struct timespec */
|
||||
#include <fcntl.h> /* open */
|
||||
#include <termios.h> /* tcflush */
|
||||
#include <math.h> /* modf */
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "loragw_gps.h"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE MACROS ------------------------------------------------------- */
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
|
||||
#if DEBUG_GPS == 1
|
||||
#define DEBUG_MSG(args...) fprintf(stderr, args)
|
||||
#define DEBUG_PRINTF(fmt, args...) fprintf(stderr,"%s:%d: "fmt, __FUNCTION__, __LINE__, args)
|
||||
#define DEBUG_ARRAY(a,b,c) for(a=0;a<b;++a) fprintf(stderr,"%x.",c[a]);fprintf(stderr,"end\n")
|
||||
#define CHECK_NULL(a) if(a==NULL){fprintf(stderr,"%s:%d: ERROR: NULL POINTER AS ARGUMENT\n", __FUNCTION__, __LINE__);return LGW_GPS_ERROR;}
|
||||
#else
|
||||
#define DEBUG_MSG(args...)
|
||||
#define DEBUG_PRINTF(fmt, args...)
|
||||
#define DEBUG_ARRAY(a,b,c) for(a=0;a!=0;){}
|
||||
#define CHECK_NULL(a) if(a==NULL){return LGW_GPS_ERROR;}
|
||||
#endif
|
||||
#define TRACE() fprintf(stderr, "@ %s %d\n", __FUNCTION__, __LINE__);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE CONSTANTS ---------------------------------------------------- */
|
||||
|
||||
#define TS_CPS 1E6 /* count-per-second of the timestamp counter */
|
||||
#define PLUS_10PPM 1.00001
|
||||
#define MINUS_10PPM 0.99999
|
||||
#define DEFAULT_BAUDRATE B9600
|
||||
|
||||
#define UBX_MSG_NAVTIMEGPS_LEN 16
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE VARIABLES ---------------------------------------------------- */
|
||||
|
||||
|
||||
/* result of the NMEA parsing */
|
||||
static short gps_yea = 0; /* year (2 or 4 digits) */
|
||||
static short gps_mon = 0; /* month (1-12) */
|
||||
static short gps_day = 0; /* day of the month (1-31) */
|
||||
static short gps_hou = 0; /* hours (0-23) */
|
||||
static short gps_min = 0; /* minutes (0-59) */
|
||||
static short gps_sec = 0; /* seconds (0-60)(60 is for leap second) */
|
||||
static float gps_fra = 0.0; /* fractions of seconds (<1) */
|
||||
static bool gps_time_ok = false;
|
||||
static int16_t gps_week = 0; /* GPS week number of the navigation epoch */
|
||||
static uint32_t gps_iTOW = 0; /* GPS time of week in milliseconds */
|
||||
static int32_t gps_fTOW = 0; /* Fractional part of iTOW (+/-500000) in nanosec */
|
||||
|
||||
static short gps_dla = 0; /* degrees of latitude */
|
||||
static double gps_mla = 0.0; /* minutes of latitude */
|
||||
static char gps_ola = 0; /* orientation (N-S) of latitude */
|
||||
static short gps_dlo = 0; /* degrees of longitude */
|
||||
static double gps_mlo = 0.0; /* minutes of longitude */
|
||||
static char gps_olo = 0; /* orientation (E-W) of longitude */
|
||||
static short gps_alt = 0; /* altitude */
|
||||
static bool gps_pos_ok = false;
|
||||
|
||||
static char gps_mod = 'N'; /* GPS mode (N no fix, A autonomous, D differential) */
|
||||
static short gps_sat = 0; /* number of satellites used for fix */
|
||||
|
||||
static struct termios ttyopt_restore;
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE FUNCTIONS DECLARATION ---------------------------------------- */
|
||||
|
||||
static int nmea_checksum(const char *nmea_string, int buff_size, char *checksum);
|
||||
|
||||
static char nibble_to_hexchar(uint8_t a);
|
||||
|
||||
static bool validate_nmea_checksum(const char *serial_buff, int buff_size);
|
||||
|
||||
static bool match_label(const char *s, char *label, int size, char wildcard);
|
||||
|
||||
static int str_chop(char *s, int buff_size, char separator, int *idx_ary, int max_idx);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE FUNCTIONS DEFINITION ----------------------------------------- */
|
||||
|
||||
/*
|
||||
Calculate the checksum for a NMEA string
|
||||
Skip the first '$' if necessary and calculate checksum until '*' character is
|
||||
reached (or buff_size exceeded).
|
||||
Checksum must point to a 2-byte (or more) char array.
|
||||
Return position of the checksum in the string
|
||||
*/
|
||||
static int nmea_checksum(const char *nmea_string, int buff_size, char *checksum) {
|
||||
int i = 0;
|
||||
uint8_t check_num = 0;
|
||||
|
||||
/* check input parameters */
|
||||
if ((nmea_string == NULL) || (checksum == NULL) || (buff_size <= 1)) {
|
||||
DEBUG_MSG("Invalid parameters for nmea_checksum\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* skip the first '$' if necessary */
|
||||
if (nmea_string[i] == '$') {
|
||||
i += 1;
|
||||
}
|
||||
|
||||
/* xor until '*' or max length is reached */
|
||||
while (nmea_string[i] != '*') {
|
||||
check_num ^= nmea_string[i];
|
||||
i += 1;
|
||||
if (i >= buff_size) {
|
||||
DEBUG_MSG("Maximum length reached for nmea_checksum\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert checksum value to 2 hexadecimal characters */
|
||||
checksum[0] = nibble_to_hexchar(check_num / 16); /* upper nibble */
|
||||
checksum[1] = nibble_to_hexchar(check_num % 16); /* lower nibble */
|
||||
|
||||
return i + 1;
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
static char nibble_to_hexchar(uint8_t a) {
|
||||
if (a < 10) {
|
||||
return '0' + a;
|
||||
} else if (a < 16) {
|
||||
return 'A' + (a-10);
|
||||
} else {
|
||||
return '?';
|
||||
}
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
/*
|
||||
Calculate the checksum of a NMEA frame and compare it to the checksum that is
|
||||
present at the end of it.
|
||||
Return true if it matches
|
||||
*/
|
||||
static bool validate_nmea_checksum(const char *serial_buff, int buff_size) {
|
||||
int checksum_index;
|
||||
char checksum[2]; /* 2 characters to calculate NMEA checksum */
|
||||
|
||||
checksum_index = nmea_checksum(serial_buff, buff_size, checksum);
|
||||
|
||||
/* could we calculate a verification checksum ? */
|
||||
if (checksum_index < 0) {
|
||||
DEBUG_MSG("ERROR: IMPOSSIBLE TO PARSE NMEA SENTENCE\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* check if there are enough char in the serial buffer to read checksum */
|
||||
if (checksum_index >= (buff_size - 2)) {
|
||||
DEBUG_MSG("ERROR: IMPOSSIBLE TO READ NMEA SENTENCE CHECKSUM\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* check the checksum per se */
|
||||
if ((serial_buff[checksum_index] == checksum[0]) && (serial_buff[checksum_index+1] == checksum[1])) {
|
||||
return true;
|
||||
} else {
|
||||
DEBUG_MSG("ERROR: NMEA CHECKSUM %c%c DOESN'T MATCH VERIFICATION CHECKSUM %c%c\n", serial_buff[checksum_index], serial_buff[checksum_index+1], checksum[0], checksum[1]);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
/*
|
||||
Return true if the "label" string (can contain wildcard characters) matches
|
||||
the begining of the "s" string
|
||||
*/
|
||||
static bool match_label(const char *s, char *label, int size, char wildcard) {
|
||||
int i;
|
||||
|
||||
for (i=0; i < size; i++) {
|
||||
if (label[i] == wildcard) continue;
|
||||
if (label[i] != s[i]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
/*
|
||||
Chop a string into smaller strings
|
||||
Replace every separator in the input character buffer by a null character so
|
||||
that all s[index] are valid strings.
|
||||
Populate an array of integer 'idx_ary' representing indexes of token in the
|
||||
string.
|
||||
buff_size and max_idx are there to prevent segfaults.
|
||||
Return the number of token found (number of idx_ary filled).
|
||||
*/
|
||||
int str_chop(char *s, int buff_size, char separator, int *idx_ary, int max_idx) {
|
||||
int i = 0; /* index in the string */
|
||||
int j = 0; /* index in the result array */
|
||||
|
||||
if ((s == NULL) || (buff_size < 0) || (separator == 0) || (idx_ary == NULL) || (max_idx < 0)) {
|
||||
/* unsafe to do anything */
|
||||
return -1;
|
||||
}
|
||||
if ((buff_size == 0) || (max_idx == 0)) {
|
||||
/* nothing to do */
|
||||
return 0;
|
||||
}
|
||||
s[buff_size - 1] = 0; /* add string terminator at the end of the buffer, just to be sure */
|
||||
idx_ary[j] = 0;
|
||||
j += 1;
|
||||
/* loop until string terminator is reached */
|
||||
while (s[i] != 0) {
|
||||
if (s[i] == separator) {
|
||||
s[i] = 0; /* replace separator by string terminator */
|
||||
if (j >= max_idx) { /* no more room in the index array */
|
||||
return j;
|
||||
}
|
||||
idx_ary[j] = i+1; /* next token start after replaced separator */
|
||||
++j;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
return j;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PUBLIC FUNCTIONS DEFINITION ------------------------------------------ */
|
||||
|
||||
int lgw_gps_enable(char *tty_path, char *gps_family, speed_t target_brate, int *fd_ptr) {
|
||||
int i;
|
||||
struct termios ttyopt; /* serial port options */
|
||||
int gps_tty_dev; /* file descriptor to the serial port of the GNSS module */
|
||||
uint8_t ubx_cmd_timegps[UBX_MSG_NAVTIMEGPS_LEN] = {
|
||||
0xB5, 0x62, /* UBX Sync Chars */
|
||||
0x06, 0x01, /* CFG-MSG Class/ID */
|
||||
0x08, 0x00, /* Payload length */
|
||||
0x01, 0x20, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, /* Enable NAV-TIMEGPS output on serial */
|
||||
0x32, 0x94 }; /* Checksum */
|
||||
ssize_t num_written;
|
||||
|
||||
/* check input parameters */
|
||||
CHECK_NULL(tty_path);
|
||||
CHECK_NULL(fd_ptr);
|
||||
|
||||
/* open TTY device */
|
||||
gps_tty_dev = open(tty_path, O_RDWR | O_NOCTTY);
|
||||
if (gps_tty_dev <= 0) {
|
||||
DEBUG_MSG("ERROR: TTY PORT FAIL TO OPEN, CHECK PATH AND ACCESS RIGHTS\n");
|
||||
return LGW_GPS_ERROR;
|
||||
}
|
||||
*fd_ptr = gps_tty_dev;
|
||||
|
||||
/* manage the different GPS modules families */
|
||||
if (gps_family == NULL) {
|
||||
DEBUG_MSG("WARNING: this version of GPS module may not be supported\n");
|
||||
} else if (strncmp(gps_family, "ubx7", 4) != 0) {
|
||||
/* The current implementation relies on proprietary messages from U-Blox */
|
||||
/* GPS modules (UBX, NAV-TIMEGPS...) and has only be tested with a u-blox 7. */
|
||||
/* Those messages allow to get NATIVE GPS time (no leap seconds) required */
|
||||
/* for class-B handling and GPS synchronization */
|
||||
/* see lgw_parse_ubx() function for details */
|
||||
DEBUG_MSG("WARNING: this version of GPS module may not be supported\n");
|
||||
}
|
||||
|
||||
/* manage the target bitrate */
|
||||
if (target_brate != 0) {
|
||||
DEBUG_MSG("WARNING: target_brate parameter ignored for now\n"); // TODO
|
||||
}
|
||||
|
||||
/* get actual serial port configuration */
|
||||
i = tcgetattr(gps_tty_dev, &ttyopt);
|
||||
if (i != 0) {
|
||||
DEBUG_MSG("ERROR: IMPOSSIBLE TO GET TTY PORT CONFIGURATION\n");
|
||||
return LGW_GPS_ERROR;
|
||||
}
|
||||
|
||||
/* Save current serial port configuration for restoring later */
|
||||
memcpy(&ttyopt_restore, &ttyopt, sizeof ttyopt);
|
||||
|
||||
/* update baudrates */
|
||||
cfsetispeed(&ttyopt, DEFAULT_BAUDRATE);
|
||||
cfsetospeed(&ttyopt, DEFAULT_BAUDRATE);
|
||||
|
||||
/* update terminal parameters */
|
||||
/* The following configuration should allow to:
|
||||
- Get ASCII NMEA messages
|
||||
- Get UBX binary messages
|
||||
- Send UBX binary commands
|
||||
Note: as binary data have to be read/written, we need to disable
|
||||
various character processing to avoid loosing data */
|
||||
/* Control Modes */
|
||||
ttyopt.c_cflag |= CLOCAL; /* local connection, no modem control */
|
||||
ttyopt.c_cflag |= CREAD; /* enable receiving characters */
|
||||
ttyopt.c_cflag |= CS8; /* 8 bit frames */
|
||||
ttyopt.c_cflag &= ~PARENB; /* no parity */
|
||||
ttyopt.c_cflag &= ~CSTOPB; /* one stop bit */
|
||||
/* Input Modes */
|
||||
ttyopt.c_iflag |= IGNPAR; /* ignore bytes with parity errors */
|
||||
ttyopt.c_iflag &= ~ICRNL; /* do not map CR to NL on input*/
|
||||
ttyopt.c_iflag &= ~IGNCR; /* do not ignore carriage return on input */
|
||||
ttyopt.c_iflag &= ~IXON; /* disable Start/Stop output control */
|
||||
ttyopt.c_iflag &= ~IXOFF; /* do not send Start/Stop characters */
|
||||
/* Output Modes */
|
||||
ttyopt.c_oflag = 0; /* disable everything on output as we only write binary */
|
||||
/* Local Modes */
|
||||
ttyopt.c_lflag &= ~ICANON; /* disable canonical input - cannot use with binary input */
|
||||
ttyopt.c_lflag &= ~ISIG; /* disable check for INTR, QUIT, SUSP special characters */
|
||||
ttyopt.c_lflag &= ~IEXTEN; /* disable any special control character */
|
||||
ttyopt.c_lflag &= ~ECHO; /* do not echo back every character typed */
|
||||
ttyopt.c_lflag &= ~ECHOE; /* does not erase the last character in current line */
|
||||
ttyopt.c_lflag &= ~ECHOK; /* do not echo NL after KILL character */
|
||||
|
||||
/* settings for non-canonical mode
|
||||
read will block for until the lesser of VMIN or requested chars have been received */
|
||||
ttyopt.c_cc[VMIN] = LGW_GPS_MIN_MSG_SIZE;
|
||||
ttyopt.c_cc[VTIME] = 0;
|
||||
|
||||
/* set new serial ports parameters */
|
||||
i = tcsetattr(gps_tty_dev, TCSANOW, &ttyopt);
|
||||
if (i != 0){
|
||||
DEBUG_MSG("ERROR: IMPOSSIBLE TO UPDATE TTY PORT CONFIGURATION\n");
|
||||
return LGW_GPS_ERROR;
|
||||
}
|
||||
tcflush(gps_tty_dev, TCIOFLUSH);
|
||||
|
||||
/* Send UBX CFG NAV-TIMEGPS message to tell GPS module to output native GPS time */
|
||||
/* This is a binary message, serial port has to be properly configured to handle this */
|
||||
num_written = write (gps_tty_dev, ubx_cmd_timegps, UBX_MSG_NAVTIMEGPS_LEN);
|
||||
if (num_written != UBX_MSG_NAVTIMEGPS_LEN) {
|
||||
DEBUG_MSG("ERROR: Failed to write on serial port (written=%d)\n", (int) num_written);
|
||||
}
|
||||
|
||||
/* get timezone info */
|
||||
tzset();
|
||||
|
||||
/* initialize global variables */
|
||||
gps_time_ok = false;
|
||||
gps_pos_ok = false;
|
||||
gps_mod = 'N';
|
||||
|
||||
return LGW_GPS_SUCCESS;
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
int lgw_gps_disable(int fd) {
|
||||
int i;
|
||||
|
||||
/* restore serial ports parameters */
|
||||
i = tcsetattr(fd, TCSANOW, &ttyopt_restore);
|
||||
if (i != 0){
|
||||
DEBUG_MSG("ERROR: IMPOSSIBLE TO RESTORE TTY PORT CONFIGURATION - %s\n", strerror(errno));
|
||||
return LGW_GPS_ERROR;
|
||||
}
|
||||
tcflush(fd, TCIOFLUSH);
|
||||
|
||||
i = close(fd);
|
||||
if (i != 0) {
|
||||
DEBUG_PRINTF("ERROR: TTY PORT FAIL TO CLOSE - %s\n", strerror(errno));
|
||||
return LGW_GPS_ERROR;
|
||||
}
|
||||
|
||||
return LGW_GPS_SUCCESS;
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
enum gps_msg lgw_parse_ubx(const char *serial_buff, size_t buff_size, size_t *msg_size) {
|
||||
bool valid = 0; /* iTOW, fTOW and week validity */
|
||||
unsigned int payload_length;
|
||||
uint8_t ck_a, ck_b;
|
||||
uint8_t ck_a_rcv, ck_b_rcv;
|
||||
unsigned int i;
|
||||
|
||||
*msg_size = 0; /* ensure msg_size alway receives a value */
|
||||
|
||||
/* check input parameters */
|
||||
if (serial_buff == NULL) {
|
||||
return IGNORED;
|
||||
}
|
||||
if (buff_size < 8) {
|
||||
DEBUG_MSG("ERROR: TOO SHORT TO BE A VALID UBX MESSAGE\n");
|
||||
return IGNORED;
|
||||
}
|
||||
|
||||
/* display received serial data and checksum */
|
||||
DEBUG_MSG("Note: parsing UBX frame> ");
|
||||
for (i=0; i<buff_size; i++) {
|
||||
DEBUG_MSG("%02x ", serial_buff[i]);
|
||||
}
|
||||
DEBUG_MSG("\n");
|
||||
|
||||
/* Check for UBX sync chars 0xB5 0x62 */
|
||||
if ((serial_buff[0] == (char)0xB5) && (serial_buff[1] == (char)0x62)) {
|
||||
|
||||
/* Get payload length to compute message size */
|
||||
payload_length = (uint8_t)serial_buff[4];
|
||||
payload_length |= (uint8_t)serial_buff[5] << 8;
|
||||
*msg_size = 6 + payload_length + 2; /* header + payload + checksum */
|
||||
|
||||
/* check for complete message in buffer */
|
||||
if(*msg_size <= buff_size) {
|
||||
/* Validate checksum of message */
|
||||
ck_a_rcv = serial_buff[*msg_size-2]; /* received checksum */
|
||||
ck_b_rcv = serial_buff[*msg_size-1]; /* received checksum */
|
||||
/* Use 8-bit Fletcher Algorithm to compute checksum of actual payload */
|
||||
ck_a = 0; ck_b = 0;
|
||||
for (i=0; i<(4 + payload_length); i++) {
|
||||
ck_a = ck_a + serial_buff[i+2];
|
||||
ck_b = ck_b + ck_a;
|
||||
}
|
||||
|
||||
/* Compare checksums and parse if OK */
|
||||
if ((ck_a == ck_a_rcv) && (ck_b == ck_b_rcv)) {
|
||||
/* Check for Class 0x01 (NAV) and ID 0x20 (NAV-TIMEGPS) */
|
||||
if ((serial_buff[2] == 0x01) && (serial_buff[3] == 0x20)) {
|
||||
/* Check validity of information */
|
||||
valid = serial_buff[17] & 0x3; /* towValid, weekValid */
|
||||
if (valid) {
|
||||
/* Parse buffer to extract GPS time */
|
||||
/* Warning: payload byte ordering is Little Endian */
|
||||
gps_iTOW = (uint8_t)serial_buff[6];
|
||||
gps_iTOW |= (uint8_t)serial_buff[7] << 8;
|
||||
gps_iTOW |= (uint8_t)serial_buff[8] << 16;
|
||||
gps_iTOW |= (uint8_t)serial_buff[9] << 24; /* GPS time of week, in ms */
|
||||
|
||||
gps_fTOW = (uint8_t)serial_buff[10];
|
||||
gps_fTOW |= (uint8_t)serial_buff[11] << 8;
|
||||
gps_fTOW |= (uint8_t)serial_buff[12] << 16;
|
||||
gps_fTOW |= (uint8_t)serial_buff[13] << 24; /* Fractional part of iTOW, in ns */
|
||||
|
||||
gps_week = (uint8_t)serial_buff[14];
|
||||
gps_week |= (uint8_t)serial_buff[15] << 8; /* GPS week number */
|
||||
|
||||
gps_time_ok = true;
|
||||
#if 0
|
||||
/* For debug */
|
||||
{
|
||||
short ubx_gps_hou = 0; /* hours (0-23) */
|
||||
short ubx_gps_min = 0; /* minutes (0-59) */
|
||||
short ubx_gps_sec = 0; /* seconds (0-59) */
|
||||
|
||||
/* Format GPS time in hh:mm:ss based on iTOW */
|
||||
ubx_gps_sec = (gps_iTOW / 1000) % 60;
|
||||
ubx_gps_min = (gps_iTOW / 1000 / 60) % 60;
|
||||
ubx_gps_hou = (gps_iTOW / 1000 / 60 / 60) % 24;
|
||||
printf(" GPS time = %02d:%02d:%02d\n", ubx_gps_hou, ubx_gps_min, ubx_gps_sec);
|
||||
}
|
||||
#endif
|
||||
} else { /* valid */
|
||||
gps_time_ok = false;
|
||||
}
|
||||
|
||||
return UBX_NAV_TIMEGPS;
|
||||
} else if ((serial_buff[2] == 0x05) && (serial_buff[3] == 0x00)) {
|
||||
DEBUG_MSG("NOTE: UBX ACK-NAK received\n");
|
||||
return IGNORED;
|
||||
} else if ((serial_buff[2] == 0x05) && (serial_buff[3] == 0x01)) {
|
||||
DEBUG_MSG("NOTE: UBX ACK-ACK received\n");
|
||||
return IGNORED;
|
||||
} else { /* not a supported message */
|
||||
DEBUG_MSG("ERROR: UBX message is not supported (%02x %02x)\n", serial_buff[2], serial_buff[3]);
|
||||
return IGNORED;
|
||||
}
|
||||
} else { /* checksum failed */
|
||||
DEBUG_MSG("ERROR: UBX message is corrupted, checksum failed\n");
|
||||
return INVALID;
|
||||
}
|
||||
} else { /* message contains less bytes than indicated by header */
|
||||
DEBUG_MSG("ERROR: UBX message incomplete\n");
|
||||
return INCOMPLETE;
|
||||
}
|
||||
} else { /* Not a UBX message */
|
||||
/* Ignore messages which are not UBX ones for now */
|
||||
return IGNORED;
|
||||
}
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
enum gps_msg lgw_parse_nmea(const char *serial_buff, int buff_size) {
|
||||
int i, j, k;
|
||||
int str_index[30]; /* string index from the string chopping */
|
||||
int nb_fields; /* number of strings detected by string chopping */
|
||||
char parser_buf[256]; /* parsing modifies buffer so need a local copy */
|
||||
|
||||
/* check input parameters */
|
||||
if (serial_buff == NULL) {
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
if(buff_size > (int)(sizeof(parser_buf) - 1)) {
|
||||
DEBUG_MSG("Note: input string to big for parsing\n");
|
||||
return INVALID;
|
||||
}
|
||||
|
||||
/* look for some NMEA sentences in particular */
|
||||
if (buff_size < 8) {
|
||||
DEBUG_MSG("ERROR: TOO SHORT TO BE A VALID NMEA SENTENCE\n");
|
||||
return UNKNOWN;
|
||||
} else if (!validate_nmea_checksum(serial_buff, buff_size)) {
|
||||
DEBUG_MSG("Warning: invalid NMEA sentence (bad checksum)\n");
|
||||
return INVALID;
|
||||
} else if (match_label(serial_buff, "$G?RMC", 6, '?')) {
|
||||
/*
|
||||
NMEA sentence format: $xxRMC,time,status,lat,NS,long,EW,spd,cog,date,mv,mvEW,posMode*cs<CR><LF>
|
||||
Valid fix: $GPRMC,083559.34,A,4717.11437,N,00833.91522,E,0.004,77.52,091202,,,A*00
|
||||
No fix: $GPRMC,,V,,,,,,,,,,N*00
|
||||
*/
|
||||
memcpy(parser_buf, serial_buff, buff_size);
|
||||
parser_buf[buff_size] = '\0';
|
||||
nb_fields = str_chop(parser_buf, buff_size, ',', str_index, ARRAY_SIZE(str_index));
|
||||
if (nb_fields != 13) {
|
||||
DEBUG_MSG("Warning: invalid RMC sentence (number of fields)\n");
|
||||
return IGNORED;
|
||||
}
|
||||
/* parse GPS status */
|
||||
gps_mod = *(parser_buf + str_index[12]); /* get first character, no need to bother with sscanf */
|
||||
if ((gps_mod != 'N') && (gps_mod != 'A') && (gps_mod != 'D')) {
|
||||
gps_mod = 'N';
|
||||
}
|
||||
/* parse complete time */
|
||||
i = sscanf(parser_buf + str_index[1], "%2hd%2hd%2hd%4f", &gps_hou, &gps_min, &gps_sec, &gps_fra);
|
||||
j = sscanf(parser_buf + str_index[9], "%2hd%2hd%2hd", &gps_day, &gps_mon, &gps_yea);
|
||||
if ((i == 4) && (j == 3)) {
|
||||
if ((gps_mod == 'A') || (gps_mod == 'D')) {
|
||||
gps_time_ok = true;
|
||||
DEBUG_MSG("Note: Valid RMC sentence, GPS locked, date: 20%02d-%02d-%02dT%02d:%02d:%06.3fZ\n", gps_yea, gps_mon, gps_day, gps_hou, gps_min, gps_fra + (float)gps_sec);
|
||||
} else {
|
||||
gps_time_ok = false;
|
||||
DEBUG_MSG("Note: Valid RMC sentence, no satellite fix, estimated date: 20%02d-%02d-%02dT%02d:%02d:%06.3fZ\n", gps_yea, gps_mon, gps_day, gps_hou, gps_min, gps_fra + (float)gps_sec);
|
||||
}
|
||||
} else {
|
||||
/* could not get a valid hour AND date */
|
||||
gps_time_ok = false;
|
||||
DEBUG_MSG("Note: Valid RMC sentence, mode %c, no date\n", gps_mod);
|
||||
}
|
||||
return NMEA_RMC;
|
||||
} else if (match_label(serial_buff, "$G?GGA", 6, '?')) {
|
||||
/*
|
||||
NMEA sentence format: $xxGGA,time,lat,NS,long,EW,quality,numSV,HDOP,alt,M,sep,M,diffAge,diffStation*cs<CR><LF>
|
||||
Valid fix: $GPGGA,092725.00,4717.11399,N,00833.91590,E,1,08,1.01,499.6,M,48.0,M,,*5B
|
||||
*/
|
||||
memcpy(parser_buf, serial_buff, buff_size);
|
||||
parser_buf[buff_size] = '\0';
|
||||
nb_fields = str_chop(parser_buf, buff_size, ',', str_index, ARRAY_SIZE(str_index));
|
||||
if (nb_fields != 15) {
|
||||
DEBUG_MSG("Warning: invalid GGA sentence (number of fields)\n");
|
||||
return IGNORED;
|
||||
}
|
||||
/* parse number of satellites used for fix */
|
||||
sscanf(parser_buf + str_index[7], "%hd", &gps_sat);
|
||||
/* parse 3D coordinates */
|
||||
i = sscanf(parser_buf + str_index[2], "%2hd%10lf", &gps_dla, &gps_mla);
|
||||
gps_ola = *(parser_buf + str_index[3]);
|
||||
j = sscanf(parser_buf + str_index[4], "%3hd%10lf", &gps_dlo, &gps_mlo);
|
||||
gps_olo = *(parser_buf + str_index[5]);
|
||||
k = sscanf(parser_buf + str_index[9], "%hd", &gps_alt);
|
||||
if ((i == 2) && (j == 2) && (k == 1) && ((gps_ola=='N')||(gps_ola=='S')) && ((gps_olo=='E')||(gps_olo=='W'))) {
|
||||
gps_pos_ok = true;
|
||||
DEBUG_MSG("Note: Valid GGA sentence, %d sat, lat %02ddeg %06.3fmin %c, lon %03ddeg%06.3fmin %c, alt %d\n", gps_sat, gps_dla, gps_mla, gps_ola, gps_dlo, gps_mlo, gps_olo, gps_alt);
|
||||
} else {
|
||||
/* could not get a valid latitude, longitude AND altitude */
|
||||
gps_pos_ok = false;
|
||||
DEBUG_MSG("Note: Valid GGA sentence, %d sat, no coordinates\n", gps_sat);
|
||||
}
|
||||
return NMEA_GGA;
|
||||
} else {
|
||||
DEBUG_MSG("Note: ignored NMEA sentence\n"); /* quite verbose */
|
||||
return IGNORED;
|
||||
}
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
int lgw_gps_get(struct timespec *utc, struct timespec *gps_time, struct coord_s *loc, struct coord_s *err) {
|
||||
struct tm x;
|
||||
time_t y;
|
||||
double intpart, fractpart;
|
||||
|
||||
if (utc != NULL) {
|
||||
if (!gps_time_ok) {
|
||||
DEBUG_MSG("ERROR: NO VALID TIME TO RETURN\n");
|
||||
return LGW_GPS_ERROR;
|
||||
}
|
||||
memset(&x, 0, sizeof(x));
|
||||
if (gps_yea < 100) { /* 2-digits year, 20xx */
|
||||
x.tm_year = gps_yea + 100; /* 100 years offset to 1900 */
|
||||
} else { /* 4-digits year, Gregorian calendar */
|
||||
x.tm_year = gps_yea - 1900;
|
||||
}
|
||||
x.tm_mon = gps_mon - 1; /* tm_mon is [0,11], gps_mon is [1,12] */
|
||||
x.tm_mday = gps_day;
|
||||
x.tm_hour = gps_hou;
|
||||
x.tm_min = gps_min;
|
||||
x.tm_sec = gps_sec;
|
||||
y = mktime(&x) - timezone; /* need to substract timezone bc mktime assumes time vector is local time */
|
||||
if (y == (time_t)(-1)) {
|
||||
DEBUG_MSG("ERROR: FAILED TO CONVERT BROKEN-DOWN TIME\n");
|
||||
return LGW_GPS_ERROR;
|
||||
}
|
||||
utc->tv_sec = y;
|
||||
utc->tv_nsec = (int32_t)(gps_fra * 1e9);
|
||||
}
|
||||
if (gps_time != NULL) {
|
||||
if (!gps_time_ok) {
|
||||
DEBUG_MSG("ERROR: NO VALID TIME TO RETURN\n");
|
||||
return LGW_GPS_ERROR;
|
||||
}
|
||||
fractpart = modf(((double)gps_iTOW / 1E3) + ((double)gps_fTOW / 1E9), &intpart);
|
||||
/* Number of seconds since beginning on current GPS week */
|
||||
gps_time->tv_sec = (time_t)intpart;
|
||||
/* Number of seconds since GPS epoch 06.Jan.1980 */
|
||||
gps_time->tv_sec += (time_t)gps_week * 604800; /* day*hours*minutes*secondes: 7*24*60*60; */
|
||||
/* Fractional part in nanoseconds */
|
||||
gps_time->tv_nsec = (long)(fractpart * 1E9);
|
||||
}
|
||||
if (loc != NULL) {
|
||||
if (!gps_pos_ok) {
|
||||
DEBUG_MSG("ERROR: NO VALID POSITION TO RETURN\n");
|
||||
return LGW_GPS_ERROR;
|
||||
}
|
||||
loc->lat = ((double)gps_dla + (gps_mla/60.0)) * ((gps_ola == 'N')?1.0:-1.0);
|
||||
loc->lon = ((double)gps_dlo + (gps_mlo/60.0)) * ((gps_olo == 'E')?1.0:-1.0);
|
||||
loc->alt = gps_alt;
|
||||
}
|
||||
if (err != NULL) {
|
||||
DEBUG_MSG("Warning: localization error processing not implemented yet\n");
|
||||
err->lat = 0.0;
|
||||
err->lon = 0.0;
|
||||
err->alt = 0;
|
||||
}
|
||||
|
||||
return LGW_GPS_SUCCESS;
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
int lgw_gps_sync(struct tref *ref, uint32_t count_us, struct timespec utc, struct timespec gps_time) {
|
||||
double cnt_diff; /* internal concentrator time difference (in seconds) */
|
||||
double utc_diff; /* UTC time difference (in seconds) */
|
||||
double slope; /* time slope between new reference and old reference (for sanity check) */
|
||||
|
||||
bool aber_n0; /* is the update value for synchronization aberrant or not ? */
|
||||
static bool aber_min1 = false; /* keep track of whether value at sync N-1 was aberrant or not */
|
||||
static bool aber_min2 = false; /* keep track of whether value at sync N-2 was aberrant or not */
|
||||
|
||||
CHECK_NULL(ref);
|
||||
|
||||
/* calculate the slope */
|
||||
|
||||
cnt_diff = (double)(count_us - ref->count_us) / (double)(TS_CPS); /* uncorrected by xtal_err */
|
||||
utc_diff = (double)(utc.tv_sec - (ref->utc).tv_sec) + (1E-9 * (double)(utc.tv_nsec - (ref->utc).tv_nsec));
|
||||
|
||||
/* detect aberrant points by measuring if slope limits are exceeded */
|
||||
if (utc_diff != 0) { // prevent divide by zero
|
||||
slope = cnt_diff/utc_diff;
|
||||
if ((slope > PLUS_10PPM) || (slope < MINUS_10PPM)) {
|
||||
DEBUG_MSG("Warning: correction range exceeded\n");
|
||||
aber_n0 = true;
|
||||
} else {
|
||||
aber_n0 = false;
|
||||
}
|
||||
} else {
|
||||
DEBUG_MSG("Warning: aberrant UTC value for synchronization\n");
|
||||
aber_n0 = true;
|
||||
}
|
||||
|
||||
/* watch if the 3 latest sync point were aberrant or not */
|
||||
if (aber_n0 == false) {
|
||||
/* value no aberrant -> sync with smoothed slope */
|
||||
ref->systime = time(NULL);
|
||||
ref->count_us = count_us;
|
||||
ref->utc.tv_sec = utc.tv_sec;
|
||||
ref->utc.tv_nsec = utc.tv_nsec;
|
||||
ref->gps.tv_sec = gps_time.tv_sec;
|
||||
ref->gps.tv_nsec = gps_time.tv_nsec;
|
||||
ref->xtal_err = slope;
|
||||
aber_min2 = aber_min1;
|
||||
aber_min1 = aber_n0;
|
||||
return LGW_GPS_SUCCESS;
|
||||
} else if (aber_n0 && aber_min1 && aber_min2) {
|
||||
/* 3 successive aberrant values -> sync reset (keep xtal_err) */
|
||||
ref->systime = time(NULL);
|
||||
ref->count_us = count_us;
|
||||
ref->utc.tv_sec = utc.tv_sec;
|
||||
ref->utc.tv_nsec = utc.tv_nsec;
|
||||
ref->gps.tv_sec = gps_time.tv_sec;
|
||||
ref->gps.tv_nsec = gps_time.tv_nsec;
|
||||
/* reset xtal_err only if the present value is out of range */
|
||||
if ((ref->xtal_err > PLUS_10PPM) || (ref->xtal_err < MINUS_10PPM)) {
|
||||
ref->xtal_err = 1.0;
|
||||
}
|
||||
DEBUG_MSG("Warning: 3 successive aberrant sync attempts, sync reset\n");
|
||||
aber_min2 = aber_min1;
|
||||
aber_min1 = aber_n0;
|
||||
return LGW_GPS_SUCCESS;
|
||||
} else {
|
||||
/* only 1 or 2 successive aberrant values -> ignore and return an error */
|
||||
aber_min2 = aber_min1;
|
||||
aber_min1 = aber_n0;
|
||||
return LGW_GPS_ERROR;
|
||||
}
|
||||
|
||||
return LGW_GPS_SUCCESS;
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
int lgw_cnt2utc(struct tref ref, uint32_t count_us, struct timespec *utc) {
|
||||
double delta_sec;
|
||||
double intpart, fractpart;
|
||||
long tmp;
|
||||
|
||||
CHECK_NULL(utc);
|
||||
if ((ref.systime == 0) || (ref.xtal_err > PLUS_10PPM) || (ref.xtal_err < MINUS_10PPM)) {
|
||||
DEBUG_MSG("ERROR: INVALID REFERENCE FOR CNT -> UTC CONVERSION\n");
|
||||
return LGW_GPS_ERROR;
|
||||
}
|
||||
|
||||
/* calculate delta in seconds between reference count_us and target count_us */
|
||||
delta_sec = (double)(count_us - ref.count_us) / (TS_CPS * ref.xtal_err);
|
||||
|
||||
/* now add that delta to reference UTC time */
|
||||
fractpart = modf (delta_sec , &intpart);
|
||||
tmp = ref.utc.tv_nsec + (long)(fractpart * 1E9);
|
||||
if (tmp < (long)1E9) { /* the nanosecond part doesn't overflow */
|
||||
utc->tv_sec = ref.utc.tv_sec + (time_t)intpart;
|
||||
utc->tv_nsec = tmp;
|
||||
} else { /* must carry one second */
|
||||
utc->tv_sec = ref.utc.tv_sec + (time_t)intpart + 1;
|
||||
utc->tv_nsec = tmp - (long)1E9;
|
||||
}
|
||||
|
||||
return LGW_GPS_SUCCESS;
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
int lgw_utc2cnt(struct tref ref, struct timespec utc, uint32_t *count_us) {
|
||||
double delta_sec;
|
||||
|
||||
CHECK_NULL(count_us);
|
||||
if ((ref.systime == 0) || (ref.xtal_err > PLUS_10PPM) || (ref.xtal_err < MINUS_10PPM)) {
|
||||
DEBUG_MSG("ERROR: INVALID REFERENCE FOR UTC -> CNT CONVERSION\n");
|
||||
return LGW_GPS_ERROR;
|
||||
}
|
||||
|
||||
/* calculate delta in seconds between reference utc and target utc */
|
||||
delta_sec = (double)(utc.tv_sec - ref.utc.tv_sec);
|
||||
delta_sec += 1E-9 * (double)(utc.tv_nsec - ref.utc.tv_nsec);
|
||||
|
||||
/* now convert that to internal counter tics and add that to reference counter value */
|
||||
*count_us = ref.count_us + (uint32_t)(delta_sec * TS_CPS * ref.xtal_err);
|
||||
|
||||
return LGW_GPS_SUCCESS;
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
int lgw_cnt2gps(struct tref ref, uint32_t count_us, struct timespec *gps_time) {
|
||||
double delta_sec;
|
||||
double intpart, fractpart;
|
||||
long tmp;
|
||||
|
||||
CHECK_NULL(gps_time);
|
||||
if ((ref.systime == 0) || (ref.xtal_err > PLUS_10PPM) || (ref.xtal_err < MINUS_10PPM)) {
|
||||
DEBUG_MSG("ERROR: INVALID REFERENCE FOR CNT -> GPS CONVERSION\n");
|
||||
return LGW_GPS_ERROR;
|
||||
}
|
||||
|
||||
/* calculate delta in milliseconds between reference count_us and target count_us */
|
||||
delta_sec = (double)(count_us - ref.count_us) / (TS_CPS * ref.xtal_err);
|
||||
|
||||
/* now add that delta to reference GPS time */
|
||||
fractpart = modf (delta_sec , &intpart);
|
||||
tmp = ref.gps.tv_nsec + (long)(fractpart * 1E9);
|
||||
if (tmp < (long)1E9) { /* the nanosecond part doesn't overflow */
|
||||
gps_time->tv_sec = ref.gps.tv_sec + (time_t)intpart;
|
||||
gps_time->tv_nsec = tmp;
|
||||
} else { /* must carry one second */
|
||||
gps_time->tv_sec = ref.gps.tv_sec + (time_t)intpart + 1;
|
||||
gps_time->tv_nsec = tmp - (long)1E9;
|
||||
}
|
||||
|
||||
return LGW_GPS_SUCCESS;
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
int lgw_gps2cnt(struct tref ref, struct timespec gps_time, uint32_t *count_us) {
|
||||
double delta_sec;
|
||||
|
||||
CHECK_NULL(count_us);
|
||||
if ((ref.systime == 0) || (ref.xtal_err > PLUS_10PPM) || (ref.xtal_err < MINUS_10PPM)) {
|
||||
DEBUG_MSG("ERROR: INVALID REFERENCE FOR GPS -> CNT CONVERSION\n");
|
||||
return LGW_GPS_ERROR;
|
||||
}
|
||||
|
||||
/* calculate delta in seconds between reference gps time and target gps time */
|
||||
delta_sec = (double)(gps_time.tv_sec - ref.gps.tv_sec);
|
||||
delta_sec += 1E-9 * (double)(gps_time.tv_nsec - ref.gps.tv_nsec);
|
||||
|
||||
/* now convert that to internal counter tics and add that to reference counter value */
|
||||
*count_us = ref.count_us + (uint32_t)(delta_sec * TS_CPS * ref.xtal_err);
|
||||
|
||||
return LGW_GPS_SUCCESS;
|
||||
}
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,156 @@
|
|||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2019 Semtech
|
||||
|
||||
Description:
|
||||
Host specific functions to address the LoRa concentrator I2C peripherals.
|
||||
|
||||
License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*/
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- DEPENDANCIES --------------------------------------------------------- */
|
||||
|
||||
#include <stdint.h> /* C99 types */
|
||||
#include <stdio.h> /* printf fprintf */
|
||||
#include <stdlib.h> /* malloc free */
|
||||
#include <unistd.h> /* lseek, close */
|
||||
#include <fcntl.h> /* open */
|
||||
#include <string.h> /* memset */
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-dev.h>
|
||||
|
||||
#include "loragw_i2c.h"
|
||||
#include "loragw_aux.h"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE MACROS ------------------------------------------------------- */
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
|
||||
#if DEBUG_I2C == 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 ---------------------------------------------------- */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PUBLIC FUNCTIONS DEFINITION ------------------------------------------ */
|
||||
|
||||
int i2c_linuxdev_open(const char *path, uint8_t device_addr, int *i2c_fd) {
|
||||
int dev;
|
||||
|
||||
/* Check input variables */
|
||||
if (path == NULL) {
|
||||
DEBUG_MSG("ERROR: null pointer path");
|
||||
return LGW_I2C_ERROR;
|
||||
}
|
||||
if (i2c_fd == NULL) {
|
||||
DEBUG_MSG("ERROR: null pointer i2c_fd");
|
||||
return LGW_I2C_ERROR;
|
||||
}
|
||||
|
||||
/* Open I2C device */
|
||||
dev = open(path, O_RDWR);
|
||||
if (dev < 0) {
|
||||
DEBUG_PRINTF("ERROR: Failed to open I2C %s - %s", path, strerror(errno));
|
||||
return LGW_I2C_ERROR;
|
||||
}
|
||||
|
||||
/* Setting I2C device mode to slave */
|
||||
if (ioctl(dev, I2C_SLAVE, device_addr) < 0) {
|
||||
DEBUG_PRINTF("ERROR: Failed to acquire bus access and/or talk to slave - %s\n", strerror(errno));
|
||||
return LGW_I2C_ERROR;
|
||||
}
|
||||
|
||||
DEBUG_MSG("INFO: I2C port opened successfully");
|
||||
*i2c_fd = dev; /* return file descriptor index */
|
||||
|
||||
return LGW_I2C_SUCCESS;
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
int i2c_linuxdev_read(int i2c_fd, uint8_t device_addr, uint8_t reg_addr, uint8_t *data) {
|
||||
uint8_t *inbuff, outbuff;
|
||||
struct i2c_rdwr_ioctl_data packets;
|
||||
struct i2c_msg messages[2];
|
||||
|
||||
outbuff = reg_addr;
|
||||
messages[0].addr = device_addr;
|
||||
messages[0].flags= 0;
|
||||
messages[0].len = sizeof(outbuff);
|
||||
messages[0].buf = &outbuff;
|
||||
|
||||
inbuff = data;
|
||||
messages[1].addr = device_addr;
|
||||
messages[1].flags = I2C_M_RD;
|
||||
messages[1].len = sizeof(*inbuff);
|
||||
messages[1].buf = inbuff;
|
||||
|
||||
packets.msgs = messages;
|
||||
packets.nmsgs = 2;
|
||||
|
||||
if (ioctl(i2c_fd, I2C_RDWR, &packets) < 0) {
|
||||
DEBUG_PRINTF("ERROR: Read from I2C Device failed (%d, 0x%02x, 0x%02x) - %s", i2c_fd, device_addr, reg_addr, strerror(errno));
|
||||
return LGW_I2C_ERROR;
|
||||
}
|
||||
|
||||
return LGW_I2C_SUCCESS;
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
int i2c_linuxdev_write(int i2c_fd, uint8_t device_addr, uint8_t reg_addr, uint8_t data) {
|
||||
unsigned char buff[2];
|
||||
struct i2c_rdwr_ioctl_data packets;
|
||||
struct i2c_msg messages[1];
|
||||
|
||||
buff[0] = reg_addr;
|
||||
buff[1] = data;
|
||||
|
||||
messages[0].addr = device_addr;
|
||||
messages[0].flags = 0;
|
||||
messages[0].len = sizeof(buff);
|
||||
messages[0].buf = buff;
|
||||
|
||||
packets.msgs = messages;
|
||||
packets.nmsgs = 1;
|
||||
|
||||
if (ioctl(i2c_fd, I2C_RDWR, &packets) < 0) {
|
||||
DEBUG_PRINTF("ERROR: Write to I2C Device failed (%d, 0x%02x, 0x%02x) - %s", i2c_fd, device_addr, reg_addr, strerror(errno));
|
||||
return LGW_I2C_ERROR;
|
||||
}
|
||||
|
||||
return LGW_I2C_SUCCESS;
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
int i2c_linuxdev_close(int i2c_fd) {
|
||||
int i;
|
||||
|
||||
i = close(i2c_fd);
|
||||
if (i == 0) {
|
||||
DEBUG_MSG("INFO: I2C port closed successfully");
|
||||
return LGW_I2C_SUCCESS;
|
||||
} else {
|
||||
DEBUG_PRINTF("ERROR: Failed to close I2C - %s", strerror(errno));
|
||||
return LGW_I2C_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,352 @@
|
|||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2019 Semtech
|
||||
|
||||
Description:
|
||||
Host specific functions to address the LoRa concentrator registers through
|
||||
a SPI interface.
|
||||
Single-byte read/write and burst read/write.
|
||||
Could be used with multiple SPI ports in parallel (explicit file descriptor)
|
||||
|
||||
License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*/
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- DEPENDANCIES --------------------------------------------------------- */
|
||||
|
||||
#include <stdint.h> /* C99 types */
|
||||
#include <stdio.h> /* printf fprintf */
|
||||
#include <stdlib.h> /* malloc free */
|
||||
#include <unistd.h> /* lseek, close */
|
||||
#include <fcntl.h> /* open */
|
||||
#include <string.h> /* memset */
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/spi/spidev.h>
|
||||
|
||||
#include "loragw_spi.h"
|
||||
#include "loragw_aux.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
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PUBLIC FUNCTIONS DEFINITION ------------------------------------------ */
|
||||
|
||||
/* SPI initialization and configuration */
|
||||
int lgw_spi_open(const char * spidev_path, void **spi_target_ptr) {
|
||||
int *spi_device = NULL;
|
||||
int dev;
|
||||
int a=0, b=0;
|
||||
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(spidev_path, O_RDWR);
|
||||
if (dev < 0) {
|
||||
DEBUG_PRINTF("ERROR: failed to open SPI device %s\n", spidev_path);
|
||||
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 spi_mux_target, uint16_t address, uint8_t data) {
|
||||
int spi_device;
|
||||
uint8_t out_buf[4];
|
||||
uint8_t command_size;
|
||||
struct spi_ioc_transfer k;
|
||||
int a;
|
||||
|
||||
/* check input variables */
|
||||
CHECK_NULL(spi_target);
|
||||
|
||||
spi_device = *(int *)spi_target; /* must check that spi_target is not null beforehand */
|
||||
|
||||
/* prepare frame to be sent */
|
||||
out_buf[0] = spi_mux_target;
|
||||
out_buf[1] = WRITE_ACCESS | ((address >> 8) & 0x7F);
|
||||
out_buf[2] = ((address >> 0) & 0xFF);
|
||||
out_buf[3] = data;
|
||||
command_size = 4;
|
||||
|
||||
/* I/O transaction */
|
||||
memset(&k, 0, sizeof(k)); /* clear k */
|
||||
k.tx_buf = (unsigned long) out_buf;
|
||||
k.len = command_size;
|
||||
k.speed_hz = SPI_SPEED;
|
||||
k.cs_change = 0;
|
||||
k.bits_per_word = 8;
|
||||
a = ioctl(spi_device, SPI_IOC_MESSAGE(1), &k);
|
||||
|
||||
/* determine return code */
|
||||
if (a != (int)k.len) {
|
||||
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 spi_mux_target, uint16_t address, uint8_t *data) {
|
||||
int spi_device;
|
||||
uint8_t out_buf[5];
|
||||
uint8_t command_size;
|
||||
uint8_t in_buf[ARRAY_SIZE(out_buf)];
|
||||
struct spi_ioc_transfer k;
|
||||
int a;
|
||||
|
||||
/* check input variables */
|
||||
CHECK_NULL(spi_target);
|
||||
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] = spi_mux_target;
|
||||
out_buf[1] = READ_ACCESS | ((address >> 8) & 0x7F);
|
||||
out_buf[2] = ((address >> 0) & 0xFF);
|
||||
out_buf[3] = 0x00;
|
||||
out_buf[4] = 0x00;
|
||||
command_size = 5;
|
||||
|
||||
/* 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 = command_size;
|
||||
k.cs_change = 0;
|
||||
a = ioctl(spi_device, SPI_IOC_MESSAGE(1), &k);
|
||||
|
||||
/* determine return code */
|
||||
if (a != (int)k.len) {
|
||||
DEBUG_MSG("ERROR: SPI READ FAILURE\n");
|
||||
return LGW_SPI_ERROR;
|
||||
} else {
|
||||
DEBUG_MSG("Note: SPI read success\n");
|
||||
*data = in_buf[command_size - 1];
|
||||
return LGW_SPI_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
/* Burst (multiple-byte) write */
|
||||
int lgw_spi_wb(void *spi_target, uint8_t spi_mux_target, uint16_t address, const uint8_t *data, uint16_t size) {
|
||||
int spi_device;
|
||||
uint8_t command[3];
|
||||
uint8_t command_size;
|
||||
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);
|
||||
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[0] = spi_mux_target;
|
||||
command[1] = WRITE_ACCESS | ((address >> 8) & 0x7F);
|
||||
command[2] = ((address >> 0) & 0xFF);
|
||||
command_size = 3;
|
||||
size_to_do = size;
|
||||
|
||||
/* I/O transaction */
|
||||
memset(&k, 0, sizeof(k)); /* clear k */
|
||||
k[0].tx_buf = (unsigned long) &command[0];
|
||||
k[0].len = command_size;
|
||||
k[0].cs_change = 0;
|
||||
k[1].cs_change = 0;
|
||||
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) - k[0].len );
|
||||
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 spi_mux_target, uint16_t address, uint8_t *data, uint16_t size) {
|
||||
int spi_device;
|
||||
uint8_t command[4];
|
||||
uint8_t command_size;
|
||||
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);
|
||||
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[0] = spi_mux_target;
|
||||
command[1] = READ_ACCESS | ((address >> 8) & 0x7F);
|
||||
command[2] = ((address >> 0) & 0xFF);
|
||||
command[3] = 0x00;
|
||||
command_size = 4;
|
||||
size_to_do = size;
|
||||
|
||||
/* I/O transaction */
|
||||
memset(&k, 0, sizeof(k)); /* clear k */
|
||||
k[0].tx_buf = (unsigned long) &command[0];
|
||||
k[0].len = command_size;
|
||||
k[0].cs_change = 0;
|
||||
k[1].cs_change = 0;
|
||||
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) - k[0].len );
|
||||
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 ------------------------------------------------------------------ */
|
|
@ -0,0 +1,213 @@
|
|||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2019 Semtech
|
||||
|
||||
Description:
|
||||
Basic driver for ST ts751 temperature sensor
|
||||
|
||||
License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*/
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- DEPENDANCIES --------------------------------------------------------- */
|
||||
|
||||
#include <stdint.h> /* C99 types */
|
||||
#include <stdbool.h> /* bool type */
|
||||
#include <stdio.h> /* printf fprintf */
|
||||
|
||||
#include "loragw_i2c.h"
|
||||
#include "loragw_stts751.h"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE MACROS ------------------------------------------------------- */
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
|
||||
#if DEBUG_I2C == 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 CONSTANTS ---------------------------------------------------- */
|
||||
|
||||
#define STTS751_REG_TEMP_H 0x00
|
||||
#define STTS751_REG_STATUS 0x01
|
||||
#define STTS751_STATUS_TRIPT BIT(0)
|
||||
#define STTS751_STATUS_TRIPL BIT(5)
|
||||
#define STTS751_STATUS_TRIPH BIT(6)
|
||||
#define STTS751_REG_TEMP_L 0x02
|
||||
#define STTS751_REG_CONF 0x03
|
||||
#define STTS751_CONF_RES_MASK 0x0C
|
||||
#define STTS751_CONF_RES_SHIFT 2
|
||||
#define STTS751_CONF_EVENT_DIS BIT(7)
|
||||
#define STTS751_CONF_STOP BIT(6)
|
||||
#define STTS751_REG_RATE 0x04
|
||||
#define STTS751_REG_HLIM_H 0x05
|
||||
#define STTS751_REG_HLIM_L 0x06
|
||||
#define STTS751_REG_LLIM_H 0x07
|
||||
#define STTS751_REG_LLIM_L 0x08
|
||||
#define STTS751_REG_TLIM 0x20
|
||||
#define STTS751_REG_HYST 0x21
|
||||
#define STTS751_REG_SMBUS_TO 0x22
|
||||
|
||||
#define STTS751_REG_PROD_ID 0xFD
|
||||
#define STTS751_REG_MAN_ID 0xFE
|
||||
#define STTS751_REG_REV_ID 0xFF
|
||||
|
||||
#define STTS751_0_PROD_ID 0x00
|
||||
#define STTS751_1_PROD_ID 0x01
|
||||
#define ST_MAN_ID 0x53
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE VARIABLES ---------------------------------------------------- */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- INTERNAL SHARED VARIABLES -------------------------------------------- */
|
||||
|
||||
extern int lgw_i2c_target;
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE FUNCTIONS ---------------------------------------------------- */
|
||||
|
||||
int stts751_configure( int i2c_fd )
|
||||
{
|
||||
int err;
|
||||
uint8_t val;
|
||||
|
||||
/* Check Input Params */
|
||||
if( i2c_fd <= 0 )
|
||||
{
|
||||
printf( "ERROR: invalid I2C file descriptor\n" );
|
||||
return LGW_I2C_ERROR;
|
||||
}
|
||||
|
||||
DEBUG_MSG("INFO: configuring STTS751 temperature sensor...\n");
|
||||
|
||||
/* Get product ID */
|
||||
err = i2c_linuxdev_read( i2c_fd, I2C_PORT_TEMP_SENSOR, STTS751_REG_PROD_ID, &val );
|
||||
if ( err != 0 )
|
||||
{
|
||||
printf( "ERROR: failed to read I2C device 0x%02X (err=%i)\n", I2C_PORT_TEMP_SENSOR, err );
|
||||
return LGW_I2C_ERROR;
|
||||
}
|
||||
switch( val )
|
||||
{
|
||||
case STTS751_0_PROD_ID:
|
||||
DEBUG_MSG("INFO: Product ID: STTS751-0\n");
|
||||
break;
|
||||
case STTS751_1_PROD_ID:
|
||||
DEBUG_MSG("INFO: Product ID: STTS751-1\n");
|
||||
break;
|
||||
default:
|
||||
printf("ERROR: Product ID: UNKNOWN\n");
|
||||
return LGW_I2C_ERROR;
|
||||
}
|
||||
|
||||
/* Get Manufacturer ID */
|
||||
err = i2c_linuxdev_read( i2c_fd, I2C_PORT_TEMP_SENSOR, STTS751_REG_MAN_ID, &val );
|
||||
if ( err != 0 )
|
||||
{
|
||||
printf( "ERROR: failed to read I2C device 0x%02X (err=%i)\n", I2C_PORT_TEMP_SENSOR, err );
|
||||
return LGW_I2C_ERROR;
|
||||
}
|
||||
if ( val != ST_MAN_ID )
|
||||
{
|
||||
printf( "ERROR: Manufacturer ID: UNKNOWN\n" );
|
||||
return LGW_I2C_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_PRINTF("INFO: Manufacturer ID: 0x%02X\n", val);
|
||||
}
|
||||
|
||||
/* Get revision number */
|
||||
err = i2c_linuxdev_read( i2c_fd, I2C_PORT_TEMP_SENSOR, STTS751_REG_REV_ID, &val );
|
||||
if ( err != 0 )
|
||||
{
|
||||
printf( "ERROR: failed to read I2C device 0x%02X (err=%i)\n", I2C_PORT_TEMP_SENSOR, err );
|
||||
return LGW_I2C_ERROR;
|
||||
}
|
||||
DEBUG_PRINTF("INFO: Revision number: 0x%02X\n", val);
|
||||
|
||||
/* Set conversion resolution to 12 bits */
|
||||
err = i2c_linuxdev_write( i2c_fd, I2C_PORT_TEMP_SENSOR, STTS751_REG_CONF, 0x8C ); /* TODO: do not hardcode the whole byte */
|
||||
if ( err != 0 )
|
||||
{
|
||||
printf( "ERROR: failed to write I2C device 0x%02X (err=%i)\n", I2C_PORT_TEMP_SENSOR, err );
|
||||
return LGW_I2C_ERROR;
|
||||
}
|
||||
|
||||
/* Set conversion rate to 1 / second */
|
||||
err = i2c_linuxdev_write( i2c_fd, I2C_PORT_TEMP_SENSOR, STTS751_REG_RATE, 0x04 );
|
||||
if ( err != 0 )
|
||||
{
|
||||
printf( "ERROR: failed to write I2C device 0x%02X (err=%i)\n", I2C_PORT_TEMP_SENSOR, err );
|
||||
return LGW_I2C_ERROR;
|
||||
}
|
||||
|
||||
return LGW_I2C_SUCCESS;
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
int stts751_get_temperature( int i2c_fd, float * temperature)
|
||||
{
|
||||
int err;
|
||||
uint8_t high_byte, low_byte;
|
||||
int8_t h;
|
||||
|
||||
/* Check Input Params */
|
||||
if( i2c_fd <= 0 )
|
||||
{
|
||||
printf( "ERROR: invalid I2C file descriptor\n" );
|
||||
return LGW_I2C_ERROR;
|
||||
}
|
||||
|
||||
/* Read Temperature LSB */
|
||||
err = i2c_linuxdev_read( i2c_fd, I2C_PORT_TEMP_SENSOR, STTS751_REG_TEMP_L, &low_byte );
|
||||
if ( err != 0 )
|
||||
{
|
||||
printf( "ERROR: failed to read I2C device 0x%02X (err=%i)\n", I2C_PORT_TEMP_SENSOR, err );
|
||||
return LGW_I2C_ERROR;
|
||||
}
|
||||
|
||||
/* Read Temperature MSB */
|
||||
err = i2c_linuxdev_read( i2c_fd, I2C_PORT_TEMP_SENSOR, STTS751_REG_TEMP_H, &high_byte );
|
||||
if ( err != 0 )
|
||||
{
|
||||
printf( "ERROR: failed to read I2C device 0x%02X (err=%i)\n", I2C_PORT_TEMP_SENSOR, err );
|
||||
return LGW_I2C_ERROR;
|
||||
}
|
||||
|
||||
h = (int8_t)high_byte;
|
||||
*temperature = ((h << 8) | low_byte) / 256.0;
|
||||
|
||||
DEBUG_PRINTF("Temperature: %f C (h:0x%02X l:0x%02X)\n", *temperature, high_byte, low_byte);
|
||||
|
||||
return LGW_I2C_SUCCESS;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PUBLIC FUNCTIONS DEFINITION ------------------------------------------ */
|
||||
|
||||
int lgw_stts751_configure(void) {
|
||||
return stts751_configure(lgw_i2c_target);
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
int lgw_stts751_get_temperature(float * temperature) {
|
||||
return stts751_get_temperature(lgw_i2c_target, temperature);
|
||||
}
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
|
@ -0,0 +1,285 @@
|
|||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2019 Semtech
|
||||
|
||||
Description:
|
||||
Functions used to handle LoRa concentrator SX1250 radios.
|
||||
|
||||
License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*/
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- DEPENDANCIES --------------------------------------------------------- */
|
||||
|
||||
#include <stdint.h> /* C99 types */
|
||||
#include <stdio.h> /* printf fprintf */
|
||||
#include <stdlib.h> /* malloc free */
|
||||
#include <unistd.h> /* lseek, close */
|
||||
#include <fcntl.h> /* open */
|
||||
#include <string.h> /* memset */
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/spi/spidev.h>
|
||||
|
||||
#include "loragw_spi.h"
|
||||
#include "loragw_reg.h"
|
||||
#include "loragw_aux.h"
|
||||
#include "loragw_sx1250.h"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE MACROS ------------------------------------------------------- */
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
|
||||
#if DEBUG_RAD == 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
|
||||
|
||||
#define SX1250_FREQ_TO_REG(f) (uint32_t)((uint64_t)f * (1 << 25) / 32000000U)
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE CONSTANTS ---------------------------------------------------- */
|
||||
|
||||
#define WAIT_BUSY_SX1250_MS 1
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- INTERNAL SHARED VARIABLES -------------------------------------------- */
|
||||
|
||||
extern void *lgw_spi_target; /*! generic pointer to the SPI device */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PUBLIC FUNCTIONS DEFINITION ------------------------------------------ */
|
||||
|
||||
int sx1250_write_command(uint8_t rf_chain, sx1250_op_code_t op_code, uint8_t *data, uint16_t size) {
|
||||
int spi_device;
|
||||
int cmd_size = 2; /* header + op_code */
|
||||
uint8_t out_buf[cmd_size + size];
|
||||
uint8_t command_size;
|
||||
struct spi_ioc_transfer k;
|
||||
int a, i;
|
||||
|
||||
/* wait BUSY */
|
||||
wait_ms(WAIT_BUSY_SX1250_MS);
|
||||
|
||||
/* check input variables */
|
||||
CHECK_NULL(lgw_spi_target);
|
||||
|
||||
spi_device = *(int *)lgw_spi_target; /* must check that spi_target is not null beforehand */
|
||||
|
||||
/* prepare frame to be sent */
|
||||
out_buf[0] = (rf_chain == 0) ? LGW_SPI_MUX_TARGET_RADIOA : LGW_SPI_MUX_TARGET_RADIOB;
|
||||
out_buf[1] = (uint8_t)op_code;
|
||||
for(i = 0; i < (int)size; i++) {
|
||||
out_buf[cmd_size + i] = data[i];
|
||||
}
|
||||
command_size = cmd_size + size;
|
||||
|
||||
/* I/O transaction */
|
||||
memset(&k, 0, sizeof(k)); /* clear k */
|
||||
k.tx_buf = (unsigned long) out_buf;
|
||||
k.len = command_size;
|
||||
k.speed_hz = SPI_SPEED;
|
||||
k.cs_change = 0;
|
||||
k.bits_per_word = 8;
|
||||
a = ioctl(spi_device, SPI_IOC_MESSAGE(1), &k);
|
||||
|
||||
/* determine return code */
|
||||
if (a != (int)k.len) {
|
||||
DEBUG_MSG("ERROR: SPI WRITE FAILURE\n");
|
||||
return LGW_SPI_ERROR;
|
||||
} else {
|
||||
DEBUG_MSG("Note: SPI write success\n");
|
||||
return LGW_SPI_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
int sx1250_read_command(uint8_t rf_chain, sx1250_op_code_t op_code, uint8_t *data, uint16_t size) {
|
||||
int spi_device;
|
||||
int cmd_size = 2; /* header + op_code + NOP */
|
||||
uint8_t out_buf[cmd_size + size];
|
||||
uint8_t command_size;
|
||||
uint8_t in_buf[ARRAY_SIZE(out_buf)];
|
||||
struct spi_ioc_transfer k;
|
||||
int a, i;
|
||||
|
||||
/* wait BUSY */
|
||||
wait_ms(WAIT_BUSY_SX1250_MS);
|
||||
|
||||
/* check input variables */
|
||||
CHECK_NULL(lgw_spi_target);
|
||||
CHECK_NULL(data);
|
||||
|
||||
spi_device = *(int *)lgw_spi_target; /* must check that spi_target is not null beforehand */
|
||||
|
||||
/* prepare frame to be sent */
|
||||
out_buf[0] = (rf_chain == 0) ? LGW_SPI_MUX_TARGET_RADIOA : LGW_SPI_MUX_TARGET_RADIOB;
|
||||
out_buf[1] = (uint8_t)op_code;
|
||||
for(i = 0; i < (int)size; i++) {
|
||||
out_buf[cmd_size + i] = data[i];
|
||||
}
|
||||
command_size = cmd_size + size;
|
||||
|
||||
/* 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 = command_size;
|
||||
k.cs_change = 0;
|
||||
a = ioctl(spi_device, SPI_IOC_MESSAGE(1), &k);
|
||||
|
||||
/* determine return code */
|
||||
if (a != (int)k.len) {
|
||||
DEBUG_MSG("ERROR: SPI READ FAILURE\n");
|
||||
return LGW_SPI_ERROR;
|
||||
} else {
|
||||
DEBUG_MSG("Note: SPI read success\n");
|
||||
//*data = in_buf[command_size - 1];
|
||||
memcpy(data, in_buf + cmd_size, size);
|
||||
return LGW_SPI_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
int sx1250_calibrate(uint8_t rf_chain, uint32_t freq_hz) {
|
||||
uint8_t buff[16];
|
||||
|
||||
buff[0] = 0x00;
|
||||
sx1250_read_command(rf_chain, GET_STATUS, buff, 1);
|
||||
|
||||
/* Run calibration */
|
||||
if ((freq_hz > 430E6) && (freq_hz < 440E6)) {
|
||||
buff[0] = 0x6B;
|
||||
buff[1] = 0x6F;
|
||||
} else if ((freq_hz > 470E6) && (freq_hz < 510E6)) {
|
||||
buff[0] = 0x75;
|
||||
buff[1] = 0x81;
|
||||
} else if ((freq_hz > 779E6) && (freq_hz < 787E6)) {
|
||||
buff[0] = 0xC1;
|
||||
buff[1] = 0xC5;
|
||||
} else if ((freq_hz > 863E6) && (freq_hz < 870E6)) {
|
||||
buff[0] = 0xD7;
|
||||
buff[1] = 0xDB;
|
||||
} else if ((freq_hz > 902E6) && (freq_hz < 928E6)) {
|
||||
buff[0] = 0xE1;
|
||||
buff[1] = 0xE9;
|
||||
} else {
|
||||
printf("ERROR: failed to calibrate sx1250 radio, frequency range not supported (%u)\n", freq_hz);
|
||||
return -1;
|
||||
}
|
||||
sx1250_write_command(rf_chain, CALIBRATE_IMAGE, buff, 2);
|
||||
|
||||
/* Wait for calibration to complete */
|
||||
wait_ms(10);
|
||||
|
||||
buff[0] = 0x00;
|
||||
buff[1] = 0x00;
|
||||
buff[2] = 0x00;
|
||||
sx1250_read_command(rf_chain, GET_DEVICE_ERRORS, buff, 3);
|
||||
if (TAKE_N_BITS_FROM(buff[2], 4, 1) != 0) {
|
||||
printf("ERROR: sx1250 Image Calibration Error\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
int sx1250_setup(uint8_t rf_chain, uint32_t freq_hz) {
|
||||
int32_t freq_reg;
|
||||
uint8_t buff[16];
|
||||
|
||||
/* Set Radio in Standby mode */
|
||||
buff[0] = (uint8_t)STDBY_XOSC;
|
||||
sx1250_write_command(rf_chain, SET_STANDBY, buff, 1);
|
||||
wait_ms(10);
|
||||
|
||||
buff[0] = 0x00;
|
||||
sx1250_read_command(rf_chain, GET_STATUS, buff, 1);
|
||||
|
||||
/* Set Bitrate to maximum (to lower TX to FS switch time) */
|
||||
buff[0] = 0x06;
|
||||
buff[1] = 0xA1;
|
||||
buff[2] = 0x01;
|
||||
sx1250_write_command(rf_chain, WRITE_REGISTER, buff, 3);
|
||||
buff[0] = 0x06;
|
||||
buff[1] = 0xA2;
|
||||
buff[2] = 0x00;
|
||||
sx1250_write_command(rf_chain, WRITE_REGISTER, buff, 3);
|
||||
buff[0] = 0x06;
|
||||
buff[1] = 0xA3;
|
||||
buff[2] = 0x00;
|
||||
sx1250_write_command(rf_chain, WRITE_REGISTER, buff, 3);
|
||||
|
||||
/* Configure DIO for Rx */
|
||||
buff[0] = 0x05;
|
||||
buff[1] = 0x82;
|
||||
buff[2] = 0x00;
|
||||
sx1250_write_command(rf_chain, WRITE_REGISTER, buff, 3); /* Drive strength to min */
|
||||
buff[0] = 0x05;
|
||||
buff[1] = 0x83;
|
||||
buff[2] = 0x00;
|
||||
sx1250_write_command(rf_chain, WRITE_REGISTER, buff, 3); /* Input enable, all disabled */
|
||||
buff[0] = 0x05;
|
||||
buff[1] = 0x84;
|
||||
buff[2] = 0x00;
|
||||
sx1250_write_command(rf_chain, WRITE_REGISTER, buff, 3); /* No pull up */
|
||||
buff[0] = 0x05;
|
||||
buff[1] = 0x85;
|
||||
buff[2] = 0x00;
|
||||
sx1250_write_command(rf_chain, WRITE_REGISTER, buff, 3); /* No pull down */
|
||||
buff[0] = 0x05;
|
||||
buff[1] = 0x80;
|
||||
buff[2] = 0x00;
|
||||
sx1250_write_command(rf_chain, WRITE_REGISTER, buff, 3); /* Output enable, all enabled */
|
||||
|
||||
/* Set fix gain (??) */
|
||||
buff[0] = 0x08;
|
||||
buff[1] = 0xB6;
|
||||
buff[2] = 0x2A;
|
||||
sx1250_write_command(rf_chain, WRITE_REGISTER, buff, 3);
|
||||
|
||||
/* Set frequency */
|
||||
freq_reg = SX1250_FREQ_TO_REG(freq_hz);
|
||||
buff[0] = (uint8_t)(freq_reg >> 24);
|
||||
buff[1] = (uint8_t)(freq_reg >> 16);
|
||||
buff[2] = (uint8_t)(freq_reg >> 8);
|
||||
buff[3] = (uint8_t)(freq_reg >> 0);
|
||||
sx1250_write_command(rf_chain, SET_RF_FREQUENCY, buff, 4);
|
||||
|
||||
/* Set frequency offset to 0 */
|
||||
buff[0] = 0x08;
|
||||
buff[1] = 0x8F;
|
||||
buff[2] = 0x00;
|
||||
buff[3] = 0x00;
|
||||
buff[4] = 0x00;
|
||||
sx1250_write_command(rf_chain, WRITE_REGISTER, buff, 5);
|
||||
|
||||
/* Set Radio in Rx mode, necessary to give a clock to SX1302 */
|
||||
buff[0] = 0xFF;
|
||||
buff[1] = 0xFF;
|
||||
buff[2] = 0xFF;
|
||||
sx1250_write_command(rf_chain, SET_RX, buff, 3); /* Rx Continuous */
|
||||
|
||||
buff[0] = 0x05;
|
||||
buff[1] = 0x87;
|
||||
buff[2] = 0x0B;
|
||||
sx1250_write_command(rf_chain, WRITE_REGISTER, buff, 3); /* FPGA_MODE_RX */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
|
@ -0,0 +1,384 @@
|
|||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2019 Semtech
|
||||
|
||||
Description:
|
||||
Functions used to handle LoRa concentrator SX1255/SX1257 radios.
|
||||
|
||||
License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*/
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- DEPENDANCIES --------------------------------------------------------- */
|
||||
|
||||
#include <stdint.h> /* C99 types */
|
||||
#include <stdbool.h> /* bool type */
|
||||
#include <stdio.h> /* printf fprintf */
|
||||
#include <string.h> /* memset */
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/spi/spidev.h>
|
||||
|
||||
#include "loragw_sx125x.h"
|
||||
#include "loragw_spi.h"
|
||||
#include "loragw_aux.h"
|
||||
#include "loragw_reg.h"
|
||||
#include "loragw_hal.h"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE MACROS ------------------------------------------------------- */
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
|
||||
#if DEBUG_RAD == 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 -------------------------------------------------------- */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE CONSTANTS ---------------------------------------------------- */
|
||||
|
||||
#define PLL_LOCK_MAX_ATTEMPTS 5
|
||||
|
||||
#define READ_ACCESS 0x00
|
||||
#define WRITE_ACCESS 0x80
|
||||
|
||||
static const struct radio_reg_s sx125x_regs[RADIO_TOTALREGS] = {
|
||||
{0,0,8}, /* MODE */
|
||||
{0,3,1}, /* MODE__PA_DRIVER_EN */
|
||||
{0,2,1}, /* MODE__TX_EN */
|
||||
{0,1,1}, /* MODE__RX_EN */
|
||||
{0,0,1}, /* MODE__STANDBY_EN */
|
||||
{1,0,8}, /* FRF_RX_MSB */
|
||||
{2,0,8}, /* FRF_RX_MID */
|
||||
{3,0,8}, /* FRF_RX_LSB */
|
||||
{4,0,8}, /* FRF_TX_MSB */
|
||||
{5,0,8}, /* FRF_TX_MID */
|
||||
{6,0,8}, /* FRF_TX_LSB */
|
||||
{7,0,8}, /* VERSION */
|
||||
{8,0,8}, /* TX_GAIN */
|
||||
{8,4,3}, /* TX_GAIN__DAC_GAIN */
|
||||
{8,0,4}, /* TX_GAIN__MIX_GAIN */
|
||||
{10,0,8}, /* TX_BW */
|
||||
{10,5,2}, /* TX_BW__PLL_BW */
|
||||
{10,0,5}, /* TX_BW__ANA_BW */
|
||||
{11,0,8}, /* TX_DAC_BW */
|
||||
{12,0,8}, /* RX_ANA_GAIN */
|
||||
{12,5,3}, /* RX_ANA_GAIN__LNA_GAIN */
|
||||
{12,1,4}, /* RX_ANA_GAIN__BB_GAIN */
|
||||
{12,0,1}, /* RX_ANA_GAIN__LNA_ZIN */
|
||||
{13,0,8}, /* RX_BW */
|
||||
{13,5,3}, /* RX_BW__ADC_BW */
|
||||
{13,2,3}, /* RX_BW__ADC_TRIM */
|
||||
{13,0,2}, /* RX_BW__BB_BW */
|
||||
{14,0,8}, /* RX_PLL_BW */
|
||||
{14,1,2}, /* RX_PLL_BW__PLL_BW */
|
||||
{14,0,1}, /* RX_PLL_BW__ADC_TEMP_EN */
|
||||
{15,0,8}, /* DIO_MAPPING */
|
||||
{15,6,2}, /* DIO_MAPPING__DIO_0_MAPPING */
|
||||
{15,4,2}, /* DIO_MAPPING__DIO_1_MAPPING */
|
||||
{15,2,2}, /* DIO_MAPPING__DIO_2_MAPPING */
|
||||
{15,0,2}, /* DIO_MAPPING__DIO_3_MAPPING */
|
||||
{16,0,8}, /* CLK_SELECT */
|
||||
{16,3,1}, /* CLK_SELECT__DIG_LOOPBACK_EN */
|
||||
{16,2,1}, /* CLK_SELECT__RF_LOOPBACK_EN */
|
||||
{16,1,1}, /* CLK_SELECT__CLK_OUT */
|
||||
{16,0,1}, /* CLK_SELECT__DAC_CLK_SELECT */
|
||||
{17,0,8}, /* MODE_STATUS */
|
||||
{17,2,1}, /* MODE_STATUS__LOW_BAT_EN */
|
||||
{17,1,1}, /* MODE_STATUS__RX_PLL_LOCKED */
|
||||
{17,0,1}, /* MODE_STATUS__TX_PLL_LOCKED */
|
||||
{26,0,8}, /* LOW_BAT_THRESH */
|
||||
{38,0,8}, /* SX1257_XOSC_TEST */
|
||||
{38,4,3}, /* SX1257_XOSC_TEST__DISABLE */
|
||||
{38,0,4}, /* SX1257_XOSC_TEST__GM_STARTUP */
|
||||
{40,0,8}, /* SX1255_XOSC_TEST */
|
||||
{40,4,3}, /* SX1255_XOSC_TEST__DISABLE */
|
||||
{40,0,4} /* SX1255_XOSC_TEST__GM_STARTUP */
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE VARIABLES ---------------------------------------------------- */
|
||||
|
||||
extern void *lgw_spi_target; /*! generic pointer to the SPI device */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE FUNCTIONS ---------------------------------------------------- */
|
||||
|
||||
/* Simple read */
|
||||
int sx125x_reg_r(void *spi_target, uint8_t spi_mux_target, uint8_t address, uint8_t *data) {
|
||||
int spi_device;
|
||||
uint8_t out_buf[3];
|
||||
uint8_t command_size;
|
||||
uint8_t in_buf[ARRAY_SIZE(out_buf)];
|
||||
struct spi_ioc_transfer k;
|
||||
int a;
|
||||
|
||||
/* check input variables */
|
||||
CHECK_NULL(spi_target);
|
||||
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] = spi_mux_target;
|
||||
out_buf[1] = READ_ACCESS | (address & 0x7F);
|
||||
out_buf[2] = 0x00;
|
||||
command_size = 3;
|
||||
|
||||
/* 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 = command_size;
|
||||
k.cs_change = 0;
|
||||
a = ioctl(spi_device, SPI_IOC_MESSAGE(1), &k);
|
||||
|
||||
/* determine return code */
|
||||
if (a != (int)k.len) {
|
||||
DEBUG_MSG("ERROR: SPI READ FAILURE\n");
|
||||
return LGW_SPI_ERROR;
|
||||
} else {
|
||||
//DEBUG_MSG("Note: SPI read success\n");
|
||||
*data = in_buf[command_size - 1];
|
||||
return LGW_SPI_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
int sx125x_reg_w(void *spi_target, uint8_t spi_mux_target, uint8_t address, uint8_t data) {
|
||||
int spi_device;
|
||||
uint8_t out_buf[3];
|
||||
uint8_t command_size;
|
||||
struct spi_ioc_transfer k;
|
||||
int a;
|
||||
|
||||
/* check input variables */
|
||||
CHECK_NULL(spi_target);
|
||||
|
||||
spi_device = *(int *)spi_target; /* must check that spi_target is not null beforehand */
|
||||
|
||||
/* prepare frame to be sent */
|
||||
out_buf[0] = spi_mux_target;
|
||||
out_buf[1] = WRITE_ACCESS | (address & 0x7F);
|
||||
out_buf[2] = data;
|
||||
command_size = 3;
|
||||
|
||||
/* I/O transaction */
|
||||
memset(&k, 0, sizeof(k)); /* clear k */
|
||||
k.tx_buf = (unsigned long) out_buf;
|
||||
k.len = command_size;
|
||||
k.speed_hz = SPI_SPEED;
|
||||
k.cs_change = 0;
|
||||
k.bits_per_word = 8;
|
||||
a = ioctl(spi_device, SPI_IOC_MESSAGE(1), &k);
|
||||
|
||||
/* determine return code */
|
||||
if (a != (int)k.len) {
|
||||
DEBUG_MSG("ERROR: SPI WRITE FAILURE\n");
|
||||
return LGW_SPI_ERROR;
|
||||
} else {
|
||||
//DEBUG_MSG("Note: SPI write success\n");
|
||||
return LGW_SPI_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
int lgw_sx125x_reg_w(radio_reg_t idx, uint8_t data, uint8_t rf_chain) {
|
||||
|
||||
int spi_stat;
|
||||
struct radio_reg_s reg;
|
||||
uint8_t mask;
|
||||
uint8_t r;
|
||||
uint8_t w;
|
||||
uint8_t val_check;
|
||||
|
||||
/* checking input parameters */
|
||||
if (rf_chain >= LGW_RF_CHAIN_NB) {
|
||||
DEBUG_MSG("ERROR: INVALID RF_CHAIN\n");
|
||||
return LGW_REG_ERROR;
|
||||
}
|
||||
if (idx >= RADIO_TOTALREGS) {
|
||||
DEBUG_MSG("ERROR: REGISTER NUMBER OUT OF DEFINED RANGE\n");
|
||||
return LGW_REG_ERROR;
|
||||
}
|
||||
|
||||
reg = sx125x_regs[idx];
|
||||
|
||||
if ((reg.leng == 8) && (reg.offs == 0)){
|
||||
/* direct write */
|
||||
spi_stat = sx125x_reg_w(lgw_spi_target, ((rf_chain == 0) ? LGW_SPI_MUX_TARGET_RADIOA : LGW_SPI_MUX_TARGET_RADIOB), reg.addr, data);
|
||||
} else {
|
||||
/* read-modify-write */
|
||||
spi_stat = sx125x_reg_r(lgw_spi_target, ((rf_chain == 0) ? LGW_SPI_MUX_TARGET_RADIOA : LGW_SPI_MUX_TARGET_RADIOB), reg.addr, &r);
|
||||
mask = ((1 << reg.leng) - 1) << reg.offs;
|
||||
w = (r & ~mask) | ((data << reg.offs) & mask);
|
||||
spi_stat |= sx125x_reg_w(lgw_spi_target, ((rf_chain == 0) ? LGW_SPI_MUX_TARGET_RADIOA : LGW_SPI_MUX_TARGET_RADIOB), reg.addr, w);
|
||||
}
|
||||
|
||||
/* Check that we can read what we have written */
|
||||
lgw_sx125x_reg_r(idx, &val_check, rf_chain);
|
||||
if (val_check != data) {
|
||||
printf("ERROR: sx125x register %d write failed (w:%u r:%u)!!\n", idx, data, val_check);
|
||||
spi_stat = LGW_SPI_ERROR;
|
||||
}
|
||||
|
||||
if (spi_stat != LGW_SPI_SUCCESS) {
|
||||
DEBUG_MSG("ERROR: SPI ERROR DURING RADIO REGISTER WRITE\n");
|
||||
return LGW_REG_ERROR;
|
||||
} else {
|
||||
return LGW_REG_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
int lgw_sx125x_reg_r(radio_reg_t idx, uint8_t *data, uint8_t rf_chain) {
|
||||
|
||||
int spi_stat;
|
||||
struct radio_reg_s reg;
|
||||
uint8_t mask;
|
||||
uint8_t r;
|
||||
|
||||
/* checking input parameters */
|
||||
if (rf_chain >= LGW_RF_CHAIN_NB) {
|
||||
DEBUG_MSG("ERROR: INVALID RF_CHAIN\n");
|
||||
return LGW_REG_ERROR;
|
||||
}
|
||||
if (idx >= RADIO_TOTALREGS) {
|
||||
DEBUG_MSG("ERROR: REGISTER NUMBER OUT OF DEFINED RANGE\n");
|
||||
return LGW_REG_ERROR;
|
||||
}
|
||||
|
||||
reg = sx125x_regs[idx];
|
||||
|
||||
spi_stat = sx125x_reg_r(lgw_spi_target, ((rf_chain == 0) ? LGW_SPI_MUX_TARGET_RADIOA : LGW_SPI_MUX_TARGET_RADIOB), reg.addr, &r);
|
||||
mask = ((1 << reg.leng) - 1) << reg.offs;
|
||||
*data = (r & mask) >> reg.offs;
|
||||
|
||||
if (spi_stat != LGW_SPI_SUCCESS) {
|
||||
DEBUG_MSG("ERROR: SPI ERROR DURING RADIO REGISTER READ\n");
|
||||
return LGW_REG_ERROR;
|
||||
} else {
|
||||
return LGW_REG_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE FUNCTIONS DEFINITION ----------------------------------------- */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PUBLIC FUNCTIONS DEFINITION ------------------------------------------ */
|
||||
|
||||
int sx125x_setup(uint8_t rf_chain, uint8_t rf_clkout, bool rf_enable, uint8_t rf_radio_type, uint32_t freq_hz) {
|
||||
uint32_t part_int = 0;
|
||||
uint32_t part_frac = 0;
|
||||
int cpt_attempts = 0;
|
||||
uint8_t val;
|
||||
|
||||
if (rf_chain >= LGW_RF_CHAIN_NB) {
|
||||
DEBUG_MSG("ERROR: INVALID RF_CHAIN\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Get version to identify SX1255/57 silicon revision */
|
||||
lgw_sx125x_reg_r(SX125x_REG_VERSION, &val, rf_chain);
|
||||
DEBUG_PRINTF("Note: SX125x #%d version register returned 0x%02x\n", rf_chain, val);
|
||||
|
||||
/* General radio setup */
|
||||
if (rf_clkout == rf_chain) {
|
||||
lgw_sx125x_reg_w(SX125x_REG_CLK_SELECT, SX125x_TX_DAC_CLK_SEL + 2, rf_chain);
|
||||
DEBUG_PRINTF("Note: SX125x #%d clock output enabled\n", rf_chain);
|
||||
} else {
|
||||
lgw_sx125x_reg_w(SX125x_REG_CLK_SELECT, SX125x_TX_DAC_CLK_SEL, rf_chain);
|
||||
DEBUG_PRINTF("Note: SX125x #%d clock output disabled\n", rf_chain);
|
||||
}
|
||||
|
||||
switch (rf_radio_type) {
|
||||
case LGW_RADIO_TYPE_SX1255:
|
||||
lgw_sx125x_reg_w(SX125x_REG_SX1255_XOSC_TEST__GM_STARTUP, SX125x_XOSC_GM_STARTUP, rf_chain);
|
||||
lgw_sx125x_reg_w(SX125x_REG_SX1255_XOSC_TEST__DISABLE, SX125x_XOSC_DISABLE, rf_chain);
|
||||
break;
|
||||
case LGW_RADIO_TYPE_SX1257:
|
||||
lgw_sx125x_reg_w(SX125x_REG_SX1257_XOSC_TEST__GM_STARTUP, SX125x_XOSC_GM_STARTUP, rf_chain);
|
||||
lgw_sx125x_reg_w(SX125x_REG_SX1257_XOSC_TEST__DISABLE, SX125x_XOSC_DISABLE, rf_chain);
|
||||
break;
|
||||
default:
|
||||
DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d FOR RADIO TYPE\n", rf_radio_type);
|
||||
break;
|
||||
}
|
||||
|
||||
if (rf_enable == true) {
|
||||
/* Tx gain and trim */
|
||||
lgw_sx125x_reg_w(SX125x_REG_TX_GAIN__MIX_GAIN, SX125x_TX_MIX_GAIN, rf_chain);
|
||||
lgw_sx125x_reg_w(SX125x_REG_TX_GAIN__DAC_GAIN, SX125x_TX_DAC_GAIN, rf_chain);
|
||||
|
||||
lgw_sx125x_reg_w(SX125x_REG_TX_BW__ANA_BW, SX125x_TX_ANA_BW, rf_chain);
|
||||
lgw_sx125x_reg_w(SX125x_REG_TX_BW__PLL_BW, SX125x_TX_PLL_BW, rf_chain);
|
||||
|
||||
lgw_sx125x_reg_w(SX125x_REG_TX_DAC_BW, SX125x_TX_DAC_BW, rf_chain);
|
||||
|
||||
/* Rx gain and trim */
|
||||
lgw_sx125x_reg_w(SX125x_REG_RX_ANA_GAIN__LNA_ZIN, SX125x_LNA_ZIN, rf_chain);
|
||||
lgw_sx125x_reg_w(SX125x_REG_RX_ANA_GAIN__BB_GAIN, SX125x_RX_BB_GAIN, rf_chain);
|
||||
lgw_sx125x_reg_w(SX125x_REG_RX_ANA_GAIN__LNA_GAIN, SX125x_RX_LNA_GAIN, rf_chain);
|
||||
|
||||
lgw_sx125x_reg_w(SX125x_REG_RX_BW__BB_BW, SX125x_RX_BB_BW, rf_chain);
|
||||
lgw_sx125x_reg_w(SX125x_REG_RX_BW__ADC_TRIM, SX125x_RX_ADC_TRIM, rf_chain);
|
||||
lgw_sx125x_reg_w(SX125x_REG_RX_BW__ADC_BW, SX125x_RX_ADC_BW, rf_chain);
|
||||
|
||||
lgw_sx125x_reg_w(SX125x_REG_RX_PLL_BW__ADC_TEMP_EN, SX125x_ADC_TEMP, rf_chain);
|
||||
lgw_sx125x_reg_w(SX125x_REG_RX_PLL_BW__PLL_BW, SX125x_RX_PLL_BW, rf_chain);
|
||||
|
||||
/* set RX PLL frequency */
|
||||
switch (rf_radio_type) {
|
||||
case LGW_RADIO_TYPE_SX1255:
|
||||
part_int = freq_hz / (SX125x_32MHz_FRAC << 7); /* integer part, gives the MSB */
|
||||
part_frac = ((freq_hz % (SX125x_32MHz_FRAC << 7)) << 9) / SX125x_32MHz_FRAC; /* fractional part, gives middle part and LSB */
|
||||
break;
|
||||
case LGW_RADIO_TYPE_SX1257:
|
||||
part_int = freq_hz / (SX125x_32MHz_FRAC << 8); /* integer part, gives the MSB */
|
||||
part_frac = ((freq_hz % (SX125x_32MHz_FRAC << 8)) << 8) / SX125x_32MHz_FRAC; /* fractional part, gives middle part and LSB */
|
||||
break;
|
||||
default:
|
||||
DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d FOR RADIO TYPE\n", rf_radio_type);
|
||||
break;
|
||||
}
|
||||
|
||||
lgw_sx125x_reg_w(SX125x_REG_FRF_RX_MSB, 0xFF & part_int, rf_chain);
|
||||
lgw_sx125x_reg_w(SX125x_REG_FRF_RX_MID, 0xFF & (part_frac >> 8), rf_chain);
|
||||
lgw_sx125x_reg_w(SX125x_REG_FRF_RX_LSB, 0xFF & part_frac, rf_chain);
|
||||
|
||||
/* start and PLL lock */
|
||||
do {
|
||||
if (cpt_attempts >= PLL_LOCK_MAX_ATTEMPTS) {
|
||||
DEBUG_MSG("ERROR: FAIL TO LOCK PLL\n");
|
||||
return -1;
|
||||
}
|
||||
lgw_sx125x_reg_w(SX125x_REG_MODE, 1, rf_chain);
|
||||
lgw_sx125x_reg_w(SX125x_REG_MODE, 3, rf_chain);
|
||||
++cpt_attempts;
|
||||
DEBUG_PRINTF("Note: SX125x #%d PLL start (attempt %d)\n", rf_chain, cpt_attempts);
|
||||
wait_ms(1);
|
||||
lgw_sx125x_reg_r(SX125x_REG_MODE_STATUS, &val, rf_chain);
|
||||
} while ((val & 0x02) == 0);
|
||||
} else {
|
||||
DEBUG_PRINTF("Note: SX125x #%d kept in standby mode\n", rf_chain);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,370 @@
|
|||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2019 Semtech
|
||||
|
||||
Description:
|
||||
SX1302 RX buffer Hardware Abstraction Layer
|
||||
|
||||
License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*/
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- DEPENDANCIES --------------------------------------------------------- */
|
||||
|
||||
#include <stdint.h> /* C99 types */
|
||||
#include <stdio.h> /* printf fprintf */
|
||||
#include <string.h> /* memset */
|
||||
#include <assert.h> /* assert */
|
||||
|
||||
#include "loragw_aux.h"
|
||||
#include "loragw_reg.h"
|
||||
#include "loragw_sx1302_rx.h"
|
||||
#include "loragw_sx1302_timestamp.h"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE MACROS ------------------------------------------------------- */
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
|
||||
#if DEBUG_SX1302 == 1
|
||||
#define DEBUG_MSG(str) fprintf(stderr, str)
|
||||
#define DEBUG_PRINTF(fmt, args...) fprintf(stderr, fmt, 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
|
||||
|
||||
#define SX1302_PKT_PAYLOAD_LENGTH(buffer, start_index) TAKE_N_BITS_FROM(buffer[start_index + 2], 0, 8)
|
||||
#define SX1302_PKT_CHANNEL(buffer, start_index) TAKE_N_BITS_FROM(buffer[start_index + 3], 0, 8)
|
||||
#define SX1302_PKT_CRC_EN(buffer, start_index) TAKE_N_BITS_FROM(buffer[start_index + 4], 0, 1)
|
||||
#define SX1302_PKT_CODING_RATE(buffer, start_index) TAKE_N_BITS_FROM(buffer[start_index + 4], 1, 3)
|
||||
#define SX1302_PKT_DATARATE(buffer, start_index) TAKE_N_BITS_FROM(buffer[start_index + 4], 4, 4)
|
||||
#define SX1302_PKT_MODEM_ID(buffer, start_index) TAKE_N_BITS_FROM(buffer[start_index + 5], 0, 8)
|
||||
#define SX1302_PKT_FREQ_OFFSET_7_0(buffer, start_index) TAKE_N_BITS_FROM(buffer[start_index + 6], 0, 8)
|
||||
#define SX1302_PKT_FREQ_OFFSET_15_8(buffer, start_index) TAKE_N_BITS_FROM(buffer[start_index + 7], 0, 8)
|
||||
#define SX1302_PKT_FREQ_OFFSET_19_16(buffer, start_index) TAKE_N_BITS_FROM(buffer[start_index + 8], 0, 4)
|
||||
#define SX1302_PKT_CRC_ERROR(buffer, start_index) TAKE_N_BITS_FROM(buffer[start_index + 9], 0, 1)
|
||||
#define SX1302_PKT_SYNC_ERROR(buffer, start_index) TAKE_N_BITS_FROM(buffer[start_index + 9], 2, 1)
|
||||
#define SX1302_PKT_HEADER_ERROR(buffer, start_index) TAKE_N_BITS_FROM(buffer[start_index + 9], 3, 1)
|
||||
#define SX1302_PKT_TIMING_SET(buffer, start_index) TAKE_N_BITS_FROM(buffer[start_index + 9], 4, 1)
|
||||
#define SX1302_PKT_SNR_AVG(buffer, start_index) TAKE_N_BITS_FROM(buffer[start_index + 10], 0, 8)
|
||||
#define SX1302_PKT_RSSI_CHAN(buffer, start_index) TAKE_N_BITS_FROM(buffer[start_index + 11], 0, 8)
|
||||
#define SX1302_PKT_RSSI_SIG(buffer, start_index) TAKE_N_BITS_FROM(buffer[start_index + 12], 0, 8)
|
||||
#define SX1302_PKT_RSSI_CHAN_MAX_NEG_DELTA(buffer, start_index) TAKE_N_BITS_FROM(buffer[start_index + 13], 0, 4)
|
||||
#define SX1302_PKT_RSSI_CHAN_MAX_POS_DELTA(buffer, start_index) TAKE_N_BITS_FROM(buffer[start_index + 13], 4, 4)
|
||||
#define SX1302_PKT_RSSI_SIG_MAX_NEG_DELTA(buffer, start_index) TAKE_N_BITS_FROM(buffer[start_index + 14], 0, 4)
|
||||
#define SX1302_PKT_RSSI_SIG_MAX_POS_DELTA(buffer, start_index) TAKE_N_BITS_FROM(buffer[start_index + 14], 4, 4)
|
||||
#define SX1302_PKT_TIMESTAMP_7_0(buffer, start_index) TAKE_N_BITS_FROM(buffer[start_index + 15], 0, 8)
|
||||
#define SX1302_PKT_TIMESTAMP_15_8(buffer, start_index) TAKE_N_BITS_FROM(buffer[start_index + 16], 0, 8)
|
||||
#define SX1302_PKT_TIMESTAMP_23_16(buffer, start_index) TAKE_N_BITS_FROM(buffer[start_index + 17], 0, 8)
|
||||
#define SX1302_PKT_TIMESTAMP_31_24(buffer, start_index) TAKE_N_BITS_FROM(buffer[start_index + 18], 0, 8)
|
||||
#define SX1302_PKT_CRC_PAYLOAD_7_0(buffer, start_index) TAKE_N_BITS_FROM(buffer[start_index + 19], 0, 8)
|
||||
#define SX1302_PKT_CRC_PAYLOAD_15_8(buffer, start_index) TAKE_N_BITS_FROM(buffer[start_index + 20], 0, 8)
|
||||
#define SX1302_PKT_NUM_TS_METRICS(buffer, start_index) TAKE_N_BITS_FROM(buffer[start_index + 21], 0, 8)
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE TYPES -------------------------------------------------------- */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE CONSTANTS ---------------------------------------------------- */
|
||||
|
||||
/* RX buffer packet structure */
|
||||
#define SX1302_PKT_SYNCWORD_BYTE_0 0xA5
|
||||
#define SX1302_PKT_SYNCWORD_BYTE_1 0xC0
|
||||
#define SX1302_PKT_HEAD_METADATA 9
|
||||
#define SX1302_PKT_TAIL_METADATA 14
|
||||
|
||||
/* modem IDs */
|
||||
#if FPGA_BOARD_16_CH
|
||||
#define SX1302_LORA_MODEM_ID_MAX 15
|
||||
#define SX1302_LORA_STD_MODEM_ID 16
|
||||
#define SX1302_FSK_MODEM_ID 17
|
||||
#else
|
||||
#define SX1302_LORA_MODEM_ID_MAX 11
|
||||
#define SX1302_LORA_STD_MODEM_ID 12
|
||||
#define SX1302_FSK_MODEM_ID 13
|
||||
#endif
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE VARIABLES ---------------------------------------------------- */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE FUNCTIONS DECLARATION ---------------------------------------- */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- INTERNAL SHARED VARIABLES -------------------------------------------- */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE FUNCTIONS DEFINITION ----------------------------------------- */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PUBLIC FUNCTIONS DEFINITION ------------------------------------------ */
|
||||
|
||||
int rx_buffer_new(rx_buffer_t * self) {
|
||||
/* Check input params */
|
||||
CHECK_NULL(self);
|
||||
|
||||
/* Initialize members */
|
||||
memset(self->buffer, 0, sizeof self->buffer);
|
||||
self->buffer_size = 0;
|
||||
self->buffer_index = 0;
|
||||
|
||||
return LGW_REG_SUCCESS;
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
int rx_buffer_del(rx_buffer_t * self) {
|
||||
/* Check input params */
|
||||
CHECK_NULL(self);
|
||||
|
||||
/* Reset index & size */
|
||||
self->buffer_size = 0;
|
||||
self->buffer_index = 0;
|
||||
|
||||
return LGW_REG_SUCCESS;
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
int rx_buffer_fetch(rx_buffer_t * self) {
|
||||
int i, res;
|
||||
uint8_t buff[2];
|
||||
|
||||
/* Check input params */
|
||||
CHECK_NULL(self);
|
||||
|
||||
/* Check if there is data in the FIFO */
|
||||
lgw_reg_rb(SX1302_REG_RX_TOP_RX_BUFFER_NB_BYTES_MSB_RX_BUFFER_NB_BYTES, buff, sizeof buff);
|
||||
self->buffer_size = (uint16_t)((buff[0] << 8) & 0xFF00);
|
||||
self->buffer_size |= (uint16_t)((buff[1] << 0) & 0x00FF);
|
||||
|
||||
/* Fetch bytes from fifo if any */
|
||||
if (self->buffer_size > 0) {
|
||||
DEBUG_MSG ("-----------------\n");
|
||||
DEBUG_PRINTF("%s: nb_bytes to be fetched: %u (%u %u)\n", __FUNCTION__, self->buffer_size, buff[1], buff[0]);
|
||||
|
||||
memset(self->buffer, 0, sizeof self->buffer);
|
||||
res = lgw_mem_rb(0x4000, self->buffer, self->buffer_size, true);
|
||||
if (res != LGW_REG_SUCCESS) {
|
||||
printf("ERROR: Failed to read RX buffer, SPI error\n");
|
||||
return LGW_REG_ERROR;
|
||||
}
|
||||
|
||||
/* print debug info : TODO to be removed */
|
||||
DEBUG_MSG("RX_BUFFER: ");
|
||||
for (i = 0; i < self->buffer_size; i++) {
|
||||
DEBUG_PRINTF("%02X ", self->buffer[i]);
|
||||
}
|
||||
DEBUG_MSG("\n");
|
||||
|
||||
}
|
||||
|
||||
/* Initialize the current buffer index to iterate on */
|
||||
self->buffer_index = 0;
|
||||
|
||||
return LGW_REG_SUCCESS;
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
int rx_buffer_pop(rx_buffer_t * self, rx_packet_t * pkt) {
|
||||
int i;
|
||||
uint8_t checksum_rcv, checksum_calc = 0;
|
||||
uint16_t checksum_idx;
|
||||
uint16_t pkt_num_bytes;
|
||||
|
||||
/* Check input params */
|
||||
CHECK_NULL(self);
|
||||
CHECK_NULL(pkt);
|
||||
|
||||
/* Is there any data to be parsed ? */
|
||||
if (self->buffer_index >= self->buffer_size) {
|
||||
DEBUG_MSG("INFO: No more data to be parsed\n");
|
||||
return LGW_REG_ERROR;
|
||||
}
|
||||
|
||||
/* Get pkt sync words */
|
||||
if ((self->buffer[self->buffer_index] != SX1302_PKT_SYNCWORD_BYTE_0) || (self->buffer[self->buffer_index + 1] != SX1302_PKT_SYNCWORD_BYTE_1)) {
|
||||
printf("INFO: searching syncword...\n");
|
||||
self->buffer_index += 1;
|
||||
return LGW_REG_ERROR;
|
||||
/* TODO: while loop until syncword found ?? */
|
||||
}
|
||||
DEBUG_PRINTF("INFO: pkt syncword found at index %u\n", self->buffer_index);
|
||||
|
||||
/* Get payload length */
|
||||
pkt->rxbytenb_modem = SX1302_PKT_PAYLOAD_LENGTH(self->buffer, self->buffer_index);
|
||||
|
||||
/* Get fine timestamp metrics */
|
||||
pkt->num_ts_metrics_stored = SX1302_PKT_NUM_TS_METRICS(self->buffer, self->buffer_index + pkt->rxbytenb_modem);
|
||||
|
||||
/* Calculate the total number of bytes in the packet */
|
||||
pkt_num_bytes = SX1302_PKT_HEAD_METADATA + pkt->rxbytenb_modem + SX1302_PKT_TAIL_METADATA + (2 * pkt->num_ts_metrics_stored);
|
||||
|
||||
/* Check if we have a complete packet in the rx buffer fetched */
|
||||
if((self->buffer_index + pkt_num_bytes) > self->buffer_size) {
|
||||
printf("WARNING: aborting truncated message (size=%u)\n", self->buffer_size);
|
||||
return LGW_REG_ERROR;
|
||||
}
|
||||
|
||||
/* Get the checksum as received in the RX buffer */
|
||||
checksum_idx = pkt_num_bytes - 1;
|
||||
checksum_rcv = self->buffer[self->buffer_index + pkt_num_bytes - 1];
|
||||
|
||||
/* Calculate the checksum from the actual payload bytes received */
|
||||
for (i = 0; i < (int)checksum_idx; i++) {
|
||||
checksum_calc += self->buffer[self->buffer_index + i];
|
||||
}
|
||||
|
||||
/* Check if the checksum is correct */
|
||||
if (checksum_rcv != checksum_calc) {
|
||||
printf("WARNING: checksum failed (got:0x%02X calc:0x%02X)\n", checksum_rcv, checksum_calc);
|
||||
return LGW_REG_ERROR;
|
||||
} else {
|
||||
DEBUG_PRINTF("Packet checksum OK (0x%02X)\n", checksum_rcv);
|
||||
}
|
||||
|
||||
/* Parse packet metadata */
|
||||
pkt->modem_id = SX1302_PKT_MODEM_ID(self->buffer, self->buffer_index);
|
||||
pkt->rx_channel_in = SX1302_PKT_CHANNEL(self->buffer, self->buffer_index);
|
||||
pkt->crc_en = SX1302_PKT_CRC_EN(self->buffer, self->buffer_index);
|
||||
pkt->payload_crc_error = SX1302_PKT_CRC_ERROR(self->buffer, self->buffer_index + pkt->rxbytenb_modem);
|
||||
pkt->sync_error = SX1302_PKT_SYNC_ERROR(self->buffer, self->buffer_index + pkt->rxbytenb_modem);
|
||||
pkt->header_error = SX1302_PKT_HEADER_ERROR(self->buffer, self->buffer_index + pkt->rxbytenb_modem);
|
||||
pkt->timing_set = SX1302_PKT_TIMING_SET(self->buffer, self->buffer_index + pkt->rxbytenb_modem);
|
||||
pkt->coding_rate = SX1302_PKT_CODING_RATE(self->buffer, self->buffer_index);
|
||||
pkt->rx_rate_sf = SX1302_PKT_DATARATE(self->buffer, self->buffer_index);
|
||||
pkt->rssi_chan_avg = SX1302_PKT_RSSI_CHAN(self->buffer, self->buffer_index + pkt->rxbytenb_modem);
|
||||
pkt->rssi_signal_avg = SX1302_PKT_RSSI_SIG(self->buffer, self->buffer_index + pkt->rxbytenb_modem);
|
||||
pkt->rx_crc16_value = (uint16_t)((SX1302_PKT_CRC_PAYLOAD_7_0(self->buffer, self->buffer_index + pkt->rxbytenb_modem) << 0) & 0x00FF);
|
||||
pkt->rx_crc16_value |= (uint16_t)((SX1302_PKT_CRC_PAYLOAD_15_8(self->buffer, self->buffer_index + pkt->rxbytenb_modem) << 8) & 0xFF00);
|
||||
pkt->snr_average = (int8_t)SX1302_PKT_SNR_AVG(self->buffer, self->buffer_index + pkt->rxbytenb_modem);
|
||||
|
||||
pkt->frequency_offset_error = (int32_t)((SX1302_PKT_FREQ_OFFSET_19_16(self->buffer, self->buffer_index) << 16) | (SX1302_PKT_FREQ_OFFSET_15_8(self->buffer, self->buffer_index) << 8) | (SX1302_PKT_FREQ_OFFSET_7_0(self->buffer, self->buffer_index) << 0));
|
||||
if (pkt->frequency_offset_error >= (1<<19)) { /* Handle signed value on 20bits */
|
||||
pkt->frequency_offset_error = (pkt->frequency_offset_error - (1<<20));
|
||||
}
|
||||
|
||||
/* Packet timestamp (32MHz ) */
|
||||
pkt->timestamp_cnt = (uint32_t)((SX1302_PKT_TIMESTAMP_7_0(self->buffer, self->buffer_index + pkt->rxbytenb_modem) << 0) & 0x000000FF);
|
||||
pkt->timestamp_cnt |= (uint32_t)((SX1302_PKT_TIMESTAMP_15_8(self->buffer, self->buffer_index + pkt->rxbytenb_modem) << 8) & 0x0000FF00);
|
||||
pkt->timestamp_cnt |= (uint32_t)((SX1302_PKT_TIMESTAMP_23_16(self->buffer, self->buffer_index + pkt->rxbytenb_modem) << 16) & 0x00FF0000);
|
||||
pkt->timestamp_cnt |= (uint32_t)((SX1302_PKT_TIMESTAMP_31_24(self->buffer, self->buffer_index + pkt->rxbytenb_modem) << 24) & 0xFF000000);
|
||||
|
||||
#if 0
|
||||
/* Scale packet timestamp to 1 MHz (microseconds) */
|
||||
pkt->timestamp_cnt /= 32;
|
||||
/* Expand 27-bits counter to 32-bits counter, based on current wrapping status */
|
||||
pkt->timestamp_cnt = timestamp_counter_expand(&counter_us, false, pkt->timestamp_cnt);
|
||||
#endif
|
||||
|
||||
DEBUG_MSG ("-----------------\n");
|
||||
DEBUG_PRINTF(" modem: %u\n", pkt->modem_id);
|
||||
DEBUG_PRINTF(" chan: %u\n", pkt->rx_channel_in);
|
||||
DEBUG_PRINTF(" size: %u\n", pkt->rxbytenb_modem);
|
||||
DEBUG_PRINTF(" crc_en: %u\n", pkt->crc_en);
|
||||
DEBUG_PRINTF(" crc_err: %u\n", pkt->payload_crc_error);
|
||||
DEBUG_PRINTF(" sync_err: %u\n", pkt->sync_error);
|
||||
DEBUG_PRINTF(" hdr_err: %u\n", pkt->header_error);
|
||||
DEBUG_PRINTF(" timing_set: %u\n", pkt->timing_set);
|
||||
DEBUG_PRINTF(" codr: %u\n", pkt->coding_rate);
|
||||
DEBUG_PRINTF(" datr: %u\n", pkt->rx_rate_sf);
|
||||
DEBUG_PRINTF(" num_ts: %u\n", pkt->num_ts_metrics_stored);
|
||||
DEBUG_MSG ("-----------------\n");
|
||||
|
||||
/* Sanity checks: check the range of few metadata */
|
||||
if (pkt->modem_id > SX1302_FSK_MODEM_ID) {
|
||||
printf("ERROR: modem_id is out of range - %u\n", pkt->modem_id);
|
||||
return LGW_REG_ERROR;
|
||||
} else {
|
||||
if (pkt->modem_id <= SX1302_LORA_STD_MODEM_ID) { /* LoRa modems */
|
||||
if (pkt->rx_channel_in > 9) {
|
||||
printf("ERROR: channel is out of range - %u\n", pkt->rx_channel_in);
|
||||
return LGW_REG_ERROR;
|
||||
}
|
||||
if ((pkt->rx_rate_sf < 5) || (pkt->rx_rate_sf > 12)) {
|
||||
printf("ERROR: SF is out of range - %u\n", pkt->rx_rate_sf);
|
||||
return LGW_REG_ERROR;
|
||||
}
|
||||
} else { /* FSK modem */
|
||||
/* TODO: not checked */
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse & copy payload in packet struct */
|
||||
memcpy((void *)pkt->payload, (void *)(&(self->buffer[self->buffer_index + SX1302_PKT_HEAD_METADATA])), pkt->rxbytenb_modem);
|
||||
|
||||
/* move buffer index toward next message */
|
||||
self->buffer_index += (SX1302_PKT_HEAD_METADATA + pkt->rxbytenb_modem + SX1302_PKT_TAIL_METADATA + (2 * pkt->num_ts_metrics_stored));
|
||||
|
||||
return LGW_REG_SUCCESS;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- DEBUG FUNCTIONS DEFINITION ------------------------------------------- */
|
||||
|
||||
uint16_t rx_buffer_read_ptr_addr(void) {
|
||||
int32_t val;
|
||||
uint16_t addr;
|
||||
|
||||
lgw_reg_r(SX1302_REG_RX_TOP_RX_BUFFER_LAST_ADDR_READ_MSB_LAST_ADDR_READ, &val); /* mandatory to read MSB first */
|
||||
addr = (uint16_t)(val << 8);
|
||||
lgw_reg_r(SX1302_REG_RX_TOP_RX_BUFFER_LAST_ADDR_READ_LSB_LAST_ADDR_READ, &val);
|
||||
addr |= (uint16_t)val;
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
uint16_t rx_buffer_write_ptr_addr(void) {
|
||||
int32_t val;
|
||||
uint16_t addr;
|
||||
|
||||
lgw_reg_r(SX1302_REG_RX_TOP_RX_BUFFER_LAST_ADDR_WRITE_MSB_LAST_ADDR_WRITE, &val); /* mandatory to read MSB first */
|
||||
addr = (uint16_t)(val << 8);
|
||||
lgw_reg_r(SX1302_REG_RX_TOP_RX_BUFFER_LAST_ADDR_WRITE_LSB_LAST_ADDR_WRITE, &val);
|
||||
addr |= (uint16_t)val;
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
void rx_buffer_dump(FILE * file, uint16_t start_addr, uint16_t end_addr) {
|
||||
int i;
|
||||
uint8_t rx_buffer_debug[4096];
|
||||
|
||||
printf("Dumping %u bytes, from 0x%X to 0x%X\n", end_addr - start_addr + 1, start_addr, end_addr);
|
||||
|
||||
memset(rx_buffer_debug, 0, sizeof rx_buffer_debug);
|
||||
|
||||
lgw_reg_w(SX1302_REG_RX_TOP_RX_BUFFER_DIRECT_RAM_IF, 1);
|
||||
lgw_mem_rb(0x4000 + start_addr, rx_buffer_debug, end_addr - start_addr + 1, false);
|
||||
lgw_reg_w(SX1302_REG_RX_TOP_RX_BUFFER_DIRECT_RAM_IF, 0);
|
||||
|
||||
for (i = 0; i < (end_addr - start_addr + 1); i++) {
|
||||
if (file == NULL) {
|
||||
printf("%02X ", rx_buffer_debug[i]);
|
||||
} else {
|
||||
fprintf(file, "%02X ", rx_buffer_debug[i]);
|
||||
}
|
||||
}
|
||||
if (file == NULL) {
|
||||
printf("\n");
|
||||
} else {
|
||||
fprintf(file, "\n");
|
||||
}
|
||||
|
||||
/* Switching to direct-access memory could lead to corruption, so to be done only for debugging */
|
||||
assert(0);
|
||||
}
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
|
@ -0,0 +1,295 @@
|
|||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2019 Semtech
|
||||
|
||||
Description:
|
||||
SX1302 timestamp counter Hardware Abstraction Layer
|
||||
Handles the conversion of a 32-bits 32MHz counter into a 32-bits 1 MHz counter.
|
||||
This modules MUST be called regularly by the application to maintain counter
|
||||
wrapping handling for conversion in 1MHz counter.
|
||||
Provides function to compute the correction to be applied to the received
|
||||
timestamp for demodulation processing time.
|
||||
|
||||
License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*/
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- DEPENDANCIES --------------------------------------------------------- */
|
||||
|
||||
#include <stdint.h> /* C99 types */
|
||||
#include <stdio.h> /* printf fprintf */
|
||||
|
||||
#include "loragw_sx1302_timestamp.h"
|
||||
#include "loragw_reg.h"
|
||||
#include "loragw_hal.h"
|
||||
#include "loragw_sx1302.h"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE MACROS ------------------------------------------------------- */
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
|
||||
#if DEBUG_SX1302 == 1
|
||||
#define DEBUG_MSG(str) fprintf(stderr, str)
|
||||
#define DEBUG_PRINTF(fmt, args...) fprintf(stderr, fmt, 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 -------------------------------------------------------- */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE CONSTANTS ---------------------------------------------------- */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE VARIABLES ---------------------------------------------------- */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE FUNCTIONS DECLARATION ---------------------------------------- */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- INTERNAL SHARED VARIABLES -------------------------------------------- */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE FUNCTIONS DEFINITION ----------------------------------------- */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PUBLIC FUNCTIONS DEFINITION ------------------------------------------ */
|
||||
|
||||
void timestamp_counter_new(timestamp_counter_t * self) {
|
||||
self->counter_us_raw_27bits_inst_prev = 0;
|
||||
self->counter_us_raw_27bits_pps_prev = 0;
|
||||
self->counter_us_raw_27bits_inst_wrap = 0;
|
||||
self->counter_us_raw_27bits_pps_wrap = 0;
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
void timestamp_counter_delete(timestamp_counter_t * self) {
|
||||
self->counter_us_raw_27bits_inst_prev = 0;
|
||||
self->counter_us_raw_27bits_pps_prev = 0;
|
||||
self->counter_us_raw_27bits_inst_wrap = 0;
|
||||
self->counter_us_raw_27bits_pps_wrap = 0;
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
void timestamp_counter_update(timestamp_counter_t * self, bool pps, uint32_t cnt) {
|
||||
uint32_t counter_us_raw_27bits_prev;
|
||||
uint8_t counter_us_raw_27bits_wrap;
|
||||
|
||||
/* Get the previous counter value and wrap status */
|
||||
if (pps == true) {
|
||||
counter_us_raw_27bits_prev = self->counter_us_raw_27bits_pps_prev;
|
||||
counter_us_raw_27bits_wrap = self->counter_us_raw_27bits_pps_wrap;
|
||||
} else {
|
||||
counter_us_raw_27bits_prev = self->counter_us_raw_27bits_inst_prev;
|
||||
counter_us_raw_27bits_wrap = self->counter_us_raw_27bits_inst_wrap;
|
||||
}
|
||||
|
||||
/* Check if counter has wrapped, and update wrap status if necessary */
|
||||
if (cnt < counter_us_raw_27bits_prev) {
|
||||
counter_us_raw_27bits_wrap += 1;
|
||||
counter_us_raw_27bits_wrap = counter_us_raw_27bits_wrap % 32;
|
||||
}
|
||||
|
||||
/* Store counter value and wrap status for next time */
|
||||
if (pps == true) {
|
||||
self->counter_us_raw_27bits_pps_prev = cnt;
|
||||
self->counter_us_raw_27bits_pps_wrap = counter_us_raw_27bits_wrap;
|
||||
} else {
|
||||
self->counter_us_raw_27bits_inst_prev = cnt;
|
||||
self->counter_us_raw_27bits_inst_wrap = counter_us_raw_27bits_wrap;
|
||||
}
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
uint32_t timestamp_counter_get(timestamp_counter_t * self, bool pps) {
|
||||
int x;
|
||||
uint8_t buff[4];
|
||||
uint32_t counter_us_raw_27bits_now;
|
||||
|
||||
/* Get the 32MHz timestamp counter - 4 bytes */
|
||||
/* step of 31.25 ns */
|
||||
x = lgw_reg_rb((pps == true) ? SX1302_REG_TIMESTAMP_TIMESTAMP_PPS_MSB2_TIMESTAMP_PPS : SX1302_REG_TIMESTAMP_TIMESTAMP_MSB2_TIMESTAMP, &buff[0], 4);
|
||||
if (x != LGW_REG_SUCCESS) {
|
||||
printf("ERROR: Failed to get timestamp counter value\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
counter_us_raw_27bits_now = (uint32_t)((buff[0] << 24) & 0xFF000000);
|
||||
counter_us_raw_27bits_now |= (uint32_t)((buff[1] << 16) & 0x00FF0000);
|
||||
counter_us_raw_27bits_now |= (uint32_t)((buff[2] << 8) & 0x0000FF00);
|
||||
counter_us_raw_27bits_now |= (uint32_t)((buff[3] << 0) & 0x000000FF);
|
||||
counter_us_raw_27bits_now /= 32; /* scale to 1MHz */
|
||||
|
||||
/* Update counter wrapping status */
|
||||
timestamp_counter_update(self, pps, counter_us_raw_27bits_now);
|
||||
|
||||
/* Convert 27-bits counter to 32-bits counter */
|
||||
return timestamp_counter_expand(self, pps, counter_us_raw_27bits_now);
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
uint32_t timestamp_counter_expand(timestamp_counter_t * self, bool pps, uint32_t cnt_us) {
|
||||
uint32_t counter_us_32bits;
|
||||
|
||||
if (pps == true) {
|
||||
counter_us_32bits = (self->counter_us_raw_27bits_pps_wrap << 27) | cnt_us;
|
||||
} else {
|
||||
counter_us_32bits = (self->counter_us_raw_27bits_inst_wrap << 27) | cnt_us;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* DEBUG: to be enabled when running test_loragw_counter test application
|
||||
This generates a CSV log, and can be plotted with gnuplot:
|
||||
> set datafile separator comma
|
||||
> plot for [col=1:2:1] 'log_count.txt' using col with lines
|
||||
*/
|
||||
printf("%u,%u,%u\n", cnt_us, counter_us_32bits, (pps == true) ? self->counter_us_raw_27bits_pps_wrap : self->counter_us_raw_27bits_inst_wrap);
|
||||
#endif
|
||||
|
||||
return counter_us_32bits;
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
int timestamp_counter_mode(bool enable_precision_ts, uint8_t max_ts_metrics, uint8_t nb_symbols) {
|
||||
if (enable_precision_ts == false) {
|
||||
DEBUG_MSG("INFO: using legacy timestamp\n");
|
||||
/* Latch end-of-packet timestamp (sx1301 compatibility) */
|
||||
lgw_reg_w(SX1302_REG_RX_TOP_RX_BUFFER_LEGACY_TIMESTAMP, 0x01);
|
||||
} else {
|
||||
DEBUG_PRINTF("INFO: using precision timestamp (max_ts_metrics:%u nb_symbols:%u)\n", max_ts_metrics, nb_symbols);
|
||||
/* Latch end-of-preamble timestamp */
|
||||
lgw_reg_w(SX1302_REG_RX_TOP_RX_BUFFER_LEGACY_TIMESTAMP, 0x00);
|
||||
lgw_reg_w(SX1302_REG_RX_TOP_RX_BUFFER_TIMESTAMP_CFG_MAX_TS_METRICS, max_ts_metrics);
|
||||
|
||||
/* LoRa multi-SF modems */
|
||||
lgw_reg_w(SX1302_REG_RX_TOP_TIMESTAMP_ENABLE, 0x01);
|
||||
lgw_reg_w(SX1302_REG_RX_TOP_TIMESTAMP_NB_SYMB, nb_symbols);
|
||||
|
||||
/* LoRa service modem */
|
||||
lgw_reg_w(SX1302_REG_RX_TOP_LORA_SERVICE_FSK_TIMESTAMP_ENABLE, 0x01);
|
||||
lgw_reg_w(SX1302_REG_RX_TOP_LORA_SERVICE_FSK_TIMESTAMP_NB_SYMB, nb_symbols);
|
||||
}
|
||||
|
||||
return LGW_REG_SUCCESS;
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
uint32_t timestamp_counter_correction(int ifmod, uint8_t bandwidth, uint8_t datarate, uint8_t coderate, uint32_t crc_en, uint16_t payload_length) {
|
||||
int32_t val;
|
||||
uint32_t sf = (uint32_t)datarate, cr = (uint32_t)coderate, bw_pow, ppm;
|
||||
uint32_t clk_period;
|
||||
uint32_t nb_nibble, nb_nibble_in_hdr, nb_nibble_in_last_block;
|
||||
uint32_t dft_peak_en, nb_iter;
|
||||
uint32_t demap_delay, decode_delay, fft_delay_state3, fft_delay, delay_x;
|
||||
uint32_t timestamp_correction;
|
||||
|
||||
/* determine if 'PPM mode' is on */
|
||||
if (SET_PPM_ON(bandwidth, datarate)) {
|
||||
ppm = 1;
|
||||
} else {
|
||||
ppm = 0;
|
||||
}
|
||||
|
||||
/* timestamp correction code, base delay */
|
||||
switch (bandwidth)
|
||||
{
|
||||
case BW_125KHZ:
|
||||
bw_pow = 1;
|
||||
delay_x = 16000000 / bw_pow + 2031250;
|
||||
break;
|
||||
case BW_250KHZ:
|
||||
bw_pow = 2;
|
||||
delay_x = 16000000 / bw_pow + 2031250;
|
||||
break;
|
||||
case BW_500KHZ:
|
||||
bw_pow = 4;
|
||||
delay_x = 16000000 / bw_pow + 2031250;
|
||||
break;
|
||||
default:
|
||||
DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", bandwidth);
|
||||
delay_x = 0;
|
||||
bw_pow = 0;
|
||||
break;
|
||||
}
|
||||
clk_period = 250000;
|
||||
|
||||
nb_nibble = (payload_length + 2 * crc_en) * 2 + 5;
|
||||
|
||||
if ((sf == 5) || (sf == 6)) {
|
||||
nb_nibble_in_hdr = sf;
|
||||
} else {
|
||||
nb_nibble_in_hdr = sf - 2;
|
||||
}
|
||||
|
||||
nb_nibble_in_last_block = nb_nibble - nb_nibble_in_hdr - (sf - 2 * ppm) * ((nb_nibble - nb_nibble_in_hdr) / (sf - 2 * ppm));
|
||||
if (nb_nibble_in_last_block == 0) {
|
||||
nb_nibble_in_last_block = sf - 2 * ppm;
|
||||
}
|
||||
|
||||
nb_iter = ((sf + 1) >> 1);
|
||||
|
||||
/* timestamp correction code, variable delay */
|
||||
if (ifmod == IF_LORA_STD) {
|
||||
lgw_reg_r(SX1302_REG_RX_TOP_LORA_SERVICE_FSK_RX_CFG0_DFT_PEAK_EN, &val);
|
||||
} else {
|
||||
lgw_reg_r(SX1302_REG_RX_TOP_RX_CFG0_DFT_PEAK_EN, &val);
|
||||
}
|
||||
if (val != 0) {
|
||||
/* TODO: should we differentiate the mode (FULL/TRACK) ? */
|
||||
dft_peak_en = 1;
|
||||
} else {
|
||||
dft_peak_en = 0;
|
||||
}
|
||||
|
||||
|
||||
if ((sf >= 5) && (sf <= 12) && (bw_pow > 0)) {
|
||||
if ((2 * (payload_length + 2 * crc_en) - (sf - 7)) <= 0) { /* payload fits entirely in first 8 symbols (header) */
|
||||
if (sf > 6) {
|
||||
nb_nibble_in_last_block = sf - 2;
|
||||
} else {
|
||||
nb_nibble_in_last_block = sf; // can't be acheived
|
||||
}
|
||||
dft_peak_en = 0;
|
||||
cr = 4; /* header coding rate is 4 */
|
||||
demap_delay = clk_period + (1 << sf) * clk_period * 3 / 4 + 3 * clk_period + (sf - 2) * clk_period;
|
||||
} else {
|
||||
demap_delay = clk_period + (1 << sf) * clk_period * (1 - ppm / 4) + 3 * clk_period + (sf - 2 * ppm) * clk_period;
|
||||
}
|
||||
|
||||
fft_delay_state3 = clk_period * (((1 << sf) - 6) + 2 * ((1 << sf) * (nb_iter - 1) + 6)) + 4 * clk_period;
|
||||
|
||||
if (dft_peak_en) {
|
||||
fft_delay = (5 - 2 * ppm) * ((1 << sf) * clk_period + 7 * clk_period) + 2 * clk_period;
|
||||
} else {
|
||||
fft_delay = (1 << sf) * 2 * clk_period + 3 * clk_period;
|
||||
}
|
||||
|
||||
decode_delay = 5 * clk_period + (9 * clk_period + clk_period * cr) * nb_nibble_in_last_block + 3 * clk_period;
|
||||
timestamp_correction = (uint32_t)(delay_x + fft_delay_state3 + fft_delay + demap_delay + decode_delay + 0.5e6) / 1e6;
|
||||
//printf("INFO: timestamp_correction = %u us (delay_x %u, fft_delay_state3=%u, fft_delay=%u, demap_delay=%u, decode_delay = %u)\n", timestamp_correction, delay_x, fft_delay_state3, fft_delay, demap_delay, decode_delay);
|
||||
}
|
||||
else
|
||||
{
|
||||
timestamp_correction = 0;
|
||||
DEBUG_MSG("WARNING: invalid packet, no timestamp correction\n");
|
||||
}
|
||||
|
||||
return timestamp_correction;
|
||||
}
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
|
@ -0,0 +1,698 @@
|
|||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2019 Semtech
|
||||
|
||||
Description:
|
||||
Minimum test program for HAL calibration
|
||||
|
||||
License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*/
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- DEPENDANCIES --------------------------------------------------------- */
|
||||
|
||||
/* fix an issue between POSIX and C99 */
|
||||
#if __STDC_VERSION__ >= 199901L
|
||||
#define _XOPEN_SOURCE 600
|
||||
#else
|
||||
#define _XOPEN_SOURCE 500
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <math.h>
|
||||
#include <signal.h> /* sigaction */
|
||||
#include <getopt.h> /* getopt_long */
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "loragw_hal.h"
|
||||
#include "loragw_reg.h"
|
||||
#include "loragw_sx1302.h"
|
||||
#include "loragw_sx125x.h"
|
||||
#include "loragw_aux.h"
|
||||
#include "loragw_cal.h"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE MACROS ------------------------------------------------------- */
|
||||
|
||||
#define RAND_RANGE(min, max) (rand() % (max + 1 - min) + min)
|
||||
|
||||
#define DEBUG_MSG(str) fprintf(stderr, str)
|
||||
#define DEBUG_PRINTF(fmt, args...) fprintf(stderr,"%s:%d: "fmt, __FUNCTION__, __LINE__, args)
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE CONSTANTS ---------------------------------------------------- */
|
||||
|
||||
#define LINUXDEV_PATH_DEFAULT "/dev/spidev0.0"
|
||||
|
||||
#define DEFAULT_CLK_SRC 0
|
||||
#define DEFAULT_FREQ_HZ 868500000U
|
||||
|
||||
#define DEFAULT_DAC_GAIN 3
|
||||
#define DEFAULT_MIX_GAIN 15
|
||||
|
||||
#define CAL_TX_TONE_FREQ_HZ 250000
|
||||
#define CAL_DEC_GAIN 8
|
||||
#define CAL_SIG_ANA_DURATION 0 /* correlation duration: 0:1, 1:2, 2:4, 3:8 ms) */
|
||||
|
||||
#define TEST_FREQ_SCAN 0
|
||||
#define TEST_OFFSET_IQ 1
|
||||
#define TEST_AMP_PHI 2
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE TYPES -------------------------------------------------------- */
|
||||
struct cal_tx_log {
|
||||
int32_t mean;
|
||||
int32_t i_offset;
|
||||
int32_t q_offset;
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE VARIABLES ---------------------------------------------------- */
|
||||
|
||||
FILE * fp;
|
||||
|
||||
static uint32_t rf_rx_freq[LGW_RF_CHAIN_NB] = {865500000, 865500000};
|
||||
static lgw_radio_type_t rf_radio_type[LGW_RF_CHAIN_NB] = {LGW_RADIO_TYPE_SX1257, LGW_RADIO_TYPE_SX1257};
|
||||
static struct lgw_tx_gain_lut_s txlut; /* TX gain table */
|
||||
|
||||
/* Signal handling 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 */
|
||||
|
||||
#include "../src/cal_fw.var" /* text_cal_sx1257_16_Nov_1 */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE FUNCTIONS ---------------------------------------------------- */
|
||||
|
||||
/* describe command line options */
|
||||
void usage(void) {
|
||||
//printf("Library version information: %s\n", lgw_version_info());
|
||||
printf("Available options:\n");
|
||||
printf(" -h print this help\n");
|
||||
printf(" -d <path> use Linux SPI device driver\n");
|
||||
printf(" => default path: " LINUXDEV_PATH_DEFAULT "\n");
|
||||
printf(" -k <uint> Concentrator clock source (Radio A or Radio B) [0..1]\n");
|
||||
printf(" -c <uint> RF chain to be used for TX (Radio A or Radio B) [0..1]\n");
|
||||
printf(" -r <uint> Radio type (1255, 1257, 1250)\n");
|
||||
printf(" -f <float> Radio TX frequency in MHz\n");
|
||||
printf( "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" );
|
||||
printf(" --pa <uint> PA gain [0..3]\n");
|
||||
printf(" --dig <uint> sx1302 digital gain [0..3]\n");
|
||||
printf(" --dac <uint> sx1257 DAC gain [0..3]\n");
|
||||
printf(" --mix <uint> sx1257 MIX gain [0..15]\n");
|
||||
}
|
||||
|
||||
/* handle signals */
|
||||
static void sig_handler(int sigio)
|
||||
{
|
||||
if (sigio == SIGQUIT) {
|
||||
quit_sig = 1;
|
||||
}
|
||||
else if((sigio == SIGINT) || (sigio == SIGTERM)) {
|
||||
exit_sig = 1;
|
||||
}
|
||||
}
|
||||
|
||||
int setup_tx_dc_offset(uint8_t rf_chain, uint32_t freq_hz, uint8_t dac_gain, uint8_t mix_gain, uint8_t radio_type) {
|
||||
uint32_t rx_freq_hz, tx_freq_hz;
|
||||
uint32_t rx_freq_int, rx_freq_frac;
|
||||
uint32_t tx_freq_int, tx_freq_frac;
|
||||
uint8_t rx_pll_locked, tx_pll_locked;
|
||||
|
||||
/* Set PLL frequencies */
|
||||
rx_freq_hz = freq_hz - CAL_TX_TONE_FREQ_HZ;
|
||||
tx_freq_hz = freq_hz;
|
||||
switch (radio_type) {
|
||||
case LGW_RADIO_TYPE_SX1255:
|
||||
rx_freq_int = rx_freq_hz / (SX125x_32MHz_FRAC << 7); /* integer part, gives the MSB */
|
||||
rx_freq_frac = ((rx_freq_hz % (SX125x_32MHz_FRAC << 7)) << 9) / SX125x_32MHz_FRAC; /* fractional part, gives middle part and LSB */
|
||||
tx_freq_int = tx_freq_hz / (SX125x_32MHz_FRAC << 7); /* integer part, gives the MSB */
|
||||
tx_freq_frac = ((tx_freq_hz % (SX125x_32MHz_FRAC << 7)) << 9) / SX125x_32MHz_FRAC; /* fractional part, gives middle part and LSB */
|
||||
break;
|
||||
case LGW_RADIO_TYPE_SX1257:
|
||||
rx_freq_int = rx_freq_hz / (SX125x_32MHz_FRAC << 8); /* integer part, gives the MSB */
|
||||
rx_freq_frac = ((rx_freq_hz % (SX125x_32MHz_FRAC << 8)) << 8) / SX125x_32MHz_FRAC; /* fractional part, gives middle part and LSB */
|
||||
tx_freq_int = tx_freq_hz / (SX125x_32MHz_FRAC << 8); /* integer part, gives the MSB */
|
||||
tx_freq_frac = ((tx_freq_hz % (SX125x_32MHz_FRAC << 8)) << 8) / SX125x_32MHz_FRAC; /* fractional part, gives middle part and LSB */
|
||||
break;
|
||||
default:
|
||||
DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d FOR RADIO TYPE\n", radio_type);
|
||||
return LGW_HAL_ERROR;
|
||||
}
|
||||
lgw_sx125x_reg_w(SX125x_REG_FRF_RX_MSB, 0xFF & rx_freq_int, rf_chain);
|
||||
lgw_sx125x_reg_w(SX125x_REG_FRF_RX_MID, 0xFF & (rx_freq_frac >> 8), rf_chain);
|
||||
lgw_sx125x_reg_w(SX125x_REG_FRF_RX_LSB, 0xFF & rx_freq_frac, rf_chain);
|
||||
lgw_sx125x_reg_w(SX125x_REG_FRF_TX_MSB, 0xFF & tx_freq_int, rf_chain);
|
||||
lgw_sx125x_reg_w(SX125x_REG_FRF_TX_MID, 0xFF & (tx_freq_frac >> 8), rf_chain);
|
||||
lgw_sx125x_reg_w(SX125x_REG_FRF_TX_LSB, 0xFF & tx_freq_frac, rf_chain);
|
||||
|
||||
/* Radio settings for calibration */
|
||||
//lgw_sx125x_reg_w(SX125x_RX_ANA_GAIN__LNA_ZIN, 1, rf_chain); /* Default: 1 */
|
||||
//lgw_sx125x_reg_w(SX125x_RX_ANA_GAIN__BB_GAIN, 15, rf_chain); /* Default: 15 */
|
||||
//lgw_sx125x_reg_w(SX125x_RX_ANA_GAIN__LNA_GAIN, 1, rf_chain); /* Default: 1 */
|
||||
lgw_sx125x_reg_w(SX125x_REG_RX_BW__BB_BW, 0, rf_chain);
|
||||
lgw_sx125x_reg_w(SX125x_REG_RX_BW__ADC_TRIM, 6, rf_chain);
|
||||
//lgw_sx125x_reg_w(SX125x_RX_BW__ADC_BW, 7, rf_chain); /* Default: 7 */
|
||||
lgw_sx125x_reg_w(SX125x_REG_RX_PLL_BW__PLL_BW, 0, rf_chain);
|
||||
lgw_sx125x_reg_w(SX125x_REG_TX_BW__PLL_BW, 0, rf_chain);
|
||||
//lgw_sx125x_reg_w(SX125x_TX_BW__ANA_BW, 0, rf_chain); /* Default: 0 */
|
||||
lgw_sx125x_reg_w(SX125x_REG_TX_DAC_BW, 5, rf_chain);
|
||||
lgw_sx125x_reg_w(SX125x_REG_CLK_SELECT__DAC_CLK_SELECT, 1, rf_chain); /* Use external clock from SX1302 */
|
||||
lgw_sx125x_reg_w(SX125x_REG_TX_GAIN__DAC_GAIN, dac_gain, rf_chain);
|
||||
lgw_sx125x_reg_w(SX125x_REG_TX_GAIN__MIX_GAIN, mix_gain, rf_chain);
|
||||
lgw_sx125x_reg_w(SX125x_REG_CLK_SELECT__RF_LOOPBACK_EN, 1, rf_chain);
|
||||
lgw_sx125x_reg_w(SX125x_REG_MODE, 15, rf_chain);
|
||||
wait_ms(1);
|
||||
lgw_sx125x_reg_r(SX125x_REG_MODE_STATUS__RX_PLL_LOCKED, &rx_pll_locked, rf_chain);
|
||||
lgw_sx125x_reg_r(SX125x_REG_MODE_STATUS__TX_PLL_LOCKED, &tx_pll_locked, rf_chain);
|
||||
if ((rx_pll_locked == 0) || (tx_pll_locked == 0)) {
|
||||
DEBUG_MSG("ERROR: PLL failed to lock\n");
|
||||
return LGW_HAL_ERROR;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cal_tx_dc_offset(uint8_t test_id, uint8_t rf_chain, uint32_t freq_hz, uint8_t dac_gain, uint8_t mix_gain, uint8_t radio_type, int32_t f_offset, int32_t i_offset, int32_t q_offset, bool full_log, bool use_agc, uint8_t amp, uint8_t phi) {
|
||||
int i;
|
||||
uint16_t reg;
|
||||
int32_t val_min, val_max;
|
||||
int32_t acc;
|
||||
int32_t val_mean;
|
||||
float val_std;
|
||||
float acc2 = 0 ;
|
||||
int loop_len = 3;
|
||||
float res_sig[loop_len];
|
||||
struct timeval start, stop;
|
||||
|
||||
//DEBUG_MSG("\n");
|
||||
//DEBUG_PRINTF("rf_chain:%u, freq_hz:%u, dac_gain:%u, mix_gain:%u, radio_type:%d\n", rf_chain, freq_hz, dac_gain, mix_gain, radio_type);
|
||||
|
||||
if (setup_tx_dc_offset(rf_chain, freq_hz, dac_gain, mix_gain, radio_type) != LGW_HAL_SUCCESS) {
|
||||
return LGW_HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Trig calibration */
|
||||
|
||||
/* Select radio to be connected to the Signal Analyzer (warning: RadioA:1, RadioB:0) */
|
||||
lgw_reg_w(SX1302_REG_RADIO_FE_SIG_ANA_CFG_RADIO_SEL, (rf_chain == 0) ? 1 : 0);
|
||||
|
||||
reg = REG_SELECT(rf_chain, SX1302_REG_TX_TOP_A_TX_RFFE_IF_CTRL_TX_MODE,
|
||||
SX1302_REG_TX_TOP_B_TX_RFFE_IF_CTRL_TX_MODE);
|
||||
lgw_reg_w(reg, 0);
|
||||
|
||||
reg = REG_SELECT(rf_chain, SX1302_REG_TX_TOP_A_TX_TRIG_TX_TRIG_IMMEDIATE,
|
||||
SX1302_REG_TX_TOP_B_TX_TRIG_TX_TRIG_IMMEDIATE);
|
||||
lgw_reg_w(reg, 1);
|
||||
lgw_reg_w(reg, 0);
|
||||
|
||||
reg = REG_SELECT(rf_chain, SX1302_REG_RADIO_FE_CTRL0_RADIO_A_DC_NOTCH_EN,
|
||||
SX1302_REG_RADIO_FE_CTRL0_RADIO_B_DC_NOTCH_EN);
|
||||
lgw_reg_w(reg, 1);
|
||||
|
||||
/* Measuring */
|
||||
if (use_agc == true) {
|
||||
uint8_t val_sig, val_sig2;
|
||||
|
||||
/* Set calibration parameters */
|
||||
sx1302_agc_mailbox_write(2, rf_chain + 4); /* Sig ana test radio A/B */
|
||||
sx1302_agc_mailbox_write(1, f_offset/*(CAL_TX_TONE_FREQ_HZ + f_offset) * 64e-6*/); /* Set frequency */
|
||||
sx1302_agc_mailbox_write(0, CAL_SIG_ANA_DURATION);
|
||||
|
||||
/* */
|
||||
sx1302_agc_mailbox_write(3, 0x00);
|
||||
sx1302_agc_mailbox_write(3, 0x01);
|
||||
sx1302_agc_wait_status(0x01);
|
||||
|
||||
sx1302_agc_mailbox_write(2, amp); /* amp */
|
||||
sx1302_agc_mailbox_write(1, phi); /* phi */
|
||||
|
||||
sx1302_agc_mailbox_write(3, 0x02);
|
||||
sx1302_agc_wait_status(0x02);
|
||||
|
||||
sx1302_agc_mailbox_write(2, i_offset); /* i offset init */
|
||||
sx1302_agc_mailbox_write(1, q_offset); /* q offset init */
|
||||
|
||||
sx1302_agc_mailbox_write(3, 0x03);
|
||||
sx1302_agc_wait_status(0x03);
|
||||
|
||||
sx1302_agc_mailbox_write(2, CAL_DEC_GAIN); /* dec_gain */
|
||||
sx1302_agc_mailbox_write(2, 0); /* threshold (not used) */
|
||||
|
||||
sx1302_agc_mailbox_write(3, 0x04);
|
||||
|
||||
reg = REG_SELECT(rf_chain, SX1302_REG_TX_TOP_A_TX_TRIG_TX_TRIG_IMMEDIATE,
|
||||
SX1302_REG_TX_TOP_B_TX_TRIG_TX_TRIG_IMMEDIATE);
|
||||
lgw_reg_w(reg, 0);
|
||||
|
||||
gettimeofday (&start, NULL);
|
||||
for (i = 0; i < loop_len; i++) {
|
||||
sx1302_agc_wait_status(0x06);
|
||||
sx1302_agc_mailbox_write(3, 0x06);
|
||||
|
||||
sx1302_agc_wait_status(0x07);
|
||||
sx1302_agc_mailbox_read(0, &val_sig);
|
||||
sx1302_agc_mailbox_read(1, &val_sig2);
|
||||
res_sig[i] = val_sig2 * 256 + val_sig;
|
||||
|
||||
if (i == (loop_len - 1)) {
|
||||
sx1302_agc_mailbox_write(3, 0x07); /* unlock */
|
||||
} else {
|
||||
sx1302_agc_mailbox_write(3, 0x00); /* unlock */
|
||||
}
|
||||
}
|
||||
gettimeofday (&stop, NULL);
|
||||
//printf("processing time: %ld us\n", ((stop.tv_sec - start.tv_sec) * 1000000 + stop.tv_usec) - start.tv_usec);
|
||||
} else {
|
||||
int32_t val;
|
||||
int32_t abs_lsb, abs_msb;
|
||||
float abs_iq;
|
||||
|
||||
reg = REG_SELECT(rf_chain, SX1302_REG_TX_TOP_A_TX_RFFE_IF_Q_OFFSET_Q_OFFSET,
|
||||
SX1302_REG_TX_TOP_B_TX_RFFE_IF_Q_OFFSET_Q_OFFSET);
|
||||
lgw_reg_w(reg, (int8_t)q_offset);
|
||||
|
||||
reg = REG_SELECT(rf_chain, SX1302_REG_TX_TOP_A_TX_RFFE_IF_I_OFFSET_I_OFFSET,
|
||||
SX1302_REG_TX_TOP_B_TX_RFFE_IF_I_OFFSET_I_OFFSET);
|
||||
lgw_reg_w(reg, (int8_t)i_offset);
|
||||
|
||||
reg = REG_SELECT(rf_chain, SX1302_REG_RADIO_FE_CTRL0_RADIO_A_DC_NOTCH_EN,
|
||||
SX1302_REG_RADIO_FE_CTRL0_RADIO_B_DC_NOTCH_EN);
|
||||
lgw_reg_w(reg, 1);
|
||||
|
||||
reg = REG_SELECT(rf_chain, SX1302_REG_RADIO_FE_CTRL0_RADIO_A_FORCE_HOST_FILTER_GAIN,
|
||||
SX1302_REG_RADIO_FE_CTRL0_RADIO_B_FORCE_HOST_FILTER_GAIN);
|
||||
lgw_reg_w(reg, 0x01);
|
||||
|
||||
reg = REG_SELECT(rf_chain, SX1302_REG_RADIO_FE_CTRL0_RADIO_A_HOST_FILTER_GAIN,
|
||||
SX1302_REG_RADIO_FE_CTRL0_RADIO_B_HOST_FILTER_GAIN);
|
||||
lgw_reg_w(reg, CAL_DEC_GAIN);
|
||||
|
||||
lgw_reg_w(SX1302_REG_RADIO_FE_SIG_ANA_CFG_FORCE_HAL_CTRL, 1);
|
||||
|
||||
lgw_reg_w(SX1302_REG_RADIO_FE_SIG_ANA_FREQ_FREQ, f_offset);
|
||||
|
||||
lgw_reg_w(SX1302_REG_RADIO_FE_SIG_ANA_CFG_DURATION, CAL_SIG_ANA_DURATION);
|
||||
lgw_reg_w(SX1302_REG_RADIO_FE_SIG_ANA_CFG_EN, 1);
|
||||
|
||||
gettimeofday (&start, NULL);
|
||||
for (i = 0; i < loop_len; i++) {
|
||||
lgw_reg_w(SX1302_REG_RADIO_FE_SIG_ANA_CFG_START, 0);
|
||||
lgw_reg_w(SX1302_REG_RADIO_FE_SIG_ANA_CFG_START, 1);
|
||||
|
||||
do {
|
||||
lgw_reg_r(SX1302_REG_RADIO_FE_SIG_ANA_CFG_VALID, &val);
|
||||
wait_ms(1);
|
||||
} while (val == 0);
|
||||
|
||||
lgw_reg_r(SX1302_REG_RADIO_FE_SIG_ANA_ABS_LSB_CORR_ABS_OUT, &abs_lsb);
|
||||
lgw_reg_r(SX1302_REG_RADIO_FE_SIG_ANA_ABS_MSB_CORR_ABS_OUT, &abs_msb);
|
||||
abs_iq = (abs_msb << 8) | abs_lsb;
|
||||
|
||||
res_sig[i] = abs_iq;
|
||||
}
|
||||
gettimeofday (&stop, NULL);
|
||||
//printf("processing time: %ld us\n", ((stop.tv_sec - start.tv_sec) * 1000000 + stop.tv_usec) - start.tv_usec);
|
||||
|
||||
lgw_reg_w(SX1302_REG_RADIO_FE_SIG_ANA_CFG_FORCE_HAL_CTRL, 0);
|
||||
}
|
||||
|
||||
if (full_log == true) {
|
||||
printf("i_offset:%d q_offset:%d f_offset:%d dac_gain:%d mix_gain:%d dec_gain:%d amp:%u phi:%u => ", i_offset, q_offset, f_offset, dac_gain, mix_gain, CAL_DEC_GAIN, amp, phi);
|
||||
} else {
|
||||
switch (test_id) {
|
||||
case TEST_FREQ_SCAN:
|
||||
fprintf(fp, "%u ", f_offset);
|
||||
break;
|
||||
case TEST_OFFSET_IQ:
|
||||
fprintf(fp, "%d %d ", i_offset, q_offset);
|
||||
break;
|
||||
case TEST_AMP_PHI:
|
||||
fprintf(fp, "%d %d ", amp, phi);
|
||||
break;
|
||||
default:
|
||||
printf("ERROR: wrong test ID (%u)\n", test_id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Analyze result */
|
||||
val_min = res_sig[0];
|
||||
val_max = res_sig[0];
|
||||
acc = 0;
|
||||
for (i = 0; i < loop_len; i++) {
|
||||
if (res_sig[i] > val_max) {
|
||||
val_max = res_sig[i];
|
||||
}
|
||||
if (res_sig[i] < val_min) {
|
||||
val_min = res_sig[i];
|
||||
}
|
||||
acc += res_sig[i];
|
||||
}
|
||||
val_mean = acc / loop_len;
|
||||
|
||||
for (i = 0; i < loop_len; i++) {
|
||||
acc2 += pow((res_sig[i]-val_mean),2);
|
||||
}
|
||||
val_std = sqrt(acc2/loop_len);
|
||||
|
||||
if (full_log == true) {
|
||||
printf(" min:%u max:%u mean:%u std:%f\n", val_min, val_max, val_mean, val_std);
|
||||
} else {
|
||||
switch (test_id) {
|
||||
case TEST_OFFSET_IQ:
|
||||
case TEST_AMP_PHI:
|
||||
fprintf(fp, "%u %u %u %f\n", val_min, val_max, val_mean, val_std);
|
||||
break;
|
||||
case TEST_FREQ_SCAN:
|
||||
fprintf(fp, "%u\n", val_mean);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return LGW_HAL_SUCCESS;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- MAIN FUNCTION -------------------------------------------------------- */
|
||||
|
||||
int test_freq_scan(uint8_t rf_chain, bool full_log, bool use_agc) {
|
||||
int f;
|
||||
|
||||
printf("-------------------------------------\n");
|
||||
for (f = 0; f < 256; f++)
|
||||
{
|
||||
cal_tx_dc_offset(TEST_FREQ_SCAN, rf_chain, rf_rx_freq[rf_chain], txlut.lut[0].dac_gain, txlut.lut[0].mix_gain, rf_radio_type[rf_chain], f, 0, 0, full_log, use_agc, 0, 0);
|
||||
|
||||
if ((quit_sig == 1) || (exit_sig == 1)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_iq_offset(uint8_t rf_chain, uint8_t f_offset, bool full_log, bool use_agc) {
|
||||
int i, q;
|
||||
|
||||
printf("-------------------------------------\n");
|
||||
for (i = -128; i < 127; i+=8)
|
||||
{
|
||||
for (q = -128; q < 127; q+=8)
|
||||
{
|
||||
cal_tx_dc_offset(TEST_OFFSET_IQ, rf_chain, rf_rx_freq[rf_chain], txlut.lut[0].dac_gain, txlut.lut[0].mix_gain, rf_radio_type[rf_chain], f_offset, i, q, full_log, use_agc, 0, 0);
|
||||
if ((quit_sig == 1) || (exit_sig == 1)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_amp_phi(uint8_t rf_chain, uint8_t f_offset, bool full_log, bool use_agc) {
|
||||
int amp, phi;
|
||||
|
||||
printf("-------------------------------------\n");
|
||||
for (amp = 0; amp < 64; amp++)
|
||||
{
|
||||
for (phi = 0; phi < 64; phi++)
|
||||
{
|
||||
cal_tx_dc_offset(TEST_AMP_PHI, rf_chain, rf_rx_freq[rf_chain], txlut.lut[0].dac_gain, txlut.lut[0].mix_gain, rf_radio_type[rf_chain], f_offset, 0, 0, full_log, use_agc, amp, phi);
|
||||
if ((quit_sig == 1) || (exit_sig == 1)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_capture_ram(uint8_t rf_chain) {
|
||||
uint16_t reg;
|
||||
|
||||
setup_tx_dc_offset(rf_chain, rf_rx_freq[rf_chain], txlut.lut[0].dac_gain, txlut.lut[0].mix_gain, rf_radio_type[rf_chain]);
|
||||
|
||||
reg = REG_SELECT(rf_chain, SX1302_REG_RADIO_FE_CTRL0_RADIO_A_DC_NOTCH_EN,
|
||||
SX1302_REG_RADIO_FE_CTRL0_RADIO_B_DC_NOTCH_EN);
|
||||
lgw_reg_w(reg, 1);
|
||||
|
||||
printf("Waiting...\n");
|
||||
while ((quit_sig != 1) && (exit_sig != 1)) {
|
||||
wait_ms(1000);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i, x;
|
||||
uint32_t ft = DEFAULT_FREQ_HZ;
|
||||
double arg_d = 0.0;
|
||||
unsigned int arg_u;
|
||||
uint8_t clocksource = 0;
|
||||
uint8_t rf_chain = 0;
|
||||
lgw_radio_type_t radio_type = LGW_RADIO_TYPE_NONE;
|
||||
|
||||
struct lgw_conf_board_s boardconf;
|
||||
struct lgw_conf_rxrf_s rfconf;
|
||||
|
||||
static struct sigaction sigact; /* SIGQUIT&SIGINT&SIGTERM signal handling */
|
||||
|
||||
/* SPI interfaces */
|
||||
const char spidev_path_default[] = LINUXDEV_PATH_DEFAULT;
|
||||
const char * spidev_path = spidev_path_default;
|
||||
|
||||
/* Initialize TX gain LUT */
|
||||
txlut.size = 1;
|
||||
memset(txlut.lut, 0, sizeof txlut.lut);
|
||||
txlut.lut[0].dac_gain = DEFAULT_DAC_GAIN;
|
||||
txlut.lut[0].mix_gain = DEFAULT_MIX_GAIN;
|
||||
|
||||
/* Parameter parsing */
|
||||
int option_index = 0;
|
||||
static struct option long_options[] = {
|
||||
{"dac", 1, 0, 0},
|
||||
{"mix", 1, 0, 0},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
/* parse command line options */
|
||||
while ((i = getopt_long (argc, argv, "hf:k:r:c:d:", long_options, &option_index)) != -1) {
|
||||
switch (i) {
|
||||
case 'h':
|
||||
usage();
|
||||
return -1;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
if (optarg != NULL) {
|
||||
spidev_path = optarg;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'r': /* <uint> Radio type */
|
||||
i = sscanf(optarg, "%u", &arg_u);
|
||||
if ((i != 1) || ((arg_u != 1255) && (arg_u != 1257) && (arg_u != 1250))) {
|
||||
printf("ERROR: argument parsing of -r argument. Use -h to print help\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
switch (arg_u) {
|
||||
case 1255:
|
||||
radio_type = LGW_RADIO_TYPE_SX1255;
|
||||
break;
|
||||
case 1257:
|
||||
radio_type = LGW_RADIO_TYPE_SX1257;
|
||||
break;
|
||||
default: /* 1250 */
|
||||
radio_type = LGW_RADIO_TYPE_SX1250;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'k': /* <uint> Clock Source */
|
||||
i = sscanf(optarg, "%u", &arg_u);
|
||||
if ((i != 1) || (arg_u > 1)) {
|
||||
printf("ERROR: argument parsing of -k argument. Use -h to print help\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
clocksource = (uint8_t)arg_u;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'c': /* <uint> RF chain */
|
||||
i = sscanf(optarg, "%u", &arg_u);
|
||||
if ((i != 1) || (arg_u > 1)) {
|
||||
printf("ERROR: argument parsing of -c argument. Use -h to print help\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
rf_chain = (uint8_t)arg_u;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'f': /* <float> Radio TX frequency in MHz */
|
||||
i = sscanf(optarg, "%lf", &arg_d);
|
||||
if (i != 1) {
|
||||
printf("ERROR: argument parsing of -f argument. Use -h to print help\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
ft = (uint32_t)((arg_d*1e6) + 0.5); /* .5 Hz offset to get rounding instead of truncating */
|
||||
}
|
||||
break;
|
||||
|
||||
case 0:
|
||||
if (strcmp(long_options[option_index].name, "dac") == 0) {
|
||||
i = sscanf(optarg, "%u", &arg_u);
|
||||
if ((i != 1) || (arg_u > 3)) {
|
||||
printf("ERROR: argument parsing of --dac argument. Use -h to print help\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
txlut.size = 1;
|
||||
txlut.lut[0].dac_gain = (uint8_t)arg_u;
|
||||
}
|
||||
} else if (strcmp(long_options[option_index].name, "mix") == 0) {
|
||||
i = sscanf(optarg, "%u", &arg_u);
|
||||
if ((i != 1) || (arg_u > 15)) {
|
||||
printf("ERROR: argument parsing of --mix argument. Use -h to print help\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
txlut.size = 1;
|
||||
txlut.lut[0].mix_gain = (uint8_t)arg_u;
|
||||
}
|
||||
} else {
|
||||
printf("ERROR: argument parsing options. Use -h to print help\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("ERROR: argument parsing\n");
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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 );
|
||||
|
||||
/* Board reset */
|
||||
if (system("./reset_lgw.sh start") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Configure the gateway */
|
||||
memset(&boardconf, 0, sizeof boardconf);
|
||||
boardconf.lorawan_public = true;
|
||||
boardconf.clksrc = clocksource;
|
||||
boardconf.full_duplex = false;
|
||||
strncpy(boardconf.spidev_path, spidev_path, sizeof boardconf.spidev_path);
|
||||
if (lgw_board_setconf(&boardconf) != LGW_HAL_SUCCESS) {
|
||||
printf("ERROR: failed to configure board\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
memset(&rfconf, 0, sizeof rfconf);
|
||||
rfconf.enable = ((rf_chain == 0) ? true : false);
|
||||
rfconf.freq_hz = ft;
|
||||
rfconf.type = radio_type;
|
||||
rfconf.tx_enable = true;
|
||||
if (lgw_rxrf_setconf(0, &rfconf) != LGW_HAL_SUCCESS) {
|
||||
printf("ERROR: failed to configure rxrf 0\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
memset(&rfconf, 0, sizeof rfconf);
|
||||
rfconf.enable = ((rf_chain == 1) ? true : false);
|
||||
rfconf.freq_hz = ft;
|
||||
rfconf.type = radio_type;
|
||||
rfconf.tx_enable = true;
|
||||
if (lgw_rxrf_setconf(1, &rfconf) != LGW_HAL_SUCCESS) {
|
||||
printf("ERROR: failed to configure rxrf 1\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (txlut.size > 0) {
|
||||
if (lgw_txgain_setconf(rf_chain, &txlut) != LGW_HAL_SUCCESS) {
|
||||
printf("ERROR: failed to configure txgain lut\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
/* open log file for writing */
|
||||
fp = fopen("log.txt", "w+");
|
||||
|
||||
/* connect the gateway */
|
||||
x = lgw_connect(spidev_path);
|
||||
if (x != 0) {
|
||||
printf("ERROR: failed to connect the gateway\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
sx1302_radio_reset(rf_chain, LGW_RADIO_TYPE_SX1257);
|
||||
sx1302_radio_clock_select(clocksource);
|
||||
sx1302_radio_set_mode(rf_chain, LGW_RADIO_TYPE_SX1257);
|
||||
|
||||
printf("Loading CAL fw for sx125x\n");
|
||||
if (sx1302_agc_load_firmware(cal_firmware_sx125x) != LGW_HAL_SUCCESS) {
|
||||
return LGW_HAL_ERROR;
|
||||
}
|
||||
|
||||
printf("waiting for capture ram\n");
|
||||
wait_ms(1000);
|
||||
|
||||
/* testing */
|
||||
printf("testing: rf_chain:%u, dac_gain: %u, mix_gain:%u, dec_gain:%u, sig_ana_duration:%u\n", rf_chain, txlut.lut[0].dac_gain, txlut.lut[0].mix_gain, CAL_DEC_GAIN, CAL_SIG_ANA_DURATION);
|
||||
|
||||
test_freq_scan(rf_chain, false, false); /* rf_chain, full_log, use_agc */
|
||||
/* gnuplot> plot 'log.txt' with lines */
|
||||
|
||||
//test_iq_offset(rf_chain, 16, false, false); /* rf_chain, f_offset, full_log, use_agc */
|
||||
|
||||
//test_amp_phi(rf_chain, 240, true, true); /* rf_chain, f_offset, full_log, use_agc */
|
||||
|
||||
//test_capture_ram(rf_chain);
|
||||
|
||||
sx1302_radio_reset(0, LGW_RADIO_TYPE_SX1257);
|
||||
sx1302_radio_reset(1, LGW_RADIO_TYPE_SX1257);
|
||||
|
||||
/* disconnect the gateway */
|
||||
x = lgw_disconnect();
|
||||
if (x != 0) {
|
||||
printf("ERROR: failed to disconnect the gateway\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* Close log file */
|
||||
fclose(fp);
|
||||
|
||||
/* Board reset */
|
||||
if (system("./reset_lgw.sh stop") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
printf("=========== Test End ===========\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
|
@ -0,0 +1,369 @@
|
|||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2019 Semtech
|
||||
|
||||
Description:
|
||||
Minimum test program to test the capture RAM block
|
||||
|
||||
License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*/
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- DEPENDANCIES --------------------------------------------------------- */
|
||||
|
||||
/* fix an issue between POSIX and C99 */
|
||||
#if __STDC_VERSION__ >= 199901L
|
||||
#define _XOPEN_SOURCE 600
|
||||
#else
|
||||
#define _XOPEN_SOURCE 500
|
||||
#endif
|
||||
|
||||
|
||||
// #include <stdint.h>
|
||||
#include <stdio.h> /* printf */
|
||||
#include <stdlib.h>
|
||||
#include <signal.h> /* sigaction */
|
||||
#include <getopt.h> /* getopt_long */
|
||||
|
||||
#include "loragw_hal.h"
|
||||
#include "loragw_reg.h"
|
||||
#include "loragw_aux.h"
|
||||
#include "loragw_sx1250.h"
|
||||
#include "loragw_sx125x.h"
|
||||
#include "loragw_sx1302.h"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE MACROS ------------------------------------------------------- */
|
||||
|
||||
#define DEBUG_MSG(str) fprintf(stderr, str)
|
||||
|
||||
#define LINUXDEV_PATH_DEFAULT "/dev/spidev0.0"
|
||||
|
||||
#define FULL_INIT 0
|
||||
#define CAPTURE_RAM_SIZE 0x4000
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE VARIABLES ---------------------------------------------------- */
|
||||
|
||||
/* Signal handling 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 */
|
||||
|
||||
uint32_t sampling_frequency[] = {4e6, 4e6, 4e6, 4e6, 4e6, 4e6, 4e6, 0, 0, 1e6, 125e3, 125e3, 125e3, 125e3, 125e3, 125e3, 125e3, 125e3, 8e6, 125e3, 125e3, 125e3, 0, 32e6, 32e6, 0, 32e6, 32e6, 0, 32e6, 32e6, 32e6};
|
||||
|
||||
#if FULL_INIT
|
||||
#include "src/text_agc_sx1250_27_Nov_1.var"
|
||||
#include "src/text_agc_sx1257_19_Nov_1.var"
|
||||
#include "src/text_arb_sx1302_13_Nov_3.var"
|
||||
|
||||
#define FW_VERSION_CAL 0 /* Expected version of calibration firmware */ /* TODO */
|
||||
#define FW_VERSION_AGC 1 /* Expected version of AGC firmware */
|
||||
#define FW_VERSION_ARB 1 /* Expected version of arbiter firmware */
|
||||
|
||||
static bool rf_enable[LGW_RF_CHAIN_NB];
|
||||
static uint32_t rf_rx_freq[LGW_RF_CHAIN_NB]; /* absolute, in Hz */
|
||||
static lgw_radio_type_t rf_radio_type[LGW_RF_CHAIN_NB];
|
||||
static uint8_t rf_clkout = 0;
|
||||
#endif
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE FUNCTIONS ---------------------------------------------------- */
|
||||
|
||||
/* describe command line options */
|
||||
void usage(void)
|
||||
{
|
||||
printf("Available options:\n");
|
||||
printf(" -h print this help\n");
|
||||
printf(" -d <path> use Linux SPI device driver\n");
|
||||
printf(" => default path: " LINUXDEV_PATH_DEFAULT "\n");
|
||||
printf(" -s <uint> Capture source [0..31]\n");
|
||||
}
|
||||
|
||||
/* handle signals */
|
||||
static void sig_handler(int sigio)
|
||||
{
|
||||
if (sigio == SIGQUIT) {
|
||||
quit_sig = 1;
|
||||
}
|
||||
else if((sigio == SIGINT) || (sigio == SIGTERM)) {
|
||||
exit_sig = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Main program */
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
int32_t val = 0;
|
||||
int reg_stat;
|
||||
unsigned int arg_u;
|
||||
uint8_t capture_source = 0;
|
||||
uint16_t period_value = 0;
|
||||
int16_t real = 0, imag = 0;
|
||||
#if FULL_INIT
|
||||
uint32_t val1, val2;
|
||||
#endif
|
||||
uint8_t capture_ram_buffer[CAPTURE_RAM_SIZE];
|
||||
|
||||
static struct sigaction sigact; /* SIGQUIT&SIGINT&SIGTERM signal handling */
|
||||
|
||||
/* SPI interfaces */
|
||||
const char spidev_path_default[] = LINUXDEV_PATH_DEFAULT;
|
||||
const char * spidev_path = spidev_path_default;
|
||||
|
||||
/* Parameter parsing */
|
||||
int option_index = 0;
|
||||
static struct option long_options[] = {
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
/* parse command line options */
|
||||
while ((i = getopt_long (argc, argv, "h:s:d:", long_options, &option_index)) != -1) {
|
||||
switch (i) {
|
||||
case 'h':
|
||||
usage();
|
||||
return -1;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
if (optarg != NULL) {
|
||||
spidev_path = optarg;
|
||||
}
|
||||
break;
|
||||
|
||||
case 's': /* <uint> Capture Source */
|
||||
i = sscanf(optarg, "%u", &arg_u);
|
||||
if ((i != 1) || (arg_u > 31)) {
|
||||
printf("ERROR: argument parsing of -s argument. Use -h to print help\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
capture_source = arg_u;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("ERROR: argument parsing\n");
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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 );
|
||||
|
||||
#if FULL_INIT
|
||||
/* Board reset */
|
||||
if (system("./reset_lgw.sh start") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Initialize memory for capture */
|
||||
for (i = 0; i < CAPTURE_RAM_SIZE; i++) {
|
||||
capture_ram_buffer[i] = i%256;
|
||||
}
|
||||
|
||||
reg_stat = lgw_connect(spidev_path);
|
||||
if (reg_stat == LGW_REG_ERROR) {
|
||||
DEBUG_MSG("ERROR: FAIL TO CONNECT BOARD\n");
|
||||
return LGW_HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Manual init */
|
||||
#if FULL_INIT
|
||||
rf_radio_type[0] = LGW_RADIO_TYPE_SX1250;
|
||||
rf_radio_type[1] = LGW_RADIO_TYPE_SX1257;
|
||||
rf_enable[0] = false;
|
||||
rf_enable[1] = true;
|
||||
rf_clkout = 1;
|
||||
rf_rx_freq[1] = 863700000;
|
||||
|
||||
/* setup radios */
|
||||
for (i=0; i < 2; i++)
|
||||
{
|
||||
if (rf_enable[i] == true) {
|
||||
sx1302_radio_reset(i, rf_radio_type[i]);
|
||||
switch (radio_type) {
|
||||
case LGW_RADIO_TYPE_SX1250:
|
||||
sx1250_setup(i, rf_rx_freq[i]);
|
||||
break;
|
||||
case LGW_RADIO_TYPE_SX1255:
|
||||
case LGW_RADIO_TYPE_SX1257:
|
||||
sx125x_setup(i, rf_clkout, true, rf_radio_type[i], rf_rx_freq[i]);
|
||||
break;
|
||||
default:
|
||||
DEBUG_MSG("ERROR: RADIO TYPE NOT SUPPORTED\n");
|
||||
return LGW_HAL_ERROR;
|
||||
}
|
||||
sx1302_radio_set_mode(i, radio_type);
|
||||
}
|
||||
}
|
||||
|
||||
/* Select the radio which provides the clock to the sx1302 */
|
||||
sx1302_radio_clock_select(rf_clkout);
|
||||
|
||||
/* Check that the SX1302 timestamp counter is running */
|
||||
lgw_get_instcnt(&val1);
|
||||
lgw_get_instcnt(&val2);
|
||||
if (val1 == val2) {
|
||||
printf("ERROR: SX1302 timestamp counter is not running (val:%u)\n", (uint32_t)val1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Configure Radio FE */
|
||||
sx1302_radio_fe_configure();
|
||||
|
||||
/* give radio control to AGC MCU */
|
||||
lgw_reg_w(SX1302_REG_COMMON_CTRL0_HOST_RADIO_CTRL, 0x00);
|
||||
|
||||
/* Load firmware */
|
||||
switch (rf_radio_type[rf_clkout]) {
|
||||
case LGW_RADIO_TYPE_SX1250:
|
||||
printf("Loading AGC fw for sx1250\n");
|
||||
if (sx1302_agc_load_firmware(agc_firmware_sx1250) != LGW_HAL_SUCCESS) {
|
||||
return LGW_HAL_ERROR;
|
||||
}
|
||||
if (sx1302_agc_start(FW_VERSION_AGC, SX1302_RADIO_TYPE_SX1250, SX1302_AGC_RADIO_GAIN_AUTO, SX1302_AGC_RADIO_GAIN_AUTO, 0) != LGW_HAL_SUCCESS) {
|
||||
return LGW_HAL_ERROR;
|
||||
}
|
||||
break;
|
||||
case LGW_RADIO_TYPE_SX1257:
|
||||
printf("Loading AGC fw for sx125x\n");
|
||||
if (sx1302_agc_load_firmware(agc_firmware_sx125x) != LGW_HAL_SUCCESS) {
|
||||
return LGW_HAL_ERROR;
|
||||
}
|
||||
if (sx1302_agc_start(FW_VERSION_AGC, SX1302_RADIO_TYPE_SX125X, SX1302_AGC_RADIO_GAIN_AUTO, SX1302_AGC_RADIO_GAIN_AUTO, 0) != LGW_HAL_SUCCESS) {
|
||||
// if (sx1302_agc_start(FW_VERSION_AGC, SX1302_RADIO_TYPE_SX125X, 1, 7, 0) != LGW_HAL_SUCCESS) {
|
||||
return LGW_HAL_ERROR;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
printf("Loading ARB fw\n");
|
||||
if (sx1302_arb_load_firmware(arb_firmware) != LGW_HAL_SUCCESS) {
|
||||
return LGW_HAL_ERROR;
|
||||
}
|
||||
if (sx1302_arb_start(FW_VERSION_ARB) != LGW_HAL_SUCCESS) {
|
||||
return LGW_HAL_ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
// lgw_reg_w(SX1302_REG_CAPTURE_RAM_CLOCK_GATE_OVERRIDE_CLK_OVERRIDE, 3);
|
||||
|
||||
/* Configure the Capture Ram block */
|
||||
lgw_reg_w(SX1302_REG_CAPTURE_RAM_CAPTURE_CFG_ENABLE, 1); /* Enable Capture RAM */
|
||||
lgw_reg_w(SX1302_REG_CAPTURE_RAM_CAPTURE_CFG_CAPTUREWRAP, 0); /* Capture once, and stop when memory is full */
|
||||
lgw_reg_w(SX1302_REG_CAPTURE_RAM_CAPTURE_CFG_RAMCONFIG, 0); /* RAM configuration, 0: 4kx32, 1: 2kx64 */
|
||||
fprintf(stdout, "Capture source: %d\n", capture_source);
|
||||
lgw_reg_w(SX1302_REG_CAPTURE_RAM_CAPTURE_SOURCE_A_SOURCEMUX, capture_source);
|
||||
|
||||
printf("Sampling frequency: %d\n", sampling_frequency[capture_source]);
|
||||
if (sampling_frequency[capture_source] != 0)
|
||||
{
|
||||
period_value = (32e6/sampling_frequency[capture_source]) - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr ,"ERROR: Sampling frequency is null\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// fprintf(stdout, "period_value=%04X\n", period_value);
|
||||
lgw_reg_w(SX1302_REG_CAPTURE_RAM_CAPTURE_PERIOD_0_CAPTUREPERIOD, period_value & 0xFF); // LSB
|
||||
lgw_reg_w(SX1302_REG_CAPTURE_RAM_CAPTURE_PERIOD_1_CAPTUREPERIOD, (period_value>>8) & 0xFF); // MSB
|
||||
|
||||
/* Read back registers */
|
||||
// lgw_reg_r(SX1302_REG_CAPTURE_RAM_CAPTURE_PERIOD_0_CAPTUREPERIOD, &val);
|
||||
// fprintf(stdout, "SX1302_REG_CAPTURE_RAM_CAPTURE_PERIOD_0_CAPTUREPERIOD value: %d\n", val);
|
||||
// lgw_reg_r(SX1302_REG_CAPTURE_RAM_CAPTURE_PERIOD_1_CAPTUREPERIOD, &val);
|
||||
// fprintf(stdout, "SX1302_REG_CAPTURE_RAM_CAPTURE_PERIOD_1_CAPTUREPERIOD value: %d\n", val);
|
||||
|
||||
/* Launch capture */
|
||||
lgw_reg_w(SX1302_REG_CAPTURE_RAM_CAPTURE_CFG_CAPTURESTART, 1);
|
||||
// lgw_reg_w(SX1302_REG_CAPTURE_RAM_CAPTURE_CFG_CAPTUREFORCETRIGGER, 1);
|
||||
|
||||
/* Poll Status.CapComplete */
|
||||
do{
|
||||
lgw_reg_r(SX1302_REG_CAPTURE_RAM_STATUS_CAPCOMPLETE, &val);
|
||||
|
||||
wait_ms(10);
|
||||
if ((quit_sig == 1) || (exit_sig == 1)) {
|
||||
break;
|
||||
}
|
||||
} while (val != 1);
|
||||
lgw_reg_w(SX1302_REG_CAPTURE_RAM_CAPTURE_CFG_CAPTURESTART, 0);
|
||||
|
||||
|
||||
// lgw_reg_r(SX1302_REG_CAPTURE_RAM_LAST_RAM_ADDR_0_LASTRAMADDR, &val);
|
||||
// fprintf(stdout, "SX1302_REG_CAPTURE_RAM_LAST_RAM_ADDR_0_LASTRAMADDR value: %02x\n", val);
|
||||
// lgw_reg_r(SX1302_REG_CAPTURE_RAM_LAST_RAM_ADDR_1_LASTRAMADDR, &val);
|
||||
// fprintf(stdout, "SX1302_REG_CAPTURE_RAM_LAST_RAM_ADDR_1_LASTRAMADDR value: %02x\n", val);
|
||||
|
||||
lgw_reg_w(SX1302_REG_COMMON_PAGE_PAGE, 1);
|
||||
lgw_mem_rb(0, capture_ram_buffer, CAPTURE_RAM_SIZE, false);
|
||||
lgw_reg_w(SX1302_REG_COMMON_PAGE_PAGE, 0);
|
||||
|
||||
printf("Data:\n");
|
||||
for (i = 0; i < CAPTURE_RAM_SIZE; i += 4)
|
||||
{
|
||||
if (((capture_source >= 2) && (capture_source <= 3)) || (capture_source == 9))
|
||||
{
|
||||
real = (int16_t)((((uint16_t)(capture_ram_buffer[i+3]) << 8) & 0xFF00) + ((uint16_t)capture_ram_buffer[i+2] & 0x00FF));
|
||||
imag = (int16_t)((((uint16_t)(capture_ram_buffer[i+1]) << 8) & 0xFF00) + ((uint16_t)capture_ram_buffer[i+0] & 0x00FF));
|
||||
real >>= 4; // 12 bits I
|
||||
imag >>= 4; // 12 bits Q
|
||||
}
|
||||
else if ((capture_source >= 4) && (capture_source <= 6))
|
||||
{
|
||||
real = (int16_t)((((uint16_t)(capture_ram_buffer[i+3]) << 8) & 0xFF00) + ((uint16_t)capture_ram_buffer[i+2] & 0x00FF)); // 16 bits I
|
||||
imag = (int16_t)((((uint16_t)(capture_ram_buffer[i+1]) << 8) & 0xFF00) + ((uint16_t)capture_ram_buffer[i+0] & 0x00FF)); // 16 bits Q
|
||||
}
|
||||
else if ((capture_source >= 10) && (capture_source <= 17))
|
||||
{
|
||||
real = (int8_t)(capture_ram_buffer[i+3]); // 8 bits I
|
||||
imag = (int8_t)(capture_ram_buffer[i+1]); // 8 bits Q
|
||||
}
|
||||
else
|
||||
{
|
||||
real = 0;
|
||||
imag = 0;
|
||||
}
|
||||
|
||||
if (((capture_source >= 2) && (capture_source <= 6)) || ((capture_source >= 9) && (capture_source <= 17)))
|
||||
{
|
||||
fprintf(stdout, "%d", real);
|
||||
if (imag >= 0)
|
||||
{
|
||||
fprintf(stdout, "+");
|
||||
}
|
||||
fprintf(stdout, "%di\n", imag);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("%02X ", capture_ram_buffer[i]);
|
||||
}
|
||||
}
|
||||
printf("End of Data\n");
|
||||
|
||||
#if FULL_INIT
|
||||
/* Board reset */
|
||||
if (system("./reset_lgw.sh stop") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,257 @@
|
|||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2019 Semtech
|
||||
|
||||
Description:
|
||||
Minimum test program for HAL timestamp counter handling
|
||||
|
||||
License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*/
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- DEPENDANCIES --------------------------------------------------------- */
|
||||
|
||||
/* fix an issue between POSIX and C99 */
|
||||
#if __STDC_VERSION__ >= 199901L
|
||||
#define _XOPEN_SOURCE 600
|
||||
#else
|
||||
#define _XOPEN_SOURCE 500
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "loragw_hal.h"
|
||||
#include "loragw_reg.h"
|
||||
#include "loragw_aux.h"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE MACROS ------------------------------------------------------- */
|
||||
|
||||
#define LINUXDEV_PATH_DEFAULT "/dev/spidev0.0"
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
|
||||
#define RAND_RANGE(min, max) (rand() % (max + 1 - min) + min)
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE CONSTANTS ---------------------------------------------------- */
|
||||
|
||||
#define DEFAULT_FREQ_HZ 868500000U
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- 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 ---------------------------------------------------- */
|
||||
|
||||
static void sig_handler(int sigio) {
|
||||
if (sigio == SIGQUIT) {
|
||||
quit_sig = 1;;
|
||||
} else if ((sigio == SIGINT) || (sigio == SIGTERM)) {
|
||||
exit_sig = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void usage(void) {
|
||||
//printf("Library version information: %s\n", lgw_version_info());
|
||||
printf( "Available options:\n");
|
||||
printf( " -h print this help\n");
|
||||
printf( " -k <uint> Concentrator clock source (Radio A or Radio B) [0..1]\n");
|
||||
printf( " -r <uint> Radio type (1255, 1257, 1250)\n");
|
||||
printf( " -p Test PPS trig counter when set\n" );
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- MAIN FUNCTION -------------------------------------------------------- */
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
/* SPI interfaces */
|
||||
const char spidev_path_default[] = LINUXDEV_PATH_DEFAULT;
|
||||
const char * spidev_path = spidev_path_default;
|
||||
|
||||
struct sigaction sigact; /* SIGQUIT&SIGINT&SIGTERM signal handling */
|
||||
|
||||
int i, x;
|
||||
uint32_t fa = DEFAULT_FREQ_HZ;
|
||||
uint32_t fb = DEFAULT_FREQ_HZ;
|
||||
unsigned int arg_u;
|
||||
uint8_t clocksource = 0;
|
||||
lgw_radio_type_t radio_type = LGW_RADIO_TYPE_NONE;
|
||||
|
||||
struct lgw_conf_board_s boardconf;
|
||||
struct lgw_conf_rxrf_s rfconf;
|
||||
struct lgw_conf_rxif_s ifconf;
|
||||
|
||||
uint32_t counter;
|
||||
bool trig_cnt = false;
|
||||
|
||||
const int32_t channel_if[9] = {
|
||||
-400000,
|
||||
-200000,
|
||||
0,
|
||||
-400000,
|
||||
-200000,
|
||||
0,
|
||||
200000,
|
||||
400000,
|
||||
-200000 /* lora service */
|
||||
};
|
||||
|
||||
const uint8_t channel_rfchain[9] = { 1, 1, 1, 0, 0, 0, 0, 0, 1 };
|
||||
|
||||
/* parse command line options */
|
||||
while ((i = getopt (argc, argv, "hk:r:p")) != -1) {
|
||||
switch (i) {
|
||||
case 'h':
|
||||
usage();
|
||||
return -1;
|
||||
break;
|
||||
case 'r': /* <uint> Radio type */
|
||||
i = sscanf(optarg, "%u", &arg_u);
|
||||
if ((i != 1) || ((arg_u != 1255) && (arg_u != 1257) && (arg_u != 1250))) {
|
||||
printf("ERROR: argument parsing of -r argument. Use -h to print help\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
switch (arg_u) {
|
||||
case 1255:
|
||||
radio_type = LGW_RADIO_TYPE_SX1255;
|
||||
break;
|
||||
case 1257:
|
||||
radio_type = LGW_RADIO_TYPE_SX1257;
|
||||
break;
|
||||
default: /* 1250 */
|
||||
radio_type = LGW_RADIO_TYPE_SX1250;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'k': /* <uint> Clock Source */
|
||||
i = sscanf(optarg, "%u", &arg_u);
|
||||
if ((i != 1) || (arg_u > 1)) {
|
||||
printf("ERROR: argument parsing of -k argument. Use -h to print help\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
clocksource = (uint8_t)arg_u;
|
||||
}
|
||||
break;
|
||||
case 'p':
|
||||
trig_cnt = true;
|
||||
break;
|
||||
default:
|
||||
printf("ERROR: argument parsing\n");
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
||||
printf("===== sx1302 counter test =====\n");
|
||||
|
||||
/* Board reset */
|
||||
if (system("./reset_lgw.sh start") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Configure the gateway */
|
||||
memset( &boardconf, 0, sizeof boardconf);
|
||||
boardconf.lorawan_public = true;
|
||||
boardconf.clksrc = clocksource;
|
||||
boardconf.full_duplex = false;
|
||||
strncpy(boardconf.spidev_path, spidev_path, sizeof boardconf.spidev_path);
|
||||
if (lgw_board_setconf(&boardconf) != LGW_HAL_SUCCESS) {
|
||||
printf("ERROR: failed to configure board\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* set configuration for RF chains */
|
||||
memset( &rfconf, 0, sizeof rfconf);
|
||||
rfconf.enable = true;
|
||||
rfconf.freq_hz = fa;
|
||||
rfconf.type = radio_type;
|
||||
rfconf.tx_enable = false;
|
||||
if (lgw_rxrf_setconf(0, &rfconf) != LGW_HAL_SUCCESS) {
|
||||
printf("ERROR: failed to configure rxrf 0\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
memset( &rfconf, 0, sizeof rfconf);
|
||||
rfconf.enable = true;
|
||||
rfconf.freq_hz = fb;
|
||||
rfconf.type = radio_type;
|
||||
rfconf.tx_enable = false;
|
||||
if (lgw_rxrf_setconf(1, &rfconf) != LGW_HAL_SUCCESS) {
|
||||
printf("ERROR: failed to configure rxrf 1\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* set configuration for LoRa multi-SF channels (bandwidth cannot be set) */
|
||||
memset(&ifconf, 0, sizeof(ifconf));
|
||||
for (i = 0; i < 9; i++) {
|
||||
ifconf.enable = true;
|
||||
ifconf.rf_chain = channel_rfchain[i];
|
||||
ifconf.freq_hz = channel_if[i];
|
||||
ifconf.datarate = DR_LORA_SF7;
|
||||
if (lgw_rxif_setconf(i, &ifconf) != LGW_HAL_SUCCESS) {
|
||||
printf("ERROR: failed to configure rxif %d\n", i);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
/* connect, configure and start the LoRa concentrator */
|
||||
x = lgw_start();
|
||||
if (x != 0) {
|
||||
printf("ERROR: failed to start the gateway\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* Loop until user quits */
|
||||
while( (quit_sig != 1) && (exit_sig != 1) ) {
|
||||
if (trig_cnt == false) {
|
||||
lgw_get_instcnt(&counter);
|
||||
} else {
|
||||
lgw_get_trigcnt(&counter);
|
||||
}
|
||||
wait_ms(10);
|
||||
}
|
||||
|
||||
/* Stop the gateway */
|
||||
x = lgw_stop();
|
||||
if (x != 0) {
|
||||
printf("ERROR: failed to stop the gateway\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* Board reset */
|
||||
if (system("./reset_lgw.sh stop") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
printf("=========== Test End ===========\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
|
@ -0,0 +1,415 @@
|
|||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2019 Semtech
|
||||
|
||||
Description:
|
||||
Minimum test program for the loragw_gps module
|
||||
|
||||
License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*/
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- DEPENDANCIES --------------------------------------------------------- */
|
||||
|
||||
/* fix an issue between POSIX and C99 */
|
||||
#if __STDC_VERSION__ >= 199901L
|
||||
#define _XOPEN_SOURCE 600
|
||||
#else
|
||||
#define _XOPEN_SOURCE 500
|
||||
#endif
|
||||
|
||||
#include <stdint.h> /* C99 types */
|
||||
#include <stdbool.h> /* bool type */
|
||||
#include <stdio.h> /* printf */
|
||||
#include <string.h> /* memset */
|
||||
#include <signal.h> /* sigaction */
|
||||
#include <stdlib.h> /* exit */
|
||||
#include <unistd.h> /* read */
|
||||
|
||||
#include "loragw_hal.h"
|
||||
#include "loragw_gps.h"
|
||||
#include "loragw_aux.h"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE MACROS ------------------------------------------------------- */
|
||||
|
||||
#define MATCH(a,b) ( ((int32_t)(a-b)<=1) && ((int32_t)(a-b)>=-1) ) /* tolerate 1µs */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE CONSTANTS ---------------------------------------------------- */
|
||||
|
||||
#define LINUXDEV_PATH_DEFAULT "/dev/spidev0.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 */
|
||||
|
||||
struct tref ppm_ref;
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE FUNCTIONS DECLARATION ---------------------------------------- */
|
||||
|
||||
static void sig_handler(int sigio);
|
||||
static void gps_process_sync(void);
|
||||
static void gps_process_coords(void);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE FUNCTIONS DEFINITION ----------------------------------------- */
|
||||
|
||||
void usage(void) {
|
||||
//printf("Library version information: %s\n", lgw_version_info());
|
||||
printf( "Available options:\n");
|
||||
printf( " -h print this help\n");
|
||||
printf( " -k <uint> Concentrator clock source (Radio A or Radio B) [0..1]\n");
|
||||
printf( " -r <uint> Radio type (1255, 1257, 1250)\n");
|
||||
}
|
||||
|
||||
static void sig_handler(int sigio) {
|
||||
if (sigio == SIGQUIT) {
|
||||
quit_sig = 1;;
|
||||
} else if ((sigio == SIGINT) || (sigio == SIGTERM)) {
|
||||
exit_sig = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void gps_process_sync(void) {
|
||||
/* variables for PPM pulse GPS synchronization */
|
||||
uint32_t ppm_tstamp;
|
||||
struct timespec ppm_gps;
|
||||
struct timespec ppm_utc;
|
||||
|
||||
/* variables for timestamp <-> GPS time conversions */
|
||||
uint32_t x, z;
|
||||
struct timespec y;
|
||||
|
||||
/* get GPS time for synchronization */
|
||||
int i = lgw_gps_get(&ppm_utc, &ppm_gps, NULL, NULL);
|
||||
if (i != LGW_GPS_SUCCESS) {
|
||||
printf(" No valid reference GPS time available, synchronization impossible.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* get timestamp for synchronization */
|
||||
i = lgw_get_trigcnt(&ppm_tstamp);
|
||||
if (i != LGW_HAL_SUCCESS) {
|
||||
printf(" Failed to read timestamp, synchronization impossible.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* try to update synchronize time reference with the new GPS & timestamp */
|
||||
i = lgw_gps_sync(&ppm_ref, ppm_tstamp, ppm_utc, ppm_gps);
|
||||
if (i != LGW_GPS_SUCCESS) {
|
||||
printf(" Synchronization error.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* display result */
|
||||
printf(" * Synchronization successful *\n");
|
||||
printf(" UTC reference time: %lld.%09ld\n", (long long)ppm_ref.utc.tv_sec, ppm_ref.utc.tv_nsec);
|
||||
printf(" GPS reference time: %lld.%09ld\n", (long long)ppm_ref.gps.tv_sec, ppm_ref.gps.tv_nsec);
|
||||
printf(" Internal counter reference value: %u\n", ppm_ref.count_us);
|
||||
printf(" Clock error: %.9f\n", ppm_ref.xtal_err);
|
||||
|
||||
x = ppm_tstamp + 500000;
|
||||
|
||||
/* CNT -> GPS -> CNT */
|
||||
printf("\n");
|
||||
printf(" * Test of timestamp counter <-> GPS value conversion *\n");
|
||||
printf(" Test value: %u\n", x);
|
||||
lgw_cnt2gps(ppm_ref, x, &y);
|
||||
printf(" Conversion to GPS: %lld.%09ld\n", (long long)y.tv_sec, y.tv_nsec);
|
||||
lgw_gps2cnt(ppm_ref, y, &z);
|
||||
printf(" Converted back: %u ==> %dµs\n", z, (int32_t)(z-x));
|
||||
/* Display test result */
|
||||
if (MATCH(x,z)) {
|
||||
printf(" ** PASS **: (SX1302 -> GPS -> SX1302) conversion MATCH\n");
|
||||
} else {
|
||||
printf(" ** FAILED **: (SX1302 -> GPS -> SX1302) conversion MISMATCH\n");
|
||||
}
|
||||
|
||||
/* CNT -> UTC -> CNT */
|
||||
printf("\n");
|
||||
printf(" * Test of timestamp counter <-> UTC value conversion *\n");
|
||||
printf(" Test value: %u\n", x);
|
||||
lgw_cnt2utc(ppm_ref, x, &y);
|
||||
printf(" Conversion to UTC: %lld.%09ld\n", (long long)y.tv_sec, y.tv_nsec);
|
||||
lgw_utc2cnt(ppm_ref, y, &z);
|
||||
printf(" Converted back: %u ==> %dµs\n", z, (int32_t)(z-x));
|
||||
/* Display test result */
|
||||
if (MATCH(x,z)) {
|
||||
printf(" ** PASS **: (SX1302 -> UTC -> SX1302) conversion MATCH\n");
|
||||
} else {
|
||||
printf(" ** FAILED **: (SX1302 -> UTC -> SX1302) conversion MISMATCH\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void gps_process_coords(void) {
|
||||
/* position variable */
|
||||
struct coord_s coord;
|
||||
struct coord_s gpserr;
|
||||
int i = lgw_gps_get(NULL, NULL, &coord, &gpserr);
|
||||
|
||||
/* update gateway coordinates */
|
||||
if (i == LGW_GPS_SUCCESS) {
|
||||
printf("\n");
|
||||
printf("# GPS coordinates: latitude %.5f, longitude %.5f, altitude %i m\n", coord.lat, coord.lon, coord.alt);
|
||||
printf("# GPS err: latitude %.5f, longitude %.5f, altitude %i m\n", gpserr.lat, gpserr.lon, gpserr.alt);
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- MAIN FUNCTION -------------------------------------------------------- */
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
/* SPI interfaces */
|
||||
const char spidev_path_default[] = LINUXDEV_PATH_DEFAULT;
|
||||
const char * spidev_path = spidev_path_default;
|
||||
|
||||
struct sigaction sigact; /* SIGQUIT&SIGINT&SIGTERM signal handling */
|
||||
|
||||
int i;
|
||||
unsigned int arg_u;
|
||||
|
||||
/* concentrator variables */
|
||||
uint8_t clocksource = 0;
|
||||
lgw_radio_type_t radio_type = LGW_RADIO_TYPE_NONE;
|
||||
struct lgw_conf_board_s boardconf;
|
||||
struct lgw_conf_rxrf_s rfconf;
|
||||
|
||||
/* serial variables */
|
||||
char serial_buff[128]; /* buffer to receive GPS data */
|
||||
size_t wr_idx = 0; /* pointer to end of chars in buffer */
|
||||
int gps_tty_dev; /* file descriptor to the serial port of the GNSS module */
|
||||
|
||||
/* NMEA/UBX variables */
|
||||
enum gps_msg latest_msg; /* keep track of latest NMEA/UBX message parsed */
|
||||
|
||||
/* parse command line options */
|
||||
while ((i = getopt (argc, argv, "hk:r:")) != -1) {
|
||||
switch (i) {
|
||||
case 'h':
|
||||
usage();
|
||||
return -1;
|
||||
break;
|
||||
case 'r': /* <uint> Radio type */
|
||||
i = sscanf(optarg, "%u", &arg_u);
|
||||
if ((i != 1) || ((arg_u != 1255) && (arg_u != 1257) && (arg_u != 1250))) {
|
||||
printf("ERROR: argument parsing of -r argument. Use -h to print help\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
switch (arg_u) {
|
||||
case 1255:
|
||||
radio_type = LGW_RADIO_TYPE_SX1255;
|
||||
break;
|
||||
case 1257:
|
||||
radio_type = LGW_RADIO_TYPE_SX1257;
|
||||
break;
|
||||
default: /* 1250 */
|
||||
radio_type = LGW_RADIO_TYPE_SX1250;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'k': /* <uint> Clock Source */
|
||||
i = sscanf(optarg, "%u", &arg_u);
|
||||
if ((i != 1) || (arg_u > 1)) {
|
||||
printf("ERROR: argument parsing of -k argument. Use -h to print help\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
clocksource = (uint8_t)arg_u;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printf("ERROR: argument parsing\n");
|
||||
usage();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check arguments */
|
||||
if (radio_type == LGW_RADIO_TYPE_NONE) {
|
||||
printf("ERROR: radio type must be specified\n");
|
||||
usage();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
||||
/* Intro message and library information */
|
||||
printf("Beginning of test for loragw_gps.c\n");
|
||||
printf("*** Library version information ***\n%s\n***\n", lgw_version_info());
|
||||
|
||||
/* Board reset */
|
||||
if (system("./reset_lgw.sh start") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Open and configure GPS */
|
||||
i = lgw_gps_enable("/dev/ttyS0", "ubx7", 0, &gps_tty_dev);
|
||||
if (i != LGW_GPS_SUCCESS) {
|
||||
printf("ERROR: Failed to enable GPS\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* start concentrator (default conf for IoT SK) */
|
||||
/* board config */
|
||||
memset(&boardconf, 0, sizeof(boardconf));
|
||||
boardconf.lorawan_public = true;
|
||||
boardconf.clksrc = clocksource;
|
||||
boardconf.full_duplex = false;
|
||||
strncpy(boardconf.spidev_path, spidev_path, sizeof boardconf.spidev_path);
|
||||
if (lgw_board_setconf(&boardconf) != LGW_HAL_SUCCESS) {
|
||||
printf("ERROR: failed to configure board\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* set configuration for RF chains */
|
||||
memset( &rfconf, 0, sizeof rfconf);
|
||||
rfconf.enable = true;
|
||||
rfconf.freq_hz = 868000000;
|
||||
rfconf.rssi_offset = 0.0;
|
||||
rfconf.type = radio_type;
|
||||
rfconf.tx_enable = false;
|
||||
if (lgw_rxrf_setconf(0, &rfconf) != LGW_HAL_SUCCESS) {
|
||||
printf("ERROR: failed to configure rxrf 0\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
memset( &rfconf, 0, sizeof rfconf);
|
||||
rfconf.enable = true;
|
||||
rfconf.freq_hz = 868000000;
|
||||
rfconf.rssi_offset = 0.0;
|
||||
rfconf.type = radio_type;
|
||||
rfconf.tx_enable = false;
|
||||
if (lgw_rxrf_setconf(1, &rfconf) != LGW_HAL_SUCCESS) {
|
||||
printf("ERROR: failed to configure rxrf 1\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* start */
|
||||
if (lgw_start() != LGW_HAL_SUCCESS) {
|
||||
printf("ERROR: IMPOSSIBLE TO START THE GATEWAY\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* initialize some variables before loop */
|
||||
memset(serial_buff, 0, sizeof serial_buff);
|
||||
memset(&ppm_ref, 0, sizeof ppm_ref);
|
||||
|
||||
/* loop until user action */
|
||||
while ((quit_sig != 1) && (exit_sig != 1)) {
|
||||
size_t rd_idx = 0;
|
||||
size_t frame_end_idx = 0;
|
||||
|
||||
/* blocking non-canonical read on serial port */
|
||||
ssize_t nb_char = read(gps_tty_dev, serial_buff + wr_idx, LGW_GPS_MIN_MSG_SIZE);
|
||||
if (nb_char <= 0) {
|
||||
printf("WARNING: [gps] read() returned value %d\n", nb_char);
|
||||
continue;
|
||||
}
|
||||
wr_idx += (size_t)nb_char;
|
||||
|
||||
/*******************************************
|
||||
* Scan buffer for UBX/NMEA sync chars and *
|
||||
* attempt to decode frame if one is found *
|
||||
*******************************************/
|
||||
while (rd_idx < wr_idx) {
|
||||
size_t frame_size = 0;
|
||||
|
||||
/* Scan buffer for UBX sync char */
|
||||
if (serial_buff[rd_idx] == LGW_GPS_UBX_SYNC_CHAR) {
|
||||
|
||||
/***********************
|
||||
* Found UBX sync char *
|
||||
***********************/
|
||||
latest_msg = lgw_parse_ubx(&serial_buff[rd_idx], (wr_idx - rd_idx), &frame_size);
|
||||
|
||||
if (frame_size > 0) {
|
||||
if (latest_msg == INCOMPLETE) {
|
||||
/* UBX header found but frame appears to be missing bytes */
|
||||
frame_size = 0;
|
||||
} else if (latest_msg == INVALID) {
|
||||
/* message header received but message appears to be corrupted */
|
||||
printf("WARNING: [gps] could not get a valid message from GPS (no time)\n");
|
||||
frame_size = 0;
|
||||
} else if (latest_msg == UBX_NAV_TIMEGPS) {
|
||||
printf("\n~~ UBX NAV-TIMEGPS sentence, triggering synchronization attempt ~~\n");
|
||||
gps_process_sync();
|
||||
}
|
||||
}
|
||||
} else if(serial_buff[rd_idx] == LGW_GPS_NMEA_SYNC_CHAR) {
|
||||
/************************
|
||||
* Found NMEA sync char *
|
||||
************************/
|
||||
/* scan for NMEA end marker (LF = 0x0a) */
|
||||
char* nmea_end_ptr = memchr(&serial_buff[rd_idx],(int)0x0a, (wr_idx - rd_idx));
|
||||
|
||||
if (nmea_end_ptr) {
|
||||
/* found end marker */
|
||||
frame_size = nmea_end_ptr - &serial_buff[rd_idx] + 1;
|
||||
latest_msg = lgw_parse_nmea(&serial_buff[rd_idx], frame_size);
|
||||
|
||||
if(latest_msg == INVALID || latest_msg == UNKNOWN) {
|
||||
/* checksum failed */
|
||||
frame_size = 0;
|
||||
} else if (latest_msg == NMEA_RMC) { /* Get location from RMC frames */
|
||||
gps_process_coords();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (frame_size > 0) {
|
||||
/* At this point message is a checksum verified frame
|
||||
we're processed or ignored. Remove frame from buffer */
|
||||
rd_idx += frame_size;
|
||||
frame_end_idx = rd_idx;
|
||||
} else {
|
||||
rd_idx++;
|
||||
}
|
||||
} /* ...for(rd_idx = 0... */
|
||||
|
||||
if (frame_end_idx) {
|
||||
/* Frames have been processed. Remove bytes to end of last processed frame */
|
||||
memcpy(serial_buff,&serial_buff[frame_end_idx],wr_idx - frame_end_idx);
|
||||
wr_idx -= frame_end_idx;
|
||||
} /* ...for(rd_idx = 0... */
|
||||
|
||||
/* Prevent buffer overflow */
|
||||
if ((sizeof(serial_buff) - wr_idx) < LGW_GPS_MIN_MSG_SIZE) {
|
||||
memcpy(serial_buff,&serial_buff[LGW_GPS_MIN_MSG_SIZE],wr_idx - LGW_GPS_MIN_MSG_SIZE);
|
||||
wr_idx -= LGW_GPS_MIN_MSG_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
/* clean up before leaving */
|
||||
if (exit_sig == 1) {
|
||||
lgw_gps_disable(gps_tty_dev);
|
||||
lgw_stop();
|
||||
}
|
||||
|
||||
/* Board reset */
|
||||
if (system("./reset_lgw.sh stop") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
printf("\nEnd of test for loragw_gps.c\n");
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
|
@ -0,0 +1,320 @@
|
|||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2019 Semtech
|
||||
|
||||
Description:
|
||||
Minimum test program for HAL RX capability
|
||||
|
||||
License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*/
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- DEPENDANCIES --------------------------------------------------------- */
|
||||
|
||||
/* fix an issue between POSIX and C99 */
|
||||
#if __STDC_VERSION__ >= 199901L
|
||||
#define _XOPEN_SOURCE 600
|
||||
#else
|
||||
#define _XOPEN_SOURCE 500
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "loragw_hal.h"
|
||||
#include "loragw_reg.h"
|
||||
#include "loragw_aux.h"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE MACROS ------------------------------------------------------- */
|
||||
|
||||
#define LINUXDEV_PATH_DEFAULT "/dev/spidev0.0"
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
|
||||
#define RAND_RANGE(min, max) (rand() % (max + 1 - min) + min)
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE CONSTANTS ---------------------------------------------------- */
|
||||
|
||||
#define DEFAULT_FREQ_HZ 868500000U
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- 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 ---------------------------------------------------- */
|
||||
|
||||
static void sig_handler(int sigio) {
|
||||
if (sigio == SIGQUIT) {
|
||||
quit_sig = 1;
|
||||
} else if ((sigio == SIGINT) || (sigio == SIGTERM)) {
|
||||
exit_sig = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void usage(void) {
|
||||
//printf("Library version information: %s\n", lgw_version_info());
|
||||
printf( "Available options:\n");
|
||||
printf( " -h print this help\n");
|
||||
printf( " -k <uint> Concentrator clock source (Radio A or Radio B) [0..1]\n");
|
||||
printf( " -r <uint> Radio type (1255, 1257, 1250)\n");
|
||||
printf( " -a <float> Radio A RX frequency in MHz\n");
|
||||
printf( " -b <float> Radio B RX frequency in MHz\n");
|
||||
printf( " -n <uint> number of packet received with CRC OK for each HAL start/stop loop\n");
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- MAIN FUNCTION -------------------------------------------------------- */
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
/* SPI interfaces */
|
||||
const char spidev_path_default[] = LINUXDEV_PATH_DEFAULT;
|
||||
const char * spidev_path = spidev_path_default;
|
||||
|
||||
struct sigaction sigact; /* SIGQUIT&SIGINT&SIGTERM signal handling */
|
||||
|
||||
int i, j, x;
|
||||
uint32_t fa = DEFAULT_FREQ_HZ;
|
||||
uint32_t fb = DEFAULT_FREQ_HZ;
|
||||
double arg_d = 0.0;
|
||||
unsigned int arg_u;
|
||||
uint8_t clocksource = 0;
|
||||
lgw_radio_type_t radio_type = LGW_RADIO_TYPE_NONE;
|
||||
|
||||
struct lgw_conf_board_s boardconf;
|
||||
struct lgw_conf_rxrf_s rfconf;
|
||||
struct lgw_conf_rxif_s ifconf;
|
||||
struct lgw_pkt_rx_s rxpkt[16];
|
||||
|
||||
unsigned long nb_pkt_crc_ok = 0, nb_loop = 1, cnt_loop;
|
||||
int nb_pkt;
|
||||
|
||||
const int32_t channel_if[9] = {
|
||||
-400000,
|
||||
-200000,
|
||||
0,
|
||||
-400000,
|
||||
-200000,
|
||||
0,
|
||||
200000,
|
||||
400000,
|
||||
-200000 /* lora service */
|
||||
};
|
||||
|
||||
const uint8_t channel_rfchain[9] = { 1, 1, 1, 0, 0, 0, 0, 0, 1 };
|
||||
|
||||
/* parse command line options */
|
||||
while ((i = getopt (argc, argv, "ha:b:k:r:n:")) != -1) {
|
||||
switch (i) {
|
||||
case 'h':
|
||||
usage();
|
||||
return -1;
|
||||
break;
|
||||
case 'r': /* <uint> Radio type */
|
||||
i = sscanf(optarg, "%u", &arg_u);
|
||||
if ((i != 1) || ((arg_u != 1255) && (arg_u != 1257) && (arg_u != 1250))) {
|
||||
printf("ERROR: argument parsing of -r argument. Use -h to print help\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
switch (arg_u) {
|
||||
case 1255:
|
||||
radio_type = LGW_RADIO_TYPE_SX1255;
|
||||
break;
|
||||
case 1257:
|
||||
radio_type = LGW_RADIO_TYPE_SX1257;
|
||||
break;
|
||||
default: /* 1250 */
|
||||
radio_type = LGW_RADIO_TYPE_SX1250;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'k': /* <uint> Clock Source */
|
||||
i = sscanf(optarg, "%u", &arg_u);
|
||||
if ((i != 1) || (arg_u > 1)) {
|
||||
printf("ERROR: argument parsing of -k argument. Use -h to print help\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
clocksource = (uint8_t)arg_u;
|
||||
}
|
||||
break;
|
||||
case 'a': /* <float> Radio A RX frequency in MHz */
|
||||
i = sscanf(optarg, "%lf", &arg_d);
|
||||
if (i != 1) {
|
||||
printf("ERROR: argument parsing of -f argument. Use -h to print help\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
fa = (uint32_t)((arg_d*1e6) + 0.5); /* .5 Hz offset to get rounding instead of truncating */
|
||||
}
|
||||
break;
|
||||
case 'b': /* <float> Radio B RX frequency in MHz */
|
||||
i = sscanf(optarg, "%lf", &arg_d);
|
||||
if (i != 1) {
|
||||
printf("ERROR: argument parsing of -f argument. Use -h to print help\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
fb = (uint32_t)((arg_d*1e6) + 0.5); /* .5 Hz offset to get rounding instead of truncating */
|
||||
}
|
||||
break;
|
||||
case 'n': /* <uint> NUmber of packets to be received before exiting */
|
||||
i = sscanf(optarg, "%u", &arg_u);
|
||||
if (i != 1) {
|
||||
printf("ERROR: argument parsing of -n argument. Use -h to print help\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
nb_loop = arg_u;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printf("ERROR: argument parsing\n");
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
||||
printf("===== sx1302 HAL RX test =====\n");
|
||||
|
||||
/* Configure the gateway */
|
||||
memset( &boardconf, 0, sizeof boardconf);
|
||||
boardconf.lorawan_public = true;
|
||||
boardconf.clksrc = clocksource;
|
||||
boardconf.full_duplex = false;
|
||||
strncpy(boardconf.spidev_path, spidev_path, sizeof boardconf.spidev_path);
|
||||
if (lgw_board_setconf(&boardconf) != LGW_HAL_SUCCESS) {
|
||||
printf("ERROR: failed to configure board\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* set configuration for RF chains */
|
||||
memset( &rfconf, 0, sizeof rfconf);
|
||||
rfconf.enable = true;
|
||||
rfconf.freq_hz = fa;
|
||||
rfconf.type = radio_type;
|
||||
rfconf.tx_enable = false;
|
||||
if (lgw_rxrf_setconf(0, &rfconf) != LGW_HAL_SUCCESS) {
|
||||
printf("ERROR: failed to configure rxrf 0\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
memset( &rfconf, 0, sizeof rfconf);
|
||||
rfconf.enable = true;
|
||||
rfconf.freq_hz = fb;
|
||||
rfconf.type = radio_type;
|
||||
rfconf.tx_enable = false;
|
||||
if (lgw_rxrf_setconf(1, &rfconf) != LGW_HAL_SUCCESS) {
|
||||
printf("ERROR: failed to configure rxrf 1\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* set configuration for LoRa multi-SF channels (bandwidth cannot be set) */
|
||||
memset(&ifconf, 0, sizeof(ifconf));
|
||||
for (i = 0; i < 9; i++) {
|
||||
ifconf.enable = true;
|
||||
ifconf.rf_chain = channel_rfchain[i];
|
||||
ifconf.freq_hz = channel_if[i];
|
||||
ifconf.datarate = DR_LORA_SF7;
|
||||
if (lgw_rxif_setconf(i, &ifconf) != LGW_HAL_SUCCESS) {
|
||||
printf("ERROR: failed to configure rxif %d\n", i);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Loop until user quits */
|
||||
cnt_loop = 0;
|
||||
while( (quit_sig != 1) && (exit_sig != 1) )
|
||||
{
|
||||
cnt_loop += 1;
|
||||
|
||||
/* Board reset */
|
||||
if (system("./reset_lgw.sh start") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* connect, configure and start the LoRa concentrator */
|
||||
x = lgw_start();
|
||||
if (x != 0) {
|
||||
printf("ERROR: failed to start the gateway\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* Loop until we have enough packets with CRC OK */
|
||||
printf("Waiting for packets...\n");
|
||||
nb_pkt_crc_ok = 0;
|
||||
while ((nb_pkt_crc_ok < nb_loop) && (quit_sig != 1) && (exit_sig != 1)) {
|
||||
/* fetch N packets */
|
||||
nb_pkt = lgw_receive(ARRAY_SIZE(rxpkt), rxpkt);
|
||||
|
||||
if (nb_pkt == 0) {
|
||||
wait_ms(10);
|
||||
} else {
|
||||
printf("Received %d packets\n", nb_pkt);
|
||||
for (i = 0; i < nb_pkt; i++) {
|
||||
if (rxpkt[i].status == STAT_CRC_OK) {
|
||||
nb_pkt_crc_ok += 1;
|
||||
}
|
||||
printf("\n----- %s packet -----\n", (rxpkt[i].modulation == MOD_LORA) ? "LoRa" : "FSK");
|
||||
printf(" count_us: %u\n", rxpkt[i].count_us);
|
||||
printf(" size: %u\n", rxpkt[i].size);
|
||||
printf(" chan: %u\n", rxpkt[i].if_chain);
|
||||
printf(" status: 0x%02X\n", rxpkt[i].status);
|
||||
printf(" datr: %u\n", rxpkt[i].datarate);
|
||||
printf(" codr: %u\n", rxpkt[i].coderate);
|
||||
printf(" rf_chain %u\n", rxpkt[i].rf_chain);
|
||||
printf(" freq_hz %u\n", rxpkt[i].freq_hz);
|
||||
printf(" snr_avg: %.1f\n", rxpkt[i].snr);
|
||||
printf(" rssi_chan:%.1f\n", rxpkt[i].rssic);
|
||||
printf(" rssi_sig :%.1f\n", rxpkt[i].rssis);
|
||||
printf(" crc: 0x%04X\n", rxpkt[i].crc);
|
||||
for (j = 0; j < rxpkt[i].size; j++) {
|
||||
printf("%02X ", rxpkt[i].payload[j]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printf( "\nNb valid packets received: %lu CRC OK (%lu)\n", nb_pkt_crc_ok, cnt_loop );
|
||||
|
||||
/* Stop the gateway */
|
||||
x = lgw_stop();
|
||||
if (x != 0) {
|
||||
printf("ERROR: failed to stop the gateway\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* Board reset */
|
||||
if (system("./reset_lgw.sh stop") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
printf("=========== Test End ===========\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
|
@ -0,0 +1,583 @@
|
|||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2019 Semtech
|
||||
|
||||
Description:
|
||||
Minimum test program for HAL TX capability
|
||||
|
||||
License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*/
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- DEPENDANCIES --------------------------------------------------------- */
|
||||
|
||||
/* fix an issue between POSIX and C99 */
|
||||
#if __STDC_VERSION__ >= 199901L
|
||||
#define _XOPEN_SOURCE 600
|
||||
#else
|
||||
#define _XOPEN_SOURCE 500
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <math.h>
|
||||
#include <signal.h> /* sigaction */
|
||||
#include <getopt.h> /* getopt_long */
|
||||
|
||||
#include "loragw_hal.h"
|
||||
#include "loragw_reg.h"
|
||||
#include "loragw_aux.h"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE MACROS ------------------------------------------------------- */
|
||||
|
||||
#define RAND_RANGE(min, max) (rand() % (max + 1 - min) + min)
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE CONSTANTS ---------------------------------------------------- */
|
||||
|
||||
#define LINUXDEV_PATH_DEFAULT "/dev/spidev0.0"
|
||||
|
||||
#define DEFAULT_CLK_SRC 0
|
||||
#define DEFAULT_FREQ_HZ 868500000U
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE VARIABLES ---------------------------------------------------- */
|
||||
|
||||
/* Signal handling 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 ---------------------------------------------------- */
|
||||
|
||||
/* describe command line options */
|
||||
void usage(void) {
|
||||
//printf("Library version information: %s\n", lgw_version_info());
|
||||
printf("Available options:\n");
|
||||
printf(" -h print this help\n");
|
||||
printf(" -k <uint> Concentrator clock source (Radio A or Radio B) [0..1]\n");
|
||||
printf(" -c <uint> RF chain to be used for TX (Radio A or Radio B) [0..1]\n");
|
||||
printf(" -r <uint> Radio type (1255, 1257, 1250)\n");
|
||||
printf(" -f <float> Radio TX frequency in MHz\n");
|
||||
printf(" -m <str> modulation type ['CW', 'LORA', 'FSK']\n");
|
||||
printf(" -o <int> CW frequency offset from Radio TX frequency in kHz [-65..65]\n");
|
||||
printf(" -s <uint> LoRa datarate 0:random, [5..12]\n");
|
||||
printf(" -b <uint> LoRa bandwidth in khz 0:random, [125, 250, 500]\n");
|
||||
printf(" -l <uint> FSK/LoRa preamble length, [6..65535]\n");
|
||||
printf(" -d <uint> FSK frequency deviation in kHz [1:250]\n");
|
||||
printf(" -q <float> FSK bitrate in kbps [0.5:250]\n");
|
||||
printf(" -n <uint> Number of packets to be sent\n");
|
||||
printf(" -z <uint> size of packets to be sent 0:random, [9..255]\n");
|
||||
printf(" -t <uint> TX mode timestamped with delay in ms. If delay is 0, TX mode GPS trigger\n");
|
||||
printf(" -p <int> RF power in dBm\n");
|
||||
printf(" -i Send LoRa packet using inverted modulation polarity\n");
|
||||
printf( "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" );
|
||||
printf(" --pa <uint> PA gain SX125x:[0..3], SX1250:[0,1]\n");
|
||||
printf(" --dig <uint> sx1302 digital gain for sx125x [0..3]\n");
|
||||
printf(" --dac <uint> sx125x DAC gain [0..3]\n");
|
||||
printf(" --mix <uint> sx125x MIX gain [5..15]\n");
|
||||
printf(" --pwid <uint> sx1250 power index [0..22]\n");
|
||||
printf( "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" );
|
||||
printf(" --nhdr Send LoRa packet with implicit header\n");
|
||||
printf( "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" );
|
||||
printf(" --loop Number of loops for HAL start/stop (HAL unitary test)\n");
|
||||
}
|
||||
|
||||
/* handle signals */
|
||||
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)
|
||||
{
|
||||
int i, x;
|
||||
uint32_t ft = DEFAULT_FREQ_HZ;
|
||||
int8_t rf_power = 0;
|
||||
uint8_t sf = 0;
|
||||
uint16_t bw_khz = 0;
|
||||
uint32_t nb_pkt = 1;
|
||||
unsigned int nb_loop = 1, cnt_loop;
|
||||
uint8_t size = 0;
|
||||
char mod[64] = "LORA";
|
||||
float br_kbps = 50;
|
||||
uint8_t fdev_khz = 25;
|
||||
int8_t freq_offset = 0;
|
||||
double arg_d = 0.0;
|
||||
unsigned int arg_u;
|
||||
int arg_i;
|
||||
char arg_s[64];
|
||||
float xf = 0.0;
|
||||
uint8_t clocksource = 0;
|
||||
uint8_t rf_chain = 0;
|
||||
lgw_radio_type_t radio_type = LGW_RADIO_TYPE_NONE;
|
||||
uint16_t preamble = 8;
|
||||
bool invert_pol = false;
|
||||
bool no_header = false;
|
||||
|
||||
struct lgw_conf_board_s boardconf;
|
||||
struct lgw_conf_rxrf_s rfconf;
|
||||
struct lgw_pkt_tx_s pkt;
|
||||
struct lgw_tx_gain_lut_s txlut; /* TX gain table */
|
||||
uint8_t tx_status;
|
||||
uint32_t count_us;
|
||||
uint32_t trig_delay_us = 1000000;
|
||||
bool trig_delay = false;
|
||||
|
||||
/* SPI interfaces */
|
||||
const char spidev_path_default[] = LINUXDEV_PATH_DEFAULT;
|
||||
const char * spidev_path = spidev_path_default;
|
||||
|
||||
static struct sigaction sigact; /* SIGQUIT&SIGINT&SIGTERM signal handling */
|
||||
|
||||
/* Initialize TX gain LUT */
|
||||
txlut.size = 0;
|
||||
memset(txlut.lut, 0, sizeof txlut.lut);
|
||||
|
||||
/* Parameter parsing */
|
||||
int option_index = 0;
|
||||
static struct option long_options[] = {
|
||||
{"pa", required_argument, 0, 0},
|
||||
{"dac", required_argument, 0, 0},
|
||||
{"dig", required_argument, 0, 0},
|
||||
{"mix", required_argument, 0, 0},
|
||||
{"pwid", required_argument, 0, 0},
|
||||
{"loop", required_argument, 0, 0},
|
||||
{"nhdr", no_argument, 0, 0},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
/* parse command line options */
|
||||
while ((i = getopt_long (argc, argv, "hif:s:b:n:z:p:k:r:c:l:t:m:o:q:d:", long_options, &option_index)) != -1) {
|
||||
switch (i) {
|
||||
case 'h':
|
||||
usage();
|
||||
return -1;
|
||||
break;
|
||||
case 'i': /* Send packet using inverted modulation polarity */
|
||||
invert_pol = true;
|
||||
break;
|
||||
case 'r': /* <uint> Radio type */
|
||||
i = sscanf(optarg, "%u", &arg_u);
|
||||
if ((i != 1) || ((arg_u != 1255) && (arg_u != 1257) && (arg_u != 1250))) {
|
||||
printf("ERROR: argument parsing of -r argument. Use -h to print help\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
switch (arg_u) {
|
||||
case 1255:
|
||||
radio_type = LGW_RADIO_TYPE_SX1255;
|
||||
break;
|
||||
case 1257:
|
||||
radio_type = LGW_RADIO_TYPE_SX1257;
|
||||
break;
|
||||
default: /* 1250 */
|
||||
radio_type = LGW_RADIO_TYPE_SX1250;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'l': /* <uint> LoRa/FSK preamble length */
|
||||
i = sscanf(optarg, "%u", &arg_u);
|
||||
if ((i != 1) || (arg_u > 65535)) {
|
||||
printf("ERROR: argument parsing of -l argument. Use -h to print help\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
preamble = (uint16_t)arg_u;
|
||||
}
|
||||
break;
|
||||
case 'm': /* <str> Modulation type */
|
||||
i = sscanf(optarg, "%s", arg_s);
|
||||
if ((i != 1) || ((strcmp(arg_s, "CW") != 0) && (strcmp(arg_s, "LORA") != 0) && (strcmp(arg_s, "FSK")))) {
|
||||
printf("ERROR: invalid modulation type\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
sprintf(mod, "%s", arg_s);
|
||||
}
|
||||
break;
|
||||
case 'o': /* <int> CW frequency offset from Radio TX frequency */
|
||||
i = sscanf(optarg, "%d", &arg_i);
|
||||
if ((arg_i < -65) || (arg_i > 65)) {
|
||||
printf("ERROR: invalid frequency offset\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
freq_offset = (int32_t)arg_i;
|
||||
}
|
||||
break;
|
||||
case 'd': /* <uint> FSK frequency deviation */
|
||||
i = sscanf(optarg, "%u", &arg_u);
|
||||
if ((i != 1) || (arg_u < 1) || (arg_u > 250)) {
|
||||
printf("ERROR: invalid FSK frequency deviation\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
fdev_khz = (uint8_t)arg_u;
|
||||
}
|
||||
break;
|
||||
case 'q': /* <float> FSK bitrate */
|
||||
i = sscanf(optarg, "%f", &xf);
|
||||
if ((i != 1) || (xf < 0.5) || (xf > 250)) {
|
||||
printf("ERROR: invalid FSK bitrate\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
br_kbps = xf;
|
||||
}
|
||||
break;
|
||||
case 't': /* <uint> Trigger delay in ms */
|
||||
i = sscanf(optarg, "%u", &arg_u);
|
||||
if (i != 1) {
|
||||
printf("ERROR: argument parsing of -t argument. Use -h to print help\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
trig_delay = true;
|
||||
trig_delay_us = (uint32_t)(arg_u * 1E3);
|
||||
}
|
||||
break;
|
||||
case 'k': /* <uint> Clock Source */
|
||||
i = sscanf(optarg, "%u", &arg_u);
|
||||
if ((i != 1) || (arg_u > 1)) {
|
||||
printf("ERROR: argument parsing of -k argument. Use -h to print help\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
clocksource = (uint8_t)arg_u;
|
||||
}
|
||||
break;
|
||||
case 'c': /* <uint> RF chain */
|
||||
i = sscanf(optarg, "%u", &arg_u);
|
||||
if ((i != 1) || (arg_u > 1)) {
|
||||
printf("ERROR: argument parsing of -c argument. Use -h to print help\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
rf_chain = (uint8_t)arg_u;
|
||||
}
|
||||
break;
|
||||
case 'f': /* <float> Radio TX frequency in MHz */
|
||||
i = sscanf(optarg, "%lf", &arg_d);
|
||||
if (i != 1) {
|
||||
printf("ERROR: argument parsing of -f argument. Use -h to print help\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
ft = (uint32_t)((arg_d*1e6) + 0.5); /* .5 Hz offset to get rounding instead of truncating */
|
||||
}
|
||||
break;
|
||||
case 's': /* <uint> LoRa datarate */
|
||||
i = sscanf(optarg, "%u", &arg_u);
|
||||
if ((i != 1) || (arg_u < 5) || (arg_u > 12)) {
|
||||
printf("ERROR: argument parsing of -s argument. Use -h to print help\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
sf = (uint8_t)arg_u;
|
||||
}
|
||||
break;
|
||||
case 'b': /* <uint> LoRa bandwidth in khz */
|
||||
i = sscanf(optarg, "%u", &arg_u);
|
||||
if ((i != 1) || ((arg_u != 125) && (arg_u != 250) && (arg_u != 500))) {
|
||||
printf("ERROR: argument parsing of -b argument. Use -h to print help\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
bw_khz = (uint16_t)arg_u;
|
||||
}
|
||||
break;
|
||||
case 'n': /* <uint> Number of packets to be sent */
|
||||
i = sscanf(optarg, "%u", &arg_u);
|
||||
if (i != 1) {
|
||||
printf("ERROR: argument parsing of -n argument. Use -h to print help\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
nb_pkt = (uint32_t)arg_u;
|
||||
}
|
||||
break;
|
||||
case 'p': /* <int> RF power */
|
||||
i = sscanf(optarg, "%d", &arg_i);
|
||||
if (i != 1) {
|
||||
printf("ERROR: argument parsing of -p argument. Use -h to print help\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
rf_power = (int8_t)arg_i;
|
||||
txlut.size = 1;
|
||||
txlut.lut[0].rf_power = rf_power;
|
||||
}
|
||||
break;
|
||||
case 'z': /* <uint> packet size */
|
||||
i = sscanf(optarg, "%u", &arg_u);
|
||||
if ((i != 1) || (arg_u < 9) || (arg_u > 255)) {
|
||||
printf("ERROR: argument parsing of -z argument. Use -h to print help\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
size = (uint8_t)arg_u;
|
||||
}
|
||||
break;
|
||||
case 0:
|
||||
if (strcmp(long_options[option_index].name, "pa") == 0) {
|
||||
i = sscanf(optarg, "%u", &arg_u);
|
||||
if ((i != 1) || (arg_u > 3)) {
|
||||
printf("ERROR: argument parsing of --pa argument. Use -h to print help\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
txlut.size = 1;
|
||||
txlut.lut[0].pa_gain = (uint8_t)arg_u;
|
||||
}
|
||||
} else if (strcmp(long_options[option_index].name, "dac") == 0) {
|
||||
i = sscanf(optarg, "%u", &arg_u);
|
||||
if ((i != 1) || (arg_u > 3)) {
|
||||
printf("ERROR: argument parsing of --dac argument. Use -h to print help\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
txlut.size = 1;
|
||||
txlut.lut[0].dac_gain = (uint8_t)arg_u;
|
||||
}
|
||||
} else if (strcmp(long_options[option_index].name, "mix") == 0) {
|
||||
i = sscanf(optarg, "%u", &arg_u);
|
||||
if ((i != 1) || (arg_u > 15)) {
|
||||
printf("ERROR: argument parsing of --mix argument. Use -h to print help\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
txlut.size = 1;
|
||||
txlut.lut[0].mix_gain = (uint8_t)arg_u;
|
||||
}
|
||||
} else if (strcmp(long_options[option_index].name, "dig") == 0) {
|
||||
i = sscanf(optarg, "%u", &arg_u);
|
||||
if ((i != 1) || (arg_u > 3)) {
|
||||
printf("ERROR: argument parsing of --dig argument. Use -h to print help\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
txlut.size = 1;
|
||||
txlut.lut[0].dig_gain = (uint8_t)arg_u;
|
||||
}
|
||||
} else if (strcmp(long_options[option_index].name, "pwid") == 0) {
|
||||
i = sscanf(optarg, "%u", &arg_u);
|
||||
if ((i != 1) || (arg_u > 22)) {
|
||||
printf("ERROR: argument parsing of --pwid argument. Use -h to print help\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
txlut.size = 1;
|
||||
txlut.lut[0].mix_gain = 5; /* TODO: rework this, should not be needed for sx1250 */
|
||||
txlut.lut[0].pwr_idx = (uint8_t)arg_u;
|
||||
}
|
||||
} else if (strcmp(long_options[option_index].name, "loop") == 0) {
|
||||
printf("%p\n", optarg);
|
||||
i = sscanf(optarg, "%u", &arg_u);
|
||||
if (i != 1) {
|
||||
printf("ERROR: argument parsing of --loop argument. Use -h to print help\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
nb_loop = arg_u;
|
||||
}
|
||||
} else if (strcmp(long_options[option_index].name, "nhdr") == 0) {
|
||||
no_header = true;
|
||||
} else {
|
||||
printf("ERROR: argument parsing options. Use -h to print help\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printf("ERROR: argument parsing\n");
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Summary of packet parameters */
|
||||
if (strcmp(mod, "CW") == 0) {
|
||||
printf("Sending %i CW on %u Hz (Freq. offset %d kHz) at %i dBm\n", nb_pkt, ft, freq_offset, rf_power);
|
||||
}
|
||||
else if (strcmp(mod, "FSK") == 0) {
|
||||
printf("Sending %i FSK packets on %u Hz (FDev %u kHz, Bitrate %.2f, %i bytes payload, %i symbols preamble) at %i dBm\n", nb_pkt, ft, fdev_khz, br_kbps, size, preamble, rf_power);
|
||||
} else {
|
||||
printf("Sending %i LoRa packets on %u Hz (BW %i kHz, SF %i, CR %i, %i bytes payload, %i symbols preamble, %s header, %s polarity) at %i dBm\n", nb_pkt, ft, bw_khz, sf, 1, size, preamble, (no_header == false) ? "explicit" : "implicit", (invert_pol == false) ? "non-inverted" : "inverted", rf_power);
|
||||
}
|
||||
|
||||
/* 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 );
|
||||
|
||||
/* Configure the gateway */
|
||||
memset( &boardconf, 0, sizeof boardconf);
|
||||
boardconf.lorawan_public = true;
|
||||
boardconf.clksrc = clocksource;
|
||||
boardconf.full_duplex = false;
|
||||
strncpy(boardconf.spidev_path, spidev_path, sizeof boardconf.spidev_path);
|
||||
if (lgw_board_setconf(&boardconf) != LGW_HAL_SUCCESS) {
|
||||
printf("ERROR: failed to configure board\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
memset( &rfconf, 0, sizeof rfconf);
|
||||
rfconf.enable = true; /* rf chain 0 needs to be enabled for calibration to work on sx1257 */
|
||||
rfconf.freq_hz = 868500000; /* dummy */
|
||||
rfconf.type = radio_type;
|
||||
rfconf.tx_enable = true;
|
||||
if (lgw_rxrf_setconf(0, &rfconf) != LGW_HAL_SUCCESS) {
|
||||
printf("ERROR: failed to configure rxrf 0\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
memset( &rfconf, 0, sizeof rfconf);
|
||||
rfconf.enable = (((rf_chain == 1) || (clocksource == 1)) ? true : false);
|
||||
rfconf.freq_hz = 868500000; /* dummy */
|
||||
rfconf.type = radio_type;
|
||||
rfconf.tx_enable = false;
|
||||
if (lgw_rxrf_setconf(1, &rfconf) != LGW_HAL_SUCCESS) {
|
||||
printf("ERROR: failed to configure rxrf 1\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (txlut.size > 0) {
|
||||
if (lgw_txgain_setconf(rf_chain, &txlut) != LGW_HAL_SUCCESS) {
|
||||
printf("ERROR: failed to configure txgain lut\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
for (cnt_loop = 0; cnt_loop < nb_loop; cnt_loop++) {
|
||||
/* Board reset */
|
||||
if (system("./reset_lgw.sh start") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* connect, configure and start the LoRa concentrator */
|
||||
x = lgw_start();
|
||||
if (x != 0) {
|
||||
printf("ERROR: failed to start the gateway\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* Send packets */
|
||||
memset(&pkt, 0, sizeof pkt);
|
||||
pkt.rf_chain = rf_chain;
|
||||
pkt.freq_hz = ft;
|
||||
pkt.rf_power = rf_power;
|
||||
if (trig_delay == false) {
|
||||
pkt.tx_mode = IMMEDIATE;
|
||||
} else {
|
||||
if (trig_delay_us == 0) {
|
||||
pkt.tx_mode = ON_GPS;
|
||||
} else {
|
||||
pkt.tx_mode = TIMESTAMPED;
|
||||
}
|
||||
}
|
||||
if ( strcmp( mod, "CW" ) == 0 ) {
|
||||
pkt.modulation = MOD_CW;
|
||||
pkt.freq_offset = freq_offset;
|
||||
pkt.f_dev = fdev_khz;
|
||||
}
|
||||
else if( strcmp( mod, "FSK" ) == 0 ) {
|
||||
pkt.modulation = MOD_FSK;
|
||||
pkt.no_crc = false;
|
||||
pkt.datarate = br_kbps * 1e3;
|
||||
pkt.f_dev = fdev_khz;
|
||||
} else {
|
||||
pkt.modulation = MOD_LORA;
|
||||
pkt.coderate = CR_LORA_4_5;
|
||||
pkt.no_crc = true;
|
||||
}
|
||||
pkt.invert_pol = invert_pol;
|
||||
pkt.preamble = preamble;
|
||||
pkt.no_header = no_header;
|
||||
pkt.payload[0] = 0x40; /* Confirmed Data Up */
|
||||
pkt.payload[1] = 0xAB;
|
||||
pkt.payload[2] = 0xAB;
|
||||
pkt.payload[3] = 0xAB;
|
||||
pkt.payload[4] = 0xAB;
|
||||
pkt.payload[5] = 0x00; /* FCTrl */
|
||||
pkt.payload[6] = 0; /* FCnt */
|
||||
pkt.payload[7] = 0; /* FCnt */
|
||||
pkt.payload[8] = 0x02; /* FPort */
|
||||
for (i = 9; i < 255; i++) {
|
||||
pkt.payload[i] = i;
|
||||
}
|
||||
|
||||
for (i = 0; i < (int)nb_pkt; i++) {
|
||||
if (trig_delay == true) {
|
||||
if (trig_delay_us > 0) {
|
||||
lgw_get_instcnt(&count_us);
|
||||
printf("count_us:%u\n", count_us);
|
||||
pkt.count_us = count_us + trig_delay_us;
|
||||
printf("programming TX for %u\n", pkt.count_us);
|
||||
} else {
|
||||
printf("programming TX for next PPS (GPS)\n");
|
||||
}
|
||||
}
|
||||
|
||||
if( strcmp( mod, "LORA" ) == 0 ) {
|
||||
pkt.datarate = (sf == 0) ? (uint8_t)RAND_RANGE(5, 12) : sf;
|
||||
}
|
||||
|
||||
switch (bw_khz) {
|
||||
case 125:
|
||||
pkt.bandwidth = BW_125KHZ;
|
||||
break;
|
||||
case 250:
|
||||
pkt.bandwidth = BW_250KHZ;
|
||||
break;
|
||||
case 500:
|
||||
pkt.bandwidth = BW_500KHZ;
|
||||
break;
|
||||
default:
|
||||
pkt.bandwidth = (uint8_t)RAND_RANGE(BW_125KHZ, BW_500KHZ);
|
||||
break;
|
||||
}
|
||||
|
||||
pkt.size = (size == 0) ? (uint8_t)RAND_RANGE(9, 255) : size;
|
||||
|
||||
pkt.payload[6] = (uint8_t)(i >> 0); /* FCnt */
|
||||
pkt.payload[7] = (uint8_t)(i >> 8); /* FCnt */
|
||||
x = lgw_send(&pkt);
|
||||
if (x != 0) {
|
||||
printf("ERROR: failed to send packet\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
/* wait for packet to finish sending */
|
||||
do {
|
||||
wait_ms(5);
|
||||
lgw_status(pkt.rf_chain, TX_STATUS, &tx_status); /* get TX status */
|
||||
} while ((tx_status != TX_FREE) && (quit_sig != 1) && (exit_sig != 1));
|
||||
|
||||
if ((quit_sig == 1) || (exit_sig == 1)) {
|
||||
break;
|
||||
}
|
||||
printf("TX done\n");
|
||||
}
|
||||
|
||||
printf( "\nNb packets sent: %u (%u)\n", i, cnt_loop + 1 );
|
||||
|
||||
/* Stop the gateway */
|
||||
x = lgw_stop();
|
||||
if (x != 0) {
|
||||
printf("ERROR: failed to stop the gateway\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* Board reset */
|
||||
if (system("./reset_lgw.sh stop") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
printf("=========== Test End ===========\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
|
@ -0,0 +1,245 @@
|
|||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2019 Semtech
|
||||
|
||||
Description:
|
||||
Minimum test program for the loragw_i2c module
|
||||
|
||||
License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*/
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- DEPENDANCIES --------------------------------------------------------- */
|
||||
|
||||
/* Fix an issue between POSIX and C99 */
|
||||
#if __STDC_VERSION__ >= 199901L
|
||||
#define _XOPEN_SOURCE 600
|
||||
#else
|
||||
#define _XOPEN_SOURCE 500
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <signal.h> /* sigaction */
|
||||
#include <unistd.h> /* getopt, access */
|
||||
#include <time.h>
|
||||
|
||||
#include "loragw_i2c.h"
|
||||
#include "loragw_aux.h"
|
||||
#include "loragw_hal.h"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE MACROS ------------------------------------------------------- */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE CONSTANTS ---------------------------------------------------- */
|
||||
|
||||
#define I2C_PORT_STTS751 0x39
|
||||
|
||||
#define STTS751_REG_TEMP_H 0x00
|
||||
#define STTS751_REG_TEMP_L 0x02
|
||||
#define STTS751_REG_CONF 0x03
|
||||
#define STTS751_REG_RATE 0x04
|
||||
#define STTS751_REG_PROD_ID 0xFD
|
||||
#define STTS751_REG_MAN_ID 0xFE
|
||||
#define STTS751_REG_REV_ID 0xFF
|
||||
|
||||
#define STTS751_0_PROD_ID 0x00
|
||||
#define STTS751_1_PROD_ID 0x01
|
||||
#define ST_MAN_ID 0x53
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- GLOBAL VARIABLES ----------------------------------------------------- */
|
||||
|
||||
/* Signal handling 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 */
|
||||
|
||||
static int i2c_dev = -1;
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- SUBFUNCTIONS DECLARATION --------------------------------------------- */
|
||||
|
||||
static void sig_handler(int sigio);
|
||||
static void usage(void);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- MAIN FUNCTION -------------------------------------------------------- */
|
||||
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
int i, err;
|
||||
static struct sigaction sigact; /* SIGQUIT&SIGINT&SIGTERM signal handling */
|
||||
uint8_t val;
|
||||
uint8_t high_byte, low_byte;
|
||||
int8_t h;
|
||||
float temperature;
|
||||
|
||||
/* Parse command line options */
|
||||
while ((i = getopt(argc, argv, "hd:")) != -1) {
|
||||
switch (i) {
|
||||
case 'h':
|
||||
usage();
|
||||
return EXIT_SUCCESS;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
if (optarg != NULL) {
|
||||
/* TODO */
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("ERROR: argument parsing options, use -h option for help\n");
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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 );
|
||||
|
||||
printf( "+++ Start of I2C test program +++\n" );
|
||||
|
||||
/* Open I2C port expander */
|
||||
err = i2c_linuxdev_open( I2C_DEVICE, I2C_PORT_STTS751, &i2c_dev );
|
||||
if ( (err != 0) || (i2c_dev <= 0) )
|
||||
{
|
||||
printf( "ERROR: failed to open I2C device %s (err=%i)\n", I2C_DEVICE, err );
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* Get temperature sensor product ID */
|
||||
err = i2c_linuxdev_read( i2c_dev, I2C_PORT_STTS751, STTS751_REG_PROD_ID, &val );
|
||||
if ( err != 0 )
|
||||
{
|
||||
printf( "ERROR: failed to read I2C device %s (err=%i)\n", I2C_DEVICE, err );
|
||||
return EXIT_FAILURE;;
|
||||
}
|
||||
switch( val )
|
||||
{
|
||||
case STTS751_0_PROD_ID:
|
||||
printf("INFO: Product ID: STTS751-0\n");
|
||||
break;
|
||||
case STTS751_1_PROD_ID:
|
||||
printf("INFO: Product ID: STTS751-1\n");
|
||||
break;
|
||||
default:
|
||||
printf("ERROR: Product ID: UNKNOWN\n");
|
||||
return EXIT_FAILURE;;
|
||||
}
|
||||
|
||||
/* Get temperature sensor Manufacturer ID */
|
||||
err = i2c_linuxdev_read( i2c_dev, I2C_PORT_STTS751, STTS751_REG_MAN_ID, &val );
|
||||
if ( err != 0 )
|
||||
{
|
||||
printf( "ERROR: failed to read I2C device %s (err=%i)\n", I2C_DEVICE, err );
|
||||
return EXIT_FAILURE;;
|
||||
}
|
||||
if ( val != ST_MAN_ID )
|
||||
{
|
||||
printf( "ERROR: Manufacturer ID: UNKNOWN\n" );
|
||||
return EXIT_FAILURE;;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("INFO: Manufacturer ID: 0x%02X\n", val);
|
||||
}
|
||||
|
||||
/* Get temperature sensor revision number */
|
||||
err = i2c_linuxdev_read( i2c_dev, I2C_PORT_STTS751, STTS751_REG_REV_ID, &val );
|
||||
if ( err != 0 )
|
||||
{
|
||||
printf( "ERROR: failed to read I2C device %s (err=%i)\n", I2C_DEVICE, err );
|
||||
return EXIT_FAILURE;;
|
||||
}
|
||||
printf("INFO: Revision number: 0x%02X\n", val);
|
||||
|
||||
/* Set conversion resolution to 12 bits */
|
||||
err = i2c_linuxdev_write( i2c_dev, I2C_PORT_STTS751, STTS751_REG_CONF, 0x8C ); /* TODO: do not hardcode the whole byte */
|
||||
if ( err != 0 )
|
||||
{
|
||||
printf( "ERROR: failed to write I2C device 0x%02X (err=%i)\n", I2C_PORT_STTS751, err );
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* Set conversion rate to 1 / second */
|
||||
err = i2c_linuxdev_write( i2c_dev, I2C_PORT_STTS751, STTS751_REG_RATE, 0x04 );
|
||||
if ( err != 0 )
|
||||
{
|
||||
printf( "ERROR: failed to write I2C device 0x%02X (err=%i)\n", I2C_PORT_STTS751, err );
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
while ((quit_sig != 1) && (exit_sig != 1)) {
|
||||
/* Read Temperature LSB */
|
||||
err = i2c_linuxdev_read( i2c_dev, I2C_PORT_STTS751, STTS751_REG_TEMP_L, &low_byte );
|
||||
if ( err != 0 )
|
||||
{
|
||||
printf( "ERROR: failed to read I2C device 0x%02X (err=%i)\n", I2C_PORT_STTS751, err );
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* Read Temperature MSB */
|
||||
err = i2c_linuxdev_read( i2c_dev, I2C_PORT_STTS751, STTS751_REG_TEMP_H, &high_byte );
|
||||
if ( err != 0 )
|
||||
{
|
||||
printf( "ERROR: failed to read I2C device 0x%02X (err=%i)\n", I2C_PORT_STTS751, err );
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
h = (int8_t)high_byte;
|
||||
temperature = ((h << 8) | low_byte) / 256.0;
|
||||
|
||||
printf( "Temperature: %f C (h:0x%02X l:0x%02X)\n", temperature, high_byte, low_byte );
|
||||
wait_ms( 100 );
|
||||
}
|
||||
|
||||
/* Terminate */
|
||||
printf( "+++ End of I2C test program +++\n" );
|
||||
|
||||
err = i2c_linuxdev_close( i2c_dev );
|
||||
if ( err != 0 )
|
||||
{
|
||||
printf( "ERROR: failed to close I2C device (err=%i)\n", err );
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- SUBFUNCTIONS DEFINITION ---------------------------------------------- */
|
||||
|
||||
static void sig_handler(int sigio) {
|
||||
if (sigio == SIGQUIT) {
|
||||
quit_sig = 1;
|
||||
} else if((sigio == SIGINT) || (sigio == SIGTERM)) {
|
||||
exit_sig = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
static void usage(void) {
|
||||
printf("~~~ Library version string~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
|
||||
printf(" %s\n", lgw_version_info());
|
||||
printf("~~~ Available options ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
|
||||
printf(" -h print this help\n");
|
||||
printf(" -d <path> use Linux I2C device driver\n");
|
||||
printf(" => default path: " I2C_DEVICE "\n");
|
||||
}
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
|
@ -0,0 +1,204 @@
|
|||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2019 Semtech
|
||||
|
||||
Description:
|
||||
Minimum test program for the loragw_reg module
|
||||
|
||||
License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*/
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- DEPENDANCIES --------------------------------------------------------- */
|
||||
|
||||
/* Fix an issue between POSIX and C99 */
|
||||
#if __STDC_VERSION__ >= 199901L
|
||||
#define _XOPEN_SOURCE 600
|
||||
#else
|
||||
#define _XOPEN_SOURCE 500
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h> /* getopt, access */
|
||||
#include <math.h>
|
||||
|
||||
#include "loragw_reg.h"
|
||||
#include "loragw_aux.h"
|
||||
#include "loragw_hal.h"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE MACROS ------------------------------------------------------- */
|
||||
|
||||
#define LINUXDEV_PATH_DEFAULT "/dev/spidev0.0"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE CONSTANTS ---------------------------------------------------- */
|
||||
|
||||
extern const struct lgw_reg_s loregs[LGW_TOTALREGS+1];
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- SUBFUNCTIONS DECLARATION --------------------------------------------- */
|
||||
|
||||
static void usage(void);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- MAIN FUNCTION -------------------------------------------------------- */
|
||||
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
int x, i;
|
||||
int32_t val;
|
||||
bool error_found = false;
|
||||
uint8_t rand_values[LGW_TOTALREGS];
|
||||
bool reg_ignored[LGW_TOTALREGS]; /* store register to be ignored */
|
||||
uint8_t reg_val;
|
||||
uint8_t reg_max;
|
||||
|
||||
/* SPI interfaces */
|
||||
const char spidev_path_default[] = LINUXDEV_PATH_DEFAULT;
|
||||
const char * spidev_path = spidev_path_default;
|
||||
|
||||
/* Parse command line options */
|
||||
while ((i = getopt(argc, argv, "hd:")) != -1) {
|
||||
switch (i) {
|
||||
case 'h':
|
||||
usage();
|
||||
return EXIT_SUCCESS;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
if (optarg != NULL) {
|
||||
spidev_path = optarg;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("ERROR: argument parsing options, use -h option for help\n");
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Board reset */
|
||||
if (system("./reset_lgw.sh start") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
x = lgw_connect(spidev_path);
|
||||
if (x != LGW_REG_SUCCESS) {
|
||||
printf("ERROR: failed to connect\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* The following registers cannot be tested this way */
|
||||
memset(reg_ignored, 0, sizeof reg_ignored);
|
||||
reg_ignored[SX1302_REG_COMMON_CTRL0_CLK32_RIF_CTRL] = true; /* all test fails if we set this one to 1 */
|
||||
|
||||
/* Test 1: read all registers and check default value for non-read-only registers */
|
||||
printf("## TEST#1: read all registers and check default value for non-read-only registers\n");
|
||||
error_found = false;
|
||||
for (i = 0; i < LGW_TOTALREGS; i++) {
|
||||
if (loregs[i].rdon == 0) {
|
||||
x = lgw_reg_r(i, &val);
|
||||
if (x != LGW_REG_SUCCESS) {
|
||||
printf("ERROR: failed to read register at index %d\n", i);
|
||||
return -1;
|
||||
}
|
||||
if (val != loregs[i].dflt) {
|
||||
printf("ERROR: default value for register at index %d is %d, should be %d\n", i, val, loregs[i].dflt);
|
||||
error_found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("------------------\n");
|
||||
printf(" TEST#1 %s\n", (error_found == false) ? "PASSED" : "FAILED");
|
||||
printf("------------------\n\n");
|
||||
|
||||
/* Test 2: read/write test on all non-read-only, non-pulse, non-w0clr, non-w1clr registers */
|
||||
printf("## TEST#2: read/write test on all non-read-only, non-pulse, non-w0clr, non-w1clr registers\n");
|
||||
/* Write all registers with a random value */
|
||||
error_found = false;
|
||||
for (i = 0; i < LGW_TOTALREGS; i++) {
|
||||
if ((loregs[i].rdon == 0) && (reg_ignored[i] == false)) {
|
||||
/* Peek a random value different form the default reg value */
|
||||
reg_max = pow(2, loregs[i].leng) - 1;
|
||||
if (loregs[i].leng == 1) {
|
||||
reg_val = !loregs[i].dflt;
|
||||
} else {
|
||||
/* ensure random value is not the default one */
|
||||
do {
|
||||
if (loregs[i].sign == 1) {
|
||||
reg_val = rand() % (reg_max / 2);
|
||||
} else {
|
||||
reg_val = rand() % reg_max;
|
||||
}
|
||||
} while (reg_val == loregs[i].dflt);
|
||||
}
|
||||
/* Write selected value */
|
||||
x = lgw_reg_w(i, reg_val);
|
||||
if (x != LGW_REG_SUCCESS) {
|
||||
printf("ERROR: failed to read register at index %d\n", i);
|
||||
return -1;
|
||||
}
|
||||
/* store value for later check */
|
||||
rand_values[i] = reg_val;
|
||||
}
|
||||
}
|
||||
/* Read all registers and check if we got proper random value back */
|
||||
for (i = 0; i < LGW_TOTALREGS; i++) {
|
||||
if ((loregs[i].rdon == 0) && (loregs[i].chck == 1) && (reg_ignored[i] == false)) {
|
||||
x = lgw_reg_r(i, &val);
|
||||
if (x != LGW_REG_SUCCESS) {
|
||||
printf("ERROR: failed to read register at index %d\n", i);
|
||||
return -1;
|
||||
}
|
||||
/* check value */
|
||||
if (val != rand_values[i]) {
|
||||
printf("ERROR: value read from register at index %d differs from the written value (w:%u r:%d)\n", i, rand_values[i], val);
|
||||
error_found = true;
|
||||
} else {
|
||||
//printf("INFO: MATCH reg %d (%u, %u)\n", i, rand_values[i], (uint8_t)val);
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("------------------\n");
|
||||
printf(" TEST#2 %s\n", (error_found == false) ? "PASSED" : "FAILED");
|
||||
printf("------------------\n\n");
|
||||
|
||||
x = lgw_disconnect();
|
||||
if (x != LGW_REG_SUCCESS) {
|
||||
printf("ERROR: failed to disconnect\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Board reset */
|
||||
if (system("./reset_lgw.sh stop") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- SUBFUNCTIONS DEFINITION ---------------------------------------------- */
|
||||
|
||||
static void usage(void) {
|
||||
printf("~~~ Library version string~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
|
||||
printf(" %s\n", lgw_version_info());
|
||||
printf("~~~ Available options ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
|
||||
printf(" -h print this help\n");
|
||||
printf(" -d <path> use Linux SPI device driver\n");
|
||||
printf(" => default path: " LINUXDEV_PATH_DEFAULT "\n");
|
||||
}
|
||||
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
|
@ -0,0 +1,208 @@
|
|||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2019 Semtech
|
||||
|
||||
Description:
|
||||
Minimum test program for the loragw_spi module
|
||||
|
||||
License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*/
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- DEPENDANCIES --------------------------------------------------------- */
|
||||
|
||||
/* Fix an issue between POSIX and C99 */
|
||||
#if __STDC_VERSION__ >= 199901L
|
||||
#define _XOPEN_SOURCE 600
|
||||
#else
|
||||
#define _XOPEN_SOURCE 500
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <signal.h> /* sigaction */
|
||||
#include <unistd.h> /* getopt, access */
|
||||
#include <time.h>
|
||||
|
||||
#include "loragw_spi.h"
|
||||
#include "loragw_aux.h"
|
||||
#include "loragw_hal.h"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE MACROS ------------------------------------------------------- */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE CONSTANTS ---------------------------------------------------- */
|
||||
|
||||
#define BUFF_SIZE 1024
|
||||
|
||||
#define SX1302_AGC_MCU_MEM 0x0000
|
||||
#define SX1302_REG_COMMON 0x5600
|
||||
#define SX1302_REG_AGC_MCU 0x5780
|
||||
|
||||
#define LINUXDEV_PATH_DEFAULT "/dev/spidev0.0"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- GLOBAL VARIABLES ----------------------------------------------------- */
|
||||
|
||||
/* Signal handling 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 */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- SUBFUNCTIONS DECLARATION --------------------------------------------- */
|
||||
|
||||
static void sig_handler(int sigio);
|
||||
static void usage(void);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- MAIN FUNCTION -------------------------------------------------------- */
|
||||
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
static struct sigaction sigact; /* SIGQUIT&SIGINT&SIGTERM signal handling */
|
||||
|
||||
uint8_t data = 0;
|
||||
uint8_t test_buff[BUFF_SIZE];
|
||||
uint8_t read_buff[BUFF_SIZE];
|
||||
int cycle_number = 0;
|
||||
int i;
|
||||
uint16_t size;
|
||||
|
||||
/* SPI interfaces */
|
||||
const char spidev_path_default[] = LINUXDEV_PATH_DEFAULT;
|
||||
const char * spidev_path = spidev_path_default;
|
||||
void *spi_target = NULL;
|
||||
|
||||
/* Parse command line options */
|
||||
while ((i = getopt(argc, argv, "hd:")) != -1) {
|
||||
switch (i) {
|
||||
case 'h':
|
||||
usage();
|
||||
return EXIT_SUCCESS;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
if (optarg != NULL) {
|
||||
spidev_path = optarg;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("ERROR: argument parsing options, use -h option for help\n");
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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 );
|
||||
|
||||
/* Board reset */
|
||||
if (system("./reset_lgw.sh start") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
printf("Beginning of test for loragw_spi.c\n");
|
||||
i = lgw_spi_open(spidev_path, &spi_target);
|
||||
if (i != 0) {
|
||||
printf("ERROR: failed to open SPI device %s\n", spidev_path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* normal R/W test */
|
||||
/* TODO */
|
||||
|
||||
/* burst R/W test, small bursts << LGW_BURST_CHUNK */
|
||||
/* TODO */
|
||||
|
||||
/* burst R/W test, large bursts >> LGW_BURST_CHUNK */
|
||||
/* TODO */
|
||||
|
||||
lgw_spi_r(spi_target, LGW_SPI_MUX_TARGET_SX1302, SX1302_REG_COMMON + 6, &data);
|
||||
printf("SX1302 version: 0x%02X\n", data);
|
||||
|
||||
lgw_spi_r(spi_target, LGW_SPI_MUX_TARGET_SX1302, SX1302_REG_AGC_MCU + 0, &data);
|
||||
lgw_spi_w(spi_target, LGW_SPI_MUX_TARGET_SX1302, SX1302_REG_AGC_MCU + 0, 0x06); /* mcu_clear, host_prog */
|
||||
|
||||
srand(time(NULL));
|
||||
|
||||
/* databuffer R/W stress test */
|
||||
while ((quit_sig != 1) && (exit_sig != 1)) {
|
||||
size = rand() % BUFF_SIZE;
|
||||
for (i = 0; i < size; ++i) {
|
||||
test_buff[i] = rand() & 0xFF;
|
||||
}
|
||||
printf("Cycle %i > ", cycle_number);
|
||||
lgw_spi_wb(spi_target, LGW_SPI_MUX_TARGET_SX1302, SX1302_AGC_MCU_MEM, test_buff, size);
|
||||
lgw_spi_rb(spi_target, LGW_SPI_MUX_TARGET_SX1302, SX1302_AGC_MCU_MEM, read_buff, size);
|
||||
for (i=0; ((i<size) && (test_buff[i] == read_buff[i])); ++i);
|
||||
if (i != size) {
|
||||
printf("error during the buffer comparison\n");
|
||||
printf("Written values:\n");
|
||||
for (i=0; i<size; ++i) {
|
||||
printf(" %02X ", test_buff[i]);
|
||||
if (i%16 == 15) printf("\n");
|
||||
}
|
||||
printf("\n");
|
||||
printf("Read values:\n");
|
||||
for (i=0; i<size; ++i) {
|
||||
printf(" %02X ", read_buff[i]);
|
||||
if (i%16 == 15) printf("\n");
|
||||
}
|
||||
printf("\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
printf("did a %i-byte R/W on a data buffer with no error\n", size);
|
||||
++cycle_number;
|
||||
}
|
||||
}
|
||||
|
||||
lgw_spi_close(spi_target);
|
||||
printf("End of test for loragw_spi.c\n");
|
||||
|
||||
/* Board reset */
|
||||
if (system("./reset_lgw.sh stop") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- SUBFUNCTIONS DEFINITION ---------------------------------------------- */
|
||||
|
||||
static void sig_handler(int sigio) {
|
||||
if (sigio == SIGQUIT) {
|
||||
quit_sig = 1;
|
||||
} else if((sigio == SIGINT) || (sigio == SIGTERM)) {
|
||||
exit_sig = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
static void usage(void) {
|
||||
printf("~~~ Library version string~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
|
||||
printf(" %s\n", lgw_version_info());
|
||||
printf("~~~ Available options ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
|
||||
printf(" -h print this help\n");
|
||||
printf(" -d <path> use Linux SPI device driver\n");
|
||||
printf(" => default path: " LINUXDEV_PATH_DEFAULT "\n");
|
||||
}
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
|
@ -0,0 +1,216 @@
|
|||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2019 Semtech
|
||||
|
||||
Description:
|
||||
Minimum test program for the sx1250 module
|
||||
|
||||
License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*/
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- DEPENDANCIES --------------------------------------------------------- */
|
||||
|
||||
/* Fix an issue between POSIX and C99 */
|
||||
#if __STDC_VERSION__ >= 199901L
|
||||
#define _XOPEN_SOURCE 600
|
||||
#else
|
||||
#define _XOPEN_SOURCE 500
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <signal.h> /* sigaction */
|
||||
#include <unistd.h> /* getopt, access */
|
||||
|
||||
#include "loragw_spi.h"
|
||||
#include "loragw_aux.h"
|
||||
#include "loragw_reg.h"
|
||||
#include "loragw_hal.h"
|
||||
#include "loragw_sx1250.h"
|
||||
#include "loragw_sx1302.h"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE MACROS ------------------------------------------------------- */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE CONSTANTS ---------------------------------------------------- */
|
||||
|
||||
#define BUFF_SIZE 16
|
||||
|
||||
#define LINUXDEV_PATH_DEFAULT "/dev/spidev0.0"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- GLOBAL VARIABLES ----------------------------------------------------- */
|
||||
|
||||
/* Signal handling 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 */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- SUBFUNCTIONS DECLARATION --------------------------------------------- */
|
||||
|
||||
static void sig_handler(int sigio);
|
||||
static void usage(void);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- MAIN FUNCTION -------------------------------------------------------- */
|
||||
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
static struct sigaction sigact; /* SIGQUIT&SIGINT&SIGTERM signal handling */
|
||||
|
||||
uint8_t test_buff[BUFF_SIZE];
|
||||
uint8_t read_buff[BUFF_SIZE];
|
||||
uint32_t test_val, read_val;
|
||||
int cycle_number = 0;
|
||||
int i, x;
|
||||
|
||||
/* SPI interfaces */
|
||||
const char spidev_path_default[] = LINUXDEV_PATH_DEFAULT;
|
||||
const char * spidev_path = spidev_path_default;
|
||||
|
||||
/* Parse command line options */
|
||||
while ((i = getopt(argc, argv, "hd:")) != -1) {
|
||||
switch (i) {
|
||||
case 'h':
|
||||
usage();
|
||||
return EXIT_SUCCESS;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
if (optarg != NULL) {
|
||||
spidev_path = optarg;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("ERROR: argument parsing options, use -h option for help\n");
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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 );
|
||||
|
||||
/* Board reset */
|
||||
if (system("./reset_lgw.sh start") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
x = lgw_connect(spidev_path);
|
||||
if (x != LGW_REG_SUCCESS) {
|
||||
printf("ERROR: Failed to connect to the concentrator using SPI %s\n", spidev_path);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* Reset radios */
|
||||
for (i = 0; i < LGW_RF_CHAIN_NB; i++) {
|
||||
sx1302_radio_reset(i, LGW_RADIO_TYPE_SX1250);
|
||||
sx1302_radio_set_mode(i, LGW_RADIO_TYPE_SX1250);
|
||||
}
|
||||
|
||||
/* Select the radio which provides the clock to the sx1302 */
|
||||
sx1302_radio_clock_select(0);
|
||||
|
||||
/* Ensure we can control the radio */
|
||||
lgw_reg_w(SX1302_REG_COMMON_CTRL0_HOST_RADIO_CTRL, 0x01);
|
||||
|
||||
/* Ensure PA/LNA are disabled */
|
||||
lgw_reg_w(SX1302_REG_AGC_MCU_CTRL_FORCE_HOST_FE_CTRL, 1);
|
||||
lgw_reg_w(SX1302_REG_AGC_MCU_RF_EN_A_PA_EN, 0);
|
||||
lgw_reg_w(SX1302_REG_AGC_MCU_RF_EN_A_LNA_EN, 0);
|
||||
|
||||
/* Set Radio in Standby mode */
|
||||
test_buff[0] = (uint8_t)STDBY_XOSC;
|
||||
sx1250_write_command(0, SET_STANDBY, test_buff, 1);
|
||||
sx1250_write_command(1, SET_STANDBY, test_buff, 1);
|
||||
wait_ms(10);
|
||||
|
||||
test_buff[0] = 0x00;
|
||||
sx1250_read_command(0, GET_STATUS, test_buff, 1);
|
||||
printf("Radio0: get_status: 0x%02X\n", test_buff[0]);
|
||||
sx1250_read_command(1, GET_STATUS, test_buff, 1);
|
||||
printf("Radio1: get_status: 0x%02X\n", test_buff[0]);
|
||||
|
||||
/* databuffer R/W stress test */
|
||||
while ((quit_sig != 1) && (exit_sig != 1)) {
|
||||
test_buff[0] = rand() & 0x7F;
|
||||
test_buff[1] = rand() & 0xFF;
|
||||
test_buff[2] = rand() & 0xFF;
|
||||
test_buff[3] = rand() & 0xFF;
|
||||
test_val = (test_buff[0] << 24) | (test_buff[1] << 16) | (test_buff[2] << 8) | (test_buff[3] << 0);
|
||||
sx1250_write_command(0, SET_RF_FREQUENCY, test_buff, 4);
|
||||
|
||||
read_buff[0] = 0x08;
|
||||
read_buff[1] = 0x8B;
|
||||
read_buff[2] = 0x00;
|
||||
read_buff[3] = 0x00;
|
||||
read_buff[4] = 0x00;
|
||||
read_buff[5] = 0x00;
|
||||
read_buff[6] = 0x00;
|
||||
sx1250_read_command(0, READ_REGISTER, read_buff, 7);
|
||||
read_val = (read_buff[3] << 24) | (read_buff[4] << 16) | (read_buff[5] << 8) | (read_buff[6] << 0);
|
||||
|
||||
printf("Cycle %i > ", cycle_number);
|
||||
if (read_val != test_val) {
|
||||
printf("error during the buffer comparison\n");
|
||||
printf("Written value: %08X\n", test_val);
|
||||
printf("Read value: %08X\n", read_val);
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
printf("did a %i-byte R/W on a register with no error\n", 4);
|
||||
++cycle_number;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
lgw_disconnect();
|
||||
printf("End of test for loragw_spi_sx1250.c\n");
|
||||
|
||||
/* Board reset */
|
||||
if (system("./reset_lgw.sh stop") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- SUBFUNCTIONS DEFINITION ---------------------------------------------- */
|
||||
|
||||
static void sig_handler(int sigio) {
|
||||
if (sigio == SIGQUIT) {
|
||||
quit_sig = 1;
|
||||
} else if((sigio == SIGINT) || (sigio == SIGTERM)) {
|
||||
exit_sig = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
static void usage(void) {
|
||||
printf("~~~ Library version string~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
|
||||
printf(" %s\n", lgw_version_info());
|
||||
printf("~~~ Available options ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
|
||||
printf(" -h print this help\n");
|
||||
printf(" -d <path> use Linux SPI device driver\n");
|
||||
printf(" => default path: " LINUXDEV_PATH_DEFAULT "\n");
|
||||
}
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
|
@ -0,0 +1,48 @@
|
|||
### get external defined data
|
||||
|
||||
### constant symbols
|
||||
|
||||
ARCH ?=
|
||||
CROSS_COMPILE ?=
|
||||
CC := $(CROSS_COMPILE)gcc
|
||||
AR := $(CROSS_COMPILE)ar
|
||||
|
||||
CFLAGS := -O2 -Wall -Wextra -std=c99 -Iinc -I.
|
||||
|
||||
OBJDIR = obj
|
||||
INCLUDES = $(wildcard inc/*.h)
|
||||
|
||||
### linking options
|
||||
|
||||
### general build targets
|
||||
|
||||
all: libtinymt32.a libparson.a libbase64.a
|
||||
|
||||
clean:
|
||||
rm -f libtinymt32.a
|
||||
rm -f libparson.a
|
||||
rm -f libbase64.a
|
||||
rm -f $(OBJDIR)/*.o
|
||||
|
||||
### library module target
|
||||
|
||||
$(OBJDIR):
|
||||
mkdir -p $(OBJDIR)
|
||||
|
||||
$(OBJDIR)/%.o: src/%.c $(INCLUDES) | $(OBJDIR)
|
||||
$(CC) -c $(CFLAGS) $< -o $@
|
||||
|
||||
### static library
|
||||
|
||||
libtinymt32.a: $(OBJDIR)/tinymt32.o
|
||||
$(AR) rcs $@ $^
|
||||
|
||||
libparson.a: $(OBJDIR)/parson.o
|
||||
$(AR) rcs $@ $^
|
||||
|
||||
libbase64.a: $(OBJDIR)/base64.o
|
||||
$(AR) rcs $@ $^
|
||||
|
||||
### test programs
|
||||
|
||||
### EOF
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2019 Semtech
|
||||
|
||||
Description:
|
||||
Base64 encoding & decoding library
|
||||
|
||||
License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _BASE64_H
|
||||
#define _BASE64_H
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- DEPENDANCIES --------------------------------------------------------- */
|
||||
|
||||
#include <stdint.h> /* C99 types */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PUBLIC FUNCTIONS PROTOTYPES ------------------------------------------ */
|
||||
|
||||
/**
|
||||
@brief Encode binary data in Base64 string (no padding)
|
||||
@param in pointer to a table of binary data
|
||||
@param size number of bytes to be encoded to base64
|
||||
@param out pointer to a string where the function will output encoded data
|
||||
@param max_len max length of the out string (including null char)
|
||||
@return >=0 length of the resulting string (w/o null char), -1 for error
|
||||
*/
|
||||
int bin_to_b64_nopad(const uint8_t * in, int size, char * out, int max_len);
|
||||
|
||||
/**
|
||||
@brief Decode Base64 string to binary data (no padding)
|
||||
@param in string containing only base64 valid characters
|
||||
@param size number of characters to be decoded from base64 (w/o null char)
|
||||
@param out pointer to a data buffer where the function will output decoded data
|
||||
@param out_max_len usable size of the output data buffer
|
||||
@return >=0 number of bytes written to the data buffer, -1 for error
|
||||
*/
|
||||
int b64_to_bin_nopad(const char * in, int size, uint8_t * out, int max_len);
|
||||
|
||||
/* === derivative functions === */
|
||||
|
||||
/**
|
||||
@brief Encode binary data in Base64 string (with added padding)
|
||||
*/
|
||||
int bin_to_b64(const uint8_t * in, int size, char * out, int max_len);
|
||||
|
||||
/**
|
||||
@brief Decode Base64 string to binary data (remove padding if necessary)
|
||||
*/
|
||||
int b64_to_bin(const char * in, int size, uint8_t * out, int max_len);
|
||||
|
||||
#endif
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
|
@ -0,0 +1,222 @@
|
|||
/*
|
||||
Parson ( http://kgabis.github.com/parson/ )
|
||||
Copyright (c) 2012 - 2016 Krzysztof Gabis
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef parson_parson_h
|
||||
#define parson_parson_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include <stddef.h> /* size_t */
|
||||
|
||||
/* Types and enums */
|
||||
typedef struct json_object_t JSON_Object;
|
||||
typedef struct json_array_t JSON_Array;
|
||||
typedef struct json_value_t JSON_Value;
|
||||
|
||||
enum json_value_type {
|
||||
JSONError = -1,
|
||||
JSONNull = 1,
|
||||
JSONString = 2,
|
||||
JSONNumber = 3,
|
||||
JSONObject = 4,
|
||||
JSONArray = 5,
|
||||
JSONBoolean = 6
|
||||
};
|
||||
typedef int JSON_Value_Type;
|
||||
|
||||
enum json_result_t {
|
||||
JSONSuccess = 0,
|
||||
JSONFailure = -1
|
||||
};
|
||||
typedef int JSON_Status;
|
||||
|
||||
typedef void * (*JSON_Malloc_Function)(size_t);
|
||||
typedef void (*JSON_Free_Function)(void *);
|
||||
|
||||
/* Call only once, before calling any other function from parson API. If not called, malloc and free
|
||||
from stdlib will be used for all allocations */
|
||||
void json_set_allocation_functions(JSON_Malloc_Function malloc_fun, JSON_Free_Function free_fun);
|
||||
|
||||
/* Parses first JSON value in a file, returns NULL in case of error */
|
||||
JSON_Value * json_parse_file(const char *filename);
|
||||
|
||||
/* Parses first JSON value in a file and ignores comments (/ * * / and //),
|
||||
returns NULL in case of error */
|
||||
JSON_Value * json_parse_file_with_comments(const char *filename);
|
||||
|
||||
/* Parses first JSON value in a string, returns NULL in case of error */
|
||||
JSON_Value * json_parse_string(const char *string);
|
||||
|
||||
/* Parses first JSON value in a string and ignores comments (/ * * / and //),
|
||||
returns NULL in case of error */
|
||||
JSON_Value * json_parse_string_with_comments(const char *string);
|
||||
|
||||
/* Serialization */
|
||||
size_t json_serialization_size(const JSON_Value *value); /* returns 0 on fail */
|
||||
JSON_Status json_serialize_to_buffer(const JSON_Value *value, char *buf, size_t buf_size_in_bytes);
|
||||
JSON_Status json_serialize_to_file(const JSON_Value *value, const char *filename);
|
||||
char * json_serialize_to_string(const JSON_Value *value);
|
||||
|
||||
/* Pretty serialization */
|
||||
size_t json_serialization_size_pretty(const JSON_Value *value); /* returns 0 on fail */
|
||||
JSON_Status json_serialize_to_buffer_pretty(const JSON_Value *value, char *buf, size_t buf_size_in_bytes);
|
||||
JSON_Status json_serialize_to_file_pretty(const JSON_Value *value, const char *filename);
|
||||
char * json_serialize_to_string_pretty(const JSON_Value *value);
|
||||
|
||||
void json_free_serialized_string(char *string); /* frees string from json_serialize_to_string and json_serialize_to_string_pretty */
|
||||
|
||||
/* Comparing */
|
||||
int json_value_equals(const JSON_Value *a, const JSON_Value *b);
|
||||
|
||||
/* Validation
|
||||
This is *NOT* JSON Schema. It validates json by checking if object have identically
|
||||
named fields with matching types.
|
||||
For example schema {"name":"", "age":0} will validate
|
||||
{"name":"Joe", "age":25} and {"name":"Joe", "age":25, "gender":"m"},
|
||||
but not {"name":"Joe"} or {"name":"Joe", "age":"Cucumber"}.
|
||||
In case of arrays, only first value in schema is checked against all values in tested array.
|
||||
Empty objects ({}) validate all objects, empty arrays ([]) validate all arrays,
|
||||
null validates values of every type.
|
||||
*/
|
||||
JSON_Status json_validate(const JSON_Value *schema, const JSON_Value *value);
|
||||
|
||||
/*
|
||||
* JSON Object
|
||||
*/
|
||||
JSON_Value * json_object_get_value (const JSON_Object *object, const char *name);
|
||||
const char * json_object_get_string (const JSON_Object *object, const char *name);
|
||||
JSON_Object * json_object_get_object (const JSON_Object *object, const char *name);
|
||||
JSON_Array * json_object_get_array (const JSON_Object *object, const char *name);
|
||||
double json_object_get_number (const JSON_Object *object, const char *name); /* returns 0 on fail */
|
||||
int json_object_get_boolean(const JSON_Object *object, const char *name); /* returns -1 on fail */
|
||||
|
||||
/* dotget functions enable addressing values with dot notation in nested objects,
|
||||
just like in structs or c++/java/c# objects (e.g. objectA.objectB.value).
|
||||
Because valid names in JSON can contain dots, some values may be inaccessible
|
||||
this way. */
|
||||
JSON_Value * json_object_dotget_value (const JSON_Object *object, const char *name);
|
||||
const char * json_object_dotget_string (const JSON_Object *object, const char *name);
|
||||
JSON_Object * json_object_dotget_object (const JSON_Object *object, const char *name);
|
||||
JSON_Array * json_object_dotget_array (const JSON_Object *object, const char *name);
|
||||
double json_object_dotget_number (const JSON_Object *object, const char *name); /* returns 0 on fail */
|
||||
int json_object_dotget_boolean(const JSON_Object *object, const char *name); /* returns -1 on fail */
|
||||
|
||||
/* Functions to get available names */
|
||||
size_t json_object_get_count(const JSON_Object *object);
|
||||
const char * json_object_get_name (const JSON_Object *object, size_t index);
|
||||
|
||||
/* Creates new name-value pair or frees and replaces old value with a new one.
|
||||
* json_object_set_value does not copy passed value so it shouldn't be freed afterwards. */
|
||||
JSON_Status json_object_set_value(JSON_Object *object, const char *name, JSON_Value *value);
|
||||
JSON_Status json_object_set_string(JSON_Object *object, const char *name, const char *string);
|
||||
JSON_Status json_object_set_number(JSON_Object *object, const char *name, double number);
|
||||
JSON_Status json_object_set_boolean(JSON_Object *object, const char *name, int boolean);
|
||||
JSON_Status json_object_set_null(JSON_Object *object, const char *name);
|
||||
|
||||
/* Works like dotget functions, but creates whole hierarchy if necessary.
|
||||
* json_object_dotset_value does not copy passed value so it shouldn't be freed afterwards. */
|
||||
JSON_Status json_object_dotset_value(JSON_Object *object, const char *name, JSON_Value *value);
|
||||
JSON_Status json_object_dotset_string(JSON_Object *object, const char *name, const char *string);
|
||||
JSON_Status json_object_dotset_number(JSON_Object *object, const char *name, double number);
|
||||
JSON_Status json_object_dotset_boolean(JSON_Object *object, const char *name, int boolean);
|
||||
JSON_Status json_object_dotset_null(JSON_Object *object, const char *name);
|
||||
|
||||
/* Frees and removes name-value pair */
|
||||
JSON_Status json_object_remove(JSON_Object *object, const char *name);
|
||||
|
||||
/* Works like dotget function, but removes name-value pair only on exact match. */
|
||||
JSON_Status json_object_dotremove(JSON_Object *object, const char *key);
|
||||
|
||||
/* Removes all name-value pairs in object */
|
||||
JSON_Status json_object_clear(JSON_Object *object);
|
||||
|
||||
/*
|
||||
*JSON Array
|
||||
*/
|
||||
JSON_Value * json_array_get_value (const JSON_Array *array, size_t index);
|
||||
const char * json_array_get_string (const JSON_Array *array, size_t index);
|
||||
JSON_Object * json_array_get_object (const JSON_Array *array, size_t index);
|
||||
JSON_Array * json_array_get_array (const JSON_Array *array, size_t index);
|
||||
double json_array_get_number (const JSON_Array *array, size_t index); /* returns 0 on fail */
|
||||
int json_array_get_boolean(const JSON_Array *array, size_t index); /* returns -1 on fail */
|
||||
size_t json_array_get_count (const JSON_Array *array);
|
||||
|
||||
/* Frees and removes value at given index, does nothing and returns JSONFailure if index doesn't exist.
|
||||
* Order of values in array may change during execution. */
|
||||
JSON_Status json_array_remove(JSON_Array *array, size_t i);
|
||||
|
||||
/* Frees and removes from array value at given index and replaces it with given one.
|
||||
* Does nothing and returns JSONFailure if index doesn't exist.
|
||||
* json_array_replace_value does not copy passed value so it shouldn't be freed afterwards. */
|
||||
JSON_Status json_array_replace_value(JSON_Array *array, size_t i, JSON_Value *value);
|
||||
JSON_Status json_array_replace_string(JSON_Array *array, size_t i, const char* string);
|
||||
JSON_Status json_array_replace_number(JSON_Array *array, size_t i, double number);
|
||||
JSON_Status json_array_replace_boolean(JSON_Array *array, size_t i, int boolean);
|
||||
JSON_Status json_array_replace_null(JSON_Array *array, size_t i);
|
||||
|
||||
/* Frees and removes all values from array */
|
||||
JSON_Status json_array_clear(JSON_Array *array);
|
||||
|
||||
/* Appends new value at the end of array.
|
||||
* json_array_append_value does not copy passed value so it shouldn't be freed afterwards. */
|
||||
JSON_Status json_array_append_value(JSON_Array *array, JSON_Value *value);
|
||||
JSON_Status json_array_append_string(JSON_Array *array, const char *string);
|
||||
JSON_Status json_array_append_number(JSON_Array *array, double number);
|
||||
JSON_Status json_array_append_boolean(JSON_Array *array, int boolean);
|
||||
JSON_Status json_array_append_null(JSON_Array *array);
|
||||
|
||||
/*
|
||||
*JSON Value
|
||||
*/
|
||||
JSON_Value * json_value_init_object (void);
|
||||
JSON_Value * json_value_init_array (void);
|
||||
JSON_Value * json_value_init_string (const char *string); /* copies passed string */
|
||||
JSON_Value * json_value_init_number (double number);
|
||||
JSON_Value * json_value_init_boolean(int boolean);
|
||||
JSON_Value * json_value_init_null (void);
|
||||
JSON_Value * json_value_deep_copy (const JSON_Value *value);
|
||||
void json_value_free (JSON_Value *value);
|
||||
|
||||
JSON_Value_Type json_value_get_type (const JSON_Value *value);
|
||||
JSON_Object * json_value_get_object (const JSON_Value *value);
|
||||
JSON_Array * json_value_get_array (const JSON_Value *value);
|
||||
const char * json_value_get_string (const JSON_Value *value);
|
||||
double json_value_get_number (const JSON_Value *value);
|
||||
int json_value_get_boolean(const JSON_Value *value);
|
||||
|
||||
/* Same as above, but shorter */
|
||||
JSON_Value_Type json_type (const JSON_Value *value);
|
||||
JSON_Object * json_object (const JSON_Value *value);
|
||||
JSON_Array * json_array (const JSON_Value *value);
|
||||
const char * json_string (const JSON_Value *value);
|
||||
double json_number (const JSON_Value *value);
|
||||
int json_boolean(const JSON_Value *value);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,247 @@
|
|||
#ifndef TINYMT32_H
|
||||
#define TINYMT32_H
|
||||
/**
|
||||
* @file tinymt32.h
|
||||
*
|
||||
* @brief Tiny Mersenne Twister only 127 bit internal state
|
||||
*
|
||||
* @author Mutsuo Saito (Hiroshima University)
|
||||
* @author Makoto Matsumoto (University of Tokyo)
|
||||
*
|
||||
* Copyright (C) 2011 Mutsuo Saito, Makoto Matsumoto,
|
||||
* Hiroshima University and The University of Tokyo.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The 3-clause BSD License is applied to this software, see
|
||||
* LICENSE.txt
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#define TINYMT32_MEXP 127
|
||||
#define TINYMT32_SH0 1
|
||||
#define TINYMT32_SH1 10
|
||||
#define TINYMT32_SH8 8
|
||||
#define TINYMT32_MASK UINT32_C(0x7fffffff)
|
||||
#define TINYMT32_MUL (1.0f / 16777216.0f)
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* tinymt32 internal state vector and parameters
|
||||
*/
|
||||
struct TINYMT32_T {
|
||||
uint32_t status[4];
|
||||
uint32_t mat1;
|
||||
uint32_t mat2;
|
||||
uint32_t tmat;
|
||||
};
|
||||
|
||||
typedef struct TINYMT32_T tinymt32_t;
|
||||
|
||||
void tinymt32_init(tinymt32_t * random, uint32_t seed);
|
||||
void tinymt32_init_by_array(tinymt32_t * random, uint32_t init_key[],
|
||||
int key_length);
|
||||
|
||||
#if defined(__GNUC__)
|
||||
/**
|
||||
* This function always returns 127
|
||||
* @param random not used
|
||||
* @return always 127
|
||||
*/
|
||||
inline static int tinymt32_get_mexp(
|
||||
tinymt32_t * random __attribute__((unused))) {
|
||||
return TINYMT32_MEXP;
|
||||
}
|
||||
#else
|
||||
inline static int tinymt32_get_mexp(tinymt32_t * random) {
|
||||
return TINYMT32_MEXP;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This function changes internal state of tinymt32.
|
||||
* Users should not call this function directly.
|
||||
* @param random tinymt internal status
|
||||
*/
|
||||
inline static void tinymt32_next_state(tinymt32_t * random) {
|
||||
uint32_t x;
|
||||
uint32_t y;
|
||||
|
||||
y = random->status[3];
|
||||
x = (random->status[0] & TINYMT32_MASK)
|
||||
^ random->status[1]
|
||||
^ random->status[2];
|
||||
x ^= (x << TINYMT32_SH0);
|
||||
y ^= (y >> TINYMT32_SH0) ^ x;
|
||||
random->status[0] = random->status[1];
|
||||
random->status[1] = random->status[2];
|
||||
random->status[2] = x ^ (y << TINYMT32_SH1);
|
||||
random->status[3] = y;
|
||||
random->status[1] ^= -((int32_t)(y & 1)) & random->mat1;
|
||||
random->status[2] ^= -((int32_t)(y & 1)) & random->mat2;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function outputs 32-bit unsigned integer from internal state.
|
||||
* Users should not call this function directly.
|
||||
* @param random tinymt internal status
|
||||
* @return 32-bit unsigned pseudorandom number
|
||||
*/
|
||||
inline static uint32_t tinymt32_temper(tinymt32_t * random) {
|
||||
uint32_t t0, t1;
|
||||
t0 = random->status[3];
|
||||
#if defined(LINEARITY_CHECK)
|
||||
t1 = random->status[0]
|
||||
^ (random->status[2] >> TINYMT32_SH8);
|
||||
#else
|
||||
t1 = random->status[0]
|
||||
+ (random->status[2] >> TINYMT32_SH8);
|
||||
#endif
|
||||
t0 ^= t1;
|
||||
t0 ^= -((int32_t)(t1 & 1)) & random->tmat;
|
||||
return t0;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function outputs floating point number from internal state.
|
||||
* Users should not call this function directly.
|
||||
* @param random tinymt internal status
|
||||
* @return floating point number r (1.0 <= r < 2.0)
|
||||
*/
|
||||
inline static float tinymt32_temper_conv(tinymt32_t * random) {
|
||||
uint32_t t0, t1;
|
||||
union {
|
||||
uint32_t u;
|
||||
float f;
|
||||
} conv;
|
||||
|
||||
t0 = random->status[3];
|
||||
#if defined(LINEARITY_CHECK)
|
||||
t1 = random->status[0]
|
||||
^ (random->status[2] >> TINYMT32_SH8);
|
||||
#else
|
||||
t1 = random->status[0]
|
||||
+ (random->status[2] >> TINYMT32_SH8);
|
||||
#endif
|
||||
t0 ^= t1;
|
||||
conv.u = ((t0 ^ (-((int32_t)(t1 & 1)) & random->tmat)) >> 9)
|
||||
| UINT32_C(0x3f800000);
|
||||
return conv.f;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function outputs floating point number from internal state.
|
||||
* Users should not call this function directly.
|
||||
* @param random tinymt internal status
|
||||
* @return floating point number r (1.0 < r < 2.0)
|
||||
*/
|
||||
inline static float tinymt32_temper_conv_open(tinymt32_t * random) {
|
||||
uint32_t t0, t1;
|
||||
union {
|
||||
uint32_t u;
|
||||
float f;
|
||||
} conv;
|
||||
|
||||
t0 = random->status[3];
|
||||
#if defined(LINEARITY_CHECK)
|
||||
t1 = random->status[0]
|
||||
^ (random->status[2] >> TINYMT32_SH8);
|
||||
#else
|
||||
t1 = random->status[0]
|
||||
+ (random->status[2] >> TINYMT32_SH8);
|
||||
#endif
|
||||
t0 ^= t1;
|
||||
conv.u = ((t0 ^ (-((int32_t)(t1 & 1)) & random->tmat)) >> 9)
|
||||
| UINT32_C(0x3f800001);
|
||||
return conv.f;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function outputs 32-bit unsigned integer from internal state.
|
||||
* @param random tinymt internal status
|
||||
* @return 32-bit unsigned integer r (0 <= r < 2^32)
|
||||
*/
|
||||
inline static uint32_t tinymt32_generate_uint32(tinymt32_t * random) {
|
||||
tinymt32_next_state(random);
|
||||
return tinymt32_temper(random);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function outputs floating point number from internal state.
|
||||
* This function is implemented using multiplying by (1 / 2^24).
|
||||
* floating point multiplication is faster than using union trick in
|
||||
* my Intel CPU.
|
||||
* @param random tinymt internal status
|
||||
* @return floating point number r (0.0 <= r < 1.0)
|
||||
*/
|
||||
inline static float tinymt32_generate_float(tinymt32_t * random) {
|
||||
tinymt32_next_state(random);
|
||||
return (tinymt32_temper(random) >> 8) * TINYMT32_MUL;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function outputs floating point number from internal state.
|
||||
* This function is implemented using union trick.
|
||||
* @param random tinymt internal status
|
||||
* @return floating point number r (1.0 <= r < 2.0)
|
||||
*/
|
||||
inline static float tinymt32_generate_float12(tinymt32_t * random) {
|
||||
tinymt32_next_state(random);
|
||||
return tinymt32_temper_conv(random);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function outputs floating point number from internal state.
|
||||
* This function is implemented using union trick.
|
||||
* @param random tinymt internal status
|
||||
* @return floating point number r (0.0 <= r < 1.0)
|
||||
*/
|
||||
inline static float tinymt32_generate_float01(tinymt32_t * random) {
|
||||
tinymt32_next_state(random);
|
||||
return tinymt32_temper_conv(random) - 1.0f;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function outputs floating point number from internal state.
|
||||
* This function may return 1.0 and never returns 0.0.
|
||||
* @param random tinymt internal status
|
||||
* @return floating point number r (0.0 < r <= 1.0)
|
||||
*/
|
||||
inline static float tinymt32_generate_floatOC(tinymt32_t * random) {
|
||||
tinymt32_next_state(random);
|
||||
return 1.0f - tinymt32_generate_float(random);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function outputs floating point number from internal state.
|
||||
* This function returns neither 0.0 nor 1.0.
|
||||
* @param random tinymt internal status
|
||||
* @return floating point number r (0.0 < r < 1.0)
|
||||
*/
|
||||
inline static float tinymt32_generate_floatOO(tinymt32_t * random) {
|
||||
tinymt32_next_state(random);
|
||||
return tinymt32_temper_conv_open(random) - 1.0f;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function outputs double precision floating point number from
|
||||
* internal state. The returned value has 32-bit precision.
|
||||
* In other words, this function makes one double precision floating point
|
||||
* number from one 32-bit unsigned integer.
|
||||
* @param random tinymt internal status
|
||||
* @return floating point number r (0.0 <= r < 1.0)
|
||||
*/
|
||||
inline static double tinymt32_generate_32double(tinymt32_t * random) {
|
||||
tinymt32_next_state(random);
|
||||
return tinymt32_temper(random) * (1.0 / 4294967296.0);
|
||||
}
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,307 @@
|
|||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2019 Semtech
|
||||
|
||||
Description:
|
||||
Base64 encoding & decoding library
|
||||
|
||||
License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*/
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- DEPENDANCIES --------------------------------------------------------- */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "base64.h"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE MACROS ------------------------------------------------------- */
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
|
||||
#define CRIT(a) fprintf(stderr, "\nCRITICAL file:%s line:%u msg:%s\n", __FILE__, __LINE__,a);exit(EXIT_FAILURE)
|
||||
|
||||
//#define DEBUG(args...) fprintf(stderr,"debug: " args) /* diagnostic message that is destined to the user */
|
||||
#define DEBUG(args...)
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE CONSTANTS ---------------------------------------------------- */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE MODULE-WIDE VARIABLES ---------------------------------------- */
|
||||
|
||||
static char code_62 = '+'; /* RFC 1421 standard character for code 62 */
|
||||
static char code_63 = '/'; /* RFC 1421 standard character for code 63 */
|
||||
static char code_pad = '='; /* RFC 1421 padding character if padding */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE FUNCTIONS DECLARATION ---------------------------------------- */
|
||||
|
||||
/**
|
||||
@brief Convert a code in the range 0-63 to an ASCII character
|
||||
*/
|
||||
char code_to_char(uint8_t x);
|
||||
|
||||
/**
|
||||
@brief Convert an ASCII character to a code in the range 0-63
|
||||
*/
|
||||
uint8_t char_to_code(char x);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE FUNCTIONS DEFINITION ----------------------------------------- */
|
||||
|
||||
char code_to_char(uint8_t x) {
|
||||
if (x <= 25) {
|
||||
return 'A' + x;
|
||||
} else if ((x >= 26) && (x <= 51)) {
|
||||
return 'a' + (x-26);
|
||||
} else if ((x >= 52) && (x <= 61)) {
|
||||
return '0' + (x-52);
|
||||
} else if (x == 62) {
|
||||
return code_62;
|
||||
} else if (x == 63) {
|
||||
return code_63;
|
||||
} else {
|
||||
DEBUG("ERROR: %i IS OUT OF RANGE 0-63 FOR BASE64 ENCODING\n", x);
|
||||
exit(EXIT_FAILURE);
|
||||
} //TODO: improve error management
|
||||
}
|
||||
|
||||
uint8_t char_to_code(char x) {
|
||||
if ((x >= 'A') && (x <= 'Z')) {
|
||||
return (uint8_t)x - (uint8_t)'A';
|
||||
} else if ((x >= 'a') && (x <= 'z')) {
|
||||
return (uint8_t)x - (uint8_t)'a' + 26;
|
||||
} else if ((x >= '0') && (x <= '9')) {
|
||||
return (uint8_t)x - (uint8_t)'0' + 52;
|
||||
} else if (x == code_62) {
|
||||
return 62;
|
||||
} else if (x == code_63) {
|
||||
return 63;
|
||||
} else {
|
||||
DEBUG("ERROR: %c (0x%x) IS INVALID CHARACTER FOR BASE64 DECODING\n", x, x);
|
||||
exit(EXIT_FAILURE);
|
||||
} //TODO: improve error management
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PUBLIC FUNCTIONS DEFINITION ------------------------------------------ */
|
||||
|
||||
int bin_to_b64_nopad(const uint8_t * in, int size, char * out, int max_len) {
|
||||
int i;
|
||||
int result_len; /* size of the result */
|
||||
int full_blocks; /* number of 3 unsigned chars / 4 characters blocks */
|
||||
int last_bytes; /* number of unsigned chars <3 in the last block */
|
||||
int last_chars; /* number of characters <4 in the last block */
|
||||
uint32_t b;
|
||||
|
||||
/* check input values */
|
||||
if ((out == NULL) || (in == NULL)) {
|
||||
DEBUG("ERROR: NULL POINTER AS OUTPUT IN BIN_TO_B64\n");
|
||||
return -1;
|
||||
}
|
||||
if (size == 0) {
|
||||
*out = 0; /* null string */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* calculate the number of base64 'blocks' */
|
||||
full_blocks = size / 3;
|
||||
last_bytes = size % 3;
|
||||
switch (last_bytes) {
|
||||
case 0: /* no byte left to encode */
|
||||
last_chars = 0;
|
||||
break;
|
||||
case 1: /* 1 byte left to encode -> +2 chars */
|
||||
last_chars = 2;
|
||||
break;
|
||||
case 2: /* 2 bytes left to encode -> +3 chars */
|
||||
last_chars = 3;
|
||||
break;
|
||||
default:
|
||||
CRIT("switch default that should not be possible");
|
||||
}
|
||||
|
||||
/* check if output buffer is big enough */
|
||||
result_len = (4*full_blocks) + last_chars;
|
||||
if (max_len < (result_len + 1)) { /* 1 char added for string terminator */
|
||||
DEBUG("ERROR: OUTPUT BUFFER TOO SMALL IN BIN_TO_B64\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* process all the full blocks */
|
||||
for (i=0; i < full_blocks; ++i) {
|
||||
b = (0xFF & in[3*i] ) << 16;
|
||||
b |= (0xFF & in[3*i + 1]) << 8;
|
||||
b |= 0xFF & in[3*i + 2];
|
||||
out[4*i + 0] = code_to_char((b >> 18) & 0x3F);
|
||||
out[4*i + 1] = code_to_char((b >> 12) & 0x3F);
|
||||
out[4*i + 2] = code_to_char((b >> 6 ) & 0x3F);
|
||||
out[4*i + 3] = code_to_char( b & 0x3F);
|
||||
}
|
||||
|
||||
/* process the last 'partial' block and terminate string */
|
||||
i = full_blocks;
|
||||
if (last_chars == 0) {
|
||||
out[4*i] = 0; /* null character to terminate string */
|
||||
} else if (last_chars == 2) {
|
||||
b = (0xFF & in[3*i] ) << 16;
|
||||
out[4*i + 0] = code_to_char((b >> 18) & 0x3F);
|
||||
out[4*i + 1] = code_to_char((b >> 12) & 0x3F);
|
||||
out[4*i + 2] = 0; /* null character to terminate string */
|
||||
} else if (last_chars == 3) {
|
||||
b = (0xFF & in[3*i] ) << 16;
|
||||
b |= (0xFF & in[3*i + 1]) << 8;
|
||||
out[4*i + 0] = code_to_char((b >> 18) & 0x3F);
|
||||
out[4*i + 1] = code_to_char((b >> 12) & 0x3F);
|
||||
out[4*i + 2] = code_to_char((b >> 6 ) & 0x3F);
|
||||
out[4*i + 3] = 0; /* null character to terminate string */
|
||||
}
|
||||
|
||||
return result_len;
|
||||
}
|
||||
|
||||
int b64_to_bin_nopad(const char * in, int size, uint8_t * out, int max_len) {
|
||||
int i;
|
||||
int result_len; /* size of the result */
|
||||
int full_blocks; /* number of 3 unsigned chars / 4 characters blocks */
|
||||
int last_chars; /* number of characters <4 in the last block */
|
||||
int last_bytes; /* number of unsigned chars <3 in the last block */
|
||||
uint32_t b;
|
||||
;
|
||||
|
||||
/* check input values */
|
||||
if ((out == NULL) || (in == NULL)) {
|
||||
DEBUG("ERROR: NULL POINTER AS OUTPUT OR INPUT IN B64_TO_BIN\n");
|
||||
return -1;
|
||||
}
|
||||
if (size == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* calculate the number of base64 'blocks' */
|
||||
full_blocks = size / 4;
|
||||
last_chars = size % 4;
|
||||
switch (last_chars) {
|
||||
case 0: /* no char left to decode */
|
||||
last_bytes = 0;
|
||||
break;
|
||||
case 1: /* only 1 char left is an error */
|
||||
DEBUG("ERROR: ONLY ONE CHAR LEFT IN B64_TO_BIN\n");
|
||||
return -1;
|
||||
case 2: /* 2 chars left to decode -> +1 byte */
|
||||
last_bytes = 1;
|
||||
break;
|
||||
case 3: /* 3 chars left to decode -> +2 bytes */
|
||||
last_bytes = 2;
|
||||
break;
|
||||
default:
|
||||
CRIT("switch default that should not be possible");
|
||||
}
|
||||
|
||||
/* check if output buffer is big enough */
|
||||
result_len = (3*full_blocks) + last_bytes;
|
||||
if (max_len < result_len) {
|
||||
DEBUG("ERROR: OUTPUT BUFFER TOO SMALL IN B64_TO_BIN\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* process all the full blocks */
|
||||
for (i=0; i < full_blocks; ++i) {
|
||||
b = (0x3F & char_to_code(in[4*i] )) << 18;
|
||||
b |= (0x3F & char_to_code(in[4*i + 1])) << 12;
|
||||
b |= (0x3F & char_to_code(in[4*i + 2])) << 6;
|
||||
b |= 0x3F & char_to_code(in[4*i + 3]);
|
||||
out[3*i + 0] = (b >> 16) & 0xFF;
|
||||
out[3*i + 1] = (b >> 8 ) & 0xFF;
|
||||
out[3*i + 2] = b & 0xFF;
|
||||
}
|
||||
|
||||
/* process the last 'partial' block */
|
||||
i = full_blocks;
|
||||
if (last_bytes == 1) {
|
||||
b = (0x3F & char_to_code(in[4*i] )) << 18;
|
||||
b |= (0x3F & char_to_code(in[4*i + 1])) << 12;
|
||||
out[3*i + 0] = (b >> 16) & 0xFF;
|
||||
if (((b >> 12) & 0x0F) != 0) {
|
||||
DEBUG("WARNING: last character contains unusable bits\n");
|
||||
}
|
||||
} else if (last_bytes == 2) {
|
||||
b = (0x3F & char_to_code(in[4*i] )) << 18;
|
||||
b |= (0x3F & char_to_code(in[4*i + 1])) << 12;
|
||||
b |= (0x3F & char_to_code(in[4*i + 2])) << 6;
|
||||
out[3*i + 0] = (b >> 16) & 0xFF;
|
||||
out[3*i + 1] = (b >> 8 ) & 0xFF;
|
||||
if (((b >> 6) & 0x03) != 0) {
|
||||
DEBUG("WARNING: last character contains unusable bits\n");
|
||||
}
|
||||
}
|
||||
|
||||
return result_len;
|
||||
}
|
||||
|
||||
int bin_to_b64(const uint8_t * in, int size, char * out, int max_len) {
|
||||
int ret;
|
||||
|
||||
ret = bin_to_b64_nopad(in, size, out, max_len);
|
||||
|
||||
if (ret == -1) {
|
||||
return -1;
|
||||
}
|
||||
switch (ret%4) {
|
||||
case 0: /* nothing to do */
|
||||
return ret;
|
||||
case 1:
|
||||
DEBUG("ERROR: INVALID UNPADDED BASE64 STRING\n");
|
||||
return -1;
|
||||
case 2: /* 2 chars in last block, must add 2 padding char */
|
||||
if (max_len >= (ret + 2 + 1)) {
|
||||
out[ret] = code_pad;
|
||||
out[ret+1] = code_pad;
|
||||
out[ret+2] = 0;
|
||||
return ret+2;
|
||||
} else {
|
||||
DEBUG("ERROR: not enough room to add padding in bin_to_b64\n");
|
||||
return -1;
|
||||
}
|
||||
case 3: /* 3 chars in last block, must add 1 padding char */
|
||||
if (max_len >= (ret + 1 + 1)) {
|
||||
out[ret] = code_pad;
|
||||
out[ret+1] = 0;
|
||||
return ret+1;
|
||||
} else {
|
||||
DEBUG("ERROR: not enough room to add padding in bin_to_b64\n");
|
||||
return -1;
|
||||
}
|
||||
default:
|
||||
CRIT("switch default that should not be possible");
|
||||
}
|
||||
}
|
||||
|
||||
int b64_to_bin(const char * in, int size, uint8_t * out, int max_len) {
|
||||
if (in == NULL) {
|
||||
DEBUG("ERROR: NULL POINTER AS OUTPUT OR INPUT IN B64_TO_BIN\n");
|
||||
return -1;
|
||||
}
|
||||
if ((size%4 == 0) && (size >= 4)) { /* potentially padded Base64 */
|
||||
if (in[size-2] == code_pad) { /* 2 padding char to ignore */
|
||||
return b64_to_bin_nopad(in, size-2, out, max_len);
|
||||
} else if (in[size-1] == code_pad) { /* 1 padding char to ignore */
|
||||
return b64_to_bin_nopad(in, size-1, out, max_len);
|
||||
} else { /* no padding to ignore */
|
||||
return b64_to_bin_nopad(in, size, out, max_len);
|
||||
}
|
||||
} else { /* treat as unpadded Base64 */
|
||||
return b64_to_bin_nopad(in, size, out, max_len);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,145 @@
|
|||
/**
|
||||
* @file tinymt32.c
|
||||
*
|
||||
* @brief Tiny Mersenne Twister only 127 bit internal state
|
||||
*
|
||||
* @author Mutsuo Saito (Hiroshima University)
|
||||
* @author Makoto Matsumoto (The University of Tokyo)
|
||||
*
|
||||
* Copyright (C) 2011 Mutsuo Saito, Makoto Matsumoto,
|
||||
* Hiroshima University and The University of Tokyo.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The 3-clause BSD License is applied to this software, see
|
||||
* LICENSE.txt
|
||||
*/
|
||||
#include "tinymt32.h"
|
||||
#define MIN_LOOP 8
|
||||
#define PRE_LOOP 8
|
||||
|
||||
/**
|
||||
* This function represents a function used in the initialization
|
||||
* by init_by_array
|
||||
* @param x 32-bit integer
|
||||
* @return 32-bit integer
|
||||
*/
|
||||
static uint32_t ini_func1(uint32_t x) {
|
||||
return (x ^ (x >> 27)) * UINT32_C(1664525);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function represents a function used in the initialization
|
||||
* by init_by_array
|
||||
* @param x 32-bit integer
|
||||
* @return 32-bit integer
|
||||
*/
|
||||
static uint32_t ini_func2(uint32_t x) {
|
||||
return (x ^ (x >> 27)) * UINT32_C(1566083941);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function certificate the period of 2^127-1.
|
||||
* @param random tinymt state vector.
|
||||
*/
|
||||
static void period_certification(tinymt32_t * random) {
|
||||
if ((random->status[0] & TINYMT32_MASK) == 0 &&
|
||||
random->status[1] == 0 &&
|
||||
random->status[2] == 0 &&
|
||||
random->status[3] == 0) {
|
||||
random->status[0] = 'T';
|
||||
random->status[1] = 'I';
|
||||
random->status[2] = 'N';
|
||||
random->status[3] = 'Y';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function initializes the internal state array with a 32-bit
|
||||
* unsigned integer seed.
|
||||
* @param random tinymt state vector.
|
||||
* @param seed a 32-bit unsigned integer used as a seed.
|
||||
*/
|
||||
void tinymt32_init(tinymt32_t * random, uint32_t seed) {
|
||||
random->status[0] = seed;
|
||||
random->status[1] = random->mat1;
|
||||
random->status[2] = random->mat2;
|
||||
random->status[3] = random->tmat;
|
||||
for (int i = 1; i < MIN_LOOP; i++) {
|
||||
random->status[i & 3] ^= i + UINT32_C(1812433253)
|
||||
* (random->status[(i - 1) & 3]
|
||||
^ (random->status[(i - 1) & 3] >> 30));
|
||||
}
|
||||
period_certification(random);
|
||||
for (int i = 0; i < PRE_LOOP; i++) {
|
||||
tinymt32_next_state(random);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function initializes the internal state array,
|
||||
* with an array of 32-bit unsigned integers used as seeds
|
||||
* @param random tinymt state vector.
|
||||
* @param init_key the array of 32-bit integers, used as a seed.
|
||||
* @param key_length the length of init_key.
|
||||
*/
|
||||
void tinymt32_init_by_array(tinymt32_t * random, uint32_t init_key[],
|
||||
int key_length) {
|
||||
const int lag = 1;
|
||||
const int mid = 1;
|
||||
const int size = 4;
|
||||
int i, j;
|
||||
int count;
|
||||
uint32_t r;
|
||||
uint32_t * st = &random->status[0];
|
||||
|
||||
st[0] = 0;
|
||||
st[1] = random->mat1;
|
||||
st[2] = random->mat2;
|
||||
st[3] = random->tmat;
|
||||
if (key_length + 1 > MIN_LOOP) {
|
||||
count = key_length + 1;
|
||||
} else {
|
||||
count = MIN_LOOP;
|
||||
}
|
||||
r = ini_func1(st[0] ^ st[mid % size]
|
||||
^ st[(size - 1) % size]);
|
||||
st[mid % size] += r;
|
||||
r += key_length;
|
||||
st[(mid + lag) % size] += r;
|
||||
st[0] = r;
|
||||
count--;
|
||||
for (i = 1, j = 0; (j < count) && (j < key_length); j++) {
|
||||
r = ini_func1(st[i % size]
|
||||
^ st[(i + mid) % size]
|
||||
^ st[(i + size - 1) % size]);
|
||||
st[(i + mid) % size] += r;
|
||||
r += init_key[j] + i;
|
||||
st[(i + mid + lag) % size] += r;
|
||||
st[i % size] = r;
|
||||
i = (i + 1) % size;
|
||||
}
|
||||
for (; j < count; j++) {
|
||||
r = ini_func1(st[i % size]
|
||||
^ st[(i + mid) % size]
|
||||
^ st[(i + size - 1) % size]);
|
||||
st[(i + mid) % size] += r;
|
||||
r += i;
|
||||
st[(i + mid + lag) % size] += r;
|
||||
st[i % size] = r;
|
||||
i = (i + 1) % size;
|
||||
}
|
||||
for (j = 0; j < size; j++) {
|
||||
r = ini_func2(st[i % size]
|
||||
+ st[(i + mid) % size]
|
||||
+ st[(i + size - 1) % size]);
|
||||
st[(i + mid) % size] ^= r;
|
||||
r -= i;
|
||||
st[(i + mid + lag) % size] ^= r;
|
||||
st[i % size] = r;
|
||||
i = (i + 1) % size;
|
||||
}
|
||||
period_certification(random);
|
||||
for (i = 0; i < PRE_LOOP; i++) {
|
||||
tinymt32_next_state(random);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
### get external defined data
|
||||
|
||||
include ../target.cfg
|
||||
|
||||
### Application-specific constants
|
||||
|
||||
APP_NAME := lora_pkt_fwd
|
||||
|
||||
### Environment constants
|
||||
|
||||
LGW_PATH ?= ../libloragw
|
||||
LIB_PATH ?= ../libtools
|
||||
ARCH ?=
|
||||
CROSS_COMPILE ?=
|
||||
|
||||
OBJDIR = obj
|
||||
INCLUDES = $(wildcard inc/*.h)
|
||||
|
||||
### External constant definitions
|
||||
# must get library build option to know if mpsse must be linked or not
|
||||
|
||||
include $(LGW_PATH)/library.cfg
|
||||
RELEASE_VERSION := `cat ../VERSION`
|
||||
|
||||
### Constant symbols
|
||||
|
||||
CC := $(CROSS_COMPILE)gcc
|
||||
AR := $(CROSS_COMPILE)ar
|
||||
|
||||
CFLAGS := -O2 -Wall -Wextra -std=c99 -Iinc -I. -I../libtools/inc
|
||||
VFLAG := -D VERSION_STRING="\"$(RELEASE_VERSION)\""
|
||||
|
||||
### Constants for Lora concentrator HAL library
|
||||
# List the library sub-modules that are used by the application
|
||||
|
||||
LGW_INC =
|
||||
ifneq ($(wildcard $(LGW_PATH)/inc/config.h),)
|
||||
# only for HAL version 1.3 and beyond
|
||||
LGW_INC += $(LGW_PATH)/inc/config.h
|
||||
endif
|
||||
LGW_INC += $(LGW_PATH)/inc/loragw_hal.h
|
||||
|
||||
### Linking options
|
||||
|
||||
LIBS := -lloragw -ltinymt32 -lparson -lbase64 -lrt -lpthread -lm
|
||||
|
||||
### General build targets
|
||||
|
||||
all: $(APP_NAME)
|
||||
|
||||
clean:
|
||||
rm -f $(OBJDIR)/*.o
|
||||
rm -f $(APP_NAME)
|
||||
|
||||
ifneq ($(strip $(TARGET_IP)),)
|
||||
ifneq ($(strip $(TARGET_DIR)),)
|
||||
ifneq ($(strip $(TARGET_USR)),)
|
||||
install:
|
||||
@echo "---- Copying packet_forwarder files to $(TARGET_IP):$(TARGET_DIR)"
|
||||
@ssh $(TARGET_USR)@$(TARGET_IP) "mkdir -p $(TARGET_DIR)"
|
||||
@scp lora_pkt_fwd $(TARGET_USR)@$(TARGET_IP):$(TARGET_DIR)
|
||||
install_conf:
|
||||
@echo "---- Copying packet_forwarder conf files to $(TARGET_IP):$(TARGET_DIR)"
|
||||
@ssh $(TARGET_USR)@$(TARGET_IP) "mkdir -p $(TARGET_DIR)"
|
||||
@scp global_conf.json.sx1250 $(TARGET_USR)@$(TARGET_IP):$(TARGET_DIR)
|
||||
@scp global_conf.json.sx1257 $(TARGET_USR)@$(TARGET_IP):$(TARGET_DIR)
|
||||
else
|
||||
@echo "ERROR: TARGET_USR is not configured in target.cfg"
|
||||
endif
|
||||
else
|
||||
@echo "ERROR: TARGET_DIR is not configured in target.cfg"
|
||||
endif
|
||||
else
|
||||
@echo "ERROR: TARGET_IP is not configured in target.cfg"
|
||||
endif
|
||||
|
||||
### Sub-modules compilation
|
||||
|
||||
$(OBJDIR):
|
||||
mkdir -p $(OBJDIR)
|
||||
|
||||
$(OBJDIR)/%.o: src/%.c $(INCLUDES) | $(OBJDIR)
|
||||
$(CC) -c $(CFLAGS) -I$(LGW_PATH)/inc $< -o $@
|
||||
|
||||
### Main program compilation and assembly
|
||||
|
||||
$(OBJDIR)/$(APP_NAME).o: src/$(APP_NAME).c $(LGW_INC) $(INCLUDES) | $(OBJDIR)
|
||||
$(CC) -c $(CFLAGS) $(VFLAG) -I$(LGW_PATH)/inc $< -o $@
|
||||
|
||||
$(APP_NAME): $(OBJDIR)/$(APP_NAME).o $(LGW_PATH)/libloragw.a $(OBJDIR)/jitqueue.o
|
||||
$(CC) -L$(LGW_PATH) -L$(LIB_PATH) $< $(OBJDIR)/jitqueue.o -o $@ $(LIBS)
|
||||
|
||||
### EOF
|
|
@ -0,0 +1,477 @@
|
|||
______ _
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2019 Semtech
|
||||
|
||||
Basic communication protocol between LoRa gateway and Network Server
|
||||
====================================================================
|
||||
|
||||
|
||||
## 1. Introduction
|
||||
|
||||
The protocol between the gateway and the server is purposefully very basic and
|
||||
for demonstration purpose only, or for use on private and reliable networks.
|
||||
|
||||
There is no authentication of the gateway or the server, and the acknowledges
|
||||
are only used for network quality assessment, not to correct UDP datagrams
|
||||
losses (no retries).
|
||||
|
||||
|
||||
## 2. System schematic and definitions
|
||||
|
||||
((( Y )))
|
||||
|
|
||||
|
|
||||
+ - -|- - - - - - - - - - - - - + xxxxxxxxxxxx +--------+
|
||||
| +--+-----------+ +------+ | xx x x xxx | |
|
||||
| | | | | | xx Internet xx | |
|
||||
| | Concentrator |<--->| Host |<-------xx or xx-------->| |
|
||||
| | | SPI | | | xx Intranet xx | Server |
|
||||
| +--------------+ +------+ | xxxx x xxxx | |
|
||||
| ^ ^ | xxxxxxxx | |
|
||||
| | PPS +-------+ NMEA | | | |
|
||||
| +-----| GPS |-------+ | +--------+
|
||||
| | (opt) | |
|
||||
| +-------+ |
|
||||
| |
|
||||
| Gateway |
|
||||
+- - - - - - - - - - - - - - - -+
|
||||
|
||||
__Concentrator__: radio RX/TX board, based on Semtech multichannel modems
|
||||
(SX130x), transceivers (SX135x) and/or low-power stand-alone modems (SX127x).
|
||||
|
||||
__Host__: embedded computer on which the packet forwarder is run. Drives the
|
||||
concentrator through a SPI link.
|
||||
|
||||
__GPS__: GNSS (GPS, Galileo, GLONASS, etc) receiver with a "1 Pulse Per Second"
|
||||
output and a serial link to the host to send NMEA frames containing time and
|
||||
geographical coordinates data. Optional.
|
||||
|
||||
__Gateway__: a device composed of at least one radio concentrator, a host, some
|
||||
network connection to the internet or a private network (Ethernet, 3G, Wifi,
|
||||
microwave link), and optionally a GPS receiver for synchronization.
|
||||
|
||||
__Server__: an abstract computer that will process the RF packets received and
|
||||
forwarded by the gateway, and issue RF packets in response that the gateway
|
||||
will have to emit.
|
||||
|
||||
It is assumed that the gateway can be behind a NAT or a firewall stopping any
|
||||
incoming connection.
|
||||
It is assumed that the server has an static IP address (or an address solvable
|
||||
through a DNS service) and is able to receive incoming connections on a
|
||||
specific port.
|
||||
|
||||
|
||||
## 3. Upstream protocol
|
||||
|
||||
### 3.1. Sequence diagram ###
|
||||
|
||||
+---------+ +---------+
|
||||
| Gateway | | Server |
|
||||
+---------+ +---------+
|
||||
| -----------------------------------\ |
|
||||
|-| When 1-N RF packets are received | |
|
||||
| ------------------------------------ |
|
||||
| |
|
||||
| PUSH_DATA (token X, GW MAC, JSON payload) |
|
||||
|------------------------------------------------------------->|
|
||||
| |
|
||||
| PUSH_ACK (token X) |
|
||||
|<-------------------------------------------------------------|
|
||||
| ------------------------------\ |
|
||||
| | process packets *after* ack |-|
|
||||
| ------------------------------- |
|
||||
| |
|
||||
|
||||
### 3.2. PUSH_DATA packet ###
|
||||
|
||||
That packet type is used by the gateway mainly to forward the RF packets
|
||||
received, and associated metadata, to the server.
|
||||
|
||||
Bytes | Function
|
||||
:------:|---------------------------------------------------------------------
|
||||
0 | protocol version = 2
|
||||
1-2 | random token
|
||||
3 | PUSH_DATA identifier 0x00
|
||||
4-11 | Gateway unique identifier (MAC address)
|
||||
12-end | JSON object, starting with {, ending with }, see section 4
|
||||
|
||||
### 3.3. PUSH_ACK packet ###
|
||||
|
||||
That packet type is used by the server to acknowledge immediately all the
|
||||
PUSH_DATA packets received.
|
||||
|
||||
Bytes | Function
|
||||
:------:|---------------------------------------------------------------------
|
||||
0 | protocol version = 2
|
||||
1-2 | same token as the PUSH_DATA packet to acknowledge
|
||||
3 | PUSH_ACK identifier 0x01
|
||||
|
||||
|
||||
## 4. Upstream JSON data structure
|
||||
|
||||
The root object can contain an array named "rxpk":
|
||||
|
||||
``` json
|
||||
{
|
||||
"rxpk":[ {...}, ...]
|
||||
}
|
||||
```
|
||||
|
||||
That array contains at least one JSON object, each object contain a RF packet
|
||||
and associated metadata with the following fields:
|
||||
|
||||
Name | Type | Function
|
||||
:----:|:------:|--------------------------------------------------------------
|
||||
time | string | UTC time of pkt RX, us precision, ISO 8601 'compact' format
|
||||
tmms | number | GPS time of pkt RX, number of milliseconds since 06.Jan.1980
|
||||
tmst | number | Internal timestamp of "RX finished" event (32b unsigned)
|
||||
freq | number | RX central frequency in MHz (unsigned float, Hz precision)
|
||||
chan | number | Concentrator "IF" channel used for RX (unsigned integer)
|
||||
rfch | number | Concentrator "RF chain" used for RX (unsigned integer)
|
||||
mid | number | Concentrator modem ID on which pkt has been received
|
||||
stat | number | CRC status: 1 = OK, -1 = fail, 0 = no CRC
|
||||
modu | string | Modulation identifier "LORA" or "FSK"
|
||||
datr | string | LoRa datarate identifier (eg. SF12BW500)
|
||||
datr | number | FSK datarate (unsigned, in bits per second)
|
||||
codr | string | LoRa ECC coding rate identifier
|
||||
rssi | number | RSSI of the channel in dBm (signed integer, 1 dB precision)
|
||||
rssis| number | RSSI of the signal in dBm (signed integer, 1 dB precision)
|
||||
lsnr | number | Lora SNR ratio in dB (signed float, 0.1 dB precision)
|
||||
foff | number | LoRa frequency offset in Hz (signed interger)
|
||||
size | number | RF packet payload size in bytes (unsigned integer)
|
||||
data | string | Base64 encoded RF packet payload, padded
|
||||
|
||||
Example (white-spaces, indentation and newlines added for readability):
|
||||
|
||||
``` json
|
||||
{"rxpk":[
|
||||
{
|
||||
"time":"2013-03-31T16:21:17.528002Z",
|
||||
"tmst":3512348611,
|
||||
"chan":2,
|
||||
"rfch":0,
|
||||
"freq":866.349812,
|
||||
"stat":1,
|
||||
"modu":"LORA",
|
||||
"datr":"SF7BW125",
|
||||
"codr":"4/6",
|
||||
"rssi":-35,
|
||||
"lsnr":5.1,
|
||||
"size":32,
|
||||
"data":"-DS4CGaDCdG+48eJNM3Vai-zDpsR71Pn9CPA9uCON84"
|
||||
},{
|
||||
"time":"2013-03-31T16:21:17.530974Z",
|
||||
"tmst":3512348514,
|
||||
"chan":9,
|
||||
"rfch":1,
|
||||
"freq":869.1,
|
||||
"stat":1,
|
||||
"modu":"FSK",
|
||||
"datr":50000,
|
||||
"rssi":-75,
|
||||
"size":16,
|
||||
"data":"VEVTVF9QQUNLRVRfMTIzNA=="
|
||||
},{
|
||||
"time":"2013-03-31T16:21:17.532038Z",
|
||||
"tmst":3316387610,
|
||||
"chan":0,
|
||||
"rfch":0,
|
||||
"freq":863.00981,
|
||||
"stat":1,
|
||||
"modu":"LORA",
|
||||
"datr":"SF10BW125",
|
||||
"codr":"4/7",
|
||||
"rssi":-38,
|
||||
"lsnr":5.5,
|
||||
"size":32,
|
||||
"data":"ysgRl452xNLep9S1NTIg2lomKDxUgn3DJ7DE+b00Ass"
|
||||
}
|
||||
]}
|
||||
```
|
||||
|
||||
The root object can also contain an object named "stat" :
|
||||
|
||||
``` json
|
||||
{
|
||||
"rxpk":[ {...}, ...],
|
||||
"stat":{...}
|
||||
}
|
||||
```
|
||||
|
||||
It is possible for a packet to contain no "rxpk" array but a "stat" object.
|
||||
|
||||
``` json
|
||||
{
|
||||
"stat":{...}
|
||||
}
|
||||
```
|
||||
|
||||
That object contains the status of the gateway, with the following fields:
|
||||
|
||||
Name | Type | Function
|
||||
:----:|:------:|--------------------------------------------------------------
|
||||
time | string | UTC 'system' time of the gateway, ISO 8601 'expanded' format
|
||||
lati | number | GPS latitude of the gateway in degree (float, N is +)
|
||||
long | number | GPS latitude of the gateway in degree (float, E is +)
|
||||
alti | number | GPS altitude of the gateway in meter RX (integer)
|
||||
rxnb | number | Number of radio packets received (unsigned integer)
|
||||
rxok | number | Number of radio packets received with a valid PHY CRC
|
||||
rxfw | number | Number of radio packets forwarded (unsigned integer)
|
||||
ackr | number | Percentage of upstream datagrams that were acknowledged
|
||||
dwnb | number | Number of downlink datagrams received (unsigned integer)
|
||||
txnb | number | Number of packets emitted (unsigned integer)
|
||||
|
||||
Example (white-spaces, indentation and newlines added for readability):
|
||||
|
||||
``` json
|
||||
{"stat":{
|
||||
"time":"2014-01-12 08:59:28 GMT",
|
||||
"lati":46.24000,
|
||||
"long":3.25230,
|
||||
"alti":145,
|
||||
"rxnb":2,
|
||||
"rxok":2,
|
||||
"rxfw":2,
|
||||
"ackr":100.0,
|
||||
"dwnb":2,
|
||||
"txnb":2
|
||||
}}
|
||||
```
|
||||
|
||||
|
||||
## 5. Downstream protocol
|
||||
|
||||
### 5.1. Sequence diagram ###
|
||||
|
||||
+---------+ +---------+
|
||||
| Gateway | | Server |
|
||||
+---------+ +---------+
|
||||
| -----------------------------------\ |
|
||||
|-| Every N seconds (keepalive time) | |
|
||||
| ------------------------------------ |
|
||||
| |
|
||||
| PULL_DATA (token Y, MAC@) |
|
||||
|------------------------------------------------------------->|
|
||||
| |
|
||||
| PULL_ACK (token Y) |
|
||||
|<-------------------------------------------------------------|
|
||||
| |
|
||||
|
||||
+---------+ +---------+
|
||||
| Gateway | | Server |
|
||||
+---------+ +---------+
|
||||
| ------------------------------------------------------\ |
|
||||
| | Anytime after first PULL_DATA for each packet to TX |-|
|
||||
| ------------------------------------------------------- |
|
||||
| |
|
||||
| PULL_RESP (token Z, JSON payload) |
|
||||
|<-------------------------------------------------------------|
|
||||
| |
|
||||
| TX_ACK (token Z, JSON payload) |
|
||||
|------------------------------------------------------------->|
|
||||
|
||||
### 5.2. PULL_DATA packet ###
|
||||
|
||||
That packet type is used by the gateway to poll data from the server.
|
||||
|
||||
This data exchange is initialized by the gateway because it might be
|
||||
impossible for the server to send packets to the gateway if the gateway is
|
||||
behind a NAT.
|
||||
|
||||
When the gateway initialize the exchange, the network route towards the
|
||||
server will open and will allow for packets to flow both directions.
|
||||
The gateway must periodically send PULL_DATA packets to be sure the network
|
||||
route stays open for the server to be used at any time.
|
||||
|
||||
Bytes | Function
|
||||
:------:|---------------------------------------------------------------------
|
||||
0 | protocol version = 2
|
||||
1-2 | random token
|
||||
3 | PULL_DATA identifier 0x02
|
||||
4-11 | Gateway unique identifier (MAC address)
|
||||
|
||||
### 5.3. PULL_ACK packet ###
|
||||
|
||||
That packet type is used by the server to confirm that the network route is
|
||||
open and that the server can send PULL_RESP packets at any time.
|
||||
|
||||
Bytes | Function
|
||||
:------:|---------------------------------------------------------------------
|
||||
0 | protocol version = 2
|
||||
1-2 | same token as the PULL_DATA packet to acknowledge
|
||||
3 | PULL_ACK identifier 0x04
|
||||
|
||||
### 5.4. PULL_RESP packet ###
|
||||
|
||||
That packet type is used by the server to send RF packets and associated
|
||||
metadata that will have to be emitted by the gateway.
|
||||
|
||||
Bytes | Function
|
||||
:------:|---------------------------------------------------------------------
|
||||
0 | protocol version = 2
|
||||
1-2 | random token
|
||||
3 | PULL_RESP identifier 0x03
|
||||
4-end | JSON object, starting with {, ending with }, see section 6
|
||||
|
||||
### 5.5. TX_ACK packet ###
|
||||
|
||||
That packet type is used by the gateway to send a feedback to the server
|
||||
to inform if a downlink request has been accepted or rejected by the gateway.
|
||||
The datagram may optionnaly contain a JSON string to give more details on
|
||||
acknoledge. If no JSON is present (empty string), this means than no error
|
||||
occured.
|
||||
|
||||
Bytes | Function
|
||||
:------:|---------------------------------------------------------------------
|
||||
0 | protocol version = 2
|
||||
1-2 | same token as the PULL_RESP packet to acknowledge
|
||||
3 | TX_ACK identifier 0x05
|
||||
4-11 | Gateway unique identifier (MAC address)
|
||||
12-end | [optional] JSON object, starting with {, ending with }, see section 6
|
||||
|
||||
|
||||
## 6. Downstream JSON data structure
|
||||
|
||||
The root object of PULL_RESP packet must contain an object named "txpk":
|
||||
|
||||
``` json
|
||||
{
|
||||
"txpk": {...}
|
||||
}
|
||||
```
|
||||
|
||||
That object contain a RF packet to be emitted and associated metadata with the
|
||||
following fields:
|
||||
|
||||
Name | Type | Function
|
||||
:----:|:------:|--------------------------------------------------------------
|
||||
imme | bool | Send packet immediately (will ignore tmst & tmms)
|
||||
tmst | number | Send packet on a certain timestamp value (will ignore tmms)
|
||||
tmms | number | Send packet at a certain GPS time (GPS synchronization required)
|
||||
freq | number | TX central frequency in MHz (unsigned float, Hz precision)
|
||||
rfch | number | Concentrator "RF chain" used for TX (unsigned integer)
|
||||
powe | number | TX output power in dBm (unsigned integer, dBm precision)
|
||||
modu | string | Modulation identifier "LORA" or "FSK"
|
||||
datr | string | LoRa datarate identifier (eg. SF12BW500)
|
||||
datr | number | FSK datarate (unsigned, in bits per second)
|
||||
codr | string | LoRa ECC coding rate identifier
|
||||
fdev | number | FSK frequency deviation (unsigned integer, in Hz)
|
||||
ipol | bool | Lora modulation polarization inversion
|
||||
prea | number | RF preamble size (unsigned integer)
|
||||
size | number | RF packet payload size in bytes (unsigned integer)
|
||||
data | string | Base64 encoded RF packet payload, padding optional
|
||||
ncrc | bool | If true, disable the CRC of the physical layer (optional)
|
||||
|
||||
Most fields are optional.
|
||||
If a field is omitted, default parameters will be used.
|
||||
|
||||
Examples (white-spaces, indentation and newlines added for readability):
|
||||
|
||||
``` json
|
||||
{"txpk":{
|
||||
"imme":true,
|
||||
"freq":864.123456,
|
||||
"rfch":0,
|
||||
"powe":14,
|
||||
"modu":"LORA",
|
||||
"datr":"SF11BW125",
|
||||
"codr":"4/6",
|
||||
"ipol":false,
|
||||
"size":32,
|
||||
"data":"H3P3N2i9qc4yt7rK7ldqoeCVJGBybzPY5h1Dd7P7p8v"
|
||||
}}
|
||||
```
|
||||
|
||||
``` json
|
||||
{"txpk":{
|
||||
"imme":true,
|
||||
"freq":861.3,
|
||||
"rfch":0,
|
||||
"powe":12,
|
||||
"modu":"FSK",
|
||||
"datr":50000,
|
||||
"fdev":3000,
|
||||
"size":32,
|
||||
"data":"H3P3N2i9qc4yt7rK7ldqoeCVJGBybzPY5h1Dd7P7p8v"
|
||||
}}
|
||||
```
|
||||
|
||||
In case of error or warning, the root object of TX_ACK packet must contain an
|
||||
object named "txpk_ack":
|
||||
|
||||
``` json
|
||||
{
|
||||
"txpk_ack": {...}
|
||||
}
|
||||
```
|
||||
|
||||
That object contain status information concerning the associated PULL_RESP packet.
|
||||
|
||||
Name | Type | Function
|
||||
:----:|:------:|-----------------------------------------------------------------------------------------
|
||||
error | string | Indicates the type of failure that occurred for downlink request (optional)
|
||||
warn | string | Indicates that downlink request has been accepted with limitation (optional)
|
||||
value | string | When a warning is raised, it gives indications about the limitation (optional)
|
||||
value | number | When a warning is raised, it gives indications about the limitation (optional)
|
||||
|
||||
The possible values of the "error" field are:
|
||||
|
||||
Value | Definition
|
||||
:-----------------:|---------------------------------------------------------------------
|
||||
TOO_LATE | Rejected because it was already too late to program this packet for downlink
|
||||
TOO_EARLY | Rejected because downlink packet timestamp is too much in advance
|
||||
COLLISION_PACKET | Rejected because there was already a packet programmed in requested timeframe
|
||||
COLLISION_BEACON | Rejected because there was already a beacon planned in requested timeframe
|
||||
TX_FREQ | Rejected because requested frequency is not supported by TX RF chain
|
||||
GPS_UNLOCKED | Rejected because GPS is unlocked, so GPS timestamp cannot be used
|
||||
|
||||
The possible values of the "warn" field are:
|
||||
|
||||
Value | Definition
|
||||
:-----------------:|---------------------------------------------------------------------
|
||||
TX_POWER | The requested power is not supported by the gateway, the power actually used is given in the value field
|
||||
|
||||
Examples (white-spaces, indentation and newlines added for readability):
|
||||
|
||||
``` json
|
||||
{"txpk_ack":{
|
||||
"error":"COLLISION_PACKET"
|
||||
}}
|
||||
```
|
||||
|
||||
``` json
|
||||
{"txpk_ack":{
|
||||
"warn":"TX_POWER",
|
||||
"value":20
|
||||
}}
|
||||
```
|
||||
|
||||
## 7. Revisions
|
||||
|
||||
### v1.5 ###
|
||||
* Moved TX_POWER from "error" category to "warn" category in "txpk_ack" object
|
||||
|
||||
### v1.4 ###
|
||||
* Added "tmms" field for GPS time as a monotonic number of milliseconds
|
||||
ellapsed since January 6th, 1980 (GPS Epoch). No leap second.
|
||||
|
||||
### v1.3 ###
|
||||
|
||||
* Added downlink feedback from gateway to server (PULL_RESP -> TX_ACK)
|
||||
|
||||
### v1.2 ###
|
||||
|
||||
* Added value of FSK bitrate for upstream.
|
||||
* Added parameters for FSK bitrate and frequency deviation for downstream.
|
||||
|
||||
### v1.1 ###
|
||||
|
||||
* Added syntax for status report JSON object on upstream.
|
||||
|
||||
### v1.0 ###
|
||||
|
||||
* Initial version.
|
|
@ -0,0 +1,98 @@
|
|||
{
|
||||
"SX130x_conf": {
|
||||
"spidev_path": "/dev/spidev0.0",
|
||||
"lorawan_public": true,
|
||||
"clksrc": 0,
|
||||
"antenna_gain": 0, /* antenna gain, in dBi */
|
||||
"full_duplex": false,
|
||||
"precision_timestamp": {
|
||||
"enable": false,
|
||||
"max_ts_metrics": 255,
|
||||
"nb_symbols": 1
|
||||
},
|
||||
"radio_0": {
|
||||
"enable": true,
|
||||
"type": "SX1250",
|
||||
"freq": 867500000,
|
||||
"rssi_offset": -215.4,
|
||||
"rssi_tcomp": {"coeff_a": 0, "coeff_b": 0, "coeff_c": 20.41, "coeff_d": 2162.56, "coeff_e": 0},
|
||||
"tx_enable": true,
|
||||
"tx_freq_min": 863000000,
|
||||
"tx_freq_max": 870000000,
|
||||
"tx_gain_lut":[
|
||||
{"rf_power": 12, "pa_gain": 0, "pwr_idx": 16},
|
||||
{"rf_power": 13, "pa_gain": 0, "pwr_idx": 17},
|
||||
{"rf_power": 14, "pa_gain": 0, "pwr_idx": 18},
|
||||
{"rf_power": 15, "pa_gain": 0, "pwr_idx": 20},
|
||||
{"rf_power": 16, "pa_gain": 1, "pwr_idx": 0},
|
||||
{"rf_power": 17, "pa_gain": 1, "pwr_idx": 1},
|
||||
{"rf_power": 18, "pa_gain": 1, "pwr_idx": 2},
|
||||
{"rf_power": 19, "pa_gain": 1, "pwr_idx": 3},
|
||||
{"rf_power": 20, "pa_gain": 1, "pwr_idx": 4},
|
||||
{"rf_power": 21, "pa_gain": 1, "pwr_idx": 5},
|
||||
{"rf_power": 22, "pa_gain": 1, "pwr_idx": 6},
|
||||
{"rf_power": 23, "pa_gain": 1, "pwr_idx": 7},
|
||||
{"rf_power": 24, "pa_gain": 1, "pwr_idx": 8},
|
||||
{"rf_power": 25, "pa_gain": 1, "pwr_idx": 9},
|
||||
{"rf_power": 26, "pa_gain": 1, "pwr_idx": 11},
|
||||
{"rf_power": 27, "pa_gain": 1, "pwr_idx": 13}
|
||||
]
|
||||
},
|
||||
"radio_1": {
|
||||
"enable": true,
|
||||
"type": "SX1250",
|
||||
"freq": 868500000,
|
||||
"rssi_offset": -215.4,
|
||||
"rssi_tcomp": {"coeff_a": 0, "coeff_b": 0, "coeff_c": 20.41, "coeff_d": 2162.56, "coeff_e": 0},
|
||||
"tx_enable": false
|
||||
},
|
||||
"chan_multiSF_0": {"enable": true, "radio": 1, "if": -400000},
|
||||
"chan_multiSF_1": {"enable": true, "radio": 1, "if": -200000},
|
||||
"chan_multiSF_2": {"enable": true, "radio": 1, "if": 0},
|
||||
"chan_multiSF_3": {"enable": true, "radio": 0, "if": -400000},
|
||||
"chan_multiSF_4": {"enable": true, "radio": 0, "if": -200000},
|
||||
"chan_multiSF_5": {"enable": true, "radio": 0, "if": 0},
|
||||
"chan_multiSF_6": {"enable": true, "radio": 0, "if": 200000},
|
||||
"chan_multiSF_7": {"enable": true, "radio": 0, "if": 400000},
|
||||
"chan_Lora_std": {"enable": true, "radio": 1, "if": -200000, "bandwidth": 250000, "spread_factor": 7,
|
||||
"implicit_hdr": false, "implicit_payload_length": 17, "implicit_crc_en": false, "implicit_coderate": 1},
|
||||
"chan_FSK": {"enable": true, "radio": 1, "if": 300000, "bandwidth": 125000, "datarate": 50000}
|
||||
},
|
||||
|
||||
"gateway_conf": {
|
||||
"gateway_ID": "AA555A0000000000",
|
||||
/* change with default server address/ports */
|
||||
"server_address": "localhost",
|
||||
"serv_port_up": 1730,
|
||||
"serv_port_down": 1730,
|
||||
/* adjust the following parameters for your network */
|
||||
"keepalive_interval": 10,
|
||||
"stat_interval": 30,
|
||||
"push_timeout_ms": 100,
|
||||
/* forward only valid packets */
|
||||
"forward_crc_valid": true,
|
||||
"forward_crc_error": false,
|
||||
"forward_crc_disabled": false,
|
||||
/* GPS configuration */
|
||||
"gps_tty_path": "/dev/ttyS0",
|
||||
/* GPS reference coordinates */
|
||||
"ref_latitude": 0.0,
|
||||
"ref_longitude": 0.0,
|
||||
"ref_altitude": 0,
|
||||
/* Beaconing parameters */
|
||||
"beacon_period": 128,
|
||||
"beacon_freq_hz": 869525000,
|
||||
"beacon_datarate": 9,
|
||||
"beacon_bw_hz": 125000,
|
||||
"beacon_power": 14,
|
||||
"beacon_infodesc": 0
|
||||
},
|
||||
|
||||
"debug_conf": {
|
||||
"ref_payload":[
|
||||
{"id": "0xCAFE1234"},
|
||||
{"id": "0xCAFE2345"}
|
||||
],
|
||||
"log_file": "loragw_hal.log"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
{
|
||||
"SX130x_conf": {
|
||||
"spidev_path": "/dev/spidev0.0",
|
||||
"lorawan_public": true,
|
||||
"clksrc": 0,
|
||||
"antenna_gain": 0, /* antenna gain, in dBi */
|
||||
"full_duplex": false,
|
||||
"precision_timestamp": {
|
||||
"enable": false,
|
||||
"max_ts_metrics": 255,
|
||||
"nb_symbols": 1
|
||||
},
|
||||
"radio_0": {
|
||||
"enable": true,
|
||||
"type": "SX1257",
|
||||
"freq": 867500000,
|
||||
"rssi_offset": -196.0,
|
||||
"rssi_tcomp": {"coeff_a": -0.006, "coeff_b": 0.789, "coeff_c": -14.992, "coeff_d": 1988.572, "coeff_e": 105236.996},
|
||||
"tx_enable": true,
|
||||
"tx_freq_min": 863000000,
|
||||
"tx_freq_max": 870000000,
|
||||
"tx_gain_lut":[
|
||||
{"rf_power": -6, "pa_gain": 0, "dac_gain": 3, "mix_gain": 8, "dig_gain": 0},
|
||||
{"rf_power": -3, "pa_gain": 0, "dac_gain": 3, "mix_gain": 10, "dig_gain": 0},
|
||||
{"rf_power": 0, "pa_gain": 0, "dac_gain": 3, "mix_gain": 12, "dig_gain": 0},
|
||||
{"rf_power": 3, "pa_gain": 1, "dac_gain": 3, "mix_gain": 8, "dig_gain": 0},
|
||||
{"rf_power": 6, "pa_gain": 1, "dac_gain": 3, "mix_gain": 10, "dig_gain": 0},
|
||||
{"rf_power": 10, "pa_gain": 1, "dac_gain": 3, "mix_gain": 12, "dig_gain": 0},
|
||||
{"rf_power": 11, "pa_gain": 1, "dac_gain": 3, "mix_gain": 13, "dig_gain": 0},
|
||||
{"rf_power": 12, "pa_gain": 2, "dac_gain": 3, "mix_gain": 9, "dig_gain": 0},
|
||||
{"rf_power": 13, "pa_gain": 1, "dac_gain": 3, "mix_gain": 15, "dig_gain": 0},
|
||||
{"rf_power": 14, "pa_gain": 2, "dac_gain": 3, "mix_gain": 10, "dig_gain": 0},
|
||||
{"rf_power": 16, "pa_gain": 2, "dac_gain": 3, "mix_gain": 11, "dig_gain": 0},
|
||||
{"rf_power": 20, "pa_gain": 3, "dac_gain": 3, "mix_gain": 9, "dig_gain": 0},
|
||||
{"rf_power": 23, "pa_gain": 3, "dac_gain": 3, "mix_gain": 10, "dig_gain": 0},
|
||||
{"rf_power": 25, "pa_gain": 3, "dac_gain": 3, "mix_gain": 11, "dig_gain": 0},
|
||||
{"rf_power": 26, "pa_gain": 3, "dac_gain": 3, "mix_gain": 12, "dig_gain": 0},
|
||||
{"rf_power": 27, "pa_gain": 3, "dac_gain": 3, "mix_gain": 14, "dig_gain": 0}
|
||||
]
|
||||
},
|
||||
"radio_1": {
|
||||
"enable": true,
|
||||
"type": "SX1257",
|
||||
"freq": 868500000,
|
||||
"rssi_offset": -196.0,
|
||||
"rssi_tcomp": {"coeff_a": -0.006, "coeff_b": 0.789, "coeff_c": -14.992, "coeff_d": 1988.572, "coeff_e": 105236.996},
|
||||
"tx_enable": false
|
||||
},
|
||||
"chan_multiSF_0": {"enable": true, "radio": 1, "if": -400000},
|
||||
"chan_multiSF_1": {"enable": true, "radio": 1, "if": -200000},
|
||||
"chan_multiSF_2": {"enable": true, "radio": 1, "if": 0},
|
||||
"chan_multiSF_3": {"enable": true, "radio": 0, "if": -400000},
|
||||
"chan_multiSF_4": {"enable": true, "radio": 0, "if": -200000},
|
||||
"chan_multiSF_5": {"enable": true, "radio": 0, "if": 0},
|
||||
"chan_multiSF_6": {"enable": true, "radio": 0, "if": 200000},
|
||||
"chan_multiSF_7": {"enable": true, "radio": 0, "if": 400000},
|
||||
"chan_Lora_std": {"enable": true, "radio": 1, "if": -200000, "bandwidth": 250000, "spread_factor": 7,
|
||||
"implicit_hdr": false, "implicit_payload_length": 17, "implicit_crc_en": false, "implicit_coderate": 1},
|
||||
"chan_FSK": {"enable": true, "radio": 1, "if": 300000, "bandwidth": 125000, "datarate": 50000}
|
||||
},
|
||||
|
||||
"gateway_conf": {
|
||||
"gateway_ID": "AA555A0000000000",
|
||||
/* change with default server address/ports */
|
||||
"server_address": "localhost",
|
||||
"serv_port_up": 1730,
|
||||
"serv_port_down": 1730,
|
||||
/* adjust the following parameters for your network */
|
||||
"keepalive_interval": 10,
|
||||
"stat_interval": 30,
|
||||
"push_timeout_ms": 100,
|
||||
/* forward only valid packets */
|
||||
"forward_crc_valid": true,
|
||||
"forward_crc_error": false,
|
||||
"forward_crc_disabled": false,
|
||||
/* GPS configuration */
|
||||
"gps_tty_path": "/dev/ttyS0",
|
||||
/* GPS reference coordinates */
|
||||
"ref_latitude": 0.0,
|
||||
"ref_longitude": 0.0,
|
||||
"ref_altitude": 0,
|
||||
/* Beaconing parameters */
|
||||
"beacon_period": 128,
|
||||
"beacon_freq_hz": 869525000,
|
||||
"beacon_datarate": 9,
|
||||
"beacon_bw_hz": 125000,
|
||||
"beacon_power": 14,
|
||||
"beacon_infodesc": 0
|
||||
},
|
||||
|
||||
"debug_conf": {
|
||||
"ref_payload":[
|
||||
{"id": "0xCAFE1234"},
|
||||
{"id": "0xCAFE2345"}
|
||||
],
|
||||
"log_file": "loragw_hal.log"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
{
|
||||
"SX130x_conf": {
|
||||
"spidev_path": "/dev/spidev0.0",
|
||||
"lorawan_public": true,
|
||||
"clksrc": 1,
|
||||
"antenna_gain": 0, /* antenna gain, in dBi */
|
||||
"full_duplex": true,
|
||||
"precision_timestamp": {
|
||||
"enable": false,
|
||||
"max_ts_metrics": 255,
|
||||
"nb_symbols": 1
|
||||
},
|
||||
"radio_0": {
|
||||
"enable": true,
|
||||
"type": "SX1257",
|
||||
"freq": 913800000,
|
||||
"rssi_offset": -196.0,
|
||||
"tx_enable": true,
|
||||
"tx_freq_min": 100000000,
|
||||
"tx_freq_max": 950000000,
|
||||
"tx_gain_lut":[
|
||||
{"rf_power": -6, "pa_gain": 0, "dac_gain": 3, "mix_gain": 8, "dig_gain": 0},
|
||||
{"rf_power": -3, "pa_gain": 0, "dac_gain": 3, "mix_gain": 10, "dig_gain": 0},
|
||||
{"rf_power": 0, "pa_gain": 0, "dac_gain": 3, "mix_gain": 12, "dig_gain": 0},
|
||||
{"rf_power": 3, "pa_gain": 1, "dac_gain": 3, "mix_gain": 8, "dig_gain": 0},
|
||||
{"rf_power": 6, "pa_gain": 1, "dac_gain": 3, "mix_gain": 10, "dig_gain": 0},
|
||||
{"rf_power": 10, "pa_gain": 1, "dac_gain": 3, "mix_gain": 12, "dig_gain": 0},
|
||||
{"rf_power": 11, "pa_gain": 1, "dac_gain": 3, "mix_gain": 13, "dig_gain": 0},
|
||||
{"rf_power": 12, "pa_gain": 2, "dac_gain": 3, "mix_gain": 9, "dig_gain": 0},
|
||||
{"rf_power": 13, "pa_gain": 1, "dac_gain": 3, "mix_gain": 15, "dig_gain": 0},
|
||||
{"rf_power": 14, "pa_gain": 2, "dac_gain": 3, "mix_gain": 10, "dig_gain": 0},
|
||||
{"rf_power": 16, "pa_gain": 2, "dac_gain": 3, "mix_gain": 11, "dig_gain": 0},
|
||||
{"rf_power": 20, "pa_gain": 3, "dac_gain": 3, "mix_gain": 9, "dig_gain": 0},
|
||||
{"rf_power": 23, "pa_gain": 3, "dac_gain": 3, "mix_gain": 10, "dig_gain": 0},
|
||||
{"rf_power": 25, "pa_gain": 3, "dac_gain": 3, "mix_gain": 11, "dig_gain": 0},
|
||||
{"rf_power": 26, "pa_gain": 3, "dac_gain": 3, "mix_gain": 12, "dig_gain": 0},
|
||||
{"rf_power": 27, "pa_gain": 3, "dac_gain": 3, "mix_gain": 14, "dig_gain": 0}
|
||||
]
|
||||
},
|
||||
"radio_1": {
|
||||
"enable": true,
|
||||
"type": "SX1257",
|
||||
"freq": 914600000,
|
||||
"rssi_offset": -196.0,
|
||||
"tx_enable": true,
|
||||
"tx_freq_min": 100000000,
|
||||
"tx_freq_max": 950000000,
|
||||
"tx_gain_lut":[
|
||||
{"rf_power": -6, "pa_gain": 0, "dac_gain": 3, "mix_gain": 8, "dig_gain": 0},
|
||||
{"rf_power": -3, "pa_gain": 0, "dac_gain": 3, "mix_gain": 10, "dig_gain": 0},
|
||||
{"rf_power": 0, "pa_gain": 0, "dac_gain": 3, "mix_gain": 12, "dig_gain": 0},
|
||||
{"rf_power": 3, "pa_gain": 1, "dac_gain": 3, "mix_gain": 8, "dig_gain": 0},
|
||||
{"rf_power": 6, "pa_gain": 1, "dac_gain": 3, "mix_gain": 10, "dig_gain": 0},
|
||||
{"rf_power": 10, "pa_gain": 1, "dac_gain": 3, "mix_gain": 12, "dig_gain": 0},
|
||||
{"rf_power": 11, "pa_gain": 1, "dac_gain": 3, "mix_gain": 13, "dig_gain": 0},
|
||||
{"rf_power": 12, "pa_gain": 2, "dac_gain": 3, "mix_gain": 9, "dig_gain": 0},
|
||||
{"rf_power": 13, "pa_gain": 1, "dac_gain": 3, "mix_gain": 15, "dig_gain": 0},
|
||||
{"rf_power": 14, "pa_gain": 2, "dac_gain": 3, "mix_gain": 10, "dig_gain": 0},
|
||||
{"rf_power": 16, "pa_gain": 2, "dac_gain": 3, "mix_gain": 11, "dig_gain": 0},
|
||||
{"rf_power": 20, "pa_gain": 3, "dac_gain": 3, "mix_gain": 9, "dig_gain": 0},
|
||||
{"rf_power": 23, "pa_gain": 3, "dac_gain": 3, "mix_gain": 10, "dig_gain": 0},
|
||||
{"rf_power": 25, "pa_gain": 3, "dac_gain": 3, "mix_gain": 11, "dig_gain": 0},
|
||||
{"rf_power": 26, "pa_gain": 3, "dac_gain": 3, "mix_gain": 12, "dig_gain": 0},
|
||||
{"rf_power": 27, "pa_gain": 3, "dac_gain": 3, "mix_gain": 14, "dig_gain": 0}
|
||||
]
|
||||
},
|
||||
"chan_multiSF_0": {"enable": true, "radio": 0, "if": -300000},
|
||||
"chan_multiSF_1": {"enable": true, "radio": 0, "if": -100000},
|
||||
"chan_multiSF_2": {"enable": true, "radio": 0, "if": 100000},
|
||||
"chan_multiSF_3": {"enable": true, "radio": 0, "if": 300000},
|
||||
"chan_multiSF_4": {"enable": true, "radio": 1, "if": -300000},
|
||||
"chan_multiSF_5": {"enable": true, "radio": 1, "if": -100000},
|
||||
"chan_multiSF_6": {"enable": true, "radio": 1, "if": 100000},
|
||||
"chan_multiSF_7": {"enable": true, "radio": 1, "if": 300000}
|
||||
},
|
||||
|
||||
"gateway_conf": {
|
||||
"gateway_ID": "AA555A0000000000",
|
||||
/* change with default server address/ports */
|
||||
"server_address": "localhost",
|
||||
"serv_port_up": 1750,
|
||||
"serv_port_down": 1750,
|
||||
/* adjust the following parameters for your network */
|
||||
"keepalive_interval": 10,
|
||||
"stat_interval": 30,
|
||||
"push_timeout_ms": 100,
|
||||
/* forward only valid packets */
|
||||
"forward_crc_valid": true,
|
||||
"forward_crc_error": false,
|
||||
"forward_crc_disabled": false
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,154 @@
|
|||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2019 Semtech
|
||||
|
||||
Description:
|
||||
LoRa concentrator : Just In Time TX scheduling queue
|
||||
|
||||
License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _LORA_PKTFWD_JIT_H
|
||||
#define _LORA_PKTFWD_JIT_H
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- DEPENDANCIES --------------------------------------------------------- */
|
||||
|
||||
#include <stdint.h> /* C99 types */
|
||||
#include <stdbool.h> /* bool type */
|
||||
#include <sys/time.h> /* timeval */
|
||||
|
||||
#include "loragw_hal.h"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PUBLIC CONSTANTS ----------------------------------------------------- */
|
||||
|
||||
#define JIT_QUEUE_MAX 32 /* Maximum number of packets to be stored in JiT queue */
|
||||
#define JIT_NUM_BEACON_IN_QUEUE 3 /* Number of beacons to be loaded in JiT queue at any time */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PUBLIC TYPES --------------------------------------------------------- */
|
||||
|
||||
enum jit_pkt_type_e {
|
||||
JIT_PKT_TYPE_DOWNLINK_CLASS_A,
|
||||
JIT_PKT_TYPE_DOWNLINK_CLASS_B,
|
||||
JIT_PKT_TYPE_DOWNLINK_CLASS_C,
|
||||
JIT_PKT_TYPE_BEACON
|
||||
};
|
||||
|
||||
enum jit_error_e {
|
||||
JIT_ERROR_OK, /* Packet ok to be sent */
|
||||
JIT_ERROR_TOO_LATE, /* Too late to send this packet */
|
||||
JIT_ERROR_TOO_EARLY, /* Too early to queue this packet */
|
||||
JIT_ERROR_FULL, /* Downlink queue is full */
|
||||
JIT_ERROR_EMPTY, /* Downlink queue is empty */
|
||||
JIT_ERROR_COLLISION_PACKET, /* A packet is already enqueued for this timeframe */
|
||||
JIT_ERROR_COLLISION_BEACON, /* A beacon is planned for this timeframe */
|
||||
JIT_ERROR_TX_FREQ, /* The required frequency for downlink is not supported */
|
||||
JIT_ERROR_TX_POWER, /* The required power for downlink is not supported */
|
||||
JIT_ERROR_GPS_UNLOCKED, /* GPS timestamp could not be used as GPS is unlocked */
|
||||
JIT_ERROR_INVALID /* Packet is invalid */
|
||||
};
|
||||
|
||||
struct jit_node_s {
|
||||
/* API fields */
|
||||
struct lgw_pkt_tx_s pkt; /* TX packet */
|
||||
enum jit_pkt_type_e pkt_type; /* Packet type: Downlink, Beacon... */
|
||||
|
||||
/* Internal fields */
|
||||
uint32_t pre_delay; /* Amount of time before packet timestamp to be reserved */
|
||||
uint32_t post_delay; /* Amount of time after packet timestamp to be reserved (time on air) */
|
||||
};
|
||||
|
||||
struct jit_queue_s {
|
||||
uint8_t num_pkt; /* Total number of packets in the queue (downlinks, beacons...) */
|
||||
uint8_t num_beacon; /* Number of beacons in the queue */
|
||||
struct jit_node_s nodes[JIT_QUEUE_MAX]; /* Nodes/packets array in the queue */
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PUBLIC FUNCTIONS PROTOTYPES ------------------------------------------ */
|
||||
|
||||
/**
|
||||
@brief Check if a JiT queue is full.
|
||||
|
||||
@param queue[in] Just in Time queue to be checked.
|
||||
@return true if queue is full, false otherwise.
|
||||
*/
|
||||
bool jit_queue_is_full(struct jit_queue_s *queue);
|
||||
|
||||
/**
|
||||
@brief Check if a JiT queue is empty.
|
||||
|
||||
@param queue[in] Just in Time queue to be checked.
|
||||
@return true if queue is empty, false otherwise.
|
||||
*/
|
||||
bool jit_queue_is_empty(struct jit_queue_s *queue);
|
||||
|
||||
/**
|
||||
@brief Initialize a Just in Time queue.
|
||||
|
||||
@param queue[in] Just in Time queue to be initialized. Memory should have been allocated already.
|
||||
|
||||
This function is used to reset every elements in the allocated queue.
|
||||
*/
|
||||
void jit_queue_init(struct jit_queue_s *queue);
|
||||
|
||||
/**
|
||||
@brief Add a packet in a Just-in-Time queue
|
||||
|
||||
@param queue[in/out] Just in Time queue in which the packet should be inserted
|
||||
@param time_us[in] Current concentrator time
|
||||
@param packet[in] Packet to be queued in JiT queue
|
||||
@param pkt_type[in] Type of packet to be queued: Downlink, Beacon
|
||||
@return success if the function was able to queue the packet
|
||||
|
||||
This function is typically used when a packet is received from server for downlink.
|
||||
It will check if packet can be queued, with several criterias. Once the packet is queued, it has to be
|
||||
sent over the air. So all checks should happen before the packet being actually in the queue.
|
||||
*/
|
||||
enum jit_error_e jit_enqueue(struct jit_queue_s *queue, uint32_t time_us, struct lgw_pkt_tx_s *packet, enum jit_pkt_type_e pkt_type);
|
||||
|
||||
/**
|
||||
@brief Dequeue a packet from a Just-in-Time queue
|
||||
|
||||
@param queue[in/out] Just in Time queue from which the packet should be removed
|
||||
@param index[in] in the queue where to get the packet to be removed
|
||||
@param packet[out] that was at index
|
||||
@param pkt_type[out] Type of packet dequeued: Downlink, Beacon
|
||||
@return success if the function was able to dequeue the packet
|
||||
|
||||
This function is typically used when a packet is about to be placed on concentrator buffer for TX.
|
||||
The index is generally got using the jit_peek function.
|
||||
*/
|
||||
enum jit_error_e jit_dequeue(struct jit_queue_s *queue, int index, struct lgw_pkt_tx_s *packet, enum jit_pkt_type_e *pkt_type);
|
||||
|
||||
/**
|
||||
@brief Check if there is a packet soon to be sent from the JiT queue.
|
||||
|
||||
@param queue[in] Just in Time queue to parse for peeking a packet
|
||||
@param time_us[in] Current concentrator time
|
||||
@param pkt_idx[out] Packet index which is soon to be dequeued.
|
||||
@return success if the function was able to parse the queue. pkt_idx is set to -1 if no packet found.
|
||||
|
||||
This function is typically used to check in JiT queue if there is a packet soon to be sent.
|
||||
It search the packet with the highest priority in queue, and check if its timestamp is near
|
||||
enough the current concentrator time.
|
||||
*/
|
||||
enum jit_error_e jit_peek(struct jit_queue_s *queue, uint32_t time_us, int *pkt_idx);
|
||||
|
||||
/**
|
||||
@brief Debug function to print the queue's content on console
|
||||
|
||||
@param queue[in] Just in Time queue to be displayed
|
||||
@param show_all[in] Indicates if empty nodes have to be displayed or not
|
||||
*/
|
||||
void jit_print_queue(struct jit_queue_s *queue, bool show_all, int debug_level);
|
||||
|
||||
#endif
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2019 Semtech
|
||||
|
||||
Description:
|
||||
LoRa concentrator : Packet Forwarder trace helpers
|
||||
|
||||
License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _LORA_PKTFWD_TRACE_H
|
||||
#define _LORA_PKTFWD_TRACE_H
|
||||
|
||||
#define DEBUG_PKT_FWD 0
|
||||
#define DEBUG_JIT 0
|
||||
#define DEBUG_JIT_ERROR 1
|
||||
#define DEBUG_TIMERSYNC 0
|
||||
#define DEBUG_BEACON 0
|
||||
#define DEBUG_LOG 1
|
||||
|
||||
#define MSG(args...) printf(args) /* message that is destined to the user */
|
||||
#define MSG_DEBUG(FLAG, fmt, ...) \
|
||||
do { \
|
||||
if (FLAG) \
|
||||
fprintf(stdout, "%s:%d:%s(): " fmt, __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
#define MSG_PRINTF(FLAG, fmt, ...) \
|
||||
do { \
|
||||
if (FLAG) \
|
||||
fprintf(stdout, fmt, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
|
@ -0,0 +1,253 @@
|
|||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2019 Semtech
|
||||
|
||||
SX1302 packet forwarder
|
||||
=======================
|
||||
|
||||
## 1. Introduction
|
||||
|
||||
The packet forwarder is a program running on the host of a Lora gateway that
|
||||
forwards RF packets receive by the concentrator to a server through a IP/UDP
|
||||
link, and emits RF packets that are sent by the server. It can also emit a
|
||||
network-wide GPS-synchronous beacon signal used for coordinating all nodes of
|
||||
the network.
|
||||
|
||||
To learn more about the network protocol between the gateway and the server,
|
||||
please read the PROTOCOL.TXT document.
|
||||
|
||||
## 2. System schematic and definitions
|
||||
|
||||
((( Y )))
|
||||
|
|
||||
|
|
||||
+- -|- - - - - - - - - - - - -+ xxxxxxxxxxxx +--------+
|
||||
|+--+-----------+ +------+| xx x x xxx | |
|
||||
|| | | || xx Internet xx | |
|
||||
|| Concentrator |<----+ Host |<------xx or xx-------->| |
|
||||
|| | SPI | || xx Intranet xx | Server |
|
||||
|+--------------+ +------+| xxxx x xxxx | |
|
||||
| ^ ^ | xxxxxxxx | |
|
||||
| | PPS +-----+ NMEA | | | |
|
||||
| +------| GPS |-------+ | +--------+
|
||||
| +-----+ |
|
||||
| |
|
||||
| Gateway |
|
||||
+- - - - - - - - - - - - - - -+
|
||||
|
||||
Concentrator: radio RX/TX board, based on Semtech multichannel modems (SX130x),
|
||||
transceivers (SX135x) and/or low-power stand-alone modems (SX127x).
|
||||
|
||||
Host: embedded computer on which the packet forwarder is run. Drives the
|
||||
concentrator through a SPI link.
|
||||
|
||||
Gateway: a device composed of at least one radio concentrator, a host, some
|
||||
network connection to the internet or a private network (Ethernet, 3G, Wifi,
|
||||
microwave link), and optionally a GPS receiver for synchronization.
|
||||
|
||||
Server: an abstract computer that will process the RF packets received and
|
||||
forwarded by the gateway, and issue RF packets in response that the gateway
|
||||
will have to emit.
|
||||
|
||||
|
||||
## 3. Dependencies
|
||||
|
||||
This program uses the Parson library (http://kgabis.github.com/parson/) by
|
||||
Krzysztof Gabis for JSON parsing.
|
||||
Many thanks to him for that very practical and well written library.
|
||||
|
||||
This program is statically linked with the libloragw Lora concentrator library.
|
||||
It was tested with v1.3.0 of the library but should work with any later
|
||||
version provided the API is v1 or a later backward-compatible API.
|
||||
Data structures of the received packets are accessed by name (ie. not at a
|
||||
binary level) so new functionalities can be added to the API without affecting
|
||||
that program at all.
|
||||
|
||||
This program follows the v1.3 version of the gateway-to-server protocol.
|
||||
|
||||
The last dependency is the hardware concentrator (based on FPGA or SX130x
|
||||
chips) that must be matched with the proper version of the HAL.
|
||||
|
||||
## 4. Usage
|
||||
|
||||
* Pick the global_conf.json file that fit with your platform, region and feature
|
||||
need.
|
||||
* Update the JSON configuration (global and local) files, as explained below.
|
||||
* Run:
|
||||
./lora_pkt_fwd -c global_conf.json
|
||||
|
||||
To stop the application, press Ctrl+C.
|
||||
Unless it is manually stopped or encounter a critical error, the program will
|
||||
run forever.
|
||||
|
||||
The way the program takes configuration files into account is the following:
|
||||
* if a specific configuration file is given as program argument, use the
|
||||
one specified.
|
||||
* if there is a global_conf.json parse it.
|
||||
|
||||
The global configuration file should be exactly the same throughout your
|
||||
network, contain all global parameters (parameters for "sensor" radio
|
||||
channels) and preferably default "safe" values for parameters that are
|
||||
specific for each gateway (eg. specify a default MAC address).
|
||||
|
||||
In each configuration file, the program looks for a JSON object named
|
||||
"SX130x_conf" that should contain the parameters for the Lora concentrator
|
||||
board (RF channels definition, modem parameters, etc) and another JSON object
|
||||
called "gateway_conf" that should contain the gateway parameters (gateway MAC
|
||||
address, IP address of the server, keep-alive time, etc).
|
||||
|
||||
To learn more about the JSON configuration format, read the provided JSON
|
||||
files and the libloragw API documentation.
|
||||
|
||||
Every X seconds (parameter settable in the configuration files) the program
|
||||
display statistics on the RF packets received and sent, and the network
|
||||
datagrams received and sent.
|
||||
The program also send some statistics to the server in JSON format.
|
||||
|
||||
## 5. "Just-In-Time" downlink scheduling
|
||||
|
||||
The LoRa concentrator can have only one TX packet programmed for departure at a
|
||||
time. The actual departure of a downlink packet will be done based on its
|
||||
timestamp, when the concentrator internal counter reaches timestamp’s value.
|
||||
The departure of a beacon will be done based on a GPS PPS event.
|
||||
It may happen that, due to network variable latency, the gateway receives one
|
||||
or many downlink packets from the server while a TX is already programmed in the
|
||||
concentrator. The packet forwarder has to store and order incoming downlink
|
||||
packets (in a queue), so that they can all be programmed in the concentrator at
|
||||
the proper time and sent over the air.
|
||||
Possible failures that may occur and that have to be reported to the server are:
|
||||
- It is too early or too late to send a given packet
|
||||
- A packet collides with another packet already queued
|
||||
- A packet collides with a beacon
|
||||
- TX RF parameters (frequency, power) are not supported by gateway
|
||||
- Gateway’s GPS is unlocked, so cannot process Class B downlink
|
||||
It is called "Just-in-Time" (JiT) scheduling, because the packet forwarder will
|
||||
program a downlink or a beacon packet in the concentrator just before it has to
|
||||
be sent over the air.
|
||||
Another benefit of JiT is to optimize the gateway downlink capacity by avoiding
|
||||
to keep the concentrator TX buffer busy for too long.
|
||||
|
||||
In order to achieve "Just-in-Time" scheduling, the following software elements
|
||||
have been added:
|
||||
- A JiT queue, with associated enqueue/peek/dequeue functions and packet
|
||||
acceptance criterias. It is where downlink packets are stored, waiting to be
|
||||
sent.
|
||||
- A JiT thread, which regularly checks if there is a packet in the JiT queue
|
||||
ready to be programmed in the concentrator, based on current concentrator
|
||||
internal time.
|
||||
|
||||
### 5.1. Concentrator vs GPS time synchronization
|
||||
|
||||
There are 2 cases for which we need to convert a GPS time to concentrator
|
||||
counter:
|
||||
- Class B downlink: when the “time” field of JSON “txpk” is filled instead
|
||||
of the “tmst” field, we need to be able to determine if the packet can be
|
||||
queued in JiT queue or not, based on its corresponding concentrator
|
||||
counter value.
|
||||
Note: even if a Class-B downlink is given with a GPS timestamp, the
|
||||
concentrator TX mode is configured as “TIMESTAMP”, and not “ON_GPS”. So
|
||||
at the end, it is the counter value which will be used for transmission.
|
||||
- Beacons: beacons transmission time is based on GPS clock, and the
|
||||
concentrator TX mode is configured as “ON_GPS” for accurate beacon
|
||||
transmission on GPS PPS event. In this case, the concentrator does not
|
||||
need the packet counter to be set. But, as the JiT thread decides if a
|
||||
packet has to be peeked or not, based on its concentrator counter, we need
|
||||
to have the beacon packet counter set (see next chapter for more details
|
||||
on JiT scheduling).
|
||||
We also need to convert a SX1302 counter value to GPS UTC time when we receive
|
||||
an uplink, in order to fill the “time” field of JSON “rxpk” structure.
|
||||
|
||||
### 5.2. TX scheduling
|
||||
|
||||
The JiT queue implemented is a static array of nodes, where each node contains:
|
||||
- the downlink packet, with its type (beacon, downlink class A, B or C)
|
||||
- a “pre delay” which depends on packet type (BEACON_GUARD, TX_START_DELAY…)
|
||||
- a “post delay” which depends on packet type (“time on air” of this packet
|
||||
computed based on its size, datarate and coderate, or BEACON_RESERVED)
|
||||
|
||||
Several functions are implemented to manipulate this queue or get info from it:
|
||||
- init: initialize array with default values
|
||||
- is full / is empty: gives queue status
|
||||
- enqueue: checks if the given packet can be queued or not, based on several
|
||||
criteria’s
|
||||
- peek: checks if the queue contains a packet that must be passed
|
||||
immediately to the concentrator for transmission and returns corresponding
|
||||
index if any.
|
||||
- dequeue: actually removes from the queue the packet at index given by peek
|
||||
function
|
||||
|
||||
The queue is always kept sorted on ascending timestamp order.
|
||||
|
||||
The JiT thread will regularly check in the JiT queue if there is a packet to be
|
||||
sent soon. If a packet is matching, it is dequeued and programmed in the
|
||||
concentrator TX buffer.
|
||||
|
||||
### 5.3. Fine tuning parameters
|
||||
|
||||
There are few parameters of the JiT queue which could be tweaked to adapt to
|
||||
different system constraints.
|
||||
|
||||
- inc/jitqueue.h:
|
||||
JIT_QUEUE_MAX: The maximum number of nodes in the queue.
|
||||
- src/jitqueue.c:
|
||||
TX_JIT_DELAY: The number of milliseconds a packet is programmed in the
|
||||
concentrator TX buffer before its actual departure time.
|
||||
TX_MARGIN_DELAY: Packet collision check margin
|
||||
|
||||
6. License
|
||||
-----------
|
||||
|
||||
Copyright (C) 2019, SEMTECH S.A.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the Semtech corporation nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL SEMTECH S.A. BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
6. License for Parson library
|
||||
------------------------------
|
||||
|
||||
Parson ( http://kgabis.github.com/parson/ )
|
||||
Copyright (C) 2012 Krzysztof Gabis
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
*EOF*
|
|
@ -0,0 +1,458 @@
|
|||
/*
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2019 Semtech
|
||||
|
||||
Description:
|
||||
LoRa concentrator : Just In Time TX scheduling queue
|
||||
|
||||
License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*/
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- DEPENDANCIES --------------------------------------------------------- */
|
||||
|
||||
#define _GNU_SOURCE /* needed for qsort_r to be defined */
|
||||
#include <stdlib.h> /* qsort_r */
|
||||
#include <stdio.h> /* printf, fprintf, snprintf, fopen, fputs */
|
||||
#include <string.h> /* memset, memcpy */
|
||||
#include <pthread.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "trace.h"
|
||||
#include "jitqueue.h"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE MACROS ------------------------------------------------------- */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE CONSTANTS & TYPES -------------------------------------------- */
|
||||
#define TX_START_DELAY 1500 /* microseconds */
|
||||
/* TODO: get this value from HAL? */
|
||||
#define TX_MARGIN_DELAY 1000 /* Packet overlap margin in microseconds */
|
||||
/* TODO: How much margin should we take? */
|
||||
#define TX_JIT_DELAY 30000 /* Pre-delay to program packet for TX in microseconds */
|
||||
#define TX_MAX_ADVANCE_DELAY ((JIT_NUM_BEACON_IN_QUEUE + 1) * 128 * 1E6) /* Maximum advance delay accepted for a TX packet, compared to current time */
|
||||
|
||||
#define BEACON_GUARD 3000000 /* Interval where no ping slot can be placed,
|
||||
to ensure beacon can be sent */
|
||||
#define BEACON_RESERVED 2120000 /* Time on air of the beacon, with some margin */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE VARIABLES (GLOBAL) ------------------------------------------- */
|
||||
static pthread_mutex_t mx_jit_queue = PTHREAD_MUTEX_INITIALIZER; /* control access to JIT queue */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE FUNCTIONS DEFINITION ----------------------------------------- */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PUBLIC FUNCTIONS DEFINITION ----------------------------------------- */
|
||||
|
||||
bool jit_queue_is_full(struct jit_queue_s *queue) {
|
||||
bool result;
|
||||
|
||||
pthread_mutex_lock(&mx_jit_queue);
|
||||
|
||||
result = (queue->num_pkt == JIT_QUEUE_MAX)?true:false;
|
||||
|
||||
pthread_mutex_unlock(&mx_jit_queue);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool jit_queue_is_empty(struct jit_queue_s *queue) {
|
||||
bool result;
|
||||
|
||||
pthread_mutex_lock(&mx_jit_queue);
|
||||
|
||||
result = (queue->num_pkt == 0)?true:false;
|
||||
|
||||
pthread_mutex_unlock(&mx_jit_queue);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void jit_queue_init(struct jit_queue_s *queue) {
|
||||
int i;
|
||||
|
||||
pthread_mutex_lock(&mx_jit_queue);
|
||||
|
||||
memset(queue, 0, sizeof(*queue));
|
||||
for (i=0; i<JIT_QUEUE_MAX; i++) {
|
||||
queue->nodes[i].pre_delay = 0;
|
||||
queue->nodes[i].post_delay = 0;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&mx_jit_queue);
|
||||
}
|
||||
|
||||
int compare(const void *a, const void *b, void *arg)
|
||||
{
|
||||
struct jit_node_s *p = (struct jit_node_s *)a;
|
||||
struct jit_node_s *q = (struct jit_node_s *)b;
|
||||
int *counter = (int *)arg;
|
||||
int p_count, q_count;
|
||||
|
||||
p_count = p->pkt.count_us;
|
||||
q_count = q->pkt.count_us;
|
||||
|
||||
if (p_count > q_count)
|
||||
*counter = *counter + 1;
|
||||
|
||||
return p_count - q_count;
|
||||
}
|
||||
|
||||
void jit_sort_queue(struct jit_queue_s *queue) {
|
||||
int counter = 0;
|
||||
|
||||
if (queue->num_pkt == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
MSG_DEBUG(DEBUG_JIT, "sorting queue in ascending order packet timestamp - queue size:%u\n", queue->num_pkt);
|
||||
qsort_r(queue->nodes, queue->num_pkt, sizeof(queue->nodes[0]), compare, &counter);
|
||||
MSG_DEBUG(DEBUG_JIT, "sorting queue done - swapped:%d\n", counter);
|
||||
}
|
||||
|
||||
bool jit_collision_test(uint32_t p1_count_us, uint32_t p1_pre_delay, uint32_t p1_post_delay, uint32_t p2_count_us, uint32_t p2_pre_delay, uint32_t p2_post_delay) {
|
||||
if (((p1_count_us - p2_count_us) <= (p1_pre_delay + p2_post_delay + TX_MARGIN_DELAY)) ||
|
||||
((p2_count_us - p1_count_us) <= (p2_pre_delay + p1_post_delay + TX_MARGIN_DELAY))) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
enum jit_error_e jit_enqueue(struct jit_queue_s *queue, uint32_t time_us, struct lgw_pkt_tx_s *packet, enum jit_pkt_type_e pkt_type) {
|
||||
int i = 0;
|
||||
uint32_t packet_post_delay = 0;
|
||||
uint32_t packet_pre_delay = 0;
|
||||
uint32_t target_pre_delay = 0;
|
||||
enum jit_error_e err_collision;
|
||||
uint32_t asap_count_us;
|
||||
|
||||
MSG_DEBUG(DEBUG_JIT, "Current concentrator time is %u, pkt_type=%d\n", time_us, pkt_type);
|
||||
|
||||
if (packet == NULL) {
|
||||
MSG_DEBUG(DEBUG_JIT_ERROR, "ERROR: invalid parameter\n");
|
||||
return JIT_ERROR_INVALID;
|
||||
}
|
||||
|
||||
if (jit_queue_is_full(queue)) {
|
||||
MSG_DEBUG(DEBUG_JIT_ERROR, "ERROR: cannot enqueue packet, JIT queue is full\n");
|
||||
return JIT_ERROR_FULL;
|
||||
}
|
||||
|
||||
/* Compute packet pre/post delays depending on packet's type */
|
||||
switch (pkt_type) {
|
||||
case JIT_PKT_TYPE_DOWNLINK_CLASS_A:
|
||||
case JIT_PKT_TYPE_DOWNLINK_CLASS_B:
|
||||
case JIT_PKT_TYPE_DOWNLINK_CLASS_C:
|
||||
packet_pre_delay = TX_START_DELAY + TX_JIT_DELAY;
|
||||
packet_post_delay = lgw_time_on_air(packet) * 1000UL; /* in us */
|
||||
break;
|
||||
case JIT_PKT_TYPE_BEACON:
|
||||
/* As defined in LoRaWAN spec */
|
||||
packet_pre_delay = TX_START_DELAY + BEACON_GUARD + TX_JIT_DELAY;
|
||||
packet_post_delay = BEACON_RESERVED;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&mx_jit_queue);
|
||||
|
||||
/* An immediate downlink becomes a timestamped downlink "ASAP" */
|
||||
/* Set the packet count_us to the first available slot */
|
||||
if (pkt_type == JIT_PKT_TYPE_DOWNLINK_CLASS_C) {
|
||||
/* change tx_mode to timestamped */
|
||||
packet->tx_mode = TIMESTAMPED;
|
||||
|
||||
/* Search for the ASAP timestamp to be given to the packet */
|
||||
asap_count_us = time_us + 1E6; /* TODO: Take 1 second margin, to be refined */
|
||||
if (queue->num_pkt == 0) {
|
||||
/* If the jit queue is empty, we can insert this packet */
|
||||
MSG_DEBUG(DEBUG_JIT, "DEBUG: insert IMMEDIATE downlink, first in JiT queue (count_us=%u)\n", asap_count_us);
|
||||
} else {
|
||||
/* Else we can try to insert it:
|
||||
- ASAP meaning NOW + MARGIN
|
||||
- at the last index of the queue
|
||||
- between 2 downlinks in the queue
|
||||
*/
|
||||
|
||||
/* First, try if the ASAP time collides with an already enqueued downlink */
|
||||
for (i=0; i<queue->num_pkt; i++) {
|
||||
if (jit_collision_test(asap_count_us, packet_pre_delay, packet_post_delay, queue->nodes[i].pkt.count_us, queue->nodes[i].pre_delay, queue->nodes[i].post_delay) == true) {
|
||||
MSG_DEBUG(DEBUG_JIT, "DEBUG: cannot insert IMMEDIATE downlink at count_us=%u, collides with %u (index=%d)\n", asap_count_us, queue->nodes[i].pkt.count_us, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == queue->num_pkt) {
|
||||
/* No collision with ASAP time, we can insert it */
|
||||
MSG_DEBUG(DEBUG_JIT, "DEBUG: insert IMMEDIATE downlink ASAP at %u (no collision)\n", asap_count_us);
|
||||
} else {
|
||||
/* Search for the best slot then */
|
||||
for (i=0; i<queue->num_pkt; i++) {
|
||||
asap_count_us = queue->nodes[i].pkt.count_us + queue->nodes[i].post_delay + packet_pre_delay + TX_JIT_DELAY + TX_MARGIN_DELAY;
|
||||
if (i == (queue->num_pkt - 1)) {
|
||||
/* Last packet index, we can insert after this one */
|
||||
MSG_DEBUG(DEBUG_JIT, "DEBUG: insert IMMEDIATE downlink, last in JiT queue (count_us=%u)\n", asap_count_us);
|
||||
} else {
|
||||
/* Check if packet can be inserted between this index and the next one */
|
||||
MSG_DEBUG(DEBUG_JIT, "DEBUG: try to insert IMMEDIATE downlink (count_us=%u) between index %d and index %d?\n", asap_count_us, i, i+1);
|
||||
if (jit_collision_test(asap_count_us, packet_pre_delay, packet_post_delay, queue->nodes[i+1].pkt.count_us, queue->nodes[i+1].pre_delay, queue->nodes[i+1].post_delay) == true) {
|
||||
MSG_DEBUG(DEBUG_JIT, "DEBUG: failed to insert IMMEDIATE downlink (count_us=%u), continue...\n", asap_count_us);
|
||||
continue;
|
||||
} else {
|
||||
MSG_DEBUG(DEBUG_JIT, "DEBUG: insert IMMEDIATE downlink (count_us=%u)\n", asap_count_us);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Set packet with ASAP timestamp */
|
||||
packet->count_us = asap_count_us;
|
||||
}
|
||||
|
||||
/* Check criteria_1: is it already too late to send this packet ?
|
||||
* The packet should arrive at least at (tmst - TX_START_DELAY) to be programmed into concentrator
|
||||
* Note: - Also add some margin, to be checked how much is needed, if needed
|
||||
* - Valid for both Downlinks and Beacon packets
|
||||
*
|
||||
* Warning: unsigned arithmetic (handle roll-over)
|
||||
* t_packet < t_current + TX_START_DELAY + MARGIN
|
||||
*/
|
||||
if ((packet->count_us - time_us) <= (TX_START_DELAY + TX_MARGIN_DELAY + TX_JIT_DELAY)) {
|
||||
MSG_DEBUG(DEBUG_JIT_ERROR, "ERROR: Packet REJECTED, already too late to send it (current=%u, packet=%u, type=%d)\n", time_us, packet->count_us, pkt_type);
|
||||
pthread_mutex_unlock(&mx_jit_queue);
|
||||
return JIT_ERROR_TOO_LATE;
|
||||
}
|
||||
|
||||
/* Check criteria_2: Does packet timestamp seem plausible compared to current time
|
||||
* We do not expect the server to program a downlink too early compared to current time
|
||||
* Class A: downlink has to be sent in a 1s or 2s time window after RX
|
||||
* Class B: downlink has to occur in a 128s time window
|
||||
* Class C: no check needed, departure time has been calculated previously
|
||||
* So let's define a safe delay above which we can say that the packet is out of bound: TX_MAX_ADVANCE_DELAY
|
||||
* Note: - Valid for Downlinks only, not for Beacon packets
|
||||
*
|
||||
* Warning: unsigned arithmetic (handle roll-over)
|
||||
t_packet > t_current + TX_MAX_ADVANCE_DELAY
|
||||
*/
|
||||
if ((pkt_type == JIT_PKT_TYPE_DOWNLINK_CLASS_A) || (pkt_type == JIT_PKT_TYPE_DOWNLINK_CLASS_B)) {
|
||||
if ((packet->count_us - time_us) > TX_MAX_ADVANCE_DELAY) {
|
||||
MSG_DEBUG(DEBUG_JIT_ERROR, "ERROR: Packet REJECTED, timestamp seems wrong, too much in advance (current=%u, packet=%u, type=%d)\n", time_us, packet->count_us, pkt_type);
|
||||
pthread_mutex_unlock(&mx_jit_queue);
|
||||
return JIT_ERROR_TOO_EARLY;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check criteria_3: does this new packet overlap with a packet already enqueued ?
|
||||
* Note: - need to take into account packet's pre_delay and post_delay of each packet
|
||||
* - Valid for both Downlinks and beacon packets
|
||||
* - Beacon guard can be ignored if we try to queue a Class A downlink
|
||||
*/
|
||||
for (i=0; i<queue->num_pkt; i++) {
|
||||
/* We ignore Beacon Guard for Class A/C downlinks */
|
||||
if (((pkt_type == JIT_PKT_TYPE_DOWNLINK_CLASS_A) || (pkt_type == JIT_PKT_TYPE_DOWNLINK_CLASS_C)) && (queue->nodes[i].pkt_type == JIT_PKT_TYPE_BEACON)) {
|
||||
target_pre_delay = TX_START_DELAY;
|
||||
} else {
|
||||
target_pre_delay = queue->nodes[i].pre_delay;
|
||||
}
|
||||
|
||||
/* Check if there is a collision
|
||||
* Warning: unsigned arithmetic (handle roll-over)
|
||||
* t_packet_new - pre_delay_packet_new < t_packet_prev + post_delay_packet_prev (OVERLAP on post delay)
|
||||
* t_packet_new + post_delay_packet_new > t_packet_prev - pre_delay_packet_prev (OVERLAP on pre delay)
|
||||
*/
|
||||
if (jit_collision_test(packet->count_us, packet_pre_delay, packet_post_delay, queue->nodes[i].pkt.count_us, target_pre_delay, queue->nodes[i].post_delay) == true) {
|
||||
switch (queue->nodes[i].pkt_type) {
|
||||
case JIT_PKT_TYPE_DOWNLINK_CLASS_A:
|
||||
case JIT_PKT_TYPE_DOWNLINK_CLASS_B:
|
||||
case JIT_PKT_TYPE_DOWNLINK_CLASS_C:
|
||||
MSG_DEBUG(DEBUG_JIT_ERROR, "ERROR: Packet (type=%d) REJECTED, collision with packet already programmed at %u (%u)\n", pkt_type, queue->nodes[i].pkt.count_us, packet->count_us);
|
||||
err_collision = JIT_ERROR_COLLISION_PACKET;
|
||||
break;
|
||||
case JIT_PKT_TYPE_BEACON:
|
||||
if (pkt_type != JIT_PKT_TYPE_BEACON) {
|
||||
/* do not overload logs for beacon/beacon collision, as it is expected to happen with beacon pre-scheduling algorith used */
|
||||
MSG_DEBUG(DEBUG_JIT_ERROR, "ERROR: Packet (type=%d) REJECTED, collision with beacon already programmed at %u (%u)\n", pkt_type, queue->nodes[i].pkt.count_us, packet->count_us);
|
||||
}
|
||||
err_collision = JIT_ERROR_COLLISION_BEACON;
|
||||
break;
|
||||
default:
|
||||
MSG("ERROR: Unknown packet type, should not occur, BUG?\n");
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
pthread_mutex_unlock(&mx_jit_queue);
|
||||
return err_collision;
|
||||
}
|
||||
}
|
||||
|
||||
/* Finally enqueue it */
|
||||
/* Insert packet at the end of the queue */
|
||||
memcpy(&(queue->nodes[queue->num_pkt].pkt), packet, sizeof(struct lgw_pkt_tx_s));
|
||||
queue->nodes[queue->num_pkt].pre_delay = packet_pre_delay;
|
||||
queue->nodes[queue->num_pkt].post_delay = packet_post_delay;
|
||||
queue->nodes[queue->num_pkt].pkt_type = pkt_type;
|
||||
if (pkt_type == JIT_PKT_TYPE_BEACON) {
|
||||
queue->num_beacon++;
|
||||
}
|
||||
queue->num_pkt++;
|
||||
/* Sort the queue in ascending order of packet timestamp */
|
||||
jit_sort_queue(queue);
|
||||
|
||||
/* Done */
|
||||
pthread_mutex_unlock(&mx_jit_queue);
|
||||
|
||||
jit_print_queue(queue, false, DEBUG_JIT);
|
||||
|
||||
MSG_DEBUG(DEBUG_JIT, "enqueued packet with count_us=%u (size=%u bytes, toa=%u us, type=%u)\n", packet->count_us, packet->size, packet_post_delay, pkt_type);
|
||||
|
||||
return JIT_ERROR_OK;
|
||||
}
|
||||
|
||||
enum jit_error_e jit_dequeue(struct jit_queue_s *queue, int index, struct lgw_pkt_tx_s *packet, enum jit_pkt_type_e *pkt_type) {
|
||||
if (packet == NULL) {
|
||||
MSG("ERROR: invalid parameter\n");
|
||||
return JIT_ERROR_INVALID;
|
||||
}
|
||||
|
||||
if ((index < 0) || (index >= JIT_QUEUE_MAX)) {
|
||||
MSG("ERROR: invalid parameter\n");
|
||||
return JIT_ERROR_INVALID;
|
||||
}
|
||||
|
||||
if (jit_queue_is_empty(queue)) {
|
||||
MSG("ERROR: cannot dequeue packet, JIT queue is empty\n");
|
||||
return JIT_ERROR_EMPTY;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&mx_jit_queue);
|
||||
|
||||
/* Dequeue requested packet */
|
||||
memcpy(packet, &(queue->nodes[index].pkt), sizeof(struct lgw_pkt_tx_s));
|
||||
queue->num_pkt--;
|
||||
*pkt_type = queue->nodes[index].pkt_type;
|
||||
if (*pkt_type == JIT_PKT_TYPE_BEACON) {
|
||||
queue->num_beacon--;
|
||||
MSG_DEBUG(DEBUG_BEACON, "--- Beacon dequeued ---\n");
|
||||
}
|
||||
|
||||
/* Replace dequeued packet with last packet of the queue */
|
||||
memcpy(&(queue->nodes[index]), &(queue->nodes[queue->num_pkt]), sizeof(struct jit_node_s));
|
||||
memset(&(queue->nodes[queue->num_pkt]), 0, sizeof(struct jit_node_s));
|
||||
|
||||
/* Sort queue in ascending order of packet timestamp */
|
||||
jit_sort_queue(queue);
|
||||
|
||||
/* Done */
|
||||
pthread_mutex_unlock(&mx_jit_queue);
|
||||
|
||||
jit_print_queue(queue, false, DEBUG_JIT);
|
||||
|
||||
MSG_DEBUG(DEBUG_JIT, "dequeued packet with count_us=%u from index %d\n", packet->count_us, index);
|
||||
|
||||
return JIT_ERROR_OK;
|
||||
}
|
||||
|
||||
enum jit_error_e jit_peek(struct jit_queue_s *queue, uint32_t time_us, int *pkt_idx) {
|
||||
/* Return index of node containing a packet inline with given time */
|
||||
int i = 0;
|
||||
int idx_highest_priority = -1;
|
||||
if (pkt_idx == NULL) {
|
||||
MSG("ERROR: invalid parameter\n");
|
||||
return JIT_ERROR_INVALID;
|
||||
}
|
||||
|
||||
if (jit_queue_is_empty(queue)) {
|
||||
return JIT_ERROR_EMPTY;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&mx_jit_queue);
|
||||
|
||||
/* Search for highest priority packet to be sent */
|
||||
for (i=0; i<queue->num_pkt; i++) {
|
||||
/* First check if that packet is outdated:
|
||||
* If a packet seems too much in advance, and was not rejected at enqueue time,
|
||||
* it means that we missed it for peeking, we need to drop it
|
||||
*
|
||||
* Warning: unsigned arithmetic
|
||||
* t_packet > t_current + TX_MAX_ADVANCE_DELAY
|
||||
*/
|
||||
if ((queue->nodes[i].pkt.count_us - time_us) >= TX_MAX_ADVANCE_DELAY) {
|
||||
/* We drop the packet to avoid lock-up */
|
||||
queue->num_pkt--;
|
||||
if (queue->nodes[i].pkt_type == JIT_PKT_TYPE_BEACON) {
|
||||
queue->num_beacon--;
|
||||
MSG("WARNING: --- Beacon dropped (current_time=%u, packet_time=%u) ---\n", time_us, queue->nodes[i].pkt.count_us);
|
||||
} else {
|
||||
MSG("WARNING: --- Packet dropped (current_time=%u, packet_time=%u) ---\n", time_us, queue->nodes[i].pkt.count_us);
|
||||
}
|
||||
|
||||
/* Replace dropped packet with last packet of the queue */
|
||||
memcpy(&(queue->nodes[i]), &(queue->nodes[queue->num_pkt]), sizeof(struct jit_node_s));
|
||||
memset(&(queue->nodes[queue->num_pkt]), 0, sizeof(struct jit_node_s));
|
||||
|
||||
/* Sort queue in ascending order of packet timestamp */
|
||||
jit_sort_queue(queue);
|
||||
|
||||
/* restart loop after purge to find packet to be sent */
|
||||
i = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Then look for highest priority packet to be sent:
|
||||
* Warning: unsigned arithmetic (handle roll-over)
|
||||
* t_packet < t_highest
|
||||
*/
|
||||
if ((idx_highest_priority == -1) || (((queue->nodes[i].pkt.count_us - time_us) < (queue->nodes[idx_highest_priority].pkt.count_us - time_us)))) {
|
||||
idx_highest_priority = i;
|
||||
}
|
||||
}
|
||||
|
||||
/* Peek criteria 1: look for a packet to be sent in next TX_JIT_DELAY ms timeframe
|
||||
* Warning: unsigned arithmetic (handle roll-over)
|
||||
* t_packet < t_current + TX_JIT_DELAY
|
||||
*/
|
||||
if ((queue->nodes[idx_highest_priority].pkt.count_us - time_us) < TX_JIT_DELAY) {
|
||||
*pkt_idx = idx_highest_priority;
|
||||
MSG_DEBUG(DEBUG_JIT, "peek packet with count_us=%u at index %d\n",
|
||||
queue->nodes[idx_highest_priority].pkt.count_us, idx_highest_priority);
|
||||
} else {
|
||||
*pkt_idx = -1;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&mx_jit_queue);
|
||||
|
||||
return JIT_ERROR_OK;
|
||||
}
|
||||
|
||||
void jit_print_queue(struct jit_queue_s *queue, bool show_all, int debug_level) {
|
||||
int i = 0;
|
||||
int loop_end;
|
||||
|
||||
if (jit_queue_is_empty(queue)) {
|
||||
MSG_DEBUG(debug_level, "INFO: [jit] queue is empty\n");
|
||||
} else {
|
||||
pthread_mutex_lock(&mx_jit_queue);
|
||||
|
||||
MSG_DEBUG(debug_level, "INFO: [jit] queue contains %d packets:\n", queue->num_pkt);
|
||||
MSG_DEBUG(debug_level, "INFO: [jit] queue contains %d beacons:\n", queue->num_beacon);
|
||||
loop_end = (show_all == true) ? JIT_QUEUE_MAX : queue->num_pkt;
|
||||
for (i=0; i<loop_end; i++) {
|
||||
MSG_DEBUG(debug_level, " - node[%d]: count_us=%u - type=%d\n",
|
||||
i,
|
||||
queue->nodes[i].pkt.count_us,
|
||||
queue->nodes[i].pkt_type);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&mx_jit_queue);
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
194
readme.md
194
readme.md
|
@ -0,0 +1,194 @@
|
|||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2019 Semtech
|
||||
|
||||
SX1302 LoRa Gateway project
|
||||
===========================
|
||||
|
||||
## 1. Core library: libloragw
|
||||
|
||||
This directory contains the sources of the library to build a gateway based on
|
||||
a Semtech LoRa SX1302 concentrator chip (a.k.a. concentrator).
|
||||
Once compiled all the code is contained in the libloragw.a file that will be
|
||||
statically linked (ie. integrated in the final executable).
|
||||
|
||||
The library also comes with few basic tests programs that are used to test the
|
||||
different sub-modules of the library.
|
||||
|
||||
Please refer to the readme.md file located in the libloragw directory for
|
||||
more details.
|
||||
|
||||
## 2. Helper programs
|
||||
|
||||
Those programs are included in the project to provide examples on how to use
|
||||
the HAL library, and to help the system builder test different parts of it.
|
||||
|
||||
### 2.1. packet_frowarder ###
|
||||
|
||||
The packet forwarder is a program running on the host of a Lora gateway that
|
||||
forwards RF packets receive by the concentrator to a server through a IP/UDP
|
||||
link, and emits RF packets that are sent by the server.
|
||||
|
||||
((( Y )))
|
||||
|
|
||||
|
|
||||
+- -|- - - - - - - - - - - - -+ xxxxxxxxxxxx +--------+
|
||||
|+--+-----------+ +------+| xx x x xxx | |
|
||||
|| | | || xx Internet xx | |
|
||||
|| Concentrator |<----+ Host |<------xx or xx-------->| |
|
||||
|| | SPI | || xx Intranet xx | Server |
|
||||
|+--------------+ +------+| xxxx x xxxx | |
|
||||
| ^ ^ | xxxxxxxx | |
|
||||
| | PPS +-----+ NMEA | | | |
|
||||
| +------| GPS |-------+ | +--------+
|
||||
| +-----+ |
|
||||
| |
|
||||
| Gateway |
|
||||
+- - - - - - - - - - - - - - -+
|
||||
|
||||
Uplink: radio packets received by the gateway, with metadata added by the
|
||||
gateway, forwarded to the server. Might also include gateway status.
|
||||
|
||||
Downlink: packets generated by the server, with additional metadata, to be
|
||||
transmitted by the gateway on the radio channel. Might also include
|
||||
configuration data for the gateway.
|
||||
|
||||
Please refer to the readme.md file located in the packet_forwarder directory
|
||||
for more details.
|
||||
|
||||
### 2.2. util_net_downlink ###
|
||||
|
||||
The downlink packet sender is a simple helper program listening on a single
|
||||
UDP port, responding to PUSH_DATA and PULL_DATA datagrams with proper ACK, and
|
||||
sending downlink JSON packets to the socket, with given frame parameters, at
|
||||
regular time interval.
|
||||
It is a network packet sender.
|
||||
|
||||
It can also be used as a UDP packet logger to store received uplinks in a
|
||||
local CSV file.
|
||||
|
||||
Please refer to the readme.md file located in the util_net_downlink directory
|
||||
for more details.
|
||||
|
||||
## 3. Helper scripts
|
||||
|
||||
### 3.1. tools/reset_lgw.sh
|
||||
|
||||
This script is used to perform the basic initialization of the SX1302 through
|
||||
the GPIOs defined by the CoreCell reference design.
|
||||
It gets the SX1302 out of reset and set the Power Enable pin.
|
||||
This script is called by every program provided here which accesses the SX1302.
|
||||
It MUST be located in the same directory as the executable of the program.
|
||||
|
||||
## 4. Compile, install and run instructions
|
||||
|
||||
All the libraries and test programs can be compiled and installed from the
|
||||
root directory of this project.
|
||||
|
||||
### 4.1. Clean and compile everything
|
||||
|
||||
`make clean all`
|
||||
|
||||
### 4.2. Install executables and associated files in one directory
|
||||
|
||||
First edit the target.cfg file located in the root directory of the project
|
||||
in order to configure where the executables have to be installed.
|
||||
|
||||
`TARGET_IP` : sets the IP address of the host of the gateway. In case the
|
||||
project is compiled on the gateway host itself (Raspberry Pi...), this can
|
||||
be left set to `localhost`.
|
||||
|
||||
`TARGET_DIR` : sets the directory on the gateway host file system in which
|
||||
the executables must be copied. Note that the directory MUST exist when
|
||||
invoking the install command.
|
||||
|
||||
`TARGET_USR` : sets the linux user to be used to perform the SSH/SCP command
|
||||
for copying the executables.
|
||||
|
||||
In order to avoid entering the user password when installing the files, the
|
||||
following steps have to be followed.
|
||||
|
||||
Lets say you want to copy between two hosts host_src and host_dest (they can
|
||||
be the same). host_src is the host where you would run the scp command,
|
||||
irrespective of the direction of the file copy!
|
||||
|
||||
* On host_src, run this command as the user that runs scp<br/>
|
||||
`ssh-keygen -t rsa`
|
||||
|
||||
This will prompt for a passphrase. Just press the enter key. It'll then
|
||||
generate an identification (private key) and a public key. Do not ever share
|
||||
the private key with anyone! ssh-keygen shows where it saved the public key.
|
||||
This is by default ~/.ssh/id_rsa.pub
|
||||
* Transfer the id_rsa.pub file to host_dest<br/>
|
||||
`ssh-copy-id -i ~/.ssh/id_rsa.pub user@host_dest`
|
||||
|
||||
You should be able to log on host_dest without being asked for a password.
|
||||
|
||||
Now that everything is set, the following command can be invoked:<br/>
|
||||
`make install`
|
||||
|
||||
In order to also install the packet forwarder JSON configuration files:<br/>
|
||||
`make install_conf`
|
||||
|
||||
### 4.3. Cross-compile from a PC
|
||||
|
||||
* Add the path to the binaries of the compiler corresponding to the target
|
||||
platform to the `PATH` environment variable.
|
||||
* set the `ARCH` environment variable to `arm`.
|
||||
* set the `CROSS_COMPILE` environment variable to the prefix corresponding to
|
||||
the compiler for the target platform.
|
||||
|
||||
An example for a Raspberry Pi target:
|
||||
|
||||
* `export PATH=[path]/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin`
|
||||
* `export ARCH=arm`
|
||||
* `export CROSS_COMPILE=arm-linux-gnueabihf-`
|
||||
|
||||
Then, from the same console where the previous environment variables have been
|
||||
set, do:
|
||||
|
||||
`make clean all`
|
||||
|
||||
## 5. Third party libraries
|
||||
|
||||
This project relies on several third-party open source libraries, that can be
|
||||
found in the `libtools` directory.
|
||||
* parson: a JSON parser (http://kgabis.github.com/parson/)
|
||||
* tinymt32: a pseudo-random generator (only used for debug/test)
|
||||
|
||||
## 6. Changelog
|
||||
|
||||
### v1.0.0 ###
|
||||
|
||||
* HAL: Initial official release for SX1302 CoreCell Reference Design.
|
||||
|
||||
### v0.0.1 ###
|
||||
|
||||
* HAL: Initial private release for TAP program
|
||||
|
||||
## 7. Legal notice
|
||||
|
||||
The information presented in this project documentation does not form part of
|
||||
any quotation or contract, is believed to be accurate and reliable and may be
|
||||
changed without notice. No liability will be accepted by the publisher for any
|
||||
consequence of its use. Publication thereof does not convey nor imply any
|
||||
license under patent or other industrial or intellectual property rights.
|
||||
Semtech assumes no responsibility or liability whatsoever for any failure or
|
||||
unexpected operation resulting from misuse, neglect improper installation,
|
||||
repair or improper handling or unusual physical or electrical stress
|
||||
including, but not limited to, exposure to parameters beyond the specified
|
||||
maximum ratings or operation outside the specified range.
|
||||
|
||||
SEMTECH PRODUCTS ARE NOT DESIGNED, INTENDED, AUTHORIZED OR WARRANTED TO BE
|
||||
SUITABLE FOR USE IN LIFE-SUPPORT APPLICATIONS, DEVICES OR SYSTEMS OR OTHER
|
||||
CRITICAL APPLICATIONS. INCLUSION OF SEMTECH PRODUCTS IN SUCH APPLICATIONS IS
|
||||
UNDERSTOOD TO BE UNDERTAKEN SOLELY AT THE CUSTOMER'S OWN RISK. Should a
|
||||
customer purchase or use Semtech products for any such unauthorized
|
||||
application, the customer shall indemnify and hold Semtech and its officers,
|
||||
employees, subsidiaries, affiliates, and distributors harmless against all
|
||||
claims, costs damages and attorney fees which could arise.
|
||||
|
||||
*EOF*
|
|
@ -0,0 +1,10 @@
|
|||
# That file will be included in the Makefiles to configure where to install files on the target
|
||||
|
||||
# The IP address of the gateway host on which the files need to be installed
|
||||
TARGET_IP=localhost
|
||||
|
||||
# The directory on the gateway file system to which the files need to be installed
|
||||
TARGET_DIR=/home/pi/sx1302_hal/bin
|
||||
|
||||
# The user to be used by ssh/scp to copy the files on the gateway host
|
||||
TARGET_USR=pi
|
|
@ -0,0 +1,930 @@
|
|||
[
|
||||
{
|
||||
"id": "bf64d63f.630868",
|
||||
"type": "tab",
|
||||
"label": "SX1302 register C header",
|
||||
"disabled": false,
|
||||
"info": ""
|
||||
},
|
||||
{
|
||||
"id": "d60daf5.ed6835",
|
||||
"type": "file in",
|
||||
"z": "bf64d63f.630868",
|
||||
"name": "",
|
||||
"filename": "/home/mcoracin/SHARE/sx1302_reg/common.json",
|
||||
"format": "utf8",
|
||||
"chunk": false,
|
||||
"sendError": true,
|
||||
"x": 390,
|
||||
"y": 160,
|
||||
"wires": [
|
||||
[
|
||||
"ab571926.a8a0a8"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "ab571926.a8a0a8",
|
||||
"type": "json",
|
||||
"z": "bf64d63f.630868",
|
||||
"name": "",
|
||||
"property": "payload",
|
||||
"action": "",
|
||||
"pretty": false,
|
||||
"x": 660,
|
||||
"y": 160,
|
||||
"wires": [
|
||||
[
|
||||
"2efaa7ec.1e3158"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "3e749686.017e32",
|
||||
"type": "inject",
|
||||
"z": "bf64d63f.630868",
|
||||
"name": "common",
|
||||
"topic": "common",
|
||||
"payload": "true",
|
||||
"payloadType": "bool",
|
||||
"repeat": "",
|
||||
"crontab": "",
|
||||
"once": false,
|
||||
"onceDelay": 0.1,
|
||||
"x": 110,
|
||||
"y": 160,
|
||||
"wires": [
|
||||
[
|
||||
"d60daf5.ed6835"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "a8c02e96.c069",
|
||||
"type": "inject",
|
||||
"z": "bf64d63f.630868",
|
||||
"name": "Init",
|
||||
"topic": "",
|
||||
"payload": "true",
|
||||
"payloadType": "bool",
|
||||
"repeat": "",
|
||||
"crontab": "",
|
||||
"once": false,
|
||||
"onceDelay": 0.1,
|
||||
"x": 100,
|
||||
"y": 40,
|
||||
"wires": [
|
||||
[
|
||||
"13cca583.8beb3a"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "13cca583.8beb3a",
|
||||
"type": "function",
|
||||
"z": "bf64d63f.630868",
|
||||
"name": "Init global variables",
|
||||
"func": "var reg_c = 'const struct lgw_reg_s loregs[LGW_TOTALREGS+1] = {' + '\\n';\n\nvar reg_desc;\nreg_desc = '\\n/* -------------------------------------------------------------------------- */\\n';\nreg_desc += '/* --- REGISTER DESCRIPTIONS ------------------------------------------------\\n';\n\nflow.set('tx_top_macro', '');\nflow.set('reg_h', '');\nflow.set('reg_c', reg_c);\nflow.set('reg_desc', reg_desc);\nflow.set('reg_count', 0);\n\nreturn msg;",
|
||||
"outputs": 1,
|
||||
"noerr": 0,
|
||||
"x": 290,
|
||||
"y": 40,
|
||||
"wires": [
|
||||
[
|
||||
"d040198e.3a7208"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "d040198e.3a7208",
|
||||
"type": "debug",
|
||||
"z": "bf64d63f.630868",
|
||||
"name": "",
|
||||
"active": false,
|
||||
"tosidebar": true,
|
||||
"console": false,
|
||||
"tostatus": false,
|
||||
"complete": "false",
|
||||
"x": 500,
|
||||
"y": 40,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "12128a9a.ea5e35",
|
||||
"type": "file in",
|
||||
"z": "bf64d63f.630868",
|
||||
"name": "",
|
||||
"filename": "/home/mcoracin/SHARE/sx1302_reg/agc_mcu.json",
|
||||
"format": "utf8",
|
||||
"chunk": false,
|
||||
"sendError": true,
|
||||
"x": 390,
|
||||
"y": 220,
|
||||
"wires": [
|
||||
[
|
||||
"d6c34db.5471fb"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "d6c34db.5471fb",
|
||||
"type": "json",
|
||||
"z": "bf64d63f.630868",
|
||||
"name": "",
|
||||
"property": "payload",
|
||||
"action": "",
|
||||
"pretty": false,
|
||||
"x": 660,
|
||||
"y": 220,
|
||||
"wires": [
|
||||
[
|
||||
"2efaa7ec.1e3158"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "c7ba4afe.f6229",
|
||||
"type": "inject",
|
||||
"z": "bf64d63f.630868",
|
||||
"name": "agc_mcu",
|
||||
"topic": "agc_mcu",
|
||||
"payload": "true",
|
||||
"payloadType": "bool",
|
||||
"repeat": "",
|
||||
"crontab": "",
|
||||
"once": false,
|
||||
"onceDelay": 0.1,
|
||||
"x": 110,
|
||||
"y": 220,
|
||||
"wires": [
|
||||
[
|
||||
"12128a9a.ea5e35"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "917cf46c.ceaa48",
|
||||
"type": "inject",
|
||||
"z": "bf64d63f.630868",
|
||||
"name": "Create files",
|
||||
"topic": "",
|
||||
"payload": "true",
|
||||
"payloadType": "bool",
|
||||
"repeat": "",
|
||||
"crontab": "",
|
||||
"once": false,
|
||||
"onceDelay": 0.1,
|
||||
"x": 110,
|
||||
"y": 940,
|
||||
"wires": [
|
||||
[
|
||||
"67447ab8.c38edc"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "67447ab8.c38edc",
|
||||
"type": "function",
|
||||
"z": "bf64d63f.630868",
|
||||
"name": "Write header file",
|
||||
"func": "var reg_count = flow.get('reg_count') || 0;\n\nvar reg_h = flow.get('reg_h') || '';\nreg_h += '\\n#define LGW_TOTALREGS ' + reg_count + '\\n';\n\nvar reg_c = flow.get('reg_c') || '';\nreg_c += ' {0,0,0,0,0,0,0,0}\\n'\nreg_c += '};';\n\nvar reg_desc = flow.get('reg_desc') || '';\nreg_desc += \"\\n*/\";\n\nvar tx_top_macro = flow.get('tx_top_macro') || '';\n\n// write all to file\nvar file = reg_h + '\\n' + tx_top_macro + '\\n' + reg_c + '\\n' + reg_desc;\nmsg.payload = file;\n\nreturn msg;",
|
||||
"outputs": 1,
|
||||
"noerr": 0,
|
||||
"x": 290,
|
||||
"y": 940,
|
||||
"wires": [
|
||||
[
|
||||
"b1b0d974.6ae61"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "b1b0d974.6ae61",
|
||||
"type": "file",
|
||||
"z": "bf64d63f.630868",
|
||||
"name": "",
|
||||
"filename": "/home/mcoracin/SHARE/sx1302_reg/sx1302_reg.h",
|
||||
"appendNewline": true,
|
||||
"createDir": false,
|
||||
"overwriteFile": "true",
|
||||
"x": 620,
|
||||
"y": 940,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "aae4ac70.472438",
|
||||
"type": "debug",
|
||||
"z": "bf64d63f.630868",
|
||||
"name": "",
|
||||
"active": false,
|
||||
"tosidebar": true,
|
||||
"console": false,
|
||||
"tostatus": false,
|
||||
"complete": "false",
|
||||
"x": 1160,
|
||||
"y": 280,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "1450f6f8.1be259",
|
||||
"type": "file in",
|
||||
"z": "bf64d63f.630868",
|
||||
"name": "",
|
||||
"filename": "/home/mcoracin/SHARE/sx1302_reg/rif_top_mux.json",
|
||||
"format": "utf8",
|
||||
"chunk": false,
|
||||
"sendError": true,
|
||||
"x": 420,
|
||||
"y": 100,
|
||||
"wires": [
|
||||
[
|
||||
"5c712585.37aeec"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "5c712585.37aeec",
|
||||
"type": "json",
|
||||
"z": "bf64d63f.630868",
|
||||
"name": "",
|
||||
"property": "payload",
|
||||
"action": "",
|
||||
"pretty": false,
|
||||
"x": 700,
|
||||
"y": 100,
|
||||
"wires": [
|
||||
[
|
||||
"8bbc1d63.391468"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "a48ebe9c.34b028",
|
||||
"type": "inject",
|
||||
"z": "bf64d63f.630868",
|
||||
"name": "rif_top_mux",
|
||||
"topic": "",
|
||||
"payload": "true",
|
||||
"payloadType": "bool",
|
||||
"repeat": "",
|
||||
"crontab": "",
|
||||
"once": false,
|
||||
"onceDelay": 0.1,
|
||||
"x": 120,
|
||||
"y": 100,
|
||||
"wires": [
|
||||
[
|
||||
"1450f6f8.1be259"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "8bbc1d63.391468",
|
||||
"type": "function",
|
||||
"z": "bf64d63f.630868",
|
||||
"name": "JSON Parse Base Addresses",
|
||||
"func": "var reg_h = flow.get('reg_h') || '';\n\nvar prefix = 'SX1302_REG_';\nvar postfix = '_BASE_ADDR';\nvar line = '';\n\nfor(var item in msg.payload.map)\n{\n var base_addr = msg.payload.map[item].addr;\n line += '#define ' + prefix + item.toUpperCase() + postfix + ' 0x' + base_addr.toString(16) + '\\n'\n}\n//console.log(line);\n\nreg_h += line + '\\n';\n\nflow.set('reg_h', reg_h);\n\nreturn msg;",
|
||||
"outputs": 1,
|
||||
"noerr": 0,
|
||||
"x": 920,
|
||||
"y": 100,
|
||||
"wires": [
|
||||
[
|
||||
"9494d0f2.75b628"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "9494d0f2.75b628",
|
||||
"type": "debug",
|
||||
"z": "bf64d63f.630868",
|
||||
"name": "",
|
||||
"active": false,
|
||||
"tosidebar": true,
|
||||
"console": false,
|
||||
"tostatus": false,
|
||||
"complete": "false",
|
||||
"x": 1160,
|
||||
"y": 100,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "2d9b9bf2.6b3bb4",
|
||||
"type": "file in",
|
||||
"z": "bf64d63f.630868",
|
||||
"name": "",
|
||||
"filename": "/home/mcoracin/SHARE/sx1302_reg/clk_ctrl.json",
|
||||
"format": "utf8",
|
||||
"chunk": false,
|
||||
"sendError": true,
|
||||
"x": 380,
|
||||
"y": 280,
|
||||
"wires": [
|
||||
[
|
||||
"7efa17e6.f8b68"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "7efa17e6.f8b68",
|
||||
"type": "json",
|
||||
"z": "bf64d63f.630868",
|
||||
"name": "",
|
||||
"property": "payload",
|
||||
"action": "",
|
||||
"pretty": false,
|
||||
"x": 660,
|
||||
"y": 280,
|
||||
"wires": [
|
||||
[
|
||||
"2efaa7ec.1e3158"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "5883ebc9.2fede4",
|
||||
"type": "inject",
|
||||
"z": "bf64d63f.630868",
|
||||
"name": "clk_ctrl",
|
||||
"topic": "clk_ctrl",
|
||||
"payload": "true",
|
||||
"payloadType": "bool",
|
||||
"repeat": "",
|
||||
"crontab": "",
|
||||
"once": false,
|
||||
"onceDelay": 0.1,
|
||||
"x": 100,
|
||||
"y": 280,
|
||||
"wires": [
|
||||
[
|
||||
"2d9b9bf2.6b3bb4"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "54a46dd.945aa14",
|
||||
"type": "file in",
|
||||
"z": "bf64d63f.630868",
|
||||
"name": "",
|
||||
"filename": "/home/mcoracin/SHARE/sx1302_reg/tx_top.json",
|
||||
"format": "utf8",
|
||||
"chunk": false,
|
||||
"sendError": true,
|
||||
"x": 380,
|
||||
"y": 340,
|
||||
"wires": [
|
||||
[
|
||||
"5ae327f2.618788"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "5ae327f2.618788",
|
||||
"type": "json",
|
||||
"z": "bf64d63f.630868",
|
||||
"name": "",
|
||||
"property": "payload",
|
||||
"action": "",
|
||||
"pretty": false,
|
||||
"x": 660,
|
||||
"y": 340,
|
||||
"wires": [
|
||||
[
|
||||
"2efaa7ec.1e3158"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "ca4d9728.057d68",
|
||||
"type": "inject",
|
||||
"z": "bf64d63f.630868",
|
||||
"name": "tx_top_a",
|
||||
"topic": "tx_top_a",
|
||||
"payload": "true",
|
||||
"payloadType": "bool",
|
||||
"repeat": "",
|
||||
"crontab": "",
|
||||
"once": false,
|
||||
"onceDelay": 0.1,
|
||||
"x": 110,
|
||||
"y": 340,
|
||||
"wires": [
|
||||
[
|
||||
"54a46dd.945aa14"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "50b73755.13ee",
|
||||
"type": "file in",
|
||||
"z": "bf64d63f.630868",
|
||||
"name": "",
|
||||
"filename": "/home/mcoracin/SHARE/sx1302_reg/tx_top.json",
|
||||
"format": "utf8",
|
||||
"chunk": false,
|
||||
"sendError": true,
|
||||
"x": 380,
|
||||
"y": 400,
|
||||
"wires": [
|
||||
[
|
||||
"ce78d3ce.e6bf18"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "ce78d3ce.e6bf18",
|
||||
"type": "json",
|
||||
"z": "bf64d63f.630868",
|
||||
"name": "",
|
||||
"property": "payload",
|
||||
"action": "",
|
||||
"pretty": false,
|
||||
"x": 660,
|
||||
"y": 400,
|
||||
"wires": [
|
||||
[
|
||||
"2efaa7ec.1e3158"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "4791c4e5.60b12c",
|
||||
"type": "inject",
|
||||
"z": "bf64d63f.630868",
|
||||
"name": "tx_top_b",
|
||||
"topic": "tx_top_b",
|
||||
"payload": "true",
|
||||
"payloadType": "bool",
|
||||
"repeat": "",
|
||||
"crontab": "",
|
||||
"once": false,
|
||||
"onceDelay": 0.1,
|
||||
"x": 110,
|
||||
"y": 400,
|
||||
"wires": [
|
||||
[
|
||||
"50b73755.13ee"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "2efaa7ec.1e3158",
|
||||
"type": "function",
|
||||
"z": "bf64d63f.630868",
|
||||
"name": "JSON to C header",
|
||||
"func": "var reg_h = flow.get('reg_h') || '';\nvar reg_c = flow.get('reg_c') || '';\nvar reg_desc = flow.get('reg_desc') || '';\nvar reg_count = flow.get('reg_count') || 0;\nvar tx_top_macro = flow.get('tx_top_macro') || '';\n\nvar rif = msg.topic;\nvar prefix = 'SX1302_REG_';\nvar base_addr = prefix + rif.toUpperCase() + '_BASE_ADDR';\n\n// register definition\nvar page = '';\nvar addr = '';\nvar offs = '';\nvar sign = '';\nvar leng = '';\nvar rdon = '';\nvar dflt = '';\nvar chck = '';\nvar reg_comment = '';\nvar desc = '';\nvar flags;\n\nfor(var register in msg.payload)\n{\n //console.log(register);\n for(var field in msg.payload[register].fields)\n {\n //console.log(' ' + field);\n page = '0';\n addr = base_addr + '+' + msg.payload[register].addr;\n offs = msg.payload[register].fields[field].pos;\n if(msg.payload[register].fields[field].hasOwnProperty('signed'))\n {\n console.log(msg.payload[register].fields[field].signed);\n if(msg.payload[register].fields[field].signed === true)\n {\n sign = '1';\n }\n else\n {\n sign = '0';\n }\n }\n else\n {\n sign = '0';\n }\n leng = msg.payload[register].fields[field].width;\n rdon = (msg.payload[register].fields[field].readonly === false) ? '0' : '1';\n dflt = msg.payload[register].fields[field].value;\n flags = msg.payload[register].fields[field].flags;\n desc = msg.payload[register].fields[field].desc;\n //desc = desc.replace(/(?:\\r\\n|\\r|\\n)/g, ' / ');\n if (flags.length > 0)\n {\n for (var i_flag of flags) {\n console.log(i_flag);\n }\n //if(['pulse','w0clr','w1clr','interrupt'].includes(flags))\n if (flags.includes('pulse') || flags.includes('w0clr') || flags.includes('w1clr') || flags.includes('interrupt'))\n {\n console.log('non-checkable register');\n check = 0;\n }\n else\n {\n check = 1;\n }\n }\n else\n {\n check = 1;\n }\n reg_comment = (rif + '_' + register + '_' + field).toUpperCase();\n\n reg_h += '#define ' + prefix + reg_comment + ' ' + reg_count + '\\n';\n reg_c += ' '; // indent\n reg_c += '{' + page + ',' + addr + ',' + offs + ',' + sign + ',' + leng + ',' + rdon + ',' + check + ',' + dflt + '}, // ' + reg_comment + '\\n';\n reg_desc += '\\n' + reg_comment + ':\\n' + desc + '\\n';\n \n if (msg.topic === 'tx_top_a')\n {\n tx_top_macro += '#define ' + prefix + 'TX_TOP' + '_' + register.toUpperCase() + '_' + field.toUpperCase() + '(rf_chain) ((rf_chain == 0) ? \\\\\\n ' + prefix + 'TX_TOP_A' + '_' + register.toUpperCase() + '_' + field.toUpperCase() + ' : \\\\\\n ' + prefix + 'TX_TOP_B' + '_' + register.toUpperCase() + '_' + field.toUpperCase() + ')\\n';\n }\n \n reg_count += 1;\n }\n}\n\n//console.log(reg_h);\n//console.log(reg_c);\n\nflow.set('reg_count', reg_count);\nflow.set('reg_h', reg_h);\nflow.set('reg_c', reg_c);\nflow.set('reg_desc', reg_desc);\nflow.set('tx_top_macro', tx_top_macro);\n\nreturn msg;",
|
||||
"outputs": 1,
|
||||
"noerr": 0,
|
||||
"x": 940,
|
||||
"y": 280,
|
||||
"wires": [
|
||||
[
|
||||
"aae4ac70.472438"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "ab7535a2.47b2e8",
|
||||
"type": "file in",
|
||||
"z": "bf64d63f.630868",
|
||||
"name": "",
|
||||
"filename": "/home/mcoracin/SHARE/sx1302_reg/gpio.json",
|
||||
"format": "utf8",
|
||||
"chunk": false,
|
||||
"sendError": true,
|
||||
"x": 370,
|
||||
"y": 460,
|
||||
"wires": [
|
||||
[
|
||||
"6017e95e.37841"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "6017e95e.37841",
|
||||
"type": "json",
|
||||
"z": "bf64d63f.630868",
|
||||
"name": "",
|
||||
"property": "payload",
|
||||
"action": "",
|
||||
"pretty": false,
|
||||
"x": 660,
|
||||
"y": 460,
|
||||
"wires": [
|
||||
[
|
||||
"2efaa7ec.1e3158"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "626f34eb.dac1f4",
|
||||
"type": "inject",
|
||||
"z": "bf64d63f.630868",
|
||||
"name": "gpio",
|
||||
"topic": "gpio",
|
||||
"payload": "true",
|
||||
"payloadType": "bool",
|
||||
"repeat": "",
|
||||
"crontab": "",
|
||||
"once": false,
|
||||
"onceDelay": 0.1,
|
||||
"x": 100,
|
||||
"y": 460,
|
||||
"wires": [
|
||||
[
|
||||
"ab7535a2.47b2e8"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "f6871b6f.167d",
|
||||
"type": "file in",
|
||||
"z": "bf64d63f.630868",
|
||||
"name": "",
|
||||
"filename": "/home/mcoracin/SHARE/sx1302_reg/timestamp.json",
|
||||
"format": "utf8",
|
||||
"chunk": false,
|
||||
"sendError": true,
|
||||
"x": 390,
|
||||
"y": 520,
|
||||
"wires": [
|
||||
[
|
||||
"d1c6c905.bbf6a"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "d1c6c905.bbf6a",
|
||||
"type": "json",
|
||||
"z": "bf64d63f.630868",
|
||||
"name": "",
|
||||
"property": "payload",
|
||||
"action": "",
|
||||
"pretty": false,
|
||||
"x": 660,
|
||||
"y": 520,
|
||||
"wires": [
|
||||
[
|
||||
"2efaa7ec.1e3158"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "128c968f.34cc09",
|
||||
"type": "inject",
|
||||
"z": "bf64d63f.630868",
|
||||
"name": "timestamp",
|
||||
"topic": "timestamp",
|
||||
"payload": "true",
|
||||
"payloadType": "bool",
|
||||
"repeat": "",
|
||||
"crontab": "",
|
||||
"once": false,
|
||||
"onceDelay": 0.1,
|
||||
"x": 110,
|
||||
"y": 520,
|
||||
"wires": [
|
||||
[
|
||||
"f6871b6f.167d"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "38f6ab4d.eba4b4",
|
||||
"type": "file in",
|
||||
"z": "bf64d63f.630868",
|
||||
"name": "",
|
||||
"filename": "/home/mcoracin/SHARE/sx1302_reg/rx_top.json",
|
||||
"format": "utf8",
|
||||
"chunk": false,
|
||||
"sendError": true,
|
||||
"x": 380,
|
||||
"y": 580,
|
||||
"wires": [
|
||||
[
|
||||
"f464e634.1500a8"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "f464e634.1500a8",
|
||||
"type": "json",
|
||||
"z": "bf64d63f.630868",
|
||||
"name": "",
|
||||
"property": "payload",
|
||||
"action": "",
|
||||
"pretty": false,
|
||||
"x": 660,
|
||||
"y": 580,
|
||||
"wires": [
|
||||
[
|
||||
"2efaa7ec.1e3158"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "4dd5087.c34c178",
|
||||
"type": "inject",
|
||||
"z": "bf64d63f.630868",
|
||||
"name": "rx_top",
|
||||
"topic": "rx_top",
|
||||
"payload": "true",
|
||||
"payloadType": "bool",
|
||||
"repeat": "",
|
||||
"crontab": "",
|
||||
"once": false,
|
||||
"onceDelay": 0.1,
|
||||
"x": 100,
|
||||
"y": 580,
|
||||
"wires": [
|
||||
[
|
||||
"38f6ab4d.eba4b4"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "28e533a1.3ef5ac",
|
||||
"type": "file in",
|
||||
"z": "bf64d63f.630868",
|
||||
"name": "",
|
||||
"filename": "/home/mcoracin/SHARE/sx1302_reg/arb_mcu.json",
|
||||
"format": "utf8",
|
||||
"chunk": false,
|
||||
"sendError": true,
|
||||
"x": 390,
|
||||
"y": 640,
|
||||
"wires": [
|
||||
[
|
||||
"3c2109da.3df84e"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "3c2109da.3df84e",
|
||||
"type": "json",
|
||||
"z": "bf64d63f.630868",
|
||||
"name": "",
|
||||
"property": "payload",
|
||||
"action": "",
|
||||
"pretty": false,
|
||||
"x": 660,
|
||||
"y": 640,
|
||||
"wires": [
|
||||
[
|
||||
"2efaa7ec.1e3158"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "c3a46357.bf67c",
|
||||
"type": "inject",
|
||||
"z": "bf64d63f.630868",
|
||||
"name": "arb_mcu",
|
||||
"topic": "arb_mcu",
|
||||
"payload": "true",
|
||||
"payloadType": "bool",
|
||||
"repeat": "",
|
||||
"crontab": "",
|
||||
"once": false,
|
||||
"onceDelay": 0.1,
|
||||
"x": 110,
|
||||
"y": 640,
|
||||
"wires": [
|
||||
[
|
||||
"28e533a1.3ef5ac"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "b3ed4e4f.fbd358",
|
||||
"type": "file in",
|
||||
"z": "bf64d63f.630868",
|
||||
"name": "",
|
||||
"filename": "/home/mcoracin/SHARE/sx1302_reg/radio_fe.json",
|
||||
"format": "utf8",
|
||||
"chunk": false,
|
||||
"sendError": true,
|
||||
"x": 390,
|
||||
"y": 700,
|
||||
"wires": [
|
||||
[
|
||||
"37f7e33f.14dc6c"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "37f7e33f.14dc6c",
|
||||
"type": "json",
|
||||
"z": "bf64d63f.630868",
|
||||
"name": "",
|
||||
"property": "payload",
|
||||
"action": "",
|
||||
"pretty": false,
|
||||
"x": 660,
|
||||
"y": 700,
|
||||
"wires": [
|
||||
[
|
||||
"2efaa7ec.1e3158"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "e9006ee1.8d154",
|
||||
"type": "inject",
|
||||
"z": "bf64d63f.630868",
|
||||
"name": "radio_fe",
|
||||
"topic": "radio_fe",
|
||||
"payload": "true",
|
||||
"payloadType": "bool",
|
||||
"repeat": "",
|
||||
"crontab": "",
|
||||
"once": false,
|
||||
"onceDelay": 0.1,
|
||||
"x": 110,
|
||||
"y": 700,
|
||||
"wires": [
|
||||
[
|
||||
"b3ed4e4f.fbd358"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "7c16420a.7b8634",
|
||||
"type": "file in",
|
||||
"z": "bf64d63f.630868",
|
||||
"name": "",
|
||||
"filename": "/home/mcoracin/SHARE/sx1302_reg/otp.json",
|
||||
"format": "utf8",
|
||||
"chunk": false,
|
||||
"sendError": true,
|
||||
"x": 360,
|
||||
"y": 760,
|
||||
"wires": [
|
||||
[
|
||||
"4e1e58e8.d72998"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "4e1e58e8.d72998",
|
||||
"type": "json",
|
||||
"z": "bf64d63f.630868",
|
||||
"name": "",
|
||||
"property": "payload",
|
||||
"action": "",
|
||||
"pretty": false,
|
||||
"x": 650,
|
||||
"y": 760,
|
||||
"wires": [
|
||||
[
|
||||
"2efaa7ec.1e3158"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "cdd63a9c.be8f4",
|
||||
"type": "inject",
|
||||
"z": "bf64d63f.630868",
|
||||
"name": "otp",
|
||||
"topic": "otp",
|
||||
"payload": "true",
|
||||
"payloadType": "bool",
|
||||
"repeat": "",
|
||||
"crontab": "",
|
||||
"once": false,
|
||||
"onceDelay": 0.1,
|
||||
"x": 100,
|
||||
"y": 760,
|
||||
"wires": [
|
||||
[
|
||||
"7c16420a.7b8634"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "9ac5ddf6.e47048",
|
||||
"type": "file in",
|
||||
"z": "bf64d63f.630868",
|
||||
"name": "",
|
||||
"filename": "/home/mcoracin/SHARE/sx1302_reg/rx_top_lora_service_fsk.json",
|
||||
"format": "utf8",
|
||||
"chunk": false,
|
||||
"sendError": true,
|
||||
"x": 500,
|
||||
"y": 820,
|
||||
"wires": [
|
||||
[
|
||||
"5a5536dc.db687"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "5a5536dc.db687",
|
||||
"type": "json",
|
||||
"z": "bf64d63f.630868",
|
||||
"name": "",
|
||||
"property": "payload",
|
||||
"action": "",
|
||||
"pretty": false,
|
||||
"x": 800,
|
||||
"y": 820,
|
||||
"wires": [
|
||||
[
|
||||
"2efaa7ec.1e3158"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "c5ffdcfa.19ea28",
|
||||
"type": "inject",
|
||||
"z": "bf64d63f.630868",
|
||||
"name": "rx_top_lora_service_fsk",
|
||||
"topic": "rx_top_lora_service_fsk",
|
||||
"payload": "true",
|
||||
"payloadType": "bool",
|
||||
"repeat": "",
|
||||
"crontab": "",
|
||||
"once": false,
|
||||
"onceDelay": 0.1,
|
||||
"x": 150,
|
||||
"y": 820,
|
||||
"wires": [
|
||||
[
|
||||
"9ac5ddf6.e47048"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "b5897d4d.0628c",
|
||||
"type": "file in",
|
||||
"z": "bf64d63f.630868",
|
||||
"name": "",
|
||||
"filename": "/home/mcoracin/SHARE/sx1302_reg/capture_ram.json",
|
||||
"format": "utf8",
|
||||
"chunk": false,
|
||||
"sendError": true,
|
||||
"x": 410,
|
||||
"y": 880,
|
||||
"wires": [
|
||||
[
|
||||
"753bfa61.c8068c"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "753bfa61.c8068c",
|
||||
"type": "json",
|
||||
"z": "bf64d63f.630868",
|
||||
"name": "",
|
||||
"property": "payload",
|
||||
"action": "",
|
||||
"pretty": false,
|
||||
"x": 680,
|
||||
"y": 880,
|
||||
"wires": [
|
||||
[
|
||||
"2efaa7ec.1e3158"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "6ca97d0.d189b84",
|
||||
"type": "inject",
|
||||
"z": "bf64d63f.630868",
|
||||
"name": "capture_ram",
|
||||
"topic": "capture_ram",
|
||||
"payload": "true",
|
||||
"payloadType": "bool",
|
||||
"repeat": "",
|
||||
"crontab": "",
|
||||
"once": false,
|
||||
"onceDelay": 0.1,
|
||||
"x": 120,
|
||||
"y": 880,
|
||||
"wires": [
|
||||
[
|
||||
"b5897d4d.0628c"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "56ed912a.91d118",
|
||||
"type": "trigger",
|
||||
"z": "bf64d63f.630868",
|
||||
"op1": "1",
|
||||
"op2": "0",
|
||||
"op1type": "val",
|
||||
"op2type": "val",
|
||||
"duration": "250",
|
||||
"extend": "false",
|
||||
"units": "ms",
|
||||
"reset": "",
|
||||
"bytopic": "all",
|
||||
"name": "",
|
||||
"x": 1020,
|
||||
"y": 500,
|
||||
"wires": [
|
||||
[]
|
||||
]
|
||||
}
|
||||
]
|
|
@ -0,0 +1,61 @@
|
|||
### get external defined data
|
||||
|
||||
include ../../target.cfg
|
||||
|
||||
### constant symbols
|
||||
|
||||
ARCH ?=
|
||||
CROSS_COMPILE ?=
|
||||
CC := $(CROSS_COMPILE)gcc
|
||||
AR := $(CROSS_COMPILE)ar
|
||||
|
||||
CFLAGS := -O2 -Wall -Wextra -std=c99 -I. -I../../libtools/inc
|
||||
|
||||
### linking options
|
||||
|
||||
LIBS := -ltinymt32
|
||||
|
||||
### general build targets
|
||||
|
||||
all: payload_crc payload_diff payload_gen
|
||||
|
||||
clean:
|
||||
rm -f payload_crc payload_diff payload_gen
|
||||
rm -f *.o
|
||||
|
||||
install:
|
||||
ifneq ($(strip $(TARGET_IP)),)
|
||||
ifneq ($(strip $(TARGET_DIR)),)
|
||||
ifneq ($(strip $(TARGET_USR)),)
|
||||
@echo "---- Copying payload tools files to $(TARGET_IP):$(TARGET_DIR)"
|
||||
@ssh $(TARGET_USR)@$(TARGET_IP) "mkdir -p $(TARGET_DIR)"
|
||||
@scp payload_crc $(TARGET_USR)@$(TARGET_IP):$(TARGET_DIR)
|
||||
@scp payload_diff $(TARGET_USR)@$(TARGET_IP):$(TARGET_DIR)
|
||||
@scp payload_gen $(TARGET_USR)@$(TARGET_IP):$(TARGET_DIR)
|
||||
else
|
||||
@echo "ERROR: TARGET_USR is not configured in target.cfg"
|
||||
endif
|
||||
else
|
||||
@echo "ERROR: TARGET_DIR is not configured in target.cfg"
|
||||
endif
|
||||
else
|
||||
@echo "ERROR: TARGET_IP is not configured in target.cfg"
|
||||
endif
|
||||
|
||||
### rules
|
||||
|
||||
%.o : %.c
|
||||
$(CC) -c $(CFLAGS) $< -o $@
|
||||
|
||||
### test programs
|
||||
|
||||
payload_crc: payload_crc.o
|
||||
$(CC) $(CFLAGS) -o $@ $^
|
||||
|
||||
payload_diff: payload_diff.o
|
||||
$(CC) $(CFLAGS) -o $@ $^
|
||||
|
||||
payload_gen: payload_gen.o
|
||||
$(CC) $(CFLAGS) -L../../libtools -o $@ $^ $(LIBS)
|
||||
|
||||
### EOF
|
|
@ -0,0 +1,110 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- SUBFUNCTIONS DECLARATION --------------------------------------------- */
|
||||
|
||||
static void usage(void);
|
||||
uint16_t sx1302_lora_payload_crc(const uint8_t * data, uint8_t size);
|
||||
void remove_spaces(char *str);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- MAIN FUNCTION -------------------------------------------------------- */
|
||||
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
int j;
|
||||
uint8_t payload[255];
|
||||
uint8_t payload_size;
|
||||
uint16_t crc;
|
||||
char hexstr[1024];
|
||||
|
||||
if (argc < 2) {
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Get payload hex string from command line */
|
||||
memcpy(hexstr, argv[1], strlen(argv[1]));
|
||||
hexstr[strlen(argv[1])] = '\0';
|
||||
printf("Input hex string: %s\n", hexstr);
|
||||
|
||||
/* Remove spaces from the string if any */
|
||||
remove_spaces(hexstr);
|
||||
hexstr[strlen(hexstr)] = '\0';
|
||||
printf("Removing spaces: %s\n", hexstr);
|
||||
|
||||
/* Convert hex string to byte array */
|
||||
payload_size = strlen(hexstr) / 2;
|
||||
for (j = 0; j < payload_size; j++) {
|
||||
sscanf(hexstr + 2*j, "%02hhx", &payload[j]);
|
||||
}
|
||||
|
||||
/* Compute CRC */
|
||||
crc = sx1302_lora_payload_crc(payload, payload_size);
|
||||
printf("Payload CRC_16: %04X\n", crc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
void usage(void) {
|
||||
printf("Missing payload hex string\n");
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
void remove_spaces(char *str)
|
||||
{
|
||||
/* To keep track of non-space character count */
|
||||
int count = 0;
|
||||
|
||||
/* Traverse the given string. If current character
|
||||
is not space, then place it at index 'count++' */
|
||||
for (int i = 0; str[i]; i++) {
|
||||
if (str[i] != ' ') {
|
||||
str[count++] = str[i]; /* here count is incremented */
|
||||
}
|
||||
}
|
||||
str[count] = '\0';
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
void lora_crc16(const char data, int *crc) {
|
||||
int next = 0;
|
||||
next = (((data>>0)&1) ^ ((*crc>>12)&1) ^ ((*crc>> 8)&1) ) ;
|
||||
next += ((((data>>1)&1) ^ ((*crc>>13)&1) ^ ((*crc>> 9)&1) )<<1 ) ;
|
||||
next += ((((data>>2)&1) ^ ((*crc>>14)&1) ^ ((*crc>>10)&1) )<<2 ) ;
|
||||
next += ((((data>>3)&1) ^ ((*crc>>15)&1) ^ ((*crc>>11)&1) )<<3 ) ;
|
||||
next += ((((data>>4)&1) ^ ((*crc>>12)&1) )<<4 ) ;
|
||||
next += ((((data>>5)&1) ^ ((*crc>>13)&1) ^ ((*crc>>12)&1) ^ ((*crc>> 8)&1))<<5 ) ;
|
||||
next += ((((data>>6)&1) ^ ((*crc>>14)&1) ^ ((*crc>>13)&1) ^ ((*crc>> 9)&1))<<6 ) ;
|
||||
next += ((((data>>7)&1) ^ ((*crc>>15)&1) ^ ((*crc>>14)&1) ^ ((*crc>>10)&1))<<7 ) ;
|
||||
next += ((((*crc>>0)&1) ^ ((*crc>>15)&1) ^ ((*crc>>11)&1) )<<8 ) ;
|
||||
next += ((((*crc>>1)&1) ^ ((*crc>>12)&1) )<<9 ) ;
|
||||
next += ((((*crc>>2)&1) ^ ((*crc>>13)&1) )<<10) ;
|
||||
next += ((((*crc>>3)&1) ^ ((*crc>>14)&1) )<<11) ;
|
||||
next += ((((*crc>>4)&1) ^ ((*crc>>15)&1) ^ ((*crc>>12)&1) ^ ((*crc>> 8)&1))<<12) ;
|
||||
next += ((((*crc>>5)&1) ^ ((*crc>>13)&1) ^ ((*crc>> 9)&1) )<<13) ;
|
||||
next += ((((*crc>>6)&1) ^ ((*crc>>14)&1) ^ ((*crc>>10)&1) )<<14) ;
|
||||
next += ((((*crc>>7)&1) ^ ((*crc>>15)&1) ^ ((*crc>>11)&1) )<<15) ;
|
||||
(*crc) = next;
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
uint16_t sx1302_lora_payload_crc(const uint8_t * data, uint8_t size) {
|
||||
int i;
|
||||
int crc = 0;
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
lora_crc16(data[i], &crc);
|
||||
}
|
||||
|
||||
//printf("CRC16: 0x%02X 0x%02X (%X)\n", (uint8_t)(crc >> 8), (uint8_t)crc, crc);
|
||||
return (uint16_t)crc;
|
||||
}
|
|
@ -0,0 +1,116 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- MACROS --------------------------------------------------------------- */
|
||||
|
||||
#define TAKE_N_BITS_FROM(b, p, n) (((b) >> (p)) & ((1 << (n)) - 1))
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- SUBFUNCTIONS DECLARATION --------------------------------------------- */
|
||||
|
||||
static void usage(void);
|
||||
void remove_spaces(char *str);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- MAIN FUNCTION -------------------------------------------------------- */
|
||||
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
int i, j;
|
||||
uint8_t payload_a[255];
|
||||
uint8_t payload_b[255];
|
||||
uint8_t payload_diff[255];
|
||||
uint8_t payload_size;
|
||||
char hexstr[1024];
|
||||
uint16_t nb_bits_diff = 0;
|
||||
|
||||
if (argc < 3) {
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strlen(argv[1]) != strlen(argv[2])) {
|
||||
printf("ERROR: payloads A & B must have same size\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Get payload A hex string from command line */
|
||||
memcpy(hexstr, argv[1], strlen(argv[1]));
|
||||
hexstr[strlen(argv[1])] = '\0';
|
||||
printf("Input hex string: %s\n", hexstr);
|
||||
|
||||
/* Remove spaces from the string if any */
|
||||
remove_spaces(hexstr);
|
||||
hexstr[strlen(hexstr)] = '\0';
|
||||
printf("Removing spaces: %s\n", hexstr);
|
||||
|
||||
/* Convert hex string to byte array */
|
||||
payload_size = strlen(hexstr) / 2;
|
||||
for (j = 0; j < payload_size; j++) {
|
||||
sscanf(hexstr + 2*j, "%02hhx", &payload_a[j]);
|
||||
}
|
||||
|
||||
/* Get payload B hex string from command line */
|
||||
memcpy(hexstr, argv[2], strlen(argv[2]));
|
||||
hexstr[strlen(argv[2])] = '\0';
|
||||
printf("Input hex string: %s\n", hexstr);
|
||||
|
||||
/* Remove spaces from the string if any */
|
||||
remove_spaces(hexstr);
|
||||
hexstr[strlen(hexstr)] = '\0';
|
||||
printf("Removing spaces: %s\n", hexstr);
|
||||
|
||||
/* Convert hex string to byte array */
|
||||
for (j = 0; j < payload_size; j++) {
|
||||
sscanf(hexstr + 2*j, "%02hhx", &payload_b[j]);
|
||||
}
|
||||
|
||||
/* Count how many bits differs */
|
||||
printf("Diff: ");
|
||||
for (j = 0; j < payload_size; j++) {
|
||||
payload_diff[j] = payload_a[j] ^ payload_b[j];
|
||||
printf("%02X ", payload_diff[j]);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
for (j = 0; j < payload_size; j++) {
|
||||
for (i = 7; i >= 0; i--) {
|
||||
printf("%u", TAKE_N_BITS_FROM(payload_diff[j], i, 1));
|
||||
if (TAKE_N_BITS_FROM(payload_diff[j], i, 1) == 1) {
|
||||
nb_bits_diff += 1;
|
||||
}
|
||||
}
|
||||
printf(" ");
|
||||
}
|
||||
printf("\n");
|
||||
printf("%u bits flipped\n", nb_bits_diff);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
void usage(void) {
|
||||
printf("Missing payload hex strings for a & b\n");
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
void remove_spaces(char *str)
|
||||
{
|
||||
/* To keep track of non-space character count */
|
||||
int count = 0;
|
||||
|
||||
/* Traverse the given string. If current character
|
||||
is not space, then place it at index 'count++' */
|
||||
for (int i = 0; str[i]; i++) {
|
||||
if (str[i] != ' ') {
|
||||
str[count++] = str[i]; /* here count is incremented */
|
||||
}
|
||||
}
|
||||
str[count] = '\0';
|
||||
}
|
||||
|
|
@ -0,0 +1,124 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "tinymt32.h"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- SUBFUNCTIONS DECLARATION --------------------------------------------- */
|
||||
|
||||
static void usage(void);
|
||||
void remove_spaces(char *str);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- MAIN FUNCTION -------------------------------------------------------- */
|
||||
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
int j;
|
||||
uint8_t dev_id[4];
|
||||
uint8_t payload[255];
|
||||
uint8_t payload_size;
|
||||
unsigned int packet_cnt;
|
||||
tinymt32_t tinymt;
|
||||
char hexstr[32];
|
||||
|
||||
if (argc < 4) {
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Get dev_id hex string from command line */
|
||||
memcpy(hexstr, argv[1], strlen(argv[1]));
|
||||
hexstr[strlen(argv[1])] = '\0';
|
||||
|
||||
/* Remove spaces from the string if any */
|
||||
remove_spaces(hexstr);
|
||||
hexstr[strlen(hexstr)] = '\0';
|
||||
printf("Dev_id: %s\n", hexstr);
|
||||
|
||||
/* Convert hex string to byte array */
|
||||
payload_size = strlen(hexstr) / 2;
|
||||
for (j = 0; j < 4; j++) {
|
||||
sscanf(hexstr + 2*j, "%02hhx", &dev_id[j]);
|
||||
}
|
||||
|
||||
/* Get packet count from which generate the random payload */
|
||||
packet_cnt = atoi(argv[2]);
|
||||
|
||||
/* Get packet payload size */
|
||||
payload_size = (uint8_t)atoi(argv[3]);
|
||||
|
||||
/* Initialize the pseudo-random generator */
|
||||
tinymt.mat1 = 0x8f7011ee;
|
||||
tinymt.mat2 = 0xfc78ff1f;
|
||||
tinymt.tmat = 0x3793fdff;
|
||||
tinymt32_init(&tinymt, packet_cnt);
|
||||
|
||||
/* Construct packet */
|
||||
payload[0] = dev_id[0];
|
||||
payload[1] = dev_id[1];
|
||||
payload[2] = dev_id[2];
|
||||
payload[3] = dev_id[3];
|
||||
payload[4] = (uint8_t)(packet_cnt >> 24);
|
||||
payload[5] = (uint8_t)(packet_cnt >> 16);
|
||||
payload[6] = (uint8_t)(packet_cnt >> 8);
|
||||
payload[7] = (uint8_t)(packet_cnt >> 0);
|
||||
for (j = 8; j < payload_size; j++) {
|
||||
payload[j] = (uint8_t)tinymt32_generate_uint32(&tinymt);
|
||||
}
|
||||
for (j = 0; j < payload_size; j++) {
|
||||
printf("%02X ", payload[j]);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
#if 0
|
||||
for (packet_cnt = 0; packet_cnt < 10; packet_cnt++) {
|
||||
tinymt32_init(&tinymt, (int)packet_cnt);
|
||||
payload[0] = 0xCA;
|
||||
payload[1] = 0xFE;
|
||||
payload[2] = 0x12;
|
||||
payload[3] = 0x34;
|
||||
payload[4] = (uint8_t)(packet_cnt >> 24);
|
||||
payload[5] = (uint8_t)(packet_cnt >> 16);
|
||||
payload[6] = (uint8_t)(packet_cnt >> 8);
|
||||
payload[7] = (uint8_t)(packet_cnt >> 0);
|
||||
for (j = 8; j < 16; j++) {
|
||||
payload[j] = (uint8_t)tinymt32_generate_uint32(&tinymt);
|
||||
}
|
||||
for (j = 0; j < 16; j++) {
|
||||
printf("%02X ", payload[j]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
void usage(void) {
|
||||
printf("Missing parameters: ./payload_gen dev_id pkt_cnt pkt_size\n");
|
||||
printf(" dev_id: hex string for 4-bytes dev_id\n");
|
||||
printf(" pkt_cnt: unsigned int used to initialize the pseudo-random generator\n");
|
||||
printf(" pkt_size: paylaod size in bytes [0..255]\n");
|
||||
}
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
void remove_spaces(char *str)
|
||||
{
|
||||
/* To keep track of non-space character count */
|
||||
int count = 0;
|
||||
|
||||
/* Traverse the given string. If current character
|
||||
is not space, then place it at index 'count++' */
|
||||
for (int i = 0; str[i]; i++) {
|
||||
if (str[i] != ' ') {
|
||||
str[count++] = str[i]; /* here count is incremented */
|
||||
}
|
||||
}
|
||||
str[count] = '\0';
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
#!/bin/sh
|
||||
|
||||
# This script is intended to be used on SX1302 CoreCell platform, it performs
|
||||
# the following actions:
|
||||
# - export/unpexort GPIO23 and GPIO18 used to reset the SX1302 chip and to enable the LDOs
|
||||
#
|
||||
# Usage examples:
|
||||
# ./reset_lgw.sh stop
|
||||
# ./reset_lgw.sh start
|
||||
|
||||
# GPIO mapping has to be adapted with HW
|
||||
#
|
||||
|
||||
SX1302_RESET_PIN=23
|
||||
SX1302_POWER_EN_PIN=18
|
||||
|
||||
WAIT_GPIO() {
|
||||
sleep 0.1
|
||||
}
|
||||
|
||||
init() {
|
||||
# setup GPIOs
|
||||
echo "$SX1302_RESET_PIN" > /sys/class/gpio/export; WAIT_GPIO
|
||||
echo "$SX1302_POWER_EN_PIN" > /sys/class/gpio/export; WAIT_GPIO
|
||||
|
||||
# set GPIOs as output
|
||||
echo "out" > /sys/class/gpio/gpio$SX1302_RESET_PIN/direction; WAIT_GPIO
|
||||
echo "out" > /sys/class/gpio/gpio$SX1302_POWER_EN_PIN/direction; WAIT_GPIO
|
||||
}
|
||||
|
||||
reset() {
|
||||
echo "CoreCell reset through GPIO$SX1302_RESET_PIN..."
|
||||
echo "CoreCell power enable through GPIO$SX1302_POWER_EN_PIN..."
|
||||
|
||||
# write output for SX1302 CoreCell power_enable and reset
|
||||
echo "1" > /sys/class/gpio/gpio$SX1302_POWER_EN_PIN/value; WAIT_GPIO
|
||||
|
||||
echo "1" > /sys/class/gpio/gpio$SX1302_RESET_PIN/value; WAIT_GPIO
|
||||
echo "0" > /sys/class/gpio/gpio$SX1302_RESET_PIN/value; WAIT_GPIO
|
||||
}
|
||||
|
||||
term() {
|
||||
# cleanup all GPIOs
|
||||
if [ -d /sys/class/gpio/gpio$SX1302_RESET_PIN ]
|
||||
then
|
||||
echo "$SX1302_RESET_PIN" > /sys/class/gpio/unexport; WAIT_GPIO
|
||||
fi
|
||||
if [ -d /sys/class/gpio/gpio$SX1302_POWER_EN_PIN ]
|
||||
then
|
||||
echo "$SX1302_POWER_EN_PIN" > /sys/class/gpio/unexport; WAIT_GPIO
|
||||
fi
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
term # just in case
|
||||
init
|
||||
reset
|
||||
;;
|
||||
stop)
|
||||
reset
|
||||
term
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 {start|stop}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
|
@ -0,0 +1,83 @@
|
|||
### get external defined data
|
||||
|
||||
include ../target.cfg
|
||||
|
||||
### User defined build options
|
||||
|
||||
ARCH ?=
|
||||
CROSS_COMPILE ?=
|
||||
BUILD_MODE := release
|
||||
OBJDIR = obj
|
||||
|
||||
### ----- AVOID MODIFICATIONS BELLOW ------ AVOID MODIFICATIONS BELLOW ----- ###
|
||||
|
||||
ifeq '$(BUILD_MODE)' 'alpha'
|
||||
$(warning /\/\/\/ Building in 'alpha' mode \/\/\/\)
|
||||
WARN_CFLAGS :=
|
||||
OPT_CFLAGS := -O0
|
||||
DEBUG_CFLAGS := -g
|
||||
LDFLAGS :=
|
||||
else ifeq '$(BUILD_MODE)' 'debug'
|
||||
$(warning /\/\/\/ Building in 'debug' mode \/\/\/\)
|
||||
WARN_CFLAGS := -Wall -Wextra
|
||||
OPT_CFLAGS := -O2
|
||||
DEBUG_CFLAGS := -g
|
||||
LDFLAGS :=
|
||||
else ifeq '$(BUILD_MODE)' 'release'
|
||||
$(warning /\/\/\/ Building in 'release' mode \/\/\/\)
|
||||
WARN_CFLAGS := -Wall -Wextra
|
||||
OPT_CFLAGS := -O2 -ffunction-sections -fdata-sections
|
||||
DEBUG_CFLAGS :=
|
||||
LDFLAGS := -Wl,--gc-sections
|
||||
else
|
||||
$(error BUILD_MODE must be set to either 'alpha', 'debug' or 'release')
|
||||
endif
|
||||
|
||||
### Application-specific variables
|
||||
APP_NAME := chip_id
|
||||
APP_LIBS := -lloragw -lm -ltinymt32 -lrt
|
||||
|
||||
### Environment constants
|
||||
LIB_PATH := ../libloragw
|
||||
|
||||
### Expand build options
|
||||
CFLAGS := -std=c99 $(WARN_CFLAGS) $(OPT_CFLAGS) $(DEBUG_CFLAGS)
|
||||
CC := $(CROSS_COMPILE)gcc
|
||||
AR := $(CROSS_COMPILE)ar
|
||||
|
||||
### General build targets
|
||||
all: $(APP_NAME)
|
||||
|
||||
clean:
|
||||
rm -f obj/*.o
|
||||
rm -f $(APP_NAME)
|
||||
|
||||
install:
|
||||
ifneq ($(strip $(TARGET_IP)),)
|
||||
ifneq ($(strip $(TARGET_DIR)),)
|
||||
ifneq ($(strip $(TARGET_USR)),)
|
||||
@echo "---- Copying chip_id files to $(TARGET_IP):$(TARGET_DIR)"
|
||||
@ssh $(TARGET_USR)@$(TARGET_IP) "mkdir -p $(TARGET_DIR)"
|
||||
@scp chip_id $(TARGET_USR)@$(TARGET_IP):$(TARGET_DIR)
|
||||
else
|
||||
@echo "ERROR: TARGET_USR is not configured in target.cfg"
|
||||
endif
|
||||
else
|
||||
@echo "ERROR: TARGET_DIR is not configured in target.cfg"
|
||||
endif
|
||||
else
|
||||
@echo "ERROR: TARGET_IP is not configured in target.cfg"
|
||||
endif
|
||||
|
||||
$(OBJDIR):
|
||||
mkdir -p $(OBJDIR)
|
||||
|
||||
### Compile main program
|
||||
$(OBJDIR)/$(APP_NAME).o: src/$(APP_NAME).c | $(OBJDIR)
|
||||
$(CC) -c $< -o $@ $(CFLAGS) -Iinc -I../libloragw/inc
|
||||
|
||||
### Link everything together
|
||||
$(APP_NAME): $(OBJDIR)/$(APP_NAME).o
|
||||
$(CC) -L$(LIB_PATH) -L../libtools $^ -o $@ $(LDFLAGS) $(APP_LIBS)
|
||||
|
||||
### EOF
|
|
@ -0,0 +1,53 @@
|
|||
______ _
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2019 Semtech
|
||||
|
||||
Utility to get SX1302 chip EUI
|
||||
==============================
|
||||
|
||||
|
||||
## 1. Introduction
|
||||
|
||||
This utility configures the SX1302 to be able to retrieve its EUI.
|
||||
It can then be used as a Gateway ID.
|
||||
|
||||
## 2. Command line options
|
||||
|
||||
### 2.1. General options ###
|
||||
|
||||
`-h`
|
||||
will display a short help and version informations.
|
||||
|
||||
### 2.2. SPI options ###
|
||||
|
||||
`-d filename`
|
||||
use the Linux SPI device driver, but with an explicit path, for systems with
|
||||
several SPI device drivers, or uncommon numbering scheme.
|
||||
|
||||
## 3. Legal notice
|
||||
|
||||
The information presented in this project documentation does not form part of
|
||||
any quotation or contract, is believed to be accurate and reliable and may be
|
||||
changed without notice. No liability will be accepted by the publisher for any
|
||||
consequence of its use. Publication thereof does not convey nor imply any
|
||||
license under patent or other industrial or intellectual property rights.
|
||||
Semtech assumes no responsibility or liability whatsoever for any failure or
|
||||
unexpected operation resulting from misuse, neglect improper installation,
|
||||
repair or improper handling or unusual physical or electrical stress
|
||||
including, but not limited to, exposure to parameters beyond the specified
|
||||
maximum ratings or operation outside the specified range.
|
||||
|
||||
SEMTECH PRODUCTS ARE NOT DESIGNED, INTENDED, AUTHORIZED OR WARRANTED TO BE
|
||||
SUITABLE FOR USE IN LIFE-SUPPORT APPLICATIONS, DEVICES OR SYSTEMS OR OTHER
|
||||
CRITICAL APPLICATIONS. INCLUSION OF SEMTECH PRODUCTS IN SUCH APPLICATIONS IS
|
||||
UNDERSTOOD TO BE UNDERTAKEN SOLELY AT THE CUSTOMER'S OWN RISK. Should a
|
||||
customer purchase or use Semtech products for any such unauthorized
|
||||
application, the customer shall indemnify and hold Semtech and its officers,
|
||||
employees, subsidiaries, affiliates, and distributors harmless against all
|
||||
claims, costs damages and attorney fees which could arise.
|
||||
|
||||
*EOF*
|
|
@ -0,0 +1,209 @@
|
|||
/*
|
||||
______ _
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2019 Semtech
|
||||
|
||||
Description:
|
||||
Utility to get SX1302 chip EUI
|
||||
|
||||
License: Revised BSD License, see LICENSE.TXT file include in the project
|
||||
*/
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- DEPENDANCIES --------------------------------------------------------- */
|
||||
|
||||
/* fix an issue between POSIX and C99 */
|
||||
#if __STDC_VERSION__ >= 199901L
|
||||
#define _XOPEN_SOURCE 600
|
||||
#else
|
||||
#define _XOPEN_SOURCE 500
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <math.h>
|
||||
#include <signal.h> /* sigaction */
|
||||
#include <getopt.h> /* getopt_long */
|
||||
|
||||
#include "loragw_hal.h"
|
||||
#include "loragw_reg.h"
|
||||
#include "loragw_aux.h"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE MACROS ------------------------------------------------------- */
|
||||
|
||||
#define RAND_RANGE(min, max) (rand() % (max + 1 - min) + min)
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE CONSTANTS ---------------------------------------------------- */
|
||||
|
||||
#define LINUXDEV_PATH_DEFAULT "/dev/spidev0.0"
|
||||
|
||||
#define DEFAULT_CLK_SRC 0
|
||||
#define DEFAULT_FREQ_HZ 868500000U
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE VARIABLES ---------------------------------------------------- */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- PRIVATE FUNCTIONS ---------------------------------------------------- */
|
||||
|
||||
/* describe command line options */
|
||||
void usage(void) {
|
||||
printf("Library version information: %s\n", lgw_version_info());
|
||||
printf("Available options:\n");
|
||||
printf(" -h print this help\n");
|
||||
printf(" -d [path] Path the spidev file (ex: /dev/spidev0.0)\n");
|
||||
printf(" -k <uint> Concentrator clock source (Radio A or Radio B) [0..1]\n");
|
||||
printf(" -r <uint> Radio type (1255, 1257, 1250)\n");
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- MAIN FUNCTION -------------------------------------------------------- */
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i, x;
|
||||
unsigned int arg_u;
|
||||
uint8_t clocksource = 0;
|
||||
lgw_radio_type_t radio_type = LGW_RADIO_TYPE_SX1250;
|
||||
|
||||
struct lgw_conf_board_s boardconf;
|
||||
struct lgw_conf_rxrf_s rfconf;
|
||||
uint64_t eui;
|
||||
|
||||
/* SPI interfaces */
|
||||
const char spidev_path_default[] = LINUXDEV_PATH_DEFAULT;
|
||||
const char * spidev_path = spidev_path_default;
|
||||
|
||||
/* Parameter parsing */
|
||||
int option_index = 0;
|
||||
static struct option long_options[] = {
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
/* parse command line options */
|
||||
while ((i = getopt_long (argc, argv, "hd:", long_options, &option_index)) != -1) {
|
||||
switch (i) {
|
||||
case 'h':
|
||||
usage();
|
||||
return -1;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
spidev_path = optarg;
|
||||
break;
|
||||
|
||||
case 'r': /* <uint> Radio type */
|
||||
i = sscanf(optarg, "%u", &arg_u);
|
||||
if ((i != 1) || ((arg_u != 1255) && (arg_u != 1257) && (arg_u != 1250))) {
|
||||
printf("ERROR: argument parsing of -r argument. Use -h to print help\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
switch (arg_u) {
|
||||
case 1255:
|
||||
radio_type = LGW_RADIO_TYPE_SX1255;
|
||||
break;
|
||||
case 1257:
|
||||
radio_type = LGW_RADIO_TYPE_SX1257;
|
||||
break;
|
||||
default: /* 1250 */
|
||||
radio_type = LGW_RADIO_TYPE_SX1250;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'k': /* <uint> Clock Source */
|
||||
i = sscanf(optarg, "%u", &arg_u);
|
||||
if ((i != 1) || (arg_u > 1)) {
|
||||
printf("ERROR: argument parsing of -k argument. Use -h to print help\n");
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
clocksource = (uint8_t)arg_u;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("ERROR: argument parsing\n");
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Board reset */
|
||||
if (system("./reset_lgw.sh start") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Configure the gateway */
|
||||
memset( &boardconf, 0, sizeof boardconf);
|
||||
boardconf.lorawan_public = true;
|
||||
boardconf.clksrc = clocksource;
|
||||
boardconf.full_duplex = false;
|
||||
strncpy(boardconf.spidev_path, spidev_path, sizeof boardconf.spidev_path);
|
||||
if (lgw_board_setconf(&boardconf) != LGW_HAL_SUCCESS) {
|
||||
printf("ERROR: failed to configure board\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
memset( &rfconf, 0, sizeof rfconf);
|
||||
rfconf.enable = true; /* rf chain 0 needs to be enabled for calibration to work on sx1257 */
|
||||
rfconf.freq_hz = 868500000; /* dummy */
|
||||
rfconf.type = radio_type;
|
||||
rfconf.tx_enable = false;
|
||||
if (lgw_rxrf_setconf(0, &rfconf) != LGW_HAL_SUCCESS) {
|
||||
printf("ERROR: failed to configure rxrf 0\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
memset( &rfconf, 0, sizeof rfconf);
|
||||
rfconf.enable = (clocksource == 1) ? true : false;
|
||||
rfconf.freq_hz = 868500000; /* dummy */
|
||||
rfconf.type = radio_type;
|
||||
rfconf.tx_enable = false;
|
||||
if (lgw_rxrf_setconf(1, &rfconf) != LGW_HAL_SUCCESS) {
|
||||
printf("ERROR: failed to configure rxrf 1\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
x = lgw_start();
|
||||
if (x != 0) {
|
||||
printf("ERROR: failed to start the gateway\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* get the concentrator EUI */
|
||||
x = lgw_get_eui(&eui);
|
||||
if (x != LGW_HAL_SUCCESS) {
|
||||
printf("ERROR: failed to get concentrator EUI\n");
|
||||
} else {
|
||||
printf("\nINFO: concentrator EUI: 0x%016llX\n\n", eui);
|
||||
}
|
||||
|
||||
/* Stop the gateway */
|
||||
x = lgw_stop();
|
||||
if (x != 0) {
|
||||
printf("ERROR: failed to stop the gateway\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* Board reset */
|
||||
if (system("./reset_lgw.sh stop") != 0) {
|
||||
printf("ERROR: failed to reset SX1302, check your reset_lgw.sh script\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
|
@ -0,0 +1,83 @@
|
|||
### get external defined data
|
||||
|
||||
include ../target.cfg
|
||||
|
||||
### User defined build options
|
||||
|
||||
ARCH ?=
|
||||
CROSS_COMPILE ?=
|
||||
BUILD_MODE := release
|
||||
OBJDIR = obj
|
||||
|
||||
### ----- AVOID MODIFICATIONS BELLOW ------ AVOID MODIFICATIONS BELLOW ----- ###
|
||||
|
||||
ifeq '$(BUILD_MODE)' 'alpha'
|
||||
$(warning /\/\/\/ Building in 'alpha' mode \/\/\/\)
|
||||
WARN_CFLAGS :=
|
||||
OPT_CFLAGS := -O0
|
||||
DEBUG_CFLAGS := -g
|
||||
LDFLAGS :=
|
||||
else ifeq '$(BUILD_MODE)' 'debug'
|
||||
$(warning /\/\/\/ Building in 'debug' mode \/\/\/\)
|
||||
WARN_CFLAGS := -Wall -Wextra
|
||||
OPT_CFLAGS := -O2
|
||||
DEBUG_CFLAGS := -g
|
||||
LDFLAGS :=
|
||||
else ifeq '$(BUILD_MODE)' 'release'
|
||||
$(warning /\/\/\/ Building in 'release' mode \/\/\/\)
|
||||
WARN_CFLAGS := -Wall -Wextra
|
||||
OPT_CFLAGS := -O2 -ffunction-sections -fdata-sections
|
||||
DEBUG_CFLAGS :=
|
||||
LDFLAGS := -Wl,--gc-sections
|
||||
else
|
||||
$(error BUILD_MODE must be set to either 'alpha', 'debug' or 'release')
|
||||
endif
|
||||
|
||||
### Application-specific variables
|
||||
APP_NAME := net_downlink
|
||||
APP_LIBS := -lparson -lbase64 -lpthread
|
||||
|
||||
### Environment constants
|
||||
LIB_PATH := ../libtools
|
||||
|
||||
### Expand build options
|
||||
CFLAGS := -std=c99 $(WARN_CFLAGS) $(OPT_CFLAGS) $(DEBUG_CFLAGS)
|
||||
CC := $(CROSS_COMPILE)gcc
|
||||
AR := $(CROSS_COMPILE)ar
|
||||
|
||||
### General build targets
|
||||
all: $(APP_NAME)
|
||||
|
||||
clean:
|
||||
rm -f obj/*.o
|
||||
rm -f $(APP_NAME)
|
||||
|
||||
install:
|
||||
ifneq ($(strip $(TARGET_IP)),)
|
||||
ifneq ($(strip $(TARGET_DIR)),)
|
||||
ifneq ($(strip $(TARGET_USR)),)
|
||||
@echo "---- Copying net_downlink files to $(TARGET_IP):$(TARGET_DIR)"
|
||||
@ssh $(TARGET_USR)@$(TARGET_IP) "mkdir -p $(TARGET_DIR)"
|
||||
@scp net_downlink $(TARGET_USR)@$(TARGET_IP):$(TARGET_DIR)
|
||||
else
|
||||
@echo "ERROR: TARGET_USR is not configured in target.cfg"
|
||||
endif
|
||||
else
|
||||
@echo "ERROR: TARGET_DIR is not configured in target.cfg"
|
||||
endif
|
||||
else
|
||||
@echo "ERROR: TARGET_IP is not configured in target.cfg"
|
||||
endif
|
||||
|
||||
$(OBJDIR):
|
||||
mkdir -p $(OBJDIR)
|
||||
|
||||
### Compile main program
|
||||
$(OBJDIR)/$(APP_NAME).o: src/$(APP_NAME).c | $(OBJDIR)
|
||||
$(CC) -c $< -o $@ $(CFLAGS) -Iinc -I../libtools/inc
|
||||
|
||||
### Link everything together
|
||||
$(APP_NAME): $(OBJDIR)/$(APP_NAME).o
|
||||
$(CC) -L$(LIB_PATH) $^ -o $@ $(LDFLAGS) $(APP_LIBS)
|
||||
|
||||
### EOF
|
|
@ -0,0 +1,62 @@
|
|||
______ _
|
||||
/ _____) _ | |
|
||||
( (____ _____ ____ _| |_ _____ ____| |__
|
||||
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
_____) ) ____| | | || |_| ____( (___| | | |
|
||||
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
(C)2019 Semtech
|
||||
|
||||
Utility: Downlink server
|
||||
========================
|
||||
|
||||
## 1. Introduction
|
||||
|
||||
This utility allows to send regular downlink requests to the packet forwarder
|
||||
running on the gateway.
|
||||
|
||||
The downlinks are sent in 'immediate' mode, meaning that the SX1302 will send
|
||||
the incoming packet over the air as soon as it receives it.
|
||||
|
||||
So, the net_downlink utility will construct a JSON 'txpk' object based on given
|
||||
command line arguments, and send it on a UDP socket on the given port. Then the
|
||||
packet forwarder receives it on its downlink socket, parses the JSON object to
|
||||
build the packet buffer to be sent to the concentrator board.
|
||||
|
||||
This utility can be compiled and run on the gateway itself, or on a PC.
|
||||
|
||||
Optionally, the net_downlink utility can forward the received uplinks
|
||||
(PUSH_DATA) to another UDP server, which can be useful for uplink Packet Error
|
||||
Rate measurement while performing downlink testing (full-duplex testing etc...)
|
||||
|
||||
In can also be used as a UDP packet logger, logging all uplinks in a CSV file.
|
||||
|
||||
## 2. Dependencies
|
||||
|
||||
A packet forwarder must be running to receive downlink packets and send it to
|
||||
the concentrator board.
|
||||
|
||||
## 3. Usage
|
||||
|
||||
### 3.1. Packet Forwarder configuration
|
||||
|
||||
The 'global_conf.json' file provided with the packet forwarder can be used, only
|
||||
the 'server_address' must be set to 'localhost' if net_downlink is running on
|
||||
the gateway itself, or set to the IP address of the PC on which the utility is
|
||||
running.
|
||||
|
||||
### 3.2. Launching the packet forwarder
|
||||
|
||||
The packet forwarder has to be launched with the global_conf.json described in
|
||||
3.1.
|
||||
|
||||
`./lora_pkt_fwd -c global_conf.json`
|
||||
|
||||
### 3.3. Launching net_downlink
|
||||
|
||||
The net_downlink utility can be started with various command line arguments.
|
||||
|
||||
In order to get the available options, and some examples, run:
|
||||
|
||||
`./net_downlink -h`
|
||||
|
||||
To stop the application, press Ctrl+C.
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue