Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
loragw_hal.cpp
00001 /* 00002 / _____) _ | | 00003 ( (____ _____ ____ _| |_ _____ ____| |__ 00004 \____ \| ___ | (_ _) ___ |/ ___) _ \ 00005 _____) ) ____| | | || |_| ____( (___| | | | 00006 (______/|_____)_|_|_| \__)_____)\____)_| |_| 00007 (C)2017 Semtech-Cycleo 00008 00009 Description: 00010 LoRa concentrator Hardware Abstraction Layer 00011 00012 License: Revised BSD License, see LICENSE.TXT file include in the project 00013 */ 00014 00015 00016 /* -------------------------------------------------------------------------- */ 00017 /* --- DEPENDANCIES --------------------------------------------------------- */ 00018 00019 #include <stdint.h> /* C99 types */ 00020 #include <stdbool.h> /* bool type */ 00021 #include <stdio.h> /* printf fprintf */ 00022 #include <string.h> /* memcpy */ 00023 #include <math.h> /* pow, cell */ 00024 #include "loragw_reg.h" 00025 #include "loragw_hal.h" 00026 #include "loragw_radio.h" 00027 #include "board.h" 00028 00029 /* -------------------------------------------------------------------------- */ 00030 /* --- PRIVATE MACROS ------------------------------------------------------- */ 00031 00032 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) 00033 #if DEBUG_HAL == 1 00034 #define DEBUG_MSG(str) pc.printf(str) 00035 #define DEBUG_PRINTF(fmt, args...) pc.printf("%s:%d: "fmt, __FUNCTION__, __LINE__, args) 00036 #define DEBUG_ARRAY(a,b,c) for(a=0;a!=0;){} 00037 #define CHECK_NULL(a) if(a==NULL){return LGW_HAL_ERROR;} 00038 #else 00039 #define DEBUG_MSG(str) 00040 #define DEBUG_PRINTF(fmt, args...) 00041 #define DEBUG_ARRAY(a,b,c) for(a=0;a!=0;){} 00042 #define CHECK_NULL(a) if(a==NULL){return LGW_HAL_ERROR;} 00043 #endif 00044 #define IF_HZ_TO_REG(f) (f << 5)/15625 00045 #define SET_PPM_ON(bw,dr) (((bw == BW_125KHZ) && ((dr == DR_LORA_SF11) || (dr == DR_LORA_SF12))) || ((bw == BW_250KHZ) && (dr == DR_LORA_SF12))) 00046 #define TRACE() 00047 00048 /* -------------------------------------------------------------------------- */ 00049 /* --- PRIVATE CONSTANTS & TYPES -------------------------------------------- */ 00050 00051 #define MCU_ARB 0 00052 #define MCU_AGC 1 00053 #define MCU_ARB_FW_BYTE 8192 /* size of the firmware IN BYTES (= twice the number of 14b words) */ 00054 #define MCU_AGC_FW_BYTE 8192 /* size of the firmware IN BYTES (= twice the number of 14b words) */ 00055 #define FW_VERSION_ADDR 0x20 /* Address of firmware version in data memory */ 00056 #define FW_VERSION_CAL 2 /* Expected version of calibration firmware */ 00057 #define FW_VERSION_AGC 4 /* Expected version of AGC firmware */ 00058 #define FW_VERSION_ARB 1 /* Expected version of arbiter firmware */ 00059 #define TX_METADATA_NB 16 00060 #define RX_METADATA_NB 16 00061 #define AGC_CMD_WAIT 16 00062 #define AGC_CMD_ABORT 17 00063 #define MIN_LORA_PREAMBLE 4 00064 #define STD_LORA_PREAMBLE 6 00065 #define MIN_FSK_PREAMBLE 3 00066 #define STD_FSK_PREAMBLE 5 00067 #define TX_START_DELAY 1500 00068 #define RSSI_MULTI_BIAS -35 /* difference between "multi" modem RSSI offset and "stand-alone" modem RSSI offset */ 00069 #define RSSI_FSK_POLY_0 60 /* polynomiam coefficients to linearize FSK RSSI */ 00070 #define RSSI_FSK_POLY_1 1.5351 00071 #define RSSI_FSK_POLY_2 0.003 00072 #define LGW_RF_RX_BANDWIDTH_125KHZ 925000 /* for 125KHz channels */ 00073 #define LGW_RF_RX_BANDWIDTH_250KHZ 1000000 /* for 250KHz channels */ 00074 #define LGW_RF_RX_BANDWIDTH_500KHZ 1100000 /* for 500KHz channels */ 00075 /* constant arrays defining hardware capability */ 00076 const uint8_t ifmod_config[LGW_IF_CHAIN_NB] = LGW_IFMODEM_CONFIG; 00077 00078 00079 /* Version string, used to identify the library version/options once compiled */ 00080 const char lgw_version_string[] = "Version: 0.1";// LIBLORAGW_VERSION ";"; 00081 00082 /* -------------------------------------------------------------------------- */ 00083 /* --- PRIVATE VARIABLES ---------------------------------------------------- */ 00084 00085 static int32_t iqrxtab[4]; 00086 00087 /* 00088 The following static variables are the configuration set that the user can 00089 modify using rxrf_setconf, rxif_setconf and txgain_setconf functions. 00090 The functions _start and _send then use that set to configure the hardware. 00091 00092 Parameters validity and coherency is verified by the _setconf functions and 00093 the _start and _send functions assume they are valid. 00094 */ 00095 00096 static bool rf_enable[LGW_RF_CHAIN_NB]; 00097 static uint32_t rf_rx_freq[LGW_RF_CHAIN_NB]; /* absolute, in Hz */ 00098 static float rf_rssi_offset[LGW_RF_CHAIN_NB]; 00099 static bool rf_tx_enable[LGW_RF_CHAIN_NB]; 00100 static enum lgw_radio_type_e rf_radio_type[LGW_RF_CHAIN_NB]; 00101 static bool if_enable[LGW_IF_CHAIN_NB]; 00102 static bool if_rf_chain[LGW_IF_CHAIN_NB]; /* for each IF, 0 -> radio A, 1 -> radio B */ 00103 static int32_t if_freq[LGW_IF_CHAIN_NB]; /* relative to radio frequency, +/- in Hz */ 00104 static uint8_t lora_multi_sfmask[LGW_MULTI_NB]; /* enables SF for LoRa 'multi' modems */ 00105 static uint8_t lora_rx_bw; /* bandwidth setting for LoRa standalone modem */ 00106 static uint8_t lora_rx_sf; /* spreading factor setting for LoRa standalone modem */ 00107 static bool lora_rx_ppm_offset; 00108 static uint8_t fsk_rx_bw; /* bandwidth setting of FSK modem */ 00109 static uint32_t fsk_rx_dr; /* FSK modem datarate in bauds */ 00110 static uint8_t fsk_sync_word_size = 3; /* default number of bytes for FSK sync word */ 00111 static uint64_t fsk_sync_word = 0xC194C1; /* default FSK sync word (ALIGNED RIGHT, MSbit first) */ 00112 static bool lorawan_public = true; 00113 00114 static struct lgw_tx_gain_lut_s txgain_lut = { 00115 .size = 2, 00116 .lut[0] = { 00117 .dig_gain = 0, 00118 .pa_gain = 2, 00119 .dac_gain = 3, 00120 .mix_gain = 10, 00121 .rf_power = 14 00122 }, 00123 .lut[1] = { 00124 .dig_gain = 0, 00125 .pa_gain = 3, 00126 .dac_gain = 3, 00127 .mix_gain = 14, 00128 .rf_power = 27 00129 } 00130 }; 00131 00132 /* TX I/Q imbalance coefficients for mixer gain = 8 to 15 */ 00133 static int8_t cal_offset_a_i[16]; /* TX I offset for radio A */ 00134 static int8_t cal_offset_a_q[16]; /* TX Q offset for radio A */ 00135 static int8_t cal_offset_b_i[16]; /* TX I offset for radio B */ 00136 static int8_t cal_offset_b_q[16]; /* TX Q offset for radio B */ 00137 00138 /* -------------------------------------------------------------------------- */ 00139 /* --- PRIVATE FUNCTIONS DECLARATION ---------------------------------------- */ 00140 00141 void lgw_constant_adjust(void); 00142 int32_t lgw_sf_getval(int x); 00143 int32_t lgw_bw_getval(int x); 00144 int reset_firmware(uint8_t target); 00145 void calibration_save(void); 00146 void calibration_reload(void); 00147 00148 /* -------------------------------------------------------------------------- */ 00149 /* --- PRIVATE FUNCTIONS DEFINITION ----------------------------------------- */ 00150 00151 int reset_firmware(uint8_t target) { 00152 int reg_rst; 00153 int reg_sel; 00154 00155 /* check parameters */ 00156 if (target == MCU_ARB) { 00157 reg_rst = LGW_MCU_RST_0; 00158 reg_sel = LGW_MCU_SELECT_MUX_0; 00159 } else if (target == MCU_AGC) { 00160 reg_rst = LGW_MCU_RST_1; 00161 reg_sel = LGW_MCU_SELECT_MUX_1; 00162 } else { 00163 DEBUG_MSG("ERROR: NOT A VALID TARGET FOR RESETTING FIRMWARE\n"); 00164 return -1; 00165 } 00166 00167 /* reset the targeted MCU */ 00168 lgw_reg_w(reg_rst, 1); 00169 00170 /* set mux to access MCU program RAM and set address to 0 */ 00171 lgw_reg_w(reg_sel, 0); 00172 lgw_reg_w(LGW_MCU_PROM_ADDR, 0); 00173 00174 /* give back control of the MCU program ram to the MCU */ 00175 lgw_reg_w(reg_sel, 1); 00176 00177 return 0; 00178 } 00179 00180 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 00181 00182 void lgw_constant_adjust(void) { 00183 00184 /* I/Q path setup */ 00185 // lgw_reg_w(LGW_RX_INVERT_IQ,0); /* default 0 */ 00186 // lgw_reg_w(LGW_MODEM_INVERT_IQ,1); /* default 1 */ 00187 // lgw_reg_w(LGW_CHIRP_INVERT_RX,1); /* default 1 */ 00188 // lgw_reg_w(LGW_RX_EDGE_SELECT,0); /* default 0 */ 00189 // lgw_reg_w(LGW_MBWSSF_MODEM_INVERT_IQ,0); /* default 0 */ 00190 // lgw_reg_w(LGW_DC_NOTCH_EN,1); /* default 1 */ 00191 lgw_reg_w(LGW_RSSI_BB_FILTER_ALPHA, 6); /* default 7 */ 00192 lgw_reg_w(LGW_RSSI_DEC_FILTER_ALPHA, 7); /* default 5 */ 00193 lgw_reg_w(LGW_RSSI_CHANN_FILTER_ALPHA, 7); /* default 8 */ 00194 lgw_reg_w(LGW_RSSI_BB_DEFAULT_VALUE, 23); /* default 32 */ 00195 lgw_reg_w(LGW_RSSI_CHANN_DEFAULT_VALUE, 85); /* default 100 */ 00196 lgw_reg_w(LGW_RSSI_DEC_DEFAULT_VALUE, 66); /* default 100 */ 00197 lgw_reg_w(LGW_DEC_GAIN_OFFSET, 7); /* default 8 */ 00198 lgw_reg_w(LGW_CHAN_GAIN_OFFSET, 6); /* default 7 */ 00199 00200 /* Correlator setup */ 00201 // lgw_reg_w(LGW_CORR_DETECT_EN,126); /* default 126 */ 00202 // lgw_reg_w(LGW_CORR_NUM_SAME_PEAK,4); /* default 4 */ 00203 // lgw_reg_w(LGW_CORR_MAC_GAIN,5); /* default 5 */ 00204 // lgw_reg_w(LGW_CORR_SAME_PEAKS_OPTION_SF6,0); /* default 0 */ 00205 // lgw_reg_w(LGW_CORR_SAME_PEAKS_OPTION_SF7,1); /* default 1 */ 00206 // lgw_reg_w(LGW_CORR_SAME_PEAKS_OPTION_SF8,1); /* default 1 */ 00207 // lgw_reg_w(LGW_CORR_SAME_PEAKS_OPTION_SF9,1); /* default 1 */ 00208 // lgw_reg_w(LGW_CORR_SAME_PEAKS_OPTION_SF10,1); /* default 1 */ 00209 // lgw_reg_w(LGW_CORR_SAME_PEAKS_OPTION_SF11,1); /* default 1 */ 00210 // lgw_reg_w(LGW_CORR_SAME_PEAKS_OPTION_SF12,1); /* default 1 */ 00211 // lgw_reg_w(LGW_CORR_SIG_NOISE_RATIO_SF6,4); /* default 4 */ 00212 // lgw_reg_w(LGW_CORR_SIG_NOISE_RATIO_SF7,4); /* default 4 */ 00213 // lgw_reg_w(LGW_CORR_SIG_NOISE_RATIO_SF8,4); /* default 4 */ 00214 // lgw_reg_w(LGW_CORR_SIG_NOISE_RATIO_SF9,4); /* default 4 */ 00215 // lgw_reg_w(LGW_CORR_SIG_NOISE_RATIO_SF10,4); /* default 4 */ 00216 // lgw_reg_w(LGW_CORR_SIG_NOISE_RATIO_SF11,4); /* default 4 */ 00217 // lgw_reg_w(LGW_CORR_SIG_NOISE_RATIO_SF12,4); /* default 4 */ 00218 00219 /* LoRa 'multi' demodulators setup */ 00220 // lgw_reg_w(LGW_PREAMBLE_SYMB1_NB,10); /* default 10 */ 00221 // lgw_reg_w(LGW_FREQ_TO_TIME_INVERT,29); /* default 29 */ 00222 // lgw_reg_w(LGW_FRAME_SYNCH_GAIN,1); /* default 1 */ 00223 // lgw_reg_w(LGW_SYNCH_DETECT_TH,1); /* default 1 */ 00224 // lgw_reg_w(LGW_ZERO_PAD,0); /* default 0 */ 00225 lgw_reg_w(LGW_SNR_AVG_CST, 3); /* default 2 */ 00226 if (lorawan_public) { /* LoRa network */ 00227 lgw_reg_w(LGW_FRAME_SYNCH_PEAK1_POS, 3); /* default 1 */ 00228 lgw_reg_w(LGW_FRAME_SYNCH_PEAK2_POS, 4); /* default 2 */ 00229 } else { /* private network */ 00230 lgw_reg_w(LGW_FRAME_SYNCH_PEAK1_POS, 1); /* default 1 */ 00231 lgw_reg_w(LGW_FRAME_SYNCH_PEAK2_POS, 2); /* default 2 */ 00232 } 00233 00234 // lgw_reg_w(LGW_PREAMBLE_FINE_TIMING_GAIN,1); /* default 1 */ 00235 // lgw_reg_w(LGW_ONLY_CRC_EN,1); /* default 1 */ 00236 // lgw_reg_w(LGW_PAYLOAD_FINE_TIMING_GAIN,2); /* default 2 */ 00237 // lgw_reg_w(LGW_TRACKING_INTEGRAL,0); /* default 0 */ 00238 // lgw_reg_w(LGW_ADJUST_MODEM_START_OFFSET_RDX8,0); /* default 0 */ 00239 // lgw_reg_w(LGW_ADJUST_MODEM_START_OFFSET_SF12_RDX4,4092); /* default 4092 */ 00240 // lgw_reg_w(LGW_MAX_PAYLOAD_LEN,255); /* default 255 */ 00241 00242 /* LoRa standalone 'MBWSSF' demodulator setup */ 00243 // lgw_reg_w(LGW_MBWSSF_PREAMBLE_SYMB1_NB,10); /* default 10 */ 00244 // lgw_reg_w(LGW_MBWSSF_FREQ_TO_TIME_INVERT,29); /* default 29 */ 00245 // lgw_reg_w(LGW_MBWSSF_FRAME_SYNCH_GAIN,1); /* default 1 */ 00246 // lgw_reg_w(LGW_MBWSSF_SYNCH_DETECT_TH,1); /* default 1 */ 00247 // lgw_reg_w(LGW_MBWSSF_ZERO_PAD,0); /* default 0 */ 00248 if (lorawan_public) { /* LoRa network */ 00249 lgw_reg_w(LGW_MBWSSF_FRAME_SYNCH_PEAK1_POS, 3); /* default 1 */ 00250 lgw_reg_w(LGW_MBWSSF_FRAME_SYNCH_PEAK2_POS, 4); /* default 2 */ 00251 } else { 00252 lgw_reg_w(LGW_MBWSSF_FRAME_SYNCH_PEAK1_POS, 1); /* default 1 */ 00253 lgw_reg_w(LGW_MBWSSF_FRAME_SYNCH_PEAK2_POS, 2); /* default 2 */ 00254 } 00255 // lgw_reg_w(LGW_MBWSSF_ONLY_CRC_EN,1); /* default 1 */ 00256 // lgw_reg_w(LGW_MBWSSF_PAYLOAD_FINE_TIMING_GAIN,2); /* default 2 */ 00257 // lgw_reg_w(LGW_MBWSSF_PREAMBLE_FINE_TIMING_GAIN,1); /* default 1 */ 00258 // lgw_reg_w(LGW_MBWSSF_TRACKING_INTEGRAL,0); /* default 0 */ 00259 // lgw_reg_w(LGW_MBWSSF_AGC_FREEZE_ON_DETECT,1); /* default 1 */ 00260 lgw_reg_w(LGW_ADJUST_MODEM_START_OFFSET_RDX4, 1); /* default 0 */ 00261 lgw_reg_w(LGW_ADJUST_MODEM_START_OFFSET_SF12_RDX4, 4094); /* default 4092 */ 00262 lgw_reg_w(LGW_CORR_MAC_GAIN, 7); /* default 5 */ 00263 00264 00265 00266 /* FSK datapath setup */ 00267 lgw_reg_w(LGW_FSK_RX_INVERT, 1); /* default 0 */ 00268 lgw_reg_w(LGW_FSK_MODEM_INVERT_IQ, 1); /* default 0 */ 00269 00270 /* FSK demodulator setup */ 00271 lgw_reg_w(LGW_FSK_RSSI_LENGTH, 4); /* default 0 */ 00272 lgw_reg_w(LGW_FSK_PKT_MODE, 1); /* variable length, default 0 */ 00273 lgw_reg_w(LGW_FSK_CRC_EN, 1); /* default 0 */ 00274 lgw_reg_w(LGW_FSK_DCFREE_ENC, 2); /* default 0 */ 00275 // lgw_reg_w(LGW_FSK_CRC_IBM,0); /* default 0 */ 00276 lgw_reg_w(LGW_FSK_ERROR_OSR_TOL, 10); /* default 0 */ 00277 lgw_reg_w(LGW_FSK_PKT_LENGTH, 255); /* max packet length in variable length mode */ 00278 // lgw_reg_w(LGW_FSK_NODE_ADRS,0); /* default 0 */ 00279 // lgw_reg_w(LGW_FSK_BROADCAST,0); /* default 0 */ 00280 // lgw_reg_w(LGW_FSK_AUTO_AFC_ON,0); /* default 0 */ 00281 lgw_reg_w(LGW_FSK_PATTERN_TIMEOUT_CFG, 128); /* sync timeout (allow 8 bytes preamble + 8 bytes sync word, default 0 */ 00282 00283 /* TX general parameters */ 00284 lgw_reg_w(LGW_TX_START_DELAY, TX_START_DELAY); /* default 0 */ 00285 00286 /* TX LoRa */ 00287 // lgw_reg_w(LGW_TX_MODE,0); /* default 0 */ 00288 lgw_reg_w(LGW_TX_SWAP_IQ, 1); /* "normal" polarity; default 0 */ 00289 if (lorawan_public) { /* LoRa network */ 00290 lgw_reg_w(LGW_TX_FRAME_SYNCH_PEAK1_POS, 3); /* default 1 */ 00291 lgw_reg_w(LGW_TX_FRAME_SYNCH_PEAK2_POS, 4); /* default 2 */ 00292 } else { /* Private network */ 00293 lgw_reg_w(LGW_TX_FRAME_SYNCH_PEAK1_POS, 1); /* default 1 */ 00294 lgw_reg_w(LGW_TX_FRAME_SYNCH_PEAK2_POS, 2); /* default 2 */ 00295 } 00296 00297 /* TX FSK */ 00298 // lgw_reg_w(LGW_FSK_TX_GAUSSIAN_EN,1); /* default 1 */ 00299 lgw_reg_w(LGW_FSK_TX_GAUSSIAN_SELECT_BT, 2); /* Gaussian filter always on TX, default 0 */ 00300 // lgw_reg_w(LGW_FSK_TX_PATTERN_EN,1); /* default 1 */ 00301 // lgw_reg_w(LGW_FSK_TX_PREAMBLE_SEQ,0); /* default 0 */ 00302 00303 return; 00304 } 00305 00306 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 00307 00308 int32_t lgw_bw_getval(int x) { 00309 switch (x) { 00310 case BW_500KHZ: 00311 return 500000; 00312 case BW_250KHZ: 00313 return 250000; 00314 case BW_125KHZ: 00315 return 125000; 00316 case BW_62K5HZ: 00317 return 62500; 00318 case BW_31K2HZ: 00319 return 31200; 00320 case BW_15K6HZ: 00321 return 15600; 00322 case BW_7K8HZ: 00323 return 7800; 00324 default: 00325 return -1; 00326 } 00327 } 00328 00329 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 00330 00331 int32_t lgw_sf_getval(int x) { 00332 switch (x) { 00333 case DR_LORA_SF7: 00334 return 7; 00335 case DR_LORA_SF8: 00336 return 8; 00337 case DR_LORA_SF9: 00338 return 9; 00339 case DR_LORA_SF10: 00340 return 10; 00341 case DR_LORA_SF11: 00342 return 11; 00343 case DR_LORA_SF12: 00344 return 12; 00345 default: 00346 return -1; 00347 } 00348 } 00349 00350 /* -------------------------------------------------------------------------- */ 00351 /* --- PUBLIC FUNCTIONS DEFINITION ------------------------------------------ */ 00352 00353 int lgw_board_setconf(struct lgw_conf_board_s conf) { 00354 00355 /* set internal config according to parameters */ 00356 lorawan_public = conf.lorawan_public; 00357 00358 DEBUG_PRINTF("Note: board configuration; lorawan_public:%d\n", lorawan_public); 00359 00360 return LGW_HAL_SUCCESS; 00361 } 00362 00363 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 00364 00365 int lgw_rxrf_setconf(uint8_t rf_chain, struct lgw_conf_rxrf_s conf) { 00366 00367 /* check input range (segfault prevention) */ 00368 if (rf_chain >= LGW_RF_CHAIN_NB) { 00369 DEBUG_MSG("ERROR: NOT A VALID RF_CHAIN NUMBER\n"); 00370 return LGW_HAL_ERROR; 00371 } 00372 00373 /* check if radio type is supported */ 00374 if ((conf.type != LGW_RADIO_TYPE_SX1255) && (conf.type != LGW_RADIO_TYPE_SX1257)) { 00375 DEBUG_MSG("ERROR: NOT A VALID RADIO TYPE\n"); 00376 return LGW_HAL_ERROR; 00377 } 00378 00379 /* set internal config according to parameters */ 00380 rf_enable[rf_chain] = conf.enable; 00381 rf_rx_freq[rf_chain] = conf.freq_hz ; 00382 rf_rssi_offset[rf_chain] = conf.rssi_offset ; 00383 rf_radio_type[rf_chain] = conf.type ; 00384 rf_tx_enable[rf_chain] = conf.tx_enable ; 00385 00386 DEBUG_PRINTF("Note: rf_chain %d configuration; en:%d freq:%d rssi_offset:%f radio_type:%d tx_enable:%d tx_notch_freq:%u\n", rf_chain, rf_enable[rf_chain], rf_rx_freq[rf_chain], rf_rssi_offset[rf_chain], rf_radio_type[rf_chain], rf_tx_enable[rf_chain]); 00387 00388 return LGW_HAL_SUCCESS; 00389 } 00390 00391 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 00392 00393 int lgw_rxif_setconf(uint8_t if_chain, struct lgw_conf_rxif_s conf) { 00394 int32_t bw_hz; 00395 uint32_t rf_rx_bandwidth; 00396 00397 /* check input range (segfault prevention) */ 00398 if (if_chain >= LGW_IF_CHAIN_NB) { 00399 DEBUG_PRINTF("ERROR: %d NOT A VALID IF_CHAIN NUMBER\n", if_chain); 00400 return LGW_HAL_ERROR; 00401 } 00402 00403 /* if chain is disabled, don't care about most parameters */ 00404 if (conf.enable == false) { 00405 if_enable[if_chain] = false; 00406 if_freq[if_chain] = 0; 00407 DEBUG_PRINTF("Note: if_chain %d disabled\n", if_chain); 00408 return LGW_HAL_SUCCESS; 00409 } 00410 00411 /* check 'general' parameters */ 00412 if (ifmod_config[if_chain] == IF_UNDEFINED) { 00413 DEBUG_PRINTF("ERROR: IF CHAIN %d NOT CONFIGURABLE\n", if_chain); 00414 } 00415 if (conf.rf_chain >= LGW_RF_CHAIN_NB) { 00416 DEBUG_MSG("ERROR: INVALID RF_CHAIN TO ASSOCIATE WITH A LORA_STD IF CHAIN\n"); 00417 return LGW_HAL_ERROR; 00418 } 00419 00420 switch (conf.bandwidth ) { 00421 case BW_250KHZ: 00422 rf_rx_bandwidth = LGW_RF_RX_BANDWIDTH_250KHZ; 00423 break; 00424 case BW_500KHZ: 00425 rf_rx_bandwidth = LGW_RF_RX_BANDWIDTH_500KHZ; 00426 break; 00427 default: 00428 rf_rx_bandwidth = LGW_RF_RX_BANDWIDTH_125KHZ; 00429 break; 00430 } 00431 00432 bw_hz = lgw_bw_getval(conf.bandwidth ); 00433 if ((conf.freq_hz + ((bw_hz == -1) ? LGW_REF_BW : bw_hz) / 2) > ((int32_t)rf_rx_bandwidth / 2)) { 00434 DEBUG_PRINTF("ERROR: IF FREQUENCY %d TOO HIGH\n", conf.freq_hz ); 00435 return LGW_HAL_ERROR; 00436 } else if ((conf.freq_hz - ((bw_hz == -1) ? LGW_REF_BW : bw_hz) / 2) < -((int32_t)rf_rx_bandwidth / 2)) { 00437 DEBUG_PRINTF("ERROR: IF FREQUENCY %d TOO LOW\n", conf.freq_hz ); 00438 return LGW_HAL_ERROR; 00439 } 00440 00441 /* check parameters according to the type of IF chain + modem, 00442 fill default if necessary, and commit configuration if everything is OK */ 00443 switch (ifmod_config[if_chain]) { 00444 case IF_LORA_STD: 00445 /* fill default parameters if needed */ 00446 if (conf.bandwidth == BW_UNDEFINED) { 00447 conf.bandwidth = BW_250KHZ; 00448 } 00449 if (conf.datarate == DR_UNDEFINED) { 00450 conf.datarate = DR_LORA_SF9; 00451 } 00452 /* check BW & DR */ 00453 if (!IS_LORA_BW(conf.bandwidth )) { 00454 DEBUG_MSG("ERROR: BANDWIDTH NOT SUPPORTED BY LORA_STD IF CHAIN\n"); 00455 return LGW_HAL_ERROR; 00456 } 00457 if (!IS_LORA_STD_DR(conf.datarate )) { 00458 DEBUG_MSG("ERROR: DATARATE NOT SUPPORTED BY LORA_STD IF CHAIN\n"); 00459 return LGW_HAL_ERROR; 00460 } 00461 /* set internal configuration */ 00462 if_enable[if_chain] = conf.enable; 00463 if_rf_chain[if_chain] = conf.rf_chain ; 00464 if_freq[if_chain] = conf.freq_hz ; 00465 lora_rx_bw = conf.bandwidth ; 00466 lora_rx_sf = (uint8_t)(DR_LORA_MULTI & conf.datarate ); /* filter SF out of the 7-12 range */ 00467 if (SET_PPM_ON(conf.bandwidth , conf.datarate )) { 00468 lora_rx_ppm_offset = true; 00469 } else { 00470 lora_rx_ppm_offset = false; 00471 } 00472 00473 DEBUG_PRINTF("Note: LoRa 'std' if_chain %d configuration; 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); 00474 break; 00475 00476 case IF_LORA_MULTI: 00477 /* fill default parameters if needed */ 00478 if (conf.bandwidth == BW_UNDEFINED) { 00479 conf.bandwidth = BW_125KHZ; 00480 } 00481 if (conf.datarate == DR_UNDEFINED) { 00482 conf.datarate = DR_LORA_MULTI; 00483 } 00484 /* check BW & DR */ 00485 if (conf.bandwidth != BW_125KHZ) { 00486 DEBUG_MSG("ERROR: BANDWIDTH NOT SUPPORTED BY LORA_MULTI IF CHAIN\n"); 00487 return LGW_HAL_ERROR; 00488 } 00489 if (!IS_LORA_MULTI_DR(conf.datarate )) { 00490 DEBUG_MSG("ERROR: DATARATE(S) NOT SUPPORTED BY LORA_MULTI IF CHAIN\n"); 00491 return LGW_HAL_ERROR; 00492 } 00493 /* set internal configuration */ 00494 if_enable[if_chain] = conf.enable; 00495 if_rf_chain[if_chain] = conf.rf_chain ; 00496 if_freq[if_chain] = conf.freq_hz ; 00497 lora_multi_sfmask[if_chain] = (uint8_t)(DR_LORA_MULTI & conf.datarate ); /* filter SF out of the 7-12 range */ 00498 00499 DEBUG_PRINTF("Note: LoRa 'multi' if_chain %d configuration; en:%d freq:%d SF_mask:0x%02x\n", if_chain, if_enable[if_chain], if_freq[if_chain], lora_multi_sfmask[if_chain]); 00500 break; 00501 00502 case IF_FSK_STD: 00503 /* fill default parameters if needed */ 00504 if (conf.bandwidth == BW_UNDEFINED) { 00505 conf.bandwidth = BW_250KHZ; 00506 } 00507 if (conf.datarate == DR_UNDEFINED) { 00508 conf.datarate = 64000; /* default datarate */ 00509 } 00510 /* check BW & DR */ 00511 if (!IS_FSK_BW(conf.bandwidth )) { 00512 DEBUG_MSG("ERROR: BANDWIDTH NOT SUPPORTED BY FSK IF CHAIN\n"); 00513 return LGW_HAL_ERROR; 00514 } 00515 if (!IS_FSK_DR(conf.datarate )) { 00516 DEBUG_MSG("ERROR: DATARATE NOT SUPPORTED BY FSK IF CHAIN\n"); 00517 return LGW_HAL_ERROR; 00518 } 00519 /* set internal configuration */ 00520 if_enable[if_chain] = conf.enable; 00521 if_rf_chain[if_chain] = conf.rf_chain ; 00522 if_freq[if_chain] = conf.freq_hz ; 00523 fsk_rx_bw = conf.bandwidth ; 00524 fsk_rx_dr = conf.datarate ; 00525 if (conf.sync_word > 0) { 00526 fsk_sync_word_size = conf.sync_word_size ; 00527 fsk_sync_word = conf.sync_word ; 00528 } 00529 DEBUG_PRINTF("Note: FSK if_chain %d configuration; en:%d freq:%d bw:%d dr:%d (%d real dr) sync:0x%0*llX\n", if_chain, if_enable[if_chain], if_freq[if_chain], fsk_rx_bw, fsk_rx_dr, LGW_XTAL_FREQU / (LGW_XTAL_FREQU / fsk_rx_dr), 2 * fsk_sync_word_size, fsk_sync_word); 00530 break; 00531 00532 default: 00533 DEBUG_PRINTF("ERROR: IF CHAIN %d TYPE NOT SUPPORTED\n", if_chain); 00534 return LGW_HAL_ERROR; 00535 } 00536 00537 return LGW_HAL_SUCCESS; 00538 } 00539 00540 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 00541 00542 int lgw_txgain_setconf(struct lgw_tx_gain_lut_s *conf) { 00543 int i; 00544 00545 /* Check LUT size */ 00546 if ((conf->size < 1) || (conf->size > TX_GAIN_LUT_SIZE_MAX)) { 00547 DEBUG_PRINTF("ERROR: TX gain LUT must have at least one entry and maximum %d entries\n", TX_GAIN_LUT_SIZE_MAX); 00548 return LGW_HAL_ERROR; 00549 } 00550 00551 txgain_lut.size = conf->size ; 00552 00553 for (i = 0; i < txgain_lut.size ; i++) { 00554 /* Check gain range */ 00555 if (conf->lut[i].dig_gain > 3) { 00556 DEBUG_MSG("ERROR: TX gain LUT: SX1308 digital gain must be between 0 and 3\n"); 00557 return LGW_HAL_ERROR; 00558 } 00559 if (conf->lut[i].dac_gain != 3) { 00560 DEBUG_MSG("ERROR: TX gain LUT: SX1257 DAC gains != 3 are not supported\n"); 00561 return LGW_HAL_ERROR; 00562 } 00563 if (conf->lut[i].mix_gain > 15) { 00564 DEBUG_MSG("WARNING: TX gain LUT: SX1257 mixer gain must not exceed 15\n"); 00565 return LGW_HAL_ERROR; 00566 } 00567 if (conf->lut[i].pa_gain > 3) { 00568 DEBUG_MSG("ERROR: TX gain LUT: External PA gain must not exceed 3\n"); 00569 return LGW_HAL_ERROR; 00570 } 00571 00572 /* Set internal LUT */ 00573 txgain_lut.lut[i].dig_gain = conf->lut[i].dig_gain; 00574 txgain_lut.lut[i].dac_gain = conf->lut[i].dac_gain ; 00575 txgain_lut.lut[i].mix_gain = conf->lut[i].mix_gain ; 00576 txgain_lut.lut[i].pa_gain = conf->lut[i].pa_gain ; 00577 txgain_lut.lut[i].rf_power = conf->lut[i].rf_power ; 00578 } 00579 00580 return LGW_HAL_SUCCESS; 00581 } 00582 00583 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 00584 00585 int lgw_start(void) { 00586 int i; 00587 uint32_t x; 00588 uint8_t radio_select; 00589 int32_t read_val; 00590 uint8_t load_val; 00591 uint8_t fw_version; 00592 uint64_t fsk_sync_word_reg; 00593 int DELAYSTART = 1; 00594 00595 /* Enable clocks */ 00596 lgw_reg_w(LGW_GLOBAL_EN, 1); 00597 lgw_reg_w(LGW_CLK32M_EN, 1); 00598 00599 /* Compute counter offset to be applied to SX1308 internal counter on receive and send */ 00600 Sx1308.offtmstpstm32 = Sx1308.timerstm32ref.read_us() - Sx1308.offtmstpstm32ref; 00601 00602 /* Set all GPIOs as output RXON/TXON*/ 00603 lgw_reg_w(LGW_GPIO_MODE, 31); 00604 lgw_reg_w(LGW_GPIO_SELECT_OUTPUT, 0); 00605 00606 /* select calibration command */ 00607 calibration_reload(); 00608 00609 /* load adjusted parameters */ 00610 lgw_constant_adjust(); 00611 00612 /* Sanity check for RX frequency */ 00613 if (rf_rx_freq[0] == 0) { 00614 DEBUG_MSG("ERROR: wrong configuration, rf_rx_freq[0] is not set\n"); 00615 return LGW_HAL_ERROR; 00616 } 00617 00618 /* Freq-to-time-drift calculation */ 00619 //float ftemp=(409600 / (rf_rx_freq[0] >> 1))*10000; 00620 float ftemp = (4096 * 2) / (rf_rx_freq[0] / 1000000); 00621 x = (uint32_t)ftemp; /* dividend: (4*2048*1000000) >> 1, rescaled to avoid 32b overflow */ 00622 x = (x > 63) ? 63 : x; /* saturation */ 00623 lgw_reg_w(LGW_FREQ_TO_TIME_DRIFT, x); /* default 9 */ 00624 00625 //ftemp=(409600 / (rf_rx_freq[0] >> 3))*10000; /* dividend: (16*2048*1000000) >> 3, rescaled to avoid 32b overflow */ 00626 ftemp = (4096 * 8) / (rf_rx_freq[0] / 1000000); 00627 x = (uint32_t)ftemp; 00628 x = (x > 63) ? 63 : x; /* saturation */ 00629 lgw_reg_w(LGW_MBWSSF_FREQ_TO_TIME_DRIFT, x); /* default 36 */ 00630 00631 /* configure LoRa 'multi' demodulators aka. LoRa 'sensor' channels (IF0-3) */ 00632 radio_select = 0; /* IF mapping to radio A/B (per bit, 0=A, 1=B) */ 00633 for (i = 0; i < LGW_MULTI_NB; ++i) { 00634 radio_select += (if_rf_chain[i] == 1 ? 1 << i : 0); /* transform bool array into binary word */ 00635 } 00636 /* 00637 lgw_reg_w(LGW_RADIO_SELECT, radio_select); 00638 LGW_RADIO_SELECT is used for communication with the firmware, "radio_select" 00639 will be loaded in LGW_RADIO_SELECT at the end of start procedure. 00640 */ 00641 00642 lgw_reg_w(LGW_IF_FREQ_0, IF_HZ_TO_REG(if_freq[0])); /* default -384 */ 00643 lgw_reg_w(LGW_IF_FREQ_1, IF_HZ_TO_REG(if_freq[1])); /* default -128 */ 00644 lgw_reg_w(LGW_IF_FREQ_2, IF_HZ_TO_REG(if_freq[2])); /* default 128 */ 00645 lgw_reg_w(LGW_IF_FREQ_3, IF_HZ_TO_REG(if_freq[3])); /* default 384 */ 00646 lgw_reg_w(LGW_IF_FREQ_4, IF_HZ_TO_REG(if_freq[4])); /* default -384 */ 00647 lgw_reg_w(LGW_IF_FREQ_5, IF_HZ_TO_REG(if_freq[5])); /* default -128 */ 00648 lgw_reg_w(LGW_IF_FREQ_6, IF_HZ_TO_REG(if_freq[6])); /* default 128 */ 00649 lgw_reg_w(LGW_IF_FREQ_7, IF_HZ_TO_REG(if_freq[7])); /* default 384 */ 00650 lgw_reg_w(LGW_CORR0_DETECT_EN, (if_enable[0] == true) ? lora_multi_sfmask[0] : 0); /* default 0 */ 00651 lgw_reg_w(LGW_CORR1_DETECT_EN, (if_enable[1] == true) ? lora_multi_sfmask[1] : 0); /* default 0 */ 00652 lgw_reg_w(LGW_CORR2_DETECT_EN, (if_enable[2] == true) ? lora_multi_sfmask[2] : 0); /* default 0 */ 00653 lgw_reg_w(LGW_CORR3_DETECT_EN, (if_enable[3] == true) ? lora_multi_sfmask[3] : 0); /* default 0 */ 00654 lgw_reg_w(LGW_CORR4_DETECT_EN, (if_enable[4] == true) ? lora_multi_sfmask[4] : 0); /* default 0 */ 00655 lgw_reg_w(LGW_CORR5_DETECT_EN, (if_enable[5] == true) ? lora_multi_sfmask[5] : 0); /* default 0 */ 00656 lgw_reg_w(LGW_CORR6_DETECT_EN, (if_enable[6] == true) ? lora_multi_sfmask[6] : 0); /* default 0 */ 00657 lgw_reg_w(LGW_CORR7_DETECT_EN, (if_enable[7] == true) ? lora_multi_sfmask[7] : 0); /* default 0 */ 00658 lgw_reg_w(LGW_PPM_OFFSET, 0x60); /* as the threshold is 16ms, use 0x60 to enable ppm_offset for SF12 and SF11 @125kHz*/ 00659 lgw_reg_w(LGW_CONCENTRATOR_MODEM_ENABLE, 1); /* default 0 */ 00660 00661 /* configure LoRa 'stand-alone' modem (IF8) */ 00662 lgw_reg_w(LGW_IF_FREQ_8, IF_HZ_TO_REG(if_freq[8])); /* MBWSSF modem (default 0) */ 00663 if (if_enable[8] == true) { 00664 lgw_reg_w(LGW_MBWSSF_RADIO_SELECT, if_rf_chain[8]); 00665 switch (lora_rx_bw) { 00666 case BW_125KHZ: 00667 lgw_reg_w(LGW_MBWSSF_MODEM_BW, 0); 00668 break; 00669 case BW_250KHZ: 00670 lgw_reg_w(LGW_MBWSSF_MODEM_BW, 1); 00671 break; 00672 case BW_500KHZ: 00673 lgw_reg_w(LGW_MBWSSF_MODEM_BW, 2); 00674 break; 00675 default: 00676 DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", lora_rx_bw); 00677 return LGW_HAL_ERROR; 00678 } 00679 switch (lora_rx_sf) { 00680 case DR_LORA_SF7: 00681 lgw_reg_w(LGW_MBWSSF_RATE_SF, 7); 00682 break; 00683 case DR_LORA_SF8: 00684 lgw_reg_w(LGW_MBWSSF_RATE_SF, 8); 00685 break; 00686 case DR_LORA_SF9: 00687 lgw_reg_w(LGW_MBWSSF_RATE_SF, 9); 00688 break; 00689 case DR_LORA_SF10: 00690 lgw_reg_w(LGW_MBWSSF_RATE_SF, 10); 00691 break; 00692 case DR_LORA_SF11: 00693 lgw_reg_w(LGW_MBWSSF_RATE_SF, 11); 00694 break; 00695 case DR_LORA_SF12: 00696 lgw_reg_w(LGW_MBWSSF_RATE_SF, 12); 00697 break; 00698 default: 00699 DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", lora_rx_sf); 00700 return LGW_HAL_ERROR; 00701 } 00702 lgw_reg_w(LGW_MBWSSF_PPM_OFFSET, lora_rx_ppm_offset); /* default 0 */ 00703 lgw_reg_w(LGW_MBWSSF_MODEM_ENABLE, 1); /* default 0 */ 00704 } else { 00705 lgw_reg_w(LGW_MBWSSF_MODEM_ENABLE, 0); 00706 } 00707 00708 /* configure FSK modem (IF9) */ 00709 lgw_reg_w(LGW_IF_FREQ_9, IF_HZ_TO_REG(if_freq[9])); /* FSK modem, default 0 */ 00710 lgw_reg_w(LGW_FSK_PSIZE, fsk_sync_word_size - 1); 00711 lgw_reg_w(LGW_FSK_TX_PSIZE, fsk_sync_word_size - 1); 00712 fsk_sync_word_reg = fsk_sync_word << (8 * (8 - fsk_sync_word_size)); 00713 lgw_reg_w(LGW_FSK_REF_PATTERN_LSB, (uint32_t)(0xFFFFFFFF & fsk_sync_word_reg)); 00714 lgw_reg_w(LGW_FSK_REF_PATTERN_MSB, (uint32_t)(0xFFFFFFFF & (fsk_sync_word_reg >> 32))); 00715 if (if_enable[9] == true) { 00716 lgw_reg_w(LGW_FSK_RADIO_SELECT, if_rf_chain[9]); 00717 lgw_reg_w(LGW_FSK_BR_RATIO, LGW_XTAL_FREQU / fsk_rx_dr); /* setting the dividing ratio for datarate */ 00718 lgw_reg_w(LGW_FSK_CH_BW_EXPO, fsk_rx_bw); 00719 lgw_reg_w(LGW_FSK_MODEM_ENABLE, 1); /* default 0 */ 00720 } else { 00721 lgw_reg_w(LGW_FSK_MODEM_ENABLE, 0); 00722 } 00723 00724 /* Load firmware */ 00725 reset_firmware(MCU_ARB); 00726 reset_firmware(MCU_AGC); 00727 lgw_reg_w(LGW_MCU_RST_0, 1); 00728 lgw_reg_w(LGW_MCU_RST_1, 1); 00729 00730 /* gives the AGC MCU control over radio, RF front-end and filter gain */ 00731 lgw_reg_w(LGW_FORCE_HOST_RADIO_CTRL, 0); 00732 lgw_reg_w(LGW_FORCE_HOST_FE_CTRL, 0); 00733 lgw_reg_w(LGW_FORCE_DEC_FILTER_GAIN, 0); 00734 00735 /* Get MCUs out of reset */ 00736 lgw_reg_w(LGW_RADIO_SELECT, 0); /* MUST not be = to 1 or 2 at firmware init */ 00737 lgw_reg_w(LGW_MCU_RST_0, 0); 00738 lgw_reg_w(LGW_MCU_RST_1, 0); 00739 00740 /* Check firmware version */ 00741 lgw_reg_w(LGW_DBG_AGC_MCU_RAM_ADDR, FW_VERSION_ADDR); 00742 lgw_reg_r(LGW_DBG_AGC_MCU_RAM_DATA, &read_val); 00743 fw_version = (uint8_t)read_val; 00744 if (fw_version != FW_VERSION_AGC) { 00745 DEBUG_PRINTF("ERROR: Version of AGC firmware not expected, actual:%d expected:%d\n", fw_version, FW_VERSION_AGC); 00746 return LGW_HAL_ERROR; 00747 } 00748 lgw_reg_w(LGW_DBG_ARB_MCU_RAM_ADDR, FW_VERSION_ADDR); 00749 lgw_reg_r(LGW_DBG_ARB_MCU_RAM_DATA, &read_val); 00750 fw_version = (uint8_t)read_val; 00751 if (fw_version != FW_VERSION_ARB) { 00752 DEBUG_PRINTF("ERROR: Version of arbiter firmware not expected, actual:%d expected:%d\n", fw_version, FW_VERSION_ARB); 00753 return LGW_HAL_ERROR; 00754 } 00755 00756 DEBUG_MSG("Info: Initialising AGC firmware...\n"); 00757 wait_us(100); /* Need to wait for long enough here */ 00758 lgw_reg_r(LGW_MCU_AGC_STATUS, &read_val); 00759 if (read_val != 0x10) { 00760 DEBUG_PRINTF("ERROR: AGC FIRMWARE INITIALIZATION FAILURE, STATUS1 0x%02X\n", (uint8_t)read_val); 00761 return LGW_HAL_ERROR; 00762 } 00763 00764 /* Update Tx gain LUT and start AGC */ 00765 for (i = 0; i < txgain_lut.size ; ++i) { 00766 lgw_reg_w(LGW_RADIO_SELECT, AGC_CMD_WAIT); /* start a transaction */ 00767 wait_us(DELAYSTART); 00768 load_val = txgain_lut.lut[i].mix_gain + (16 * txgain_lut.lut[i].dac_gain ) + (64 * txgain_lut.lut[i].pa_gain ); 00769 lgw_reg_w(LGW_RADIO_SELECT, load_val); 00770 wait_us(DELAYSTART); 00771 lgw_reg_r(LGW_MCU_AGC_STATUS, &read_val); 00772 if (read_val != (0x30 + i)) { 00773 DEBUG_PRINTF("ERROR: AGC FIRMWARE INITIALIZATION FAILURE, STATUS2 0x%02X\n", (uint8_t)read_val); 00774 return LGW_HAL_ERROR; 00775 } 00776 } 00777 00778 /* As the AGC fw is waiting for 16 entries, we need to abort the transaction if we get less entries */ 00779 if (txgain_lut.size < TX_GAIN_LUT_SIZE_MAX) { 00780 lgw_reg_w(LGW_RADIO_SELECT, AGC_CMD_WAIT); 00781 wait_us(DELAYSTART); 00782 load_val = AGC_CMD_ABORT; 00783 lgw_reg_w(LGW_RADIO_SELECT, load_val); 00784 wait_us(DELAYSTART); 00785 lgw_reg_r(LGW_MCU_AGC_STATUS, &read_val); 00786 if (read_val != 0x30) { 00787 DEBUG_PRINTF("ERROR: AGC FIRMWARE INITIALIZATION FAILURE, STATUS3 0x%02X\n", (uint8_t)read_val); 00788 return LGW_HAL_ERROR; 00789 } 00790 } 00791 00792 /* Load Tx freq MSBs (always 3 if f > 768 for SX1257 or f > 384 for SX1255 */ 00793 lgw_reg_w(LGW_RADIO_SELECT, AGC_CMD_WAIT); 00794 wait_us(DELAYSTART); 00795 lgw_reg_w(LGW_RADIO_SELECT, 3); 00796 wait_us(DELAYSTART); 00797 lgw_reg_r(LGW_MCU_AGC_STATUS, &read_val); 00798 if (read_val != 0x33) { 00799 DEBUG_PRINTF("ERROR: AGC FIRMWARE INITIALIZATION FAILURE, STATUS4 0x%02X\n", (uint8_t)read_val); 00800 return LGW_HAL_ERROR; 00801 } 00802 00803 /* Load chan_select firmware option */ 00804 lgw_reg_w(LGW_RADIO_SELECT, AGC_CMD_WAIT); 00805 wait_us(DELAYSTART); 00806 lgw_reg_w(LGW_RADIO_SELECT, 0); 00807 wait_us(DELAYSTART); 00808 lgw_reg_r(LGW_MCU_AGC_STATUS, &read_val); 00809 if (read_val != 0x30) { 00810 DEBUG_PRINTF("ERROR: AGC FIRMWARE INITIALIZATION FAILURE, STATUS5 0x%02X\n", (uint8_t)read_val); 00811 return LGW_HAL_ERROR; 00812 } 00813 00814 /* End AGC firmware init and check status */ 00815 lgw_reg_w(LGW_RADIO_SELECT, AGC_CMD_WAIT); 00816 wait_us(DELAYSTART); 00817 lgw_reg_w(LGW_RADIO_SELECT, radio_select); /* Load intended value of RADIO_SELECT */ 00818 wait_us(DELAYSTART); 00819 lgw_reg_r(LGW_MCU_AGC_STATUS, &read_val); 00820 if (read_val != 0x40) { 00821 DEBUG_PRINTF("ERROR: AGC FIRMWARE INITIALIZATION FAILURE, STATUS 0x%02X\n", (uint8_t)read_val); 00822 return LGW_HAL_ERROR; 00823 } 00824 00825 /* do not enable GPS event capture */ 00826 lgw_reg_w(LGW_GPS_EN, 0); 00827 00828 /* enable radio for V1 */ 00829 #ifndef V2 00830 lgw_reg_w(LGW_RADIO_A_EN, 1); 00831 #endif 00832 00833 DEBUG_MSG("Info: concentrator restarted...\n"); 00834 00835 return LGW_HAL_SUCCESS; 00836 } 00837 00838 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 00839 00840 int lgw_receive(uint8_t max_pkt, struct lgw_pkt_rx_s *pkt_data) { 00841 int nb_pkt_fetch; /* loop variable and return value */ 00842 struct lgw_pkt_rx_s *p; /* pointer to the current structure in the struct array */ 00843 uint8_t buff[255 + RX_METADATA_NB]; /* buffer to store the result of SPI read bursts */ 00844 unsigned sz; /* size of the payload, uses to address metadata */ 00845 int ifmod; /* type of if_chain/modem a packet was received by */ 00846 int stat_fifo; /* the packet status as indicated in the FIFO */ 00847 uint32_t raw_timestamp; /* timestamp when internal 'RX finished' was triggered */ 00848 uint32_t delay_x, delay_y, delay_z; /* temporary variable for timestamp offset calculation */ 00849 uint32_t timestamp_correction; /* correction to account for processing delay */ 00850 uint32_t sf, cr, bw_pow, crc_en, ppm; /* used to calculate timestamp correction */ 00851 00852 /* check input variables */ 00853 if ((max_pkt == 0) || (max_pkt > LGW_PKT_FIFO_SIZE)) { 00854 DEBUG_PRINTF("ERROR: %d = INVALID MAX NUMBER OF PACKETS TO FETCH\n", max_pkt); 00855 return LGW_HAL_ERROR; 00856 } 00857 CHECK_NULL(pkt_data); 00858 00859 /* Initialize buffer */ 00860 memset(buff, 0, sizeof buff); 00861 00862 /* iterate max_pkt times at most */ 00863 for (nb_pkt_fetch = 0; nb_pkt_fetch < max_pkt; ++nb_pkt_fetch) { 00864 00865 /* point to the proper struct in the struct array */ 00866 p = &pkt_data[nb_pkt_fetch]; 00867 00868 /* fetch all the RX FIFO data */ 00869 lgw_reg_rb(LGW_RX_PACKET_DATA_FIFO_NUM_STORED, buff, 5); 00870 /* 0: number of packets available in RX data buffer */ 00871 /* 1,2: start address of the current packet in RX data buffer */ 00872 /* 3: CRC status of the current packet */ 00873 /* 4: size of the current packet payload in byte */ 00874 00875 /* how many packets are in the RX buffer ? Break if zero */ 00876 if (buff[0] == 0) { 00877 break; /* no more packets to fetch, exit out of FOR loop */ 00878 } 00879 00880 /* sanity check */ 00881 if (buff[0] > LGW_PKT_FIFO_SIZE) { 00882 DEBUG_PRINTF("WARNING: %u = INVALID NUMBER OF PACKETS TO FETCH, ABORTING\n", buff[0]); 00883 break; 00884 } 00885 00886 DEBUG_PRINTF("FIFO content: %x %x %x %x %x\n", buff[0], buff[1], buff[2], buff[3], buff[4]); 00887 00888 p->size = buff[4]; 00889 sz = p->size ; 00890 stat_fifo = buff[3]; /* will be used later, need to save it before overwriting buff */ 00891 00892 /* get payload + metadata */ 00893 lgw_reg_rb(LGW_RX_DATA_BUF_DATA, buff, sz + RX_METADATA_NB); 00894 00895 /* copy payload to result struct */ 00896 memcpy((void *)p->payload , (void *)buff, sz); 00897 00898 /* process metadata */ 00899 p->if_chain = buff[sz + 0]; 00900 if (p->if_chain >= LGW_IF_CHAIN_NB) { 00901 DEBUG_PRINTF("WARNING: %u NOT A VALID IF_CHAIN NUMBER, ABORTING\n", p->if_chain ); 00902 break; 00903 } 00904 ifmod = ifmod_config[p->if_chain ]; 00905 DEBUG_PRINTF("[%d %d]\n", p->if_chain , ifmod); 00906 00907 p->rf_chain = (uint8_t)if_rf_chain[p->if_chain ]; 00908 p->freq_hz = (uint32_t)((int32_t)rf_rx_freq[p->rf_chain ] + if_freq[p->if_chain ]); 00909 p->rssi = (float)buff[sz + 5] + rf_rssi_offset[p->rf_chain ]; 00910 00911 if ((ifmod == IF_LORA_MULTI) || (ifmod == IF_LORA_STD)) { 00912 DEBUG_MSG("Note: LoRa packet\n"); 00913 switch (stat_fifo & 0x07) { 00914 case 5: 00915 p->status = STAT_CRC_OK; 00916 crc_en = 1; 00917 break; 00918 case 7: 00919 p->status = STAT_CRC_BAD; 00920 crc_en = 1; 00921 break; 00922 case 1: 00923 p->status = STAT_NO_CRC; 00924 crc_en = 0; 00925 break; 00926 default: 00927 p->status = STAT_UNDEFINED; 00928 crc_en = 0; 00929 } 00930 p->modulation = MOD_LORA; 00931 p->snr = ((float)((int8_t)buff[sz + 2])) / 4; 00932 p->snr_min = ((float)((int8_t)buff[sz + 3])) / 4; 00933 p->snr_max = ((float)((int8_t)buff[sz + 4])) / 4; 00934 if (ifmod == IF_LORA_MULTI) { 00935 p->bandwidth = BW_125KHZ; /* fixed in hardware */ 00936 } else { 00937 p->bandwidth = lora_rx_bw; /* get the parameter from the config variable */ 00938 } 00939 sf = (buff[sz + 1] >> 4) & 0x0F; 00940 00941 switch (sf) { 00942 case 7: 00943 p->datarate = DR_LORA_SF7; 00944 break; 00945 case 8: 00946 p->datarate = DR_LORA_SF8; 00947 break; 00948 case 9: 00949 p->datarate = DR_LORA_SF9; 00950 break; 00951 case 10: 00952 p->datarate = DR_LORA_SF10; 00953 break; 00954 case 11: 00955 p->datarate = DR_LORA_SF11; 00956 break; 00957 case 12: 00958 p->datarate = DR_LORA_SF12; 00959 break; 00960 default: 00961 p->datarate = DR_UNDEFINED; 00962 } 00963 cr = (buff[sz + 1] >> 1) & 0x07; 00964 switch (cr) { 00965 case 1: 00966 p->coderate = CR_LORA_4_5; 00967 break; 00968 case 2: 00969 p->coderate = CR_LORA_4_6; 00970 break; 00971 case 3: 00972 p->coderate = CR_LORA_4_7; 00973 break; 00974 case 4: 00975 p->coderate = CR_LORA_4_8; 00976 break; 00977 default: 00978 p->coderate = CR_UNDEFINED; 00979 } 00980 00981 /* determine if 'PPM mode' is on, needed for timestamp correction */ 00982 if (SET_PPM_ON(p->bandwidth , p->datarate )) { 00983 ppm = 1; 00984 } else { 00985 ppm = 0; 00986 } 00987 00988 /* timestamp correction code, base delay */ 00989 if (ifmod == IF_LORA_STD) { /* if packet was received on the stand-alone LoRa modem */ 00990 switch (lora_rx_bw) { 00991 case BW_125KHZ: 00992 delay_x = 64; 00993 bw_pow = 1; 00994 break; 00995 case BW_250KHZ: 00996 delay_x = 32; 00997 bw_pow = 2; 00998 break; 00999 case BW_500KHZ: 01000 delay_x = 16; 01001 bw_pow = 4; 01002 break; 01003 default: 01004 DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", p->bandwidth ); 01005 delay_x = 0; 01006 bw_pow = 0; 01007 } 01008 } else { /* packet was received on one of the sensor channels = 125kHz */ 01009 delay_x = 114; 01010 bw_pow = 1; 01011 } 01012 01013 /* timestamp correction code, variable delay */ 01014 if ((sf >= 6) && (sf <= 12) && (bw_pow > 0)) { 01015 if ((2 * (sz + 2 * crc_en) - (sf - 7)) <= 0) { /* payload fits entirely in first 8 symbols */ 01016 delay_y = (((1 << (sf - 1)) * (sf + 1)) + (3 * (1 << (sf - 4)))) / bw_pow; 01017 delay_z = 32 * (2 * (sz + 2 * crc_en) + 5) / bw_pow; 01018 } else { 01019 delay_y = (((1 << (sf - 1)) * (sf + 1)) + ((4 - ppm) * (1 << (sf - 4)))) / bw_pow; 01020 delay_z = (16 + 4 * cr) * (((2 * (sz + 2 * crc_en) - sf + 6) % (sf - 2 * ppm)) + 1) / bw_pow; 01021 } 01022 timestamp_correction = delay_x + delay_y + delay_z; 01023 } else { 01024 timestamp_correction = 0; 01025 DEBUG_MSG("WARNING: invalid packet, no timestamp correction\n"); 01026 } 01027 01028 /* RSSI correction */ 01029 if (ifmod == IF_LORA_MULTI) { 01030 p->rssi -= RSSI_MULTI_BIAS; 01031 } 01032 01033 } else if (ifmod == IF_FSK_STD) { 01034 DEBUG_MSG("Note: FSK packet\n"); 01035 switch (stat_fifo & 0x07) { 01036 case 5: 01037 p->status = STAT_CRC_OK; 01038 break; 01039 case 7: 01040 p->status = STAT_CRC_BAD; 01041 break; 01042 case 1: 01043 p->status = STAT_NO_CRC; 01044 break; 01045 default: 01046 p->status = STAT_UNDEFINED; 01047 break; 01048 } 01049 p->modulation = MOD_FSK; 01050 p->snr = -128.0; 01051 p->snr_min = -128.0; 01052 p->snr_max = -128.0; 01053 p->bandwidth = fsk_rx_bw; 01054 p->datarate = fsk_rx_dr; 01055 p->coderate = CR_UNDEFINED; 01056 timestamp_correction = ((uint32_t)680000 / fsk_rx_dr) - 20; 01057 01058 /* RSSI correction */ 01059 p->rssi = (RSSI_FSK_POLY_0) + ((float)(RSSI_FSK_POLY_1) * p->rssi ) + ((float)(RSSI_FSK_POLY_2) * (p->rssi ) * (p->rssi )); 01060 } else { 01061 DEBUG_MSG("ERROR: UNEXPECTED PACKET ORIGIN\n"); 01062 p->status = STAT_UNDEFINED; 01063 p->modulation = MOD_UNDEFINED; 01064 p->rssi = -128.0; 01065 p->snr = -128.0; 01066 p->snr_min = -128.0; 01067 p->snr_max = -128.0; 01068 p->bandwidth = BW_UNDEFINED; 01069 p->datarate = DR_UNDEFINED; 01070 p->coderate = CR_UNDEFINED; 01071 timestamp_correction = 0; 01072 } 01073 01074 raw_timestamp = (uint32_t)buff[sz + 6] + ((uint32_t)buff[sz + 7] << 8) + ((uint32_t)buff[sz + 8] << 16) + ((uint32_t)buff[sz + 9] << 24); 01075 p->count_us = raw_timestamp - timestamp_correction + Sx1308.offtmstpstm32; /* corrected with PicoCell offset */ 01076 p->crc = (uint16_t)buff[sz + 10] + ((uint16_t)buff[sz + 11] << 8); 01077 01078 /* advance packet FIFO */ 01079 lgw_reg_w(LGW_RX_PACKET_DATA_FIFO_NUM_STORED, 0); 01080 } 01081 01082 return nb_pkt_fetch; 01083 } 01084 01085 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 01086 01087 int lgw_send(struct lgw_pkt_tx_s pkt_data) { 01088 int i; 01089 uint8_t buff[256 + TX_METADATA_NB]; /* buffer to prepare the packet to send + metadata before SPI write burst */ 01090 uint32_t part_int = 0; /* integer part for PLL register value calculation */ 01091 uint32_t part_frac = 0; /* fractional part for PLL register value calculation */ 01092 uint16_t fsk_dr_div; /* divider to configure for target datarate */ 01093 int transfer_size = 0; /* data to transfer from host to TX databuffer */ 01094 int payload_offset = 0; /* start of the payload content in the databuffer */ 01095 uint8_t pow_index = 0; /* 4-bit value to set the firmware TX power */ 01096 uint8_t target_mix_gain = 0; /* used to select the proper I/Q offset correction */ 01097 uint32_t count_trig = 0; /* timestamp value in trigger mode corrected for TX start delay */ 01098 01099 /* check input range (segfault prevention) */ 01100 if (pkt_data.rf_chain >= LGW_RF_CHAIN_NB) { 01101 DEBUG_MSG("ERROR: INVALID RF_CHAIN TO SEND PACKETS\n"); 01102 return LGW_HAL_ERROR; 01103 } 01104 01105 /* check input variables */ 01106 if (rf_tx_enable[pkt_data.rf_chain ] == false) { 01107 DEBUG_MSG("ERROR: SELECTED RF_CHAIN IS DISABLED FOR TX ON SELECTED BOARD\n"); 01108 return LGW_HAL_ERROR; 01109 } 01110 if (rf_enable[pkt_data.rf_chain ] == false) { 01111 DEBUG_MSG("ERROR: SELECTED RF_CHAIN IS DISABLED\n"); 01112 return LGW_HAL_ERROR; 01113 } 01114 if (!IS_TX_MODE(pkt_data.tx_mode )) { 01115 DEBUG_MSG("ERROR: TX_MODE NOT SUPPORTED\n"); 01116 return LGW_HAL_ERROR; 01117 } 01118 if (pkt_data.modulation == MOD_LORA) { 01119 if (!IS_LORA_BW(pkt_data.bandwidth )) { 01120 DEBUG_MSG("ERROR: BANDWIDTH NOT SUPPORTED BY LORA TX\n"); 01121 return LGW_HAL_ERROR; 01122 } 01123 if (!IS_LORA_STD_DR(pkt_data.datarate )) { 01124 DEBUG_MSG("ERROR: DATARATE NOT SUPPORTED BY LORA TX\n"); 01125 return LGW_HAL_ERROR; 01126 } 01127 if (!IS_LORA_CR(pkt_data.coderate )) { 01128 DEBUG_MSG("ERROR: CODERATE NOT SUPPORTED BY LORA TX\n"); 01129 return LGW_HAL_ERROR; 01130 } 01131 if (pkt_data.size > 255) { 01132 DEBUG_MSG("ERROR: PAYLOAD LENGTH TOO BIG FOR LORA TX\n"); 01133 return LGW_HAL_ERROR; 01134 } 01135 } else if (pkt_data.modulation == MOD_FSK) { 01136 if ((pkt_data.f_dev < 1) || (pkt_data.f_dev > 200)) { 01137 DEBUG_MSG("ERROR: TX FREQUENCY DEVIATION OUT OF ACCEPTABLE RANGE\n"); 01138 return LGW_HAL_ERROR; 01139 } 01140 if (!IS_FSK_DR(pkt_data.datarate )) { 01141 DEBUG_MSG("ERROR: DATARATE NOT SUPPORTED BY FSK IF CHAIN\n"); 01142 return LGW_HAL_ERROR; 01143 } 01144 if (pkt_data.size > 255) { 01145 DEBUG_MSG("ERROR: PAYLOAD LENGTH TOO BIG FOR FSK TX\n"); 01146 return LGW_HAL_ERROR; 01147 } 01148 } else { 01149 DEBUG_MSG("ERROR: INVALID TX MODULATION\n"); 01150 return LGW_HAL_ERROR; 01151 } 01152 01153 /* interpretation of TX power */ 01154 for (pow_index = txgain_lut.size - 1; pow_index > 0; pow_index--) { 01155 if (txgain_lut.lut[pow_index].rf_power <= pkt_data.rf_power ) { 01156 break; 01157 } 01158 } 01159 01160 /* Save radio calibration for next restart */ 01161 calibration_save(); 01162 01163 /* loading TX imbalance correction */ 01164 target_mix_gain = txgain_lut.lut[pow_index].mix_gain ; 01165 if (pkt_data.rf_chain == 0) { /* use radio A calibration table */ 01166 lgw_reg_w(LGW_TX_OFFSET_I, cal_offset_a_i[target_mix_gain ]); 01167 lgw_reg_w(LGW_TX_OFFSET_Q, cal_offset_a_q[target_mix_gain ]); 01168 } else { /* use radio B calibration table */ 01169 lgw_reg_w(LGW_TX_OFFSET_I, cal_offset_b_i[target_mix_gain ]); 01170 lgw_reg_w(LGW_TX_OFFSET_Q, cal_offset_b_q[target_mix_gain ]); 01171 } 01172 01173 /* Set digital gain from LUT */ 01174 lgw_reg_w(LGW_TX_GAIN, txgain_lut.lut[pow_index].dig_gain); 01175 01176 /* fixed metadata, useful payload and misc metadata compositing */ 01177 transfer_size = TX_METADATA_NB + pkt_data.size ; /* */ 01178 payload_offset = TX_METADATA_NB; /* start the payload just after the metadata */ 01179 01180 /* metadata 0 to 2, TX PLL frequency */ 01181 switch (rf_radio_type[0]) { /* we assume that there is only one radio type on the board */ 01182 case LGW_RADIO_TYPE_SX1255: 01183 part_int = pkt_data.freq_hz / (SX125x_32MHz_FRAC << 7); /* integer part, gives the MSB */ 01184 part_frac = ((pkt_data.freq_hz % (SX125x_32MHz_FRAC << 7)) << 9) / SX125x_32MHz_FRAC; /* fractional part, gives middle part and LSB */ 01185 break; 01186 case LGW_RADIO_TYPE_SX1257: 01187 part_int = pkt_data.freq_hz / (SX125x_32MHz_FRAC << 8); /* integer part, gives the MSB */ 01188 part_frac = ((pkt_data.freq_hz % (SX125x_32MHz_FRAC << 8)) << 8) / SX125x_32MHz_FRAC; /* fractional part, gives middle part and LSB */ 01189 break; 01190 default: 01191 DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d FOR RADIO TYPE\n", rf_radio_type[0]); 01192 break; 01193 } 01194 01195 buff[0] = 0xFF & part_int; /* Most Significant Byte */ 01196 buff[1] = 0xFF & (part_frac >> 8); /* middle byte */ 01197 buff[2] = 0xFF & part_frac; /* Least Significant Byte */ 01198 01199 /* metadata 3 to 6, timestamp trigger value */ 01200 /* TX state machine must be triggered at T0 - TX_START_DELAY for packet to start being emitted at T0 */ 01201 if (pkt_data.tx_mode == TIMESTAMPED) { 01202 count_trig = pkt_data.count_us - TX_START_DELAY - Sx1308.offtmstpstm32; /* Corrected with PicoCell offset */ 01203 buff[3] = 0xFF & (count_trig >> 24); 01204 buff[4] = 0xFF & (count_trig >> 16); 01205 buff[5] = 0xFF & (count_trig >> 8); 01206 buff[6] = 0xFF & count_trig; 01207 } 01208 01209 /* parameters depending on modulation */ 01210 if (pkt_data.modulation == MOD_LORA) { 01211 /* metadata 7, modulation type, radio chain selection and TX power */ 01212 buff[7] = (0x20 & (pkt_data.rf_chain << 5)) | (0x0F & pow_index); /* bit 4 is 0 -> LoRa modulation */ 01213 01214 buff[8] = 0; /* metadata 8, not used */ 01215 01216 /* metadata 9, CRC, LoRa CR & SF */ 01217 switch (pkt_data.datarate ) { 01218 case DR_LORA_SF7: 01219 buff[9] = 7; 01220 break; 01221 case DR_LORA_SF8: 01222 buff[9] = 8; 01223 break; 01224 case DR_LORA_SF9: 01225 buff[9] = 9; 01226 break; 01227 case DR_LORA_SF10: 01228 buff[9] = 10; 01229 break; 01230 case DR_LORA_SF11: 01231 buff[9] = 11; 01232 break; 01233 case DR_LORA_SF12: 01234 buff[9] = 12; 01235 break; 01236 default: 01237 DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", pkt_data.datarate ); 01238 } 01239 switch (pkt_data.coderate ) { 01240 case CR_LORA_4_5: 01241 buff[9] |= 1 << 4; 01242 break; 01243 case CR_LORA_4_6: 01244 buff[9] |= 2 << 4; 01245 break; 01246 case CR_LORA_4_7: 01247 buff[9] |= 3 << 4; 01248 break; 01249 case CR_LORA_4_8: 01250 buff[9] |= 4 << 4; 01251 break; 01252 default: 01253 DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", pkt_data.coderate ); 01254 } 01255 if (pkt_data.no_crc == false) { 01256 buff[9] |= 0x80; /* set 'CRC enable' bit */ 01257 } else { 01258 DEBUG_MSG("Info: packet will be sent without CRC\n"); 01259 } 01260 01261 /* metadata 10, payload size */ 01262 buff[10] = pkt_data.size ; 01263 01264 /* metadata 11, implicit header, modulation bandwidth, PPM offset & polarity */ 01265 switch (pkt_data.bandwidth ) { 01266 case BW_125KHZ: 01267 buff[11] = 0; 01268 break; 01269 case BW_250KHZ: 01270 buff[11] = 1; 01271 break; 01272 case BW_500KHZ: 01273 buff[11] = 2; 01274 break; 01275 default: 01276 DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", pkt_data.bandwidth ); 01277 } 01278 if (pkt_data.no_header == true) { 01279 buff[11] |= 0x04; /* set 'implicit header' bit */ 01280 } 01281 if (SET_PPM_ON(pkt_data.bandwidth , pkt_data.datarate )) { 01282 buff[11] |= 0x08; /* set 'PPM offset' bit at 1 */ 01283 } 01284 if (pkt_data.invert_pol == true) { 01285 buff[11] |= 0x10; /* set 'TX polarity' bit at 1 */ 01286 } 01287 01288 /* metadata 12 & 13, LoRa preamble size */ 01289 if (pkt_data.preamble == 0) { /* if not explicit, use recommended LoRa preamble size */ 01290 pkt_data.preamble = STD_LORA_PREAMBLE; 01291 } else if (pkt_data.preamble < MIN_LORA_PREAMBLE) { /* enforce minimum preamble size */ 01292 pkt_data.preamble = MIN_LORA_PREAMBLE; 01293 DEBUG_MSG("Note: preamble length adjusted to respect minimum LoRa preamble size\n"); 01294 } 01295 buff[12] = 0xFF & (pkt_data.preamble >> 8); 01296 buff[13] = 0xFF & pkt_data.preamble ; 01297 01298 /* metadata 14 & 15, not used */ 01299 buff[14] = 0; 01300 buff[15] = 0; 01301 01302 /* MSB of RF frequency is now used in AGC firmware to implement large/narrow filtering in SX1257/55 */ 01303 buff[0] &= 0x3F; /* Unset 2 MSBs of frequency code */ 01304 if (pkt_data.bandwidth == BW_500KHZ) { 01305 buff[0] |= 0x80; /* Set MSB bit to enlarge analog filter for 500kHz BW */ 01306 } else if (pkt_data.bandwidth == BW_125KHZ) { 01307 buff[0] |= 0x40; /* Set MSB-1 bit to enable digital filter for 125kHz BW */ 01308 } 01309 01310 } else if (pkt_data.modulation == MOD_FSK) { 01311 /* metadata 7, modulation type, radio chain selection and TX power */ 01312 buff[7] = (0x20 & (pkt_data.rf_chain << 5)) | 0x10 | (0x0F & pow_index); /* bit 4 is 1 -> FSK modulation */ 01313 01314 buff[8] = 0; /* metadata 8, not used */ 01315 01316 /* metadata 9, frequency deviation */ 01317 buff[9] = pkt_data.f_dev ; 01318 01319 /* metadata 10, payload size */ 01320 buff[10] = pkt_data.size ; 01321 /* TODO: how to handle 255 bytes packets ?!? */ 01322 01323 /* metadata 11, packet mode, CRC, encoding */ 01324 buff[11] = 0x01 | (pkt_data.no_crc ? 0 : 0x02) | (0x02 << 2); /* always in variable length packet mode, whitening, and CCITT CRC if CRC is not disabled */ 01325 01326 /* metadata 12 & 13, FSK preamble size */ 01327 if (pkt_data.preamble == 0) { /* if not explicit, use LoRa MAC preamble size */ 01328 pkt_data.preamble = STD_FSK_PREAMBLE; 01329 } else if (pkt_data.preamble < MIN_FSK_PREAMBLE) { /* enforce minimum preamble size */ 01330 pkt_data.preamble = MIN_FSK_PREAMBLE; 01331 DEBUG_MSG("Note: preamble length adjusted to respect minimum FSK preamble size\n"); 01332 } 01333 buff[12] = 0xFF & (pkt_data.preamble >> 8); 01334 buff[13] = 0xFF & pkt_data.preamble ; 01335 01336 /* metadata 14 & 15, FSK baudrate */ 01337 fsk_dr_div = (uint16_t)((uint32_t)LGW_XTAL_FREQU / pkt_data.datarate ); /* Ok for datarate between 500bps and 250kbps */ 01338 buff[14] = 0xFF & (fsk_dr_div >> 8); 01339 buff[15] = 0xFF & fsk_dr_div; 01340 01341 /* insert payload size in the packet for variable mode */ 01342 buff[16] = pkt_data.size ; 01343 ++transfer_size; /* one more byte to transfer to the TX modem */ 01344 ++payload_offset; /* start the payload with one more byte of offset */ 01345 01346 /* MSB of RF frequency is now used in AGC firmware to implement large/narrow filtering in SX1257/55 */ 01347 buff[0] &= 0x7F; /* Always use narrow band for FSK (force MSB to 0) */ 01348 01349 } else { 01350 DEBUG_MSG("ERROR: INVALID TX MODULATION..\n"); 01351 return LGW_HAL_ERROR; 01352 } 01353 01354 /* copy payload from user struct to buffer containing metadata */ 01355 memcpy((void *)(buff + payload_offset), (void *)(pkt_data.payload ), pkt_data.size ); 01356 01357 /* reset TX command flags */ 01358 lgw_abort_tx(); 01359 01360 /* put metadata + payload in the TX data buffer */ 01361 lgw_reg_w(LGW_TX_DATA_BUF_ADDR, 0); 01362 lgw_reg_wb(LGW_TX_DATA_BUF_DATA, buff, transfer_size); 01363 DEBUG_ARRAY(i, transfer_size, buff); 01364 01365 switch (pkt_data.tx_mode ) { 01366 case IMMEDIATE: 01367 lgw_reg_w(LGW_TX_TRIG_IMMEDIATE, 1); 01368 break; 01369 01370 case TIMESTAMPED: 01371 lgw_reg_w(LGW_TX_TRIG_DELAYED, 1); 01372 break; 01373 01374 case ON_GPS: 01375 lgw_reg_w(LGW_TX_TRIG_GPS, 1); 01376 break; 01377 01378 default: 01379 DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", pkt_data.tx_mode ); 01380 return LGW_HAL_ERROR; 01381 } 01382 01383 DEBUG_MSG("Note: lgw_send() done.\n"); 01384 01385 return LGW_HAL_SUCCESS; 01386 } 01387 01388 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 01389 01390 int lgw_status(uint8_t select, uint8_t *code) { 01391 int32_t read_value; 01392 01393 /* check input variables */ 01394 CHECK_NULL(code); 01395 01396 if (select == TX_STATUS) { 01397 lgw_reg_r(LGW_TX_STATUS, &read_value); 01398 if ((read_value & 0x10) == 0) { /* bit 4 @1: TX programmed */ 01399 *code = TX_FREE; 01400 } else if ((read_value & 0x60) != 0) { /* bit 5 or 6 @1: TX sequence */ 01401 *code = TX_EMITTING; 01402 } else { 01403 *code = TX_SCHEDULED; 01404 } 01405 return LGW_HAL_SUCCESS; 01406 01407 } else if (select == RX_STATUS) { 01408 *code = RX_STATUS_UNKNOWN; /* todo */ 01409 return LGW_HAL_SUCCESS; 01410 01411 } else { 01412 DEBUG_MSG("ERROR: SELECTION INVALID, NO STATUS TO RETURN\n"); 01413 return LGW_HAL_ERROR; 01414 } 01415 01416 } 01417 01418 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 01419 01420 int lgw_abort_tx(void) { 01421 int i; 01422 01423 i = lgw_reg_w(LGW_TX_TRIG_ALL, 0); 01424 01425 if (i == LGW_REG_SUCCESS) { 01426 return LGW_HAL_SUCCESS; 01427 } else { 01428 return LGW_HAL_ERROR; 01429 } 01430 } 01431 01432 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 01433 01434 int lgw_get_trigcnt(uint32_t* trig_cnt_us) { 01435 int i; 01436 int32_t val; 01437 01438 i = lgw_reg_r(LGW_TIMESTAMP, &val); 01439 if (i == LGW_REG_SUCCESS) { 01440 *trig_cnt_us = (uint32_t)val; 01441 return LGW_HAL_SUCCESS; 01442 } else { 01443 return LGW_HAL_ERROR; 01444 } 01445 } 01446 01447 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 01448 01449 const char* lgw_version_info() { 01450 return lgw_version_string; 01451 } 01452 01453 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 01454 01455 uint32_t lgw_time_on_air(struct lgw_pkt_tx_s *packet) { 01456 int32_t val; 01457 uint8_t SF, H, DE; 01458 uint16_t BW; 01459 uint32_t payloadSymbNb, Tpacket; 01460 double Tsym, Tpreamble, Tpayload, Tfsk; 01461 01462 if (packet == NULL) { 01463 DEBUG_MSG("ERROR: Failed to compute time on air, wrong parameter\n"); 01464 return 0; 01465 } 01466 01467 if (packet->modulation == MOD_LORA) { 01468 /* Get bandwidth */ 01469 val = lgw_bw_getval(packet->bandwidth ); 01470 if (val != -1) { 01471 BW = (uint16_t)(val / 1E3); 01472 } else { 01473 DEBUG_PRINTF("ERROR: Cannot compute time on air for this packet, unsupported bandwidth (0x%02X)\n", packet->bandwidth ); 01474 return 0; 01475 } 01476 01477 /* Get datarate */ 01478 val = lgw_sf_getval(packet->datarate ); 01479 if (val != -1) { 01480 SF = (uint8_t)val; 01481 } else { 01482 DEBUG_PRINTF("ERROR: Cannot compute time on air for this packet, unsupported datarate (0x%02X)\n", packet->datarate ); 01483 return 0; 01484 } 01485 01486 /* Duration of 1 symbol */ 01487 Tsym = (2 ^ SF) / BW; 01488 01489 /* Duration of preamble */ 01490 Tpreamble = (8 + 4.25) * Tsym; /* 8 programmed symbols in preamble */ 01491 01492 /* Duration of payload */ 01493 H = (packet->no_header == false) ? 0 : 1; /* header is always enabled, except for beacons */ 01494 DE = (SF >= 11) ? 1 : 0; /* Low datarate optimization enabled for SF11 and SF12 */ 01495 01496 payloadSymbNb = 8 + (ceil((double)(8 * packet->size - 4 * SF + 28 + 16 - 20 * H) / (double)(4 * (SF - 2 * DE))) * (packet->coderate + 4)); /* Explicitely cast to double to keep precision of the division */ 01497 01498 Tpayload = payloadSymbNb * Tsym; 01499 01500 /* Duration of packet */ 01501 Tpacket = Tpreamble + Tpayload; 01502 } else if (packet->modulation == MOD_FSK) { 01503 /* PREAMBLE + SYNC_WORD + PKT_LEN + PKT_PAYLOAD + CRC 01504 PREAMBLE: default 5 bytes 01505 SYNC_WORD: default 3 bytes 01506 PKT_LEN: 1 byte (variable length mode) 01507 PKT_PAYLOAD: x bytes 01508 CRC: 0 or 2 bytes 01509 */ 01510 Tfsk = (8 * (double)(packet->preamble + fsk_sync_word_size + 1 + packet->size + ((packet->no_crc == true) ? 0 : 2)) / (double)packet->datarate ) * 1E3; 01511 01512 /* Duration of packet */ 01513 Tpacket = (uint32_t)Tfsk + 1; /* add margin for rounding */ 01514 } else { 01515 Tpacket = 0; 01516 DEBUG_PRINTF("ERROR: Cannot compute time on air for this packet, unsupported modulation (0x%02X)\n", packet->modulation ); 01517 } 01518 01519 return Tpacket; 01520 } 01521 01522 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 01523 01524 void lgw_calibration_offset_transfer(uint8_t idx_start, uint8_t idx_nb) { 01525 int i; 01526 int read_val; 01527 01528 DEBUG_PRINTF("start calibration for index [%u-%u]\n", idx_start, idx_start + idx_nb); 01529 01530 /* Get 'idx_nb' calibration offsets from AGC FW, and put it in the local 01531 calibration offsets array, at 'idx_start' index position */ 01532 for(i = 0; i < idx_nb; ++i) { 01533 lgw_reg_w(LGW_DBG_AGC_MCU_RAM_ADDR, 0xA0 + i); 01534 wait_ms(1); 01535 lgw_reg_r(LGW_DBG_AGC_MCU_RAM_DATA, &read_val); 01536 wait_ms(1); 01537 cal_offset_a_i[i + idx_start] = (int8_t)read_val; 01538 lgw_reg_w(LGW_DBG_AGC_MCU_RAM_ADDR, 0xA8 + i); 01539 wait_ms(1); 01540 lgw_reg_r(LGW_DBG_AGC_MCU_RAM_DATA, &read_val); 01541 wait_ms(1); 01542 cal_offset_a_q[i + idx_start] = (int8_t)read_val; 01543 lgw_reg_w(LGW_DBG_AGC_MCU_RAM_ADDR, 0xB0 + i); 01544 wait_ms(1); 01545 lgw_reg_r(LGW_DBG_AGC_MCU_RAM_DATA, &read_val); 01546 wait_ms(1); 01547 cal_offset_b_i[i + idx_start] = (int8_t)read_val; 01548 lgw_reg_w(LGW_DBG_AGC_MCU_RAM_ADDR, 0xB8 + i); 01549 wait_ms(1); 01550 lgw_reg_r(LGW_DBG_AGC_MCU_RAM_DATA, &read_val); 01551 wait_ms(1); 01552 cal_offset_b_q[i + idx_start] = (int8_t)read_val; 01553 } 01554 01555 /* Fill the first 5 offsets [0-4] with the value of index 5 */ 01556 for(i = 0; i < 5; i++) { 01557 cal_offset_a_i[i] = cal_offset_a_i[5]; 01558 cal_offset_a_q[i] = cal_offset_a_q[5]; 01559 cal_offset_b_i[i] = cal_offset_b_i[5]; 01560 cal_offset_b_q[i] = cal_offset_b_q[5]; 01561 } 01562 } 01563 01564 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 01565 01566 void calibration_save(void) { 01567 lgw_reg_r(LGW_IQ_MISMATCH_A_AMP_COEFF, &iqrxtab[0]); 01568 lgw_reg_r(LGW_IQ_MISMATCH_A_PHI_COEFF, &iqrxtab[1]); 01569 lgw_reg_r(LGW_IQ_MISMATCH_B_AMP_COEFF, &iqrxtab[2]); 01570 lgw_reg_r(LGW_IQ_MISMATCH_B_PHI_COEFF, &iqrxtab[3]); 01571 } 01572 01573 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 01574 01575 void calibration_reload(void) { 01576 lgw_reg_w(LGW_IQ_MISMATCH_A_AMP_COEFF, iqrxtab[0]); 01577 lgw_reg_w(LGW_IQ_MISMATCH_A_PHI_COEFF, iqrxtab[1]); 01578 lgw_reg_w(LGW_IQ_MISMATCH_B_AMP_COEFF, iqrxtab[2]); 01579 lgw_reg_w(LGW_IQ_MISMATCH_B_PHI_COEFF, iqrxtab[3]); 01580 } 01581 01582 /* --- EOF ------------------------------------------------------------------ */
Generated on Tue Jul 12 2022 22:19:20 by
