diff options
| author | Sylvain Miermont <smiermont@semtech.com> | 2013-07-03 17:53:18 +0200 |
|---|---|---|
| committer | Sylvain Miermont <smiermont@semtech.com> | 2013-10-23 10:16:59 +0200 |
| commit | 1361e7215cd0eb3b38faff1c403cb3077e41b2be (patch) | |
| tree | c52471c65b0a40b081b7de6a8570757f85c71704 /loragw_hal/src | |
| parent | 3357493e096fc0bd4767d1a3cc0cb7e3e52a4f53 (diff) | |
| download | lora_gateway-1361e7215cd0eb3b38faff1c403cb3077e41b2be.tar.gz lora_gateway-1361e7215cd0eb3b38faff1c403cb3077e41b2be.tar.bz2 lora_gateway-1361e7215cd0eb3b38faff1c403cb3077e41b2be.zip | |
Release Candidate 2v0.rc2
- code cleanup and formating
- variable and constants renaming
- TX polarity management
- fixed bugs thanks to Joe Knapp feedback
Diffstat (limited to 'loragw_hal/src')
| -rw-r--r-- | loragw_hal/src/agc_fw.var | 6 | ||||
| -rw-r--r-- | loragw_hal/src/arb_fw.var | 6 | ||||
| -rw-r--r-- | loragw_hal/src/loragw_aux.c | 44 | ||||
| -rw-r--r-- | loragw_hal/src/loragw_hal.c | 1667 | ||||
| -rw-r--r-- | loragw_hal/src/loragw_reg.c | 1236 | ||||
| -rw-r--r-- | loragw_hal/src/loragw_spi.c | 448 |
6 files changed, 1709 insertions, 1698 deletions
diff --git a/loragw_hal/src/agc_fw.var b/loragw_hal/src/agc_fw.var index 350e56d..a0dde65 100644 --- a/loragw_hal/src/agc_fw.var +++ b/loragw_hal/src/agc_fw.var @@ -1,13 +1,13 @@ /* - / _____) _ | | -( (____ _____ ____ _| |_ _____ ____| |__ + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ \____ \| ___ | (_ _) ___ |/ ___) _ \ _____) ) ____| | | || |_| ____( (___| | | | (______/|_____)_|_|_| \__)_____)\____)_| |_| ©2013 Semtech-Cycleo Description: - AGC firmware + AGC firmware */ static uint8_t agc_firmware[MCU_AGC_FW_BYTE] = { diff --git a/loragw_hal/src/arb_fw.var b/loragw_hal/src/arb_fw.var index 2e41dcc..2cb66f5 100644 --- a/loragw_hal/src/arb_fw.var +++ b/loragw_hal/src/arb_fw.var @@ -1,13 +1,13 @@ /* - / _____) _ | | -( (____ _____ ____ _| |_ _____ ____| |__ + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ \____ \| ___ | (_ _) ___ |/ ___) _ \ _____) ) ____| | | || |_| ____( (___| | | | (______/|_____)_|_|_| \__)_____)\____)_| |_| ©2013 Semtech-Cycleo Description: - Arbiter firmware + Arbiter firmware */ static uint8_t arb_firmware[MCU_ARB_FW_BYTE] = { diff --git a/loragw_hal/src/loragw_aux.c b/loragw_hal/src/loragw_aux.c index 52df612..9adafe3 100644 --- a/loragw_hal/src/loragw_aux.c +++ b/loragw_hal/src/loragw_aux.c @@ -1,31 +1,31 @@ /* - / _____) _ | | -( (____ _____ ____ _| |_ _____ ____| |__ + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ \____ \| ___ | (_ _) ___ |/ ___) _ \ _____) ) ____| | | || |_| ____( (___| | | | (______/|_____)_|_|_| \__)_____)\____)_| |_| ©2013 Semtech-Cycleo Description: - Lora gateway auxiliary functions + Lora gateway auxiliary functions */ /* -------------------------------------------------------------------------- */ /* --- DEPENDANCIES --------------------------------------------------------- */ -#include <stdio.h> /* printf fprintf */ -#include <time.h> /* clock_nanosleep */ +#include <stdio.h> /* printf fprintf */ +#include <time.h> /* clock_nanosleep */ /* -------------------------------------------------------------------------- */ /* --- PRIVATE MACROS ------------------------------------------------------- */ #ifdef DEBUG - #define DEBUG_MSG(str) fprintf(stderr, str) - #define DEBUG_PRINTF(fmt, args...) fprintf(stderr,"%s:%d: "fmt, __FUNCTION__, __LINE__, args) + #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...) + #define DEBUG_MSG(str) + #define DEBUG_PRINTF(fmt, args...) #endif /* -------------------------------------------------------------------------- */ @@ -33,19 +33,19 @@ Description: /* 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; + struct timespec dly; + struct timespec rem; + + dly.tv_sec = a / 1000; + dly.tv_nsec = ((long)a % 1000) * 1000000; + + DEBUG_PRINTF("NOTE dly: %ld sec %ld ns\n", dly.tv_sec, dly.tv_nsec); + + if((dly.tv_sec > 0) || ((dly.tv_sec == 0) && (dly.tv_nsec > 100000))) { + clock_nanosleep(CLOCK_MONOTONIC, 0, &dly, &rem); + DEBUG_PRINTF("NOTE remain: %ld sec %ld ns\n", rem.tv_sec, rem.tv_nsec); + } + return; } /* --- EOF ------------------------------------------------------------------ */ diff --git a/loragw_hal/src/loragw_hal.c b/loragw_hal/src/loragw_hal.c index bdf563c..d597f5d 100644 --- a/loragw_hal/src/loragw_hal.c +++ b/loragw_hal/src/loragw_hal.c @@ -1,24 +1,25 @@ /* - / _____) _ | | -( (____ _____ ____ _| |_ _____ ____| |__ + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ \____ \| ___ | (_ _) ___ |/ ___) _ \ _____) ) ____| | | || |_| ____( (___| | | | (______/|_____)_|_|_| \__)_____)\____)_| |_| ©2013 Semtech-Cycleo Description: - Lora gateway Hardware Abstraction Layer + Lora gateway Hardware Abstraction Layer */ /* -------------------------------------------------------------------------- */ /* --- DEPENDANCIES --------------------------------------------------------- */ -#include <stdint.h> /* C99 types */ -#include <stdlib.h> /* malloc & free */ -#include <stdbool.h> /* bool type */ -#include <stdio.h> /* printf fprintf */ -#include <math.h> /* NaN */ +#include <stdint.h> /* C99 types */ +#include <stdlib.h> /* malloc & free */ +#include <stdbool.h> /* bool type */ +#include <stdio.h> /* printf fprintf */ +#include <math.h> /* NaN */ +#include <string.h> /* memcpy */ #include "loragw_reg.h" #include "loragw_hal.h" @@ -29,15 +30,15 @@ Description: #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) #ifdef DEBUG - #define DEBUG_MSG(str) fprintf(stderr, str) - #define DEBUG_PRINTF(fmt, args...) fprintf(stderr,"%s:%d: "fmt, __FUNCTION__, __LINE__, args) - #define DEBUG_ARRAY(a,b,c) for(a=0;a<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_HAL_ERROR;} + #define DEBUG_MSG(str) fprintf(stderr, str) + #define DEBUG_PRINTF(fmt, args...) fprintf(stderr,"%s:%d: "fmt, __FUNCTION__, __LINE__, args) + #define DEBUG_ARRAY(a,b,c) for(a=0;a<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_HAL_ERROR;} #else - #define DEBUG_MSG(str) - #define DEBUG_PRINTF(fmt, args...) - #define DEBUG_ARRAY(a,b,c) - #define CHECK_NULL(a) if(a==NULL){return LGW_HAL_ERROR;} + #define DEBUG_MSG(str) + #define DEBUG_PRINTF(fmt, args...) + #define DEBUG_ARRAY(a,b,c) + #define CHECK_NULL(a) if(a==NULL){return LGW_HAL_ERROR;} #endif #define IF_HZ_TO_REG(f) (f << 5)/15625 @@ -45,8 +46,8 @@ Description: /* -------------------------------------------------------------------------- */ /* --- PRIVATE CONSTANTS ---------------------------------------------------- */ -#define MCU_ARB 0 -#define MCU_AGC 1 +#define MCU_ARB 0 +#define MCU_AGC 1 const uint8_t ifmod_config[LGW_IF_CHAIN_NB] = LGW_IFMODEM_CONFIG; /* define hardware capability */ @@ -55,29 +56,30 @@ const uint32_t rf_rx_upfreq[LGW_RF_CHAIN_NB] = LGW_RF_RX_UPFREQ; const uint32_t rf_tx_lowfreq[LGW_RF_CHAIN_NB] = LGW_RF_TX_LOWFREQ; const uint32_t rf_tx_upfreq[LGW_RF_CHAIN_NB] = LGW_RF_TX_UPFREQ; -#define MCU_ARB_FW_BYTE 2048 /* size of the firmware IN BYTES (= twice the number of 14b words) */ -#define MCU_AGC_FW_BYTE 8192 /* size of the firmware IN BYTES (= twice the number of 14b words) */ +#define MCU_ARB_FW_BYTE 2048 /* size of the firmware IN BYTES (= twice the number of 14b words) */ +#define MCU_AGC_FW_BYTE 8192 /* size of the firmware IN BYTES (= twice the number of 14b words) */ -#define SX1257_CLK_OUT 1 -#define SX1257_TX_DAC_CLK_SEL 1 /* 0:int, 1:ext */ -#define SX1257_TX_DAC_GAIN 2 /* 3:0, 2:-3, 1:-6, 0:-9 dBFS (default 2) */ -#define SX1257_TX_MIX_GAIN 14 /* -38 + 2*TxMixGain dB (default 14) */ -#define SX1257_TX_PLL_BW 3 /* 0:75, 1:150, 2:225, 3:300 kHz (default 3) */ -#define SX1257_TX_ANA_BW 0 /* 17.5 / 2*(41-TxAnaBw) MHz (default 0) */ -#define SX1257_TX_DAC_BW 7 /* 24 + 8*TxDacBw Nb FIR taps (default 2) */ -#define SX1257_RX_LNA_GAIN 1 /* 1 to 6, 1 highest gain */ -#define SX1257_RX_BB_GAIN 12 /* 0 to 15 , 15 highest gain */ -#define SX1257_RX_ADC_BW 7 /* 0 to 7, 2:100<BW<200, 5:200<BW<400,7:400<BW (kHz) */ -#define SX1257_RX_ADC_TRIM 7 /* 0 to 7, 6 for 32MHz ref, 5 for 36MHz ref */ -#define SX1257_RXBB_BW 2 +#define SX1257_CLK_OUT 1 +#define SX1257_TX_DAC_CLK_SEL 1 /* 0:int, 1:ext */ +#define SX1257_TX_DAC_GAIN 2 /* 3:0, 2:-3, 1:-6, 0:-9 dBFS (default 2) */ +#define SX1257_TX_MIX_GAIN 14 /* -38 + 2*TxMixGain dB (default 14) */ +#define SX1257_TX_PLL_BW 3 /* 0:75, 1:150, 2:225, 3:300 kHz (default 3) */ +#define SX1257_TX_ANA_BW 0 /* 17.5 / 2*(41-TxAnaBw) MHz (default 0) */ +#define SX1257_TX_DAC_BW 7 /* 24 + 8*TxDacBw Nb FIR taps (default 2) */ +#define SX1257_RX_LNA_GAIN 1 /* 1 to 6, 1 highest gain */ +#define SX1257_RX_BB_GAIN 12 /* 0 to 15 , 15 highest gain */ +#define SX1257_RX_ADC_BW 7 /* 0 to 7, 2:100<BW<200, 5:200<BW<400,7:400<BW (kHz) */ +#define SX1257_RX_ADC_TRIM 7 /* 0 to 7, 6 for 32MHz ref, 5 for 36MHz ref */ +#define SX1257_RXBB_BW 2 -#define RSSI_OFFSET_LORA_MULTI -100.0 // TODO -#define RSSI_OFFSET_LORA_STD -100.0 // TODO +#define RSSI_OFFSET_LORA_MULTI -100.0 // TODO: need to find proper value with calibration +#define RSSI_OFFSET_LORA_STD -100.0 // TODO: need to find proper value with calibration -#define TX_METADATA_NB 16 -#define RX_METADATA_NB 16 +#define TX_METADATA_NB 16 +#define RX_METADATA_NB 16 -#define MIN_LORA_PREAMBLE 4 +#define MIN_LORA_PREAMBLE 4 +#define PLL_LOCK_MAX_ATTEMPTS 6 /* -------------------------------------------------------------------------- */ /* --- PRIVATE VARIABLES ---------------------------------------------------- */ @@ -120,7 +122,7 @@ void sx125x_write(uint8_t rf_chain, uint8_t addr, uint8_t data); uint8_t sx125x_read(uint8_t rf_chain, uint8_t addr); -void setup_sx1257(uint8_t rf_chain, uint32_t freq_hz); +int setup_sx1257(uint8_t rf_chain, uint32_t freq_hz); void lgw_constant_adjust(void); @@ -129,846 +131,855 @@ void lgw_constant_adjust(void); /* size is the firmware size in bytes (not 14b words) */ int load_firmware(uint8_t target, uint8_t *firmware, uint16_t size) { - int i; - int32_t read_value; - int reg_rst; - int reg_sel; - - /* check parameters */ - CHECK_NULL(firmware); - if (target == MCU_ARB) { - if (size != MCU_ARB_FW_BYTE) { - DEBUG_MSG("ERROR: NOT A VALID SIZE FOR MCU ARG FIRMWARE\n"); - return -1; - } - reg_rst = LGW_MCU_RST_0; - reg_sel = LGW_MCU_SELECT_MUX_0; - }else if (target == MCU_AGC) { - if (size != MCU_AGC_FW_BYTE) { - DEBUG_MSG("ERROR: NOT A VALID SIZE FOR MCU AGC FIRMWARE\n"); - return -1; - } - reg_rst = LGW_MCU_RST_1; - reg_sel = LGW_MCU_SELECT_MUX_1; - } else { - DEBUG_MSG("ERROR: NOT A VALID TARGET FOR LOADING FIRMWARE\n"); - return -1; - } - - /* reset the targeted MCU */ - lgw_reg_w(reg_rst, 1); - - /* set mux to access MCU program RAM and set address to 0 */ - lgw_reg_w(reg_sel, 0); - lgw_reg_w(LGW_MCU_PROM_ADDR, 0); - - /* write the program in one burst */ - lgw_reg_wb(LGW_MCU_PROM_DATA, firmware, size); - - /* give back control of the MCU program ram to the MCU */ - lgw_reg_w(reg_sel, 1); - - return 0; + int32_t read_value; + int reg_rst; + int reg_sel; + + /* check parameters */ + CHECK_NULL(firmware); + if (target == MCU_ARB) { + if (size != MCU_ARB_FW_BYTE) { + DEBUG_MSG("ERROR: NOT A VALID SIZE FOR MCU ARG FIRMWARE\n"); + return -1; + } + reg_rst = LGW_MCU_RST_0; + reg_sel = LGW_MCU_SELECT_MUX_0; + }else if (target == MCU_AGC) { + if (size != MCU_AGC_FW_BYTE) { + DEBUG_MSG("ERROR: NOT A VALID SIZE FOR MCU AGC FIRMWARE\n"); + return -1; + } + reg_rst = LGW_MCU_RST_1; + reg_sel = LGW_MCU_SELECT_MUX_1; + } else { + DEBUG_MSG("ERROR: NOT A VALID TARGET FOR LOADING FIRMWARE\n"); + return -1; + } + + /* reset the targeted MCU */ + lgw_reg_w(reg_rst, 1); + + /* set mux to access MCU program RAM and set address to 0 */ + lgw_reg_w(reg_sel, 0); + lgw_reg_w(LGW_MCU_PROM_ADDR, 0); + + /* write the program in one burst */ + lgw_reg_wb(LGW_MCU_PROM_DATA, firmware, size); + + /* give back control of the MCU program ram to the MCU */ + lgw_reg_w(reg_sel, 1); + + return 0; } /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ void sx125x_write(uint8_t channel, uint8_t addr, uint8_t data) { - int reg_add, reg_dat, reg_cs; - - /* checking input parameters */ - if (channel >= LGW_RF_CHAIN_NB) { - DEBUG_MSG("ERROR: INVALID RF_CHAIN\n"); - return; - } - if (addr >= 0x7F) { - DEBUG_MSG("ERROR: ADDRESS OUT OF RANGE\n"); - return; - } - - /* selecting the target radio */ - switch (channel) { - case 0: - reg_add = LGW_SPI_RADIO_A__ADDR; - reg_dat = LGW_SPI_RADIO_A__DATA; - reg_cs = LGW_SPI_RADIO_A__CS; - break; - - case 1: - reg_add = LGW_SPI_RADIO_B__ADDR; - reg_dat = LGW_SPI_RADIO_B__DATA; - reg_cs = LGW_SPI_RADIO_B__CS; - break; - - default: - DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", channel); - return; - } - - /* SPI master data write procedure */ - lgw_reg_w(reg_add, 0x80 | addr); /* MSB at 1 for write operation */ - lgw_reg_w(reg_dat, data); - lgw_reg_w(reg_cs, 1); - lgw_reg_w(reg_cs, 0); - - return; + int reg_add, reg_dat, reg_cs; + + /* checking input parameters */ + if (channel >= LGW_RF_CHAIN_NB) { + DEBUG_MSG("ERROR: INVALID RF_CHAIN\n"); + return; + } + if (addr >= 0x7F) { + DEBUG_MSG("ERROR: ADDRESS OUT OF RANGE\n"); + return; + } + + /* selecting the target radio */ + switch (channel) { + case 0: + reg_add = LGW_SPI_RADIO_A__ADDR; + reg_dat = LGW_SPI_RADIO_A__DATA; + reg_cs = LGW_SPI_RADIO_A__CS; + break; + + case 1: + reg_add = LGW_SPI_RADIO_B__ADDR; + reg_dat = LGW_SPI_RADIO_B__DATA; + reg_cs = LGW_SPI_RADIO_B__CS; + break; + + default: + DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", channel); + return; + } + + /* SPI master data write procedure */ + lgw_reg_w(reg_cs, 0); + lgw_reg_w(reg_add, 0x80 | addr); /* MSB at 1 for write operation */ + lgw_reg_w(reg_dat, data); + lgw_reg_w(reg_cs, 1); + lgw_reg_w(reg_cs, 0); + + return; } /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ uint8_t sx125x_read(uint8_t channel, uint8_t addr) { - int reg_add, reg_dat, reg_cs, reg_rb; - int32_t read_value; - - /* checking input parameters */ - if (channel >= LGW_RF_CHAIN_NB) { - DEBUG_MSG("ERROR: INVALID RF_CHAIN\n"); - return 0; - } - if (addr >= 0x7F) { - DEBUG_MSG("ERROR: ADDRESS OUT OF RANGE\n"); - return 0; - } - - /* selecting the target radio */ - switch (channel) { - case 0: - reg_add = LGW_SPI_RADIO_A__ADDR; - reg_dat = LGW_SPI_RADIO_A__DATA; - reg_cs = LGW_SPI_RADIO_A__CS; - reg_rb = LGW_SPI_RADIO_A__DATA_READBACK; - break; - - case 1: - reg_add = LGW_SPI_RADIO_B__ADDR; - reg_dat = LGW_SPI_RADIO_B__DATA; - reg_cs = LGW_SPI_RADIO_B__CS; - reg_rb = LGW_SPI_RADIO_B__DATA_READBACK; - break; - - default: - DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", channel); - return 0; - } - - /* SPI master data read procedure */ - lgw_reg_w(reg_add, addr); /* MSB at 0 for read operation */ - lgw_reg_w(reg_dat, 0); - lgw_reg_w(reg_cs, 1); - lgw_reg_w(reg_cs, 0); - lgw_reg_r(reg_rb, &read_value); - - return (uint8_t)read_value; + int reg_add, reg_dat, reg_cs, reg_rb; + int32_t read_value; + + /* checking input parameters */ + if (channel >= LGW_RF_CHAIN_NB) { + DEBUG_MSG("ERROR: INVALID RF_CHAIN\n"); + return 0; + } + if (addr >= 0x7F) { + DEBUG_MSG("ERROR: ADDRESS OUT OF RANGE\n"); + return 0; + } + + /* selecting the target radio */ + switch (channel) { + case 0: + reg_add = LGW_SPI_RADIO_A__ADDR; + reg_dat = LGW_SPI_RADIO_A__DATA; + reg_cs = LGW_SPI_RADIO_A__CS; + reg_rb = LGW_SPI_RADIO_A__DATA_READBACK; + break; + + case 1: + reg_add = LGW_SPI_RADIO_B__ADDR; + reg_dat = LGW_SPI_RADIO_B__DATA; + reg_cs = LGW_SPI_RADIO_B__CS; + reg_rb = LGW_SPI_RADIO_B__DATA_READBACK; + break; + + default: + DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", channel); + return 0; + } + + /* SPI master data read procedure */ + lgw_reg_w(reg_cs, 0); + lgw_reg_w(reg_add, addr); /* MSB at 0 for read operation */ + lgw_reg_w(reg_dat, 0); + lgw_reg_w(reg_cs, 1); + lgw_reg_w(reg_cs, 0); + lgw_reg_r(reg_rb, &read_value); + + return (uint8_t)read_value; } /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -void setup_sx1257(uint8_t rf_chain, uint32_t freq_hz) { - uint32_t part_int; - uint32_t part_frac; - int i = 0; - - if (rf_chain >= LGW_RF_CHAIN_NB) { - DEBUG_MSG("ERROR: INVALID RF_CHAIN\n"); - return; - } - - /* misc */ - sx125x_write(rf_chain, 0x10, SX1257_TX_DAC_CLK_SEL + SX1257_CLK_OUT*2); - - /* Tx gain and trim */ - sx125x_write(rf_chain, 0x08, SX1257_TX_MIX_GAIN + SX1257_TX_DAC_GAIN*16); - sx125x_write(rf_chain, 0x0A, SX1257_TX_ANA_BW + SX1257_TX_PLL_BW*32); - sx125x_write(rf_chain, 0x0B, SX1257_TX_DAC_BW); - - /* Rx gain and trim */ - sx125x_write(rf_chain, 0x0C, 0 + SX1257_RX_BB_GAIN*2 + SX1257_RX_LNA_GAIN*32); - sx125x_write(rf_chain, 0x0D, SX1257_RXBB_BW + SX1257_RX_ADC_TRIM*4 + SX1257_RX_ADC_BW*32); - - /* set RX PLL frequency */ - part_int = freq_hz / LGW_SW1257_DENUM; /* integer part, gives the MSB and the middle byte */ - part_frac = ((freq_hz % LGW_SW1257_DENUM) << 8) / LGW_SW1257_DENUM; /* fractional part, gives LSB */ - sx125x_write(rf_chain, 0x01,0xFF & (part_int >> 8)); /* Most Significant Byte */ - sx125x_write(rf_chain, 0x02,0xFF & part_int); /* middle byte */ - sx125x_write(rf_chain, 0x03,0xFF & part_frac); /* Least Significant Byte */ - - /* start and PLL lock */ - do { - sx125x_write(rf_chain, 0x00, 1); /* enable Xtal oscillator */ - sx125x_write(rf_chain, 0x00, 3); /* Enable RX (PLL+FE) */ - ++i; - DEBUG_PRINTF("Note: SX1257 #%d PLL start (attempt %d)\n", rf_chain, i); - wait_ms(1); - } while(sx125x_read(rf_chain, 0x11) & 0x02 == 0); - - return; +int setup_sx1257(uint8_t rf_chain, uint32_t freq_hz) { + uint32_t part_int; + uint32_t part_frac; + int i = 0; + + if (rf_chain >= LGW_RF_CHAIN_NB) { + DEBUG_MSG("ERROR: INVALID RF_CHAIN\n"); + return -1; + } + + /* misc */ + sx125x_write(rf_chain, 0x10, SX1257_TX_DAC_CLK_SEL + SX1257_CLK_OUT*2); + + /* Tx gain and trim */ + sx125x_write(rf_chain, 0x08, SX1257_TX_MIX_GAIN + SX1257_TX_DAC_GAIN*16); + sx125x_write(rf_chain, 0x0A, SX1257_TX_ANA_BW + SX1257_TX_PLL_BW*32); + sx125x_write(rf_chain, 0x0B, SX1257_TX_DAC_BW); + + /* Rx gain and trim */ + sx125x_write(rf_chain, 0x0C, 0 + SX1257_RX_BB_GAIN*2 + SX1257_RX_LNA_GAIN*32); + sx125x_write(rf_chain, 0x0D, SX1257_RXBB_BW + SX1257_RX_ADC_TRIM*4 + SX1257_RX_ADC_BW*32); + + /* set RX PLL frequency */ + part_int = freq_hz / LGW_SX1257_DENOMINATOR; /* integer part, gives the MSB and the middle byte */ + part_frac = ((freq_hz % LGW_SX1257_DENOMINATOR) << 8) / LGW_SX1257_DENOMINATOR; /* fractional part, gives LSB */ + sx125x_write(rf_chain, 0x01,0xFF & (part_int >> 8)); /* Most Significant Byte */ + sx125x_write(rf_chain, 0x02,0xFF & part_int); /* middle byte */ + sx125x_write(rf_chain, 0x03,0xFF & part_frac); /* Least Significant Byte */ + + /* start and PLL lock */ + do { + if (i >= PLL_LOCK_MAX_ATTEMPTS) { + DEBUG_MSG("ERROR: FAIL TO LOCK PLL\n"); + return -1; + } + sx125x_write(rf_chain, 0x00, 1); /* enable Xtal oscillator */ + sx125x_write(rf_chain, 0x00, 3); /* Enable RX (PLL+FE) */ + ++i; + DEBUG_PRINTF("Note: SX1257 #%d PLL start (attempt %d)\n", rf_chain, i); + wait_ms(1); + } while(sx125x_read(rf_chain, 0x11) & 0x02 == 0); + + return 0; } /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ void lgw_constant_adjust(void) { - - /* I/Q path setup */ - // lgw_reg_w(LGW_RX_INVERT_IQ,0); /* default 0 */ - // lgw_reg_w(LGW_MODEM_INVERT_IQ,1); /* default 1 */ - // lgw_reg_w(LGW_CHIRP_INVERT_RX,1); /* default 1 */ - // lgw_reg_w(LGW_RX_EDGE_SELECT,0); /* default 0 */ - // lgw_reg_w(LGW_MBWSSF_MODEM_INVERT_IQ,0); /* default 0 */ - lgw_reg_w(LGW_DC_NOTCH_EN,1); /* default 0 */ - // lgw_reg_w(LGW_RSSI_BB_FILTER_ALPHA,7); /* default 7 */ - lgw_reg_w(LGW_RSSI_DEC_FILTER_ALPHA,7); /* default 5 */ - lgw_reg_w(LGW_RSSI_CHANN_FILTER_ALPHA,7); /* default 8 */ - // lgw_reg_w(LGW_RSSI_BB_DEFAULT_VALUE,32); /* default 32 */ - lgw_reg_w(LGW_RSSI_CHANN_DEFAULT_VALUE,90); /* default 100 */ - lgw_reg_w(LGW_RSSI_DEC_DEFAULT_VALUE,90); /* default 100 */ - - /* Correlator setup */ - // lgw_reg_w(LGW_CORR_DETECT_EN,126); /* default 126 */ - // lgw_reg_w(LGW_CORR_NUM_SAME_PEAK,4); /* default 4 */ - // lgw_reg_w(LGW_CORR_MAC_GAIN,5); /* default 5 */ - // lgw_reg_w(LGW_CORR_SAME_PEAKS_OPTION_SF6,0); /* default 0 */ - // lgw_reg_w(LGW_CORR_SAME_PEAKS_OPTION_SF7,1); /* default 1 */ - // lgw_reg_w(LGW_CORR_SAME_PEAKS_OPTION_SF8,1); /* default 1 */ - // lgw_reg_w(LGW_CORR_SAME_PEAKS_OPTION_SF9,1); /* default 1 */ - // lgw_reg_w(LGW_CORR_SAME_PEAKS_OPTION_SF10,1); /* default 1 */ - // lgw_reg_w(LGW_CORR_SAME_PEAKS_OPTION_SF11,1); /* default 1 */ - // lgw_reg_w(LGW_CORR_SAME_PEAKS_OPTION_SF12,1); /* default 1 */ - // lgw_reg_w(LGW_CORR_SIG_NOISE_RATIO_SF6,4); /* default 4 */ - // lgw_reg_w(LGW_CORR_SIG_NOISE_RATIO_SF7,4); /* default 4 */ - // lgw_reg_w(LGW_CORR_SIG_NOISE_RATIO_SF8,4); /* default 4 */ - // lgw_reg_w(LGW_CORR_SIG_NOISE_RATIO_SF9,4); /* default 4 */ - // lgw_reg_w(LGW_CORR_SIG_NOISE_RATIO_SF10,4); /* default 4 */ - // lgw_reg_w(LGW_CORR_SIG_NOISE_RATIO_SF11,4); /* default 4 */ - // lgw_reg_w(LGW_CORR_SIG_NOISE_RATIO_SF12,4); /* default 4 */ - - /* Lora 'multi' modems setup */ - lgw_reg_w(LGW_PREAMBLE_SYMB1_NB,4); /* default 10 */ - // lgw_reg_w(LGW_FREQ_TO_TIME_DRIFT,9); /* default 9 */ - // lgw_reg_w(LGW_FREQ_TO_TIME_INVERT,29); /* default 29 */ - // lgw_reg_w(LGW_FRAME_SYNCH_GAIN,1); /* default 1 */ - // lgw_reg_w(LGW_SYNCH_DETECT_TH,1); /* default 1 */ - // lgw_reg_w(LGW_ZERO_PAD,0); /* default 0 */ - lgw_reg_w(LGW_SNR_AVG_CST,3); /* default 2 */ - // lgw_reg_w(LGW_PPM_OFFSET,0); /* default 0 */ - // lgw_reg_w(LGW_FRAME_SYNCH_PEAK1_POS,1); /* default 1 */ - // lgw_reg_w(LGW_FRAME_SYNCH_PEAK2_POS,2); /* default 2 */ - // lgw_reg_w(LGW_PREAMBLE_FINE_TIMING_GAIN,1); /* default 1 */ - // lgw_reg_w(LGW_ONLY_CRC_EN,1); /* default 1 */ - // lgw_reg_w(LGW_PAYLOAD_FINE_TIMING_GAIN,2); /* default 2 */ - // lgw_reg_w(LGW_TRACKING_INTEGRAL,0); /* default 0 */ - // lgw_reg_w(LGW_ADJUST_MODEM_START_OFFSET_RDX8,0); /* default 0 */ - // lgw_reg_w(LGW_ADJUST_MODEM_START_OFFSET_RDX4,0); /* default 0 */ - // lgw_reg_w(LGW_ADJUST_MODEM_START_OFFSET_SF12_RDX4,4092); /* default 4092 */ - // lgw_reg_w(LGW_MAX_PAYLOAD_LEN,255); /* default 255 */ - - /* MBWSSF Modem */ - // lgw_reg_w(LGW_MBWSSF_MODEM_ENABLE,1); /* default 0 */ - // lgw_reg_w(LGW_MBWSSF_PREAMBLE_SYMB1_NB,10); /* default 10 */ - // lgw_reg_w(LGW_MBWSSF_FREQ_TO_TIME_DRIFT,36); /* default 36 */ - // lgw_reg_w(LGW_MBWSSF_FREQ_TO_TIME_INVERT,29); /* default 29 */ - // lgw_reg_w(LGW_MBWSSF_FRAME_SYNCH_GAIN,1); /* default 1 */ - // lgw_reg_w(LGW_MBWSSF_SYNCH_DETECT_TH,1); /* default 1 */ - // lgw_reg_w(LGW_MBWSSF_ZERO_PAD,0); /* default 0 */ - // lgw_reg_w(LGW_MBWSSF_PPM_OFFSET,0); /* default 0 */ - // lgw_reg_w(LGW_MBWSSF_FRAME_SYNCH_PEAK1_POS,1); /* default 1 */ - // lgw_reg_w(LGW_MBWSSF_FRAME_SYNCH_PEAK2_POS,2); /* default 2 */ - // lgw_reg_w(LGW_MBWSSF_ONLY_CRC_EN,1); /* default 1 */ - // lgw_reg_w(LGW_MBWSSF_PAYLOAD_FINE_TIMING_GAIN,2); /* default 2 */ - // lgw_reg_w(LGW_MBWSSF_PREAMBLE_FINE_TIMING_GAIN,1); /* default 1 */ - // lgw_reg_w(LGW_MBWSSF_TRACKING_INTEGRAL,0); /* default 0 */ - // lgw_reg_w(LGW_MBWSSF_AGC_FREEZE_ON_DETECT,1); /* default 1 */ - - /* TX */ - // lgw_reg_w(LGW_TX_MODE,0); /* default 0 */ - lgw_reg_w(LGW_TX_START_DELAY,5000); /* default 0 */ - - return; + + /* I/Q path setup */ + // lgw_reg_w(LGW_RX_INVERT_IQ,0); /* default 0 */ + // lgw_reg_w(LGW_MODEM_INVERT_IQ,1); /* default 1 */ + // lgw_reg_w(LGW_CHIRP_INVERT_RX,1); /* default 1 */ + // lgw_reg_w(LGW_RX_EDGE_SELECT,0); /* default 0 */ + // lgw_reg_w(LGW_MBWSSF_MODEM_INVERT_IQ,0); /* default 0 */ + lgw_reg_w(LGW_DC_NOTCH_EN,1); /* default 0 */ + // lgw_reg_w(LGW_RSSI_BB_FILTER_ALPHA,7); /* default 7 */ + lgw_reg_w(LGW_RSSI_DEC_FILTER_ALPHA,7); /* default 5 */ + lgw_reg_w(LGW_RSSI_CHANN_FILTER_ALPHA,7); /* default 8 */ + // lgw_reg_w(LGW_RSSI_BB_DEFAULT_VALUE,32); /* default 32 */ + lgw_reg_w(LGW_RSSI_CHANN_DEFAULT_VALUE,90); /* default 100 */ + lgw_reg_w(LGW_RSSI_DEC_DEFAULT_VALUE,90); /* default 100 */ + + /* Correlator setup */ + // lgw_reg_w(LGW_CORR_DETECT_EN,126); /* default 126 */ + // lgw_reg_w(LGW_CORR_NUM_SAME_PEAK,4); /* default 4 */ + // lgw_reg_w(LGW_CORR_MAC_GAIN,5); /* default 5 */ + // lgw_reg_w(LGW_CORR_SAME_PEAKS_OPTION_SF6,0); /* default 0 */ + // lgw_reg_w(LGW_CORR_SAME_PEAKS_OPTION_SF7,1); /* default 1 */ + // lgw_reg_w(LGW_CORR_SAME_PEAKS_OPTION_SF8,1); /* default 1 */ + // lgw_reg_w(LGW_CORR_SAME_PEAKS_OPTION_SF9,1); /* default 1 */ + // lgw_reg_w(LGW_CORR_SAME_PEAKS_OPTION_SF10,1); /* default 1 */ + // lgw_reg_w(LGW_CORR_SAME_PEAKS_OPTION_SF11,1); /* default 1 */ + // lgw_reg_w(LGW_CORR_SAME_PEAKS_OPTION_SF12,1); /* default 1 */ + // lgw_reg_w(LGW_CORR_SIG_NOISE_RATIO_SF6,4); /* default 4 */ + // lgw_reg_w(LGW_CORR_SIG_NOISE_RATIO_SF7,4); /* default 4 */ + // lgw_reg_w(LGW_CORR_SIG_NOISE_RATIO_SF8,4); /* default 4 */ + // lgw_reg_w(LGW_CORR_SIG_NOISE_RATIO_SF9,4); /* default 4 */ + // lgw_reg_w(LGW_CORR_SIG_NOISE_RATIO_SF10,4); /* default 4 */ + // lgw_reg_w(LGW_CORR_SIG_NOISE_RATIO_SF11,4); /* default 4 */ + // lgw_reg_w(LGW_CORR_SIG_NOISE_RATIO_SF12,4); /* default 4 */ + + /* Lora 'multi' modems setup */ + lgw_reg_w(LGW_PREAMBLE_SYMB1_NB,4); /* default 10 */ + // lgw_reg_w(LGW_FREQ_TO_TIME_DRIFT,9); /* default 9 */ + // lgw_reg_w(LGW_FREQ_TO_TIME_INVERT,29); /* default 29 */ + // lgw_reg_w(LGW_FRAME_SYNCH_GAIN,1); /* default 1 */ + // lgw_reg_w(LGW_SYNCH_DETECT_TH,1); /* default 1 */ + // lgw_reg_w(LGW_ZERO_PAD,0); /* default 0 */ + lgw_reg_w(LGW_SNR_AVG_CST,3); /* default 2 */ + // lgw_reg_w(LGW_PPM_OFFSET,0); /* default 0 */ + // lgw_reg_w(LGW_FRAME_SYNCH_PEAK1_POS,1); /* default 1 */ + // lgw_reg_w(LGW_FRAME_SYNCH_PEAK2_POS,2); /* default 2 */ + // lgw_reg_w(LGW_PREAMBLE_FINE_TIMING_GAIN,1); /* default 1 */ + // lgw_reg_w(LGW_ONLY_CRC_EN,1); /* default 1 */ + // lgw_reg_w(LGW_PAYLOAD_FINE_TIMING_GAIN,2); /* default 2 */ + // lgw_reg_w(LGW_TRACKING_INTEGRAL,0); /* default 0 */ + // lgw_reg_w(LGW_ADJUST_MODEM_START_OFFSET_RDX8,0); /* default 0 */ + // lgw_reg_w(LGW_ADJUST_MODEM_START_OFFSET_RDX4,0); /* default 0 */ + // lgw_reg_w(LGW_ADJUST_MODEM_START_OFFSET_SF12_RDX4,4092); /* default 4092 */ + // lgw_reg_w(LGW_MAX_PAYLOAD_LEN,255); /* default 255 */ + + /* MBWSSF Modem */ + // lgw_reg_w(LGW_MBWSSF_MODEM_ENABLE,1); /* default 0 */ + // lgw_reg_w(LGW_MBWSSF_PREAMBLE_SYMB1_NB,10); /* default 10 */ + // lgw_reg_w(LGW_MBWSSF_FREQ_TO_TIME_DRIFT,36); /* default 36 */ + // lgw_reg_w(LGW_MBWSSF_FREQ_TO_TIME_INVERT,29); /* default 29 */ + // lgw_reg_w(LGW_MBWSSF_FRAME_SYNCH_GAIN,1); /* default 1 */ + // lgw_reg_w(LGW_MBWSSF_SYNCH_DETECT_TH,1); /* default 1 */ + // lgw_reg_w(LGW_MBWSSF_ZERO_PAD,0); /* default 0 */ + // lgw_reg_w(LGW_MBWSSF_PPM_OFFSET,0); /* default 0 */ + // lgw_reg_w(LGW_MBWSSF_FRAME_SYNCH_PEAK1_POS,1); /* default 1 */ + // lgw_reg_w(LGW_MBWSSF_FRAME_SYNCH_PEAK2_POS,2); /* default 2 */ + // lgw_reg_w(LGW_MBWSSF_ONLY_CRC_EN,1); /* default 1 */ + // lgw_reg_w(LGW_MBWSSF_PAYLOAD_FINE_TIMING_GAIN,2); /* default 2 */ + // lgw_reg_w(LGW_MBWSSF_PREAMBLE_FINE_TIMING_GAIN,1); /* default 1 */ + // lgw_reg_w(LGW_MBWSSF_TRACKING_INTEGRAL,0); /* default 0 */ + // lgw_reg_w(LGW_MBWSSF_AGC_FREEZE_ON_DETECT,1); /* default 1 */ + + /* TX */ + // lgw_reg_w(LGW_TX_MODE,0); /* default 0 */ + lgw_reg_w(LGW_TX_START_DELAY,5000); /* default 0 */ + lgw_reg_w(LGW_TX_SWAP_IQ,1); /* "normal" polarity; default 0 */ + + return; } /* -------------------------------------------------------------------------- */ /* --- PUBLIC FUNCTIONS DEFINITION ------------------------------------------ */ int lgw_rxrf_setconf(uint8_t rf_chain, struct lgw_conf_rxrf_s conf) { - - /* check if the gateway is running */ - if (lgw_is_started == true) { - DEBUG_MSG("ERROR: GATEWAY IS RUNNING, STOP IT BEFORE TOUCHING CONFIGURATION\n"); - return LGW_HAL_ERROR; - } - - /* check input parameters */ - if (rf_chain > LGW_RF_CHAIN_NB) { - DEBUG_MSG("ERROR: NOT A VALID RF_CHAIN NUMBER\n"); - return LGW_HAL_ERROR; - } - if (conf.freq_hz > rf_rx_upfreq[rf_chain]) { - DEBUG_MSG("ERROR: FREQUENCY TOO HIGH FOR THAT RF_CHAIN\n"); - return LGW_HAL_ERROR; - } else if (conf.freq_hz < rf_rx_lowfreq[rf_chain]) { - DEBUG_MSG("ERROR: FREQUENCY TOO LOW FOR THAT RF_CHAIN\n"); - return LGW_HAL_ERROR; - } - - /* set internal config according to parameters */ - rf_enable[rf_chain] = conf.enable; - rf_rx_freq[rf_chain] = conf.freq_hz; - - return LGW_HAL_SUCCESS; + + /* check if the gateway is running */ + if (lgw_is_started == true) { + DEBUG_MSG("ERROR: GATEWAY IS RUNNING, STOP IT BEFORE TOUCHING CONFIGURATION\n"); + return LGW_HAL_ERROR; + } + + /* check input parameters */ + if (rf_chain > LGW_RF_CHAIN_NB) { + DEBUG_MSG("ERROR: NOT A VALID RF_CHAIN NUMBER\n"); + return LGW_HAL_ERROR; + } + if (conf.freq_hz > rf_rx_upfreq[rf_chain]) { + DEBUG_MSG("ERROR: FREQUENCY TOO HIGH FOR THAT RF_CHAIN\n"); + return LGW_HAL_ERROR; + } else if (conf.freq_hz < rf_rx_lowfreq[rf_chain]) { + DEBUG_MSG("ERROR: FREQUENCY TOO LOW FOR THAT RF_CHAIN\n"); + return LGW_HAL_ERROR; + } + + /* set internal config according to parameters */ + rf_enable[rf_chain] = conf.enable; + rf_rx_freq[rf_chain] = conf.freq_hz; + + return LGW_HAL_SUCCESS; } /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ int lgw_rxif_setconf(uint8_t if_chain, struct lgw_conf_rxif_s conf) { - int i, j; /* tmp variables, to shorten long 'if' lines */ - - /* check if the gateway is running */ - if (lgw_is_started == true) { - DEBUG_MSG("ERROR: GATEWAY IS RUNNING, STOP IT BEFORE TOUCHING CONFIGURATION\n"); - return LGW_HAL_ERROR; - } - - /* if chain is disabled, don't care about most parameters */ - if (conf.enable == false) { - if_enable[if_chain] = false; - if_freq[if_chain] = 0; - DEBUG_PRINTF("Note: if_chain %d disabled\n", if_chain); - return LGW_HAL_SUCCESS; - } - - /* check 'general' parameters */ - /* ? add checks to stay in band (ie. radio_freq+if+BW/2 < fmax) ? */ - if (if_chain > LGW_IF_CHAIN_NB) { - DEBUG_PRINTF("ERROR: %d NOT A VALID IF_CHAIN NUMBER\n", if_chain); - return LGW_HAL_ERROR; - } - if (ifmod_config[if_chain] == IF_UNDEFINED) { - DEBUG_PRINTF("ERROR: IF CHAIN %d NOT CONFIGURABLE\n", if_chain); - } - if (conf.freq_hz > LGW_RF_BANDWIDTH/2) { - DEBUG_PRINTF("ERROR: IF FREQUENCY %d TOO HIGH\n", conf.freq_hz); - return LGW_HAL_ERROR; - } else if (conf.freq_hz < -LGW_RF_BANDWIDTH/2) { - DEBUG_PRINTF("ERROR: IF FREQUENCY %d TOO LOW\n", conf.freq_hz); - return LGW_HAL_ERROR; - } - - /* check parameters according to the type of IF chain + modem, - fill default if necessary, and commit configuration if everything is OK */ - switch (ifmod_config[if_chain]) { - case IF_LORA_STD: - if (conf.rf_chain != 0) { - DEBUG_MSG("ERROR: LORA_STD IF CHAIN CAN ONLY BE ASSOCIATED TO RF_CHAIN 0\n"); - return LGW_HAL_ERROR; - } - /* fill default parameters if needed */ - i = (conf.bandwidth == 0) ? BW_250KHZ : conf.bandwidth; - j = (conf.datarate == 0) ? DR_LORA_SF9 : conf.datarate; - /* check BW & DR */ - if ((i != BW_125KHZ) && (i != BW_250KHZ) && (i != BW_500KHZ)) { - DEBUG_MSG("ERROR: BANDWIDTH NOT SUPPORTED BY LORA_STD IF CHAIN\n"); - return LGW_HAL_ERROR; - } - if ((j!=DR_LORA_SF7)&&(j!=DR_LORA_SF8)&&(j!=DR_LORA_SF9)&&(j!=DR_LORA_SF10)&&(j!=DR_LORA_SF11)&&(j!=DR_LORA_SF12)) { - DEBUG_MSG("ERROR: DATARATE NOT SUPPORTED BY LORA_STD IF CHAIN\n"); - return LGW_HAL_ERROR; - } - /* set internal configuration */ - if_enable[if_chain] = conf.enable; - if_freq[if_chain] = conf.freq_hz; - lora_rx_bw = i; - lora_rx_sf = j; - DEBUG_PRINTF("Note: Lora 'std' if_chain %d configured; en:%d freq:%d bw:%d dr:%d\n", if_chain, if_enable[if_chain], if_freq[if_chain], lora_rx_bw, lora_rx_sf); - break; - - case IF_LORA_MULTI: - if (conf.rf_chain >= LGW_RF_CHAIN_NB) { - DEBUG_MSG("ERROR: INVALID RF_CHAIN TO ASSOCIATE WITH A LORA_STD IF CHAIN\n"); - return LGW_HAL_ERROR; - } - /* fill default parameters if needed */ - i = (conf.bandwidth == 0) ? BW_125KHZ : conf.bandwidth; - j = (conf.datarate == 0) ? DR_LORA_MULTI : conf.datarate; - /* check BW & DR */ - if (i != BW_125KHZ) { - DEBUG_MSG("ERROR: BANDWIDTH NOT SUPPORTED BY LORA_MULTI IF CHAIN\n"); - return LGW_HAL_ERROR; - } - if ((j & DR_LORA_MULTI) == 0) { /* supports any combination of SF between 7 and 12 */ - DEBUG_MSG("ERROR: DATARATE(S) NOT SUPPORTED BY LORA_MULTI IF CHAIN\n"); - return LGW_HAL_ERROR; - } - /* set internal configuration */ - if_enable[if_chain] = conf.enable; - switch (conf.rf_chain) { - case 0: if_rf_switch &= ~((uint8_t)1 << if_chain); break; /* force a 0 at the if_chain-th position */ - case 1: if_rf_switch |= ((uint8_t)1 << if_chain); break; /* force a 1 at the if_chain-th position */ - default: DEBUG_MSG("ERROR: IMPROPRER IF_CHAIN/RF_CHAIN ASSOCIATION\n"); - } - if_freq[if_chain] = |
