Damian Gabino / picoGW_mcu
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers loragw_reg.cpp Source File

loragw_reg.cpp

00001 /*
00002  / _____)             _              | |
00003 ( (____  _____ ____ _| |_ _____  ____| |__
00004  \____ \| ___ |    (_   _) ___ |/ ___)  _ \
00005  _____) ) ____| | | || |_| ____( (___| | | |
00006 (______/|_____)_|_|_| \__)_____)\____)_| |_|
00007   (C)2017 Semtech
00008 
00009 
00010 */
00011 #include "SX1308.h"
00012 #include "loragw_reg.h"
00013 #include "board.h"
00014 
00015 /* -------------------------------------------------------------------------- */
00016 /* --- PRIVATE CONSTANTS ---------------------------------------------------- */
00017 
00018 #define PAGE_ADDR        0x00
00019 #define PAGE_MASK        0x03
00020 
00021 const struct lgw_reg_s loregs[LGW_TOTALREGS] = {
00022     {-1, 0, 0, 0, 2, 0, 0},   /* PAGE_REG */
00023     {-1, 0, 7, 0, 1, 0, 0},   /* SOFT_RESET */
00024     {-1, 1, 0, 0, 8, 1, 103}, /* VERSION */
00025     {-1, 2, 0, 0, 16, 0, 0},  /* RX_DATA_BUF_ADDR */
00026     {-1, 4, 0, 0, 8, 0, 0},   /* RX_DATA_BUF_DATA */
00027     {-1, 5, 0, 0, 8, 0, 0},   /* TX_DATA_BUF_ADDR */
00028     {-1, 6, 0, 0, 8, 0, 0},   /* TX_DATA_BUF_DATA */
00029     {-1, 7, 0, 0, 8, 0, 0},   /* CAPTURE_RAM_ADDR */
00030     {-1, 8, 0, 0, 8, 1, 0},   /* CAPTURE_RAM_DATA */
00031     {-1, 9, 0, 0, 8, 0, 0},   /* MCU_PROM_ADDR */
00032     {-1, 10, 0, 0, 8, 0, 0},  /* MCU_PROM_DATA */
00033     {-1, 11, 0, 0, 8, 0, 0},  /* RX_PACKET_DATA_FIFO_NUM_STORED */
00034     {-1, 12, 0, 0, 16, 1, 0}, /* RX_PACKET_DATA_FIFO_ADDR_POINTER */
00035     {-1, 14, 0, 0, 8, 1, 0},  /* RX_PACKET_DATA_FIFO_STATUS */
00036     {-1, 15, 0, 0, 8, 1, 0},  /* RX_PACKET_DATA_FIFO_PAYLOAD_SIZE */
00037     {-1, 16, 0, 0, 1, 0, 0},  /* MBWSSF_MODEM_ENABLE */
00038     {-1, 16, 1, 0, 1, 0, 0},  /* CONCENTRATOR_MODEM_ENABLE */
00039     {-1, 16, 2, 0, 1, 0, 0},  /* FSK_MODEM_ENABLE */
00040     {-1, 16, 3, 0, 1, 0, 0},  /* GLOBAL_EN */
00041     {-1, 17, 0, 0, 1, 0, 1},  /* CLK32M_EN */
00042     {-1, 17, 1, 0, 1, 0, 1},  /* CLKHS_EN */
00043     {-1, 18, 0, 0, 1, 0, 0},  /* START_BIST0 */
00044     {-1, 18, 1, 0, 1, 0, 0},  /* START_BIST1 */
00045     {-1, 18, 2, 0, 1, 0, 0},  /* CLEAR_BIST0 */
00046     {-1, 18, 3, 0, 1, 0, 0},  /* CLEAR_BIST1 */
00047     {-1, 19, 0, 0, 1, 1, 0},  /* BIST0_FINISHED */
00048     {-1, 19, 1, 0, 1, 1, 0},  /* BIST1_FINISHED */
00049     {-1, 20, 0, 0, 1, 1, 0},  /* MCU_AGC_PROG_RAM_BIST_STATUS */
00050     {-1, 20, 1, 0, 1, 1, 0},  /* MCU_ARB_PROG_RAM_BIST_STATUS */
00051     {-1, 20, 2, 0, 1, 1, 0},  /* CAPTURE_RAM_BIST_STATUS */
00052     {-1, 20, 3, 0, 1, 1, 0},  /* CHAN_FIR_RAM0_BIST_STATUS */
00053     {-1, 20, 4, 0, 1, 1, 0},  /* CHAN_FIR_RAM1_BIST_STATUS */
00054     {-1, 21, 0, 0, 1, 1, 0},  /* CORR0_RAM_BIST_STATUS */
00055     {-1, 21, 1, 0, 1, 1, 0},  /* CORR1_RAM_BIST_STATUS */
00056     {-1, 21, 2, 0, 1, 1, 0},  /* CORR2_RAM_BIST_STATUS */
00057     {-1, 21, 3, 0, 1, 1, 0},  /* CORR3_RAM_BIST_STATUS */
00058     {-1, 21, 4, 0, 1, 1, 0},  /* CORR4_RAM_BIST_STATUS */
00059     {-1, 21, 5, 0, 1, 1, 0},  /* CORR5_RAM_BIST_STATUS */
00060     {-1, 21, 6, 0, 1, 1, 0},  /* CORR6_RAM_BIST_STATUS */
00061     {-1, 21, 7, 0, 1, 1, 0},  /* CORR7_RAM_BIST_STATUS */
00062     {-1, 22, 0, 0, 1, 1, 0},  /* MODEM0_RAM0_BIST_STATUS */
00063     {-1, 22, 1, 0, 1, 1, 0},  /* MODEM1_RAM0_BIST_STATUS */
00064     {-1, 22, 2, 0, 1, 1, 0},  /* MODEM2_RAM0_BIST_STATUS */
00065     {-1, 22, 3, 0, 1, 1, 0},  /* MODEM3_RAM0_BIST_STATUS */
00066     {-1, 22, 4, 0, 1, 1, 0},  /* MODEM4_RAM0_BIST_STATUS */
00067     {-1, 22, 5, 0, 1, 1, 0},  /* MODEM5_RAM0_BIST_STATUS */
00068     {-1, 22, 6, 0, 1, 1, 0},  /* MODEM6_RAM0_BIST_STATUS */
00069     {-1, 22, 7, 0, 1, 1, 0},  /* MODEM7_RAM0_BIST_STATUS */
00070     {-1, 23, 0, 0, 1, 1, 0},  /* MODEM0_RAM1_BIST_STATUS */
00071     {-1, 23, 1, 0, 1, 1, 0},  /* MODEM1_RAM1_BIST_STATUS */
00072     {-1, 23, 2, 0, 1, 1, 0},  /* MODEM2_RAM1_BIST_STATUS */
00073     {-1, 23, 3, 0, 1, 1, 0},  /* MODEM3_RAM1_BIST_STATUS */
00074     {-1, 23, 4, 0, 1, 1, 0},  /* MODEM4_RAM1_BIST_STATUS */
00075     {-1, 23, 5, 0, 1, 1, 0},  /* MODEM5_RAM1_BIST_STATUS */
00076     {-1, 23, 6, 0, 1, 1, 0},  /* MODEM6_RAM1_BIST_STATUS */
00077     {-1, 23, 7, 0, 1, 1, 0},  /* MODEM7_RAM1_BIST_STATUS */
00078     {-1, 24, 0, 0, 1, 1, 0},  /* MODEM0_RAM2_BIST_STATUS */
00079     {-1, 24, 1, 0, 1, 1, 0},  /* MODEM1_RAM2_BIST_STATUS */
00080     {-1, 24, 2, 0, 1, 1, 0},  /* MODEM2_RAM2_BIST_STATUS */
00081     {-1, 24, 3, 0, 1, 1, 0},  /* MODEM3_RAM2_BIST_STATUS */
00082     {-1, 24, 4, 0, 1, 1, 0},  /* MODEM4_RAM2_BIST_STATUS */
00083     {-1, 24, 5, 0, 1, 1, 0},  /* MODEM5_RAM2_BIST_STATUS */
00084     {-1, 24, 6, 0, 1, 1, 0},  /* MODEM6_RAM2_BIST_STATUS */
00085     {-1, 24, 7, 0, 1, 1, 0},  /* MODEM7_RAM2_BIST_STATUS */
00086     {-1, 25, 0, 0, 1, 1, 0},  /* MODEM_MBWSSF_RAM0_BIST_STATUS */
00087     {-1, 25, 1, 0, 1, 1, 0},  /* MODEM_MBWSSF_RAM1_BIST_STATUS */
00088     {-1, 25, 2, 0, 1, 1, 0},  /* MODEM_MBWSSF_RAM2_BIST_STATUS */
00089     {-1, 26, 0, 0, 1, 1, 0},  /* MCU_AGC_DATA_RAM_BIST0_STATUS */
00090     {-1, 26, 1, 0, 1, 1, 0},  /* MCU_AGC_DATA_RAM_BIST1_STATUS */
00091     {-1, 26, 2, 0, 1, 1, 0},  /* MCU_ARB_DATA_RAM_BIST0_STATUS */
00092     {-1, 26, 3, 0, 1, 1, 0},  /* MCU_ARB_DATA_RAM_BIST1_STATUS */
00093     {-1, 26, 4, 0, 1, 1, 0},  /* TX_TOP_RAM_BIST0_STATUS */
00094     {-1, 26, 5, 0, 1, 1, 0},  /* TX_TOP_RAM_BIST1_STATUS */
00095     {-1, 26, 6, 0, 1, 1, 0},  /* DATA_MNGT_RAM_BIST0_STATUS */
00096     {-1, 26, 7, 0, 1, 1, 0},  /* DATA_MNGT_RAM_BIST1_STATUS */
00097     {-1, 27, 0, 0, 4, 0, 0},  /* GPIO_SELECT_INPUT */
00098     {-1, 28, 0, 0, 4, 0, 0},  /* GPIO_SELECT_OUTPUT */
00099     {-1, 29, 0, 0, 5, 0, 0},  /* GPIO_MODE */
00100     {-1, 30, 0, 0, 5, 1, 0},  /* GPIO_PIN_REG_IN */
00101     {-1, 31, 0, 0, 5, 0, 0},  /* GPIO_PIN_REG_OUT */
00102     {-1, 32, 0, 0, 8, 1, 0},  /* MCU_AGC_STATUS */
00103     {-1, 125, 0, 0, 8, 1, 0}, /* MCU_ARB_STATUS */
00104     {-1, 126, 0, 0, 8, 1, 1}, /* CHIP_ID */
00105     {-1, 127, 0, 0, 1, 0, 1}, /* EMERGENCY_FORCE_HOST_CTRL */
00106     {0, 33, 0, 0, 1, 0, 0},   /* RX_INVERT_IQ */
00107     {0, 33, 1, 0, 1, 0, 1},   /* MODEM_INVERT_IQ */
00108     {0, 33, 2, 0, 1, 0, 0},   /* MBWSSF_MODEM_INVERT_IQ */
00109     {0, 33, 3, 0, 1, 0, 0},   /* RX_EDGE_SELECT */
00110     {0, 33, 4, 0, 1, 0, 0},   /* MISC_RADIO_EN */
00111     {0, 33, 5, 0, 1, 0, 0},   /* FSK_MODEM_INVERT_IQ */
00112     {0, 34, 0, 0, 4, 0, 7},   /* FILTER_GAIN */
00113     {0, 35, 0, 0, 8, 0, 240}, /* RADIO_SELECT */
00114     {0, 36, 0, 1, 13, 0, -384}, /* IF_FREQ_0 */
00115     {0, 38, 0, 1, 13, 0, -128}, /* IF_FREQ_1 */
00116     {0, 40, 0, 1, 13, 0, 128}, /* IF_FREQ_2 */
00117     {0, 42, 0, 1, 13, 0, 384}, /* IF_FREQ_3 */
00118     {0, 44, 0, 1, 13, 0, -384}, /* IF_FREQ_4 */
00119     {0, 46, 0, 1, 13, 0, -128}, /* IF_FREQ_5 */
00120     {0, 48, 0, 1, 13, 0, 128}, /* IF_FREQ_6 */
00121     {0, 50, 0, 1, 13, 0, 384}, /* IF_FREQ_7 */
00122     {0, 52, 0, 1, 13, 0, 0},  /* IF_FREQ_8 */
00123     {0, 54, 0, 1, 13, 0, 0},  /* IF_FREQ_9 */
00124     {0, 64, 0, 0, 1, 0, 0},  /* CHANN_OVERRIDE_AGC_GAIN */
00125     {0, 64, 1, 0, 4, 0, 7},  /* CHANN_AGC_GAIN */
00126     {0, 65, 0, 0, 7, 0, 0},  /* CORR0_DETECT_EN */
00127     {0, 66, 0, 0, 7, 0, 0},  /* CORR1_DETECT_EN */
00128     {0, 67, 0, 0, 7, 0, 0},  /* CORR2_DETECT_EN */
00129     {0, 68, 0, 0, 7, 0, 0},  /* CORR3_DETECT_EN */
00130     {0, 69, 0, 0, 7, 0, 0},  /* CORR4_DETECT_EN */
00131     {0, 70, 0, 0, 7, 0, 0},  /* CORR5_DETECT_EN */
00132     {0, 71, 0, 0, 7, 0, 0},  /* CORR6_DETECT_EN */
00133     {0, 72, 0, 0, 7, 0, 0},  /* CORR7_DETECT_EN */
00134     {0, 73, 0, 0, 1, 0, 0},  /* CORR_SAME_PEAKS_OPTION_SF6 */
00135     {0, 73, 1, 0, 1, 0, 1},  /* CORR_SAME_PEAKS_OPTION_SF7 */
00136     {0, 73, 2, 0, 1, 0, 1},  /* CORR_SAME_PEAKS_OPTION_SF8 */
00137     {0, 73, 3, 0, 1, 0, 1},  /* CORR_SAME_PEAKS_OPTION_SF9 */
00138     {0, 73, 4, 0, 1, 0, 1},  /* CORR_SAME_PEAKS_OPTION_SF10 */
00139     {0, 73, 5, 0, 1, 0, 1},  /* CORR_SAME_PEAKS_OPTION_SF11 */
00140     {0, 73, 6, 0, 1, 0, 1},  /* CORR_SAME_PEAKS_OPTION_SF12 */
00141     {0, 74, 0, 0, 4, 0, 4},  /* CORR_SIG_NOISE_RATIO_SF6 */
00142     {0, 74, 4, 0, 4, 0, 4},  /* CORR_SIG_NOISE_RATIO_SF7 */
00143     {0, 75, 0, 0, 4, 0, 4},  /* CORR_SIG_NOISE_RATIO_SF8 */
00144     {0, 75, 4, 0, 4, 0, 4},  /* CORR_SIG_NOISE_RATIO_SF9 */
00145     {0, 76, 0, 0, 4, 0, 4},  /* CORR_SIG_NOISE_RATIO_SF10 */
00146     {0, 76, 4, 0, 4, 0, 4},  /* CORR_SIG_NOISE_RATIO_SF11 */
00147     {0, 77, 0, 0, 4, 0, 4},  /* CORR_SIG_NOISE_RATIO_SF12 */
00148     {0, 78, 0, 0, 4, 0, 4},  /* CORR_NUM_SAME_PEAK */
00149     {0, 78, 4, 0, 3, 0, 5},  /* CORR_MAC_GAIN */
00150     {0, 81, 0, 0, 12, 0, 0}, /* ADJUST_MODEM_START_OFFSET_RDX4 */
00151     {0, 83, 0, 0, 12, 0, 4092}, /* ADJUST_MODEM_START_OFFSET_SF12_RDX4 */
00152     {0, 85, 0, 0, 8, 0, 7},  /* DBG_CORR_SELECT_SF */
00153     {0, 86, 0, 0, 8, 0, 0},  /* DBG_CORR_SELECT_CHANNEL */
00154     {0, 87, 0, 0, 8, 1, 0},  /* DBG_DETECT_CPT */
00155     {0, 88, 0, 0, 8, 1, 0},  /* DBG_SYMB_CPT */
00156     {0, 89, 0, 0, 1, 0, 1},  /* CHIRP_INVERT_RX */
00157     {0, 89, 1, 0, 1, 0, 1},  /* DC_NOTCH_EN */
00158     {0, 90, 0, 0, 1, 0, 0},  /* IMPLICIT_CRC_EN */
00159     {0, 90, 1, 0, 3, 0, 0},  /* IMPLICIT_CODING_RATE */
00160     {0, 91, 0, 0, 8, 0, 0},  /* IMPLICIT_PAYLOAD_LENGHT */
00161     {0, 92, 0, 0, 8, 0, 29}, /* FREQ_TO_TIME_INVERT */
00162     {0, 93, 0, 0, 6, 0, 9},  /* FREQ_TO_TIME_DRIFT */
00163     {0, 94, 0, 0, 2, 0, 2},  /* PAYLOAD_FINE_TIMING_GAIN */
00164     {0, 94, 2, 0, 2, 0, 1},  /* PREAMBLE_FINE_TIMING_GAIN */
00165     {0, 94, 4, 0, 2, 0, 0},  /* TRACKING_INTEGRAL */
00166     {0, 95, 0, 0, 4, 0, 1},  /* FRAME_SYNCH_PEAK1_POS */
00167     {0, 95, 4, 0, 4, 0, 2},  /* FRAME_SYNCH_PEAK2_POS */
00168     {0, 96, 0, 0, 16, 0, 10}, /* PREAMBLE_SYMB1_NB */
00169     {0, 98, 0, 0, 1, 0, 1},  /* FRAME_SYNCH_GAIN */
00170     {0, 98, 1, 0, 1, 0, 1},  /* SYNCH_DETECT_TH */
00171     {0, 99, 0, 0, 4, 0, 8},  /* LLR_SCALE */
00172     {0, 99, 4, 0, 2, 0, 2},  /* SNR_AVG_CST */
00173     {0, 100, 0, 0, 7, 0, 0}, /* PPM_OFFSET */
00174     {0, 101, 0, 0, 8, 0, 255}, /* MAX_PAYLOAD_LEN */
00175     {0, 102, 0, 0, 1, 0, 1},  /* ONLY_CRC_EN */
00176     {0, 103, 0, 0, 8, 0, 0},  /* ZERO_PAD */
00177     {0, 104, 0, 0, 4, 0, 8},  /* DEC_GAIN_OFFSET */
00178     {0, 104, 4, 0, 4, 0, 7},  /* CHAN_GAIN_OFFSET */
00179     {0, 105, 1, 0, 1, 0, 1},  /* FORCE_HOST_RADIO_CTRL */
00180     {0, 105, 2, 0, 1, 0, 1},  /* FORCE_HOST_FE_CTRL */
00181     {0, 105, 3, 0, 1, 0, 1},  /* FORCE_DEC_FILTER_GAIN */
00182     {0, 106, 0, 0, 1, 0, 1},  /* MCU_RST_0 */
00183     {0, 106, 1, 0, 1, 0, 1},  /* MCU_RST_1 */
00184     {0, 106, 2, 0, 1, 0, 0},  /* MCU_SELECT_MUX_0 */
00185     {0, 106, 3, 0, 1, 0, 0},  /* MCU_SELECT_MUX_1 */
00186     {0, 106, 4, 0, 1, 1, 0},  /* MCU_CORRUPTION_DETECTED_0 */
00187     {0, 106, 5, 0, 1, 1, 0},  /* MCU_CORRUPTION_DETECTED_1 */
00188     {0, 106, 6, 0, 1, 0, 0},  /* MCU_SELECT_EDGE_0 */
00189     {0, 106, 7, 0, 1, 0, 0},  /* MCU_SELECT_EDGE_1 */
00190     {0, 107, 0, 0, 8, 0, 1},  /* CHANN_SELECT_RSSI */
00191     {0, 108, 0, 0, 8, 0, 32}, /* RSSI_BB_DEFAULT_VALUE */
00192     {0, 109, 0, 0, 8, 0, 100}, /* RSSI_DEC_DEFAULT_VALUE */
00193     {0, 110, 0, 0, 8, 0, 100}, /* RSSI_CHANN_DEFAULT_VALUE */
00194     {0, 111, 0, 0, 5, 0, 7},  /* RSSI_BB_FILTER_ALPHA */
00195     {0, 112, 0, 0, 5, 0, 5},  /* RSSI_DEC_FILTER_ALPHA */
00196     {0, 113, 0, 0, 5, 0, 8},  /* RSSI_CHANN_FILTER_ALPHA */
00197     {0, 114, 0, 0, 6, 0, 0},  /* IQ_MISMATCH_A_AMP_COEFF */
00198     {0, 115, 0, 0, 6, 0, 0},  /* IQ_MISMATCH_A_PHI_COEFF */
00199     {0, 116, 0, 0, 6, 0, 0},  /* IQ_MISMATCH_B_AMP_COEFF */
00200     {0, 116, 6, 0, 1, 0, 0},  /* IQ_MISMATCH_B_SEL_I */
00201     {0, 117, 0, 0, 6, 0, 0},  /* IQ_MISMATCH_B_PHI_COEFF */
00202     {1, 33, 0, 0, 1, 0, 0},   /* TX_TRIG_IMMEDIATE */
00203     {1, 33, 1, 0, 1, 0, 0},   /* TX_TRIG_DELAYED */
00204     {1, 33, 2, 0, 1, 0, 0},   /* TX_TRIG_GPS */
00205     {1, 34, 0, 0, 16, 0, 0},  /* TX_START_DELAY */
00206     {1, 36, 0, 0, 4, 0, 1},  /* TX_FRAME_SYNCH_PEAK1_POS */
00207     {1, 36, 4, 0, 4, 0, 2},  /* TX_FRAME_SYNCH_PEAK2_POS */
00208     {1, 37, 0, 0, 3, 0, 0},  /* TX_RAMP_DURATION */
00209     {1, 39, 0, 1, 8, 0, 0},  /* TX_OFFSET_I */
00210     {1, 40, 0, 1, 8, 0, 0},  /* TX_OFFSET_Q */
00211     {1, 41, 0, 0, 1, 0, 0},  /* TX_MODE */
00212     {1, 41, 1, 0, 4, 0, 0},  /* TX_ZERO_PAD */
00213     {1, 41, 5, 0, 1, 0, 0},  /* TX_EDGE_SELECT */
00214     {1, 41, 6, 0, 1, 0, 0},  /* TX_EDGE_SELECT_TOP */
00215     {1, 42, 0, 0, 2, 0, 0},  /* TX_GAIN */
00216     {1, 42, 2, 0, 3, 0, 5},  /* TX_CHIRP_LOW_PASS */
00217     {1, 42, 5, 0, 2, 0, 0},  /* TX_FCC_WIDEBAND */
00218     {1, 42, 7, 0, 1, 0, 1},  /* TX_SWAP_IQ */
00219     {1, 43, 0, 0, 1, 0, 0},  /* MBWSSF_IMPLICIT_HEADER */
00220     {1, 43, 1, 0, 1, 0, 0},  /* MBWSSF_IMPLICIT_CRC_EN */
00221     {1, 43, 2, 0, 3, 0, 0},  /* MBWSSF_IMPLICIT_CODING_RATE */
00222     {1, 44, 0, 0, 8, 0, 0},  /* MBWSSF_IMPLICIT_PAYLOAD_LENGHT */
00223     {1, 45, 0, 0, 1, 0, 1},  /* MBWSSF_AGC_FREEZE_ON_DETECT */
00224     {1, 46, 0, 0, 4, 0, 1},  /* MBWSSF_FRAME_SYNCH_PEAK1_POS */
00225     {1, 46, 4, 0, 4, 0, 2},  /* MBWSSF_FRAME_SYNCH_PEAK2_POS */
00226     {1, 47, 0, 0, 16, 0, 10}, /* MBWSSF_PREAMBLE_SYMB1_NB */
00227     {1, 49, 0, 0, 1, 0, 1},  /* MBWSSF_FRAME_SYNCH_GAIN */
00228     {1, 49, 1, 0, 1, 0, 1},  /* MBWSSF_SYNCH_DETECT_TH */
00229     {1, 50, 0, 0, 8, 0, 10}, /* MBWSSF_DETECT_MIN_SINGLE_PEAK */
00230     {1, 51, 0, 0, 3, 0, 3},  /* MBWSSF_DETECT_TRIG_SAME_PEAK_NB */
00231     {1, 52, 0, 0, 8, 0, 29}, /* MBWSSF_FREQ_TO_TIME_INVERT */
00232     {1, 53, 0, 0, 6, 0, 36}, /* MBWSSF_FREQ_TO_TIME_DRIFT */
00233     {1, 54, 0, 0, 12, 0, 0}, /* MBWSSF_PPM_CORRECTION */
00234     {1, 56, 0, 0, 2, 0, 2},  /* MBWSSF_PAYLOAD_FINE_TIMING_GAIN */
00235     {1, 56, 2, 0, 2, 0, 1},  /* MBWSSF_PREAMBLE_FINE_TIMING_GAIN */
00236     {1, 56, 4, 0, 2, 0, 0},  /* MBWSSF_TRACKING_INTEGRAL */
00237     {1, 57, 0, 0, 8, 0, 0},  /* MBWSSF_ZERO_PAD */
00238     {1, 58, 0, 0, 2, 0, 0},  /* MBWSSF_MODEM_BW */
00239     {1, 58, 2, 0, 1, 0, 0},  /* MBWSSF_RADIO_SELECT */
00240     {1, 58, 3, 0, 1, 0, 1},  /* MBWSSF_RX_CHIRP_INVERT */
00241     {1, 59, 0, 0, 4, 0, 8},  /* MBWSSF_LLR_SCALE */
00242     {1, 59, 4, 0, 2, 0, 3},  /* MBWSSF_SNR_AVG_CST */
00243     {1, 59, 6, 0, 1, 0, 0},  /* MBWSSF_PPM_OFFSET */
00244     {1, 60, 0, 0, 4, 0, 7},  /* MBWSSF_RATE_SF */
00245     {1, 60, 4, 0, 1, 0, 1},  /* MBWSSF_ONLY_CRC_EN */
00246     {1, 61, 0, 0, 8, 0, 255}, /* MBWSSF_MAX_PAYLOAD_LEN */
00247     {1, 62, 0, 0, 8, 1, 128}, /* TX_STATUS */
00248     {1, 63, 0, 0, 3, 0, 0},  /* FSK_CH_BW_EXPO */
00249     {1, 63, 3, 0, 3, 0, 0},  /* FSK_RSSI_LENGTH */
00250     {1, 63, 6, 0, 1, 0, 0},  /* FSK_RX_INVERT */
00251     {1, 63, 7, 0, 1, 0, 0},  /* FSK_PKT_MODE */
00252     {1, 64, 0, 0, 3, 0, 0},  /* FSK_PSIZE */
00253     {1, 64, 3, 0, 1, 0, 0},  /* FSK_CRC_EN */
00254     {1, 64, 4, 0, 2, 0, 0},  /* FSK_DCFREE_ENC */
00255     {1, 64, 6, 0, 1, 0, 0},  /* FSK_CRC_IBM */
00256     {1, 65, 0, 0, 5, 0, 0},  /* FSK_ERROR_OSR_TOL */
00257     {1, 65, 7, 0, 1, 0, 0},  /* FSK_RADIO_SELECT */
00258     {1, 66, 0, 0, 16, 0, 0}, /* FSK_BR_RATIO */
00259     {1, 68, 0, 0, 32, 0, 0}, /* FSK_REF_PATTERN_LSB */
00260     {1, 72, 0, 0, 32, 0, 0}, /* FSK_REF_PATTERN_MSB */
00261     {1, 76, 0, 0, 8, 0, 0},  /* FSK_PKT_LENGTH */
00262     {1, 77, 0, 0, 1, 0, 1},  /* FSK_TX_GAUSSIAN_EN */
00263     {1, 77, 1, 0, 2, 0, 0},  /* FSK_TX_GAUSSIAN_SELECT_BT */
00264     {1, 77, 3, 0, 1, 0, 1},  /* FSK_TX_PATTERN_EN */
00265     {1, 77, 4, 0, 1, 0, 0},  /* FSK_TX_PREAMBLE_SEQ */
00266     {1, 77, 5, 0, 3, 0, 0},  /* FSK_TX_PSIZE */
00267     {1, 80, 0, 0, 8, 0, 0},  /* FSK_NODE_ADRS */
00268     {1, 81, 0, 0, 8, 0, 0},  /* FSK_BROADCAST */
00269     {1, 82, 0, 0, 1, 0, 1},  /* FSK_AUTO_AFC_ON */
00270     {1, 83, 0, 0, 10, 0, 0}, /* FSK_PATTERN_TIMEOUT_CFG */
00271     {2, 33, 0, 0, 8, 0, 0},  /* SPI_RADIO_A__DATA */
00272     {2, 34, 0, 0, 8, 1, 0},  /* SPI_RADIO_A__DATA_READBACK */
00273     {2, 35, 0, 0, 8, 0, 0},  /* SPI_RADIO_A__ADDR */
00274     {2, 37, 0, 0, 1, 0, 0},  /* SPI_RADIO_A__CS */
00275     {2, 38, 0, 0, 8, 0, 0},  /* SPI_RADIO_B__DATA */
00276     {2, 39, 0, 0, 8, 1, 0},  /* SPI_RADIO_B__DATA_READBACK */
00277     {2, 40, 0, 0, 8, 0, 0},  /* SPI_RADIO_B__ADDR */
00278     {2, 42, 0, 0, 1, 0, 0},  /* SPI_RADIO_B__CS */
00279     {2, 43, 0, 0, 1, 0, 0},  /* RADIO_A_EN */
00280     {2, 43, 1, 0, 1, 0, 0},  /* RADIO_B_EN */
00281     {2, 43, 2, 0, 1, 0, 1},  /* RADIO_RST */
00282     {2, 43, 3, 0, 1, 0, 0},  /* LNA_A_EN */
00283     {2, 43, 4, 0, 1, 0, 0},  /* PA_A_EN */
00284     {2, 43, 5, 0, 1, 0, 0},  /* LNA_B_EN */
00285     {2, 43, 6, 0, 1, 0, 0},  /* PA_B_EN */
00286     {2, 44, 0, 0, 2, 0, 0},  /* PA_GAIN */
00287     {2, 45, 0, 0, 4, 0, 2},  /* LNA_A_CTRL_LUT */
00288     {2, 45, 4, 0, 4, 0, 4},  /* PA_A_CTRL_LUT */
00289     {2, 46, 0, 0, 4, 0, 2},  /* LNA_B_CTRL_LUT */
00290     {2, 46, 4, 0, 4, 0, 4},  /* PA_B_CTRL_LUT */
00291     {2, 47, 0, 0, 5, 0, 0},  /* CAPTURE_SOURCE */
00292     {2, 47, 5, 0, 1, 0, 0},  /* CAPTURE_START */
00293     {2, 47, 6, 0, 1, 0, 0},  /* CAPTURE_FORCE_TRIGGER */
00294     {2, 47, 7, 0, 1, 0, 0},  /* CAPTURE_WRAP */
00295     {2, 48, 0, 0, 16, 0, 0}, /* CAPTURE_PERIOD */
00296     {2, 51, 0, 0, 8, 1, 0},  /* MODEM_STATUS */
00297     {2, 52, 0, 0, 8, 1, 0},  /* VALID_HEADER_COUNTER_0 */
00298     {2, 54, 0, 0, 8, 1, 0},  /* VALID_PACKET_COUNTER_0 */
00299     {2, 56, 0, 0, 8, 1, 0},  /* VALID_HEADER_COUNTER_MBWSSF */
00300     {2, 57, 0, 0, 8, 1, 0},  /* VALID_HEADER_COUNTER_FSK */
00301     {2, 58, 0, 0, 8, 1, 0},  /* VALID_PACKET_COUNTER_MBWSSF */
00302     {2, 59, 0, 0, 8, 1, 0},  /* VALID_PACKET_COUNTER_FSK */
00303     {2, 60, 0, 0, 8, 1, 0},  /* CHANN_RSSI */
00304     {2, 61, 0, 0, 8, 1, 0},  /* BB_RSSI */
00305     {2, 62, 0, 0, 8, 1, 0},  /* DEC_RSSI */
00306     {2, 63, 0, 0, 8, 1, 0},  /* DBG_MCU_DATA */
00307     {2, 64, 0, 0, 8, 1, 0},  /* DBG_ARB_MCU_RAM_DATA */
00308     {2, 65, 0, 0, 8, 1, 0},  /* DBG_AGC_MCU_RAM_DATA */
00309     {2, 66, 0, 0, 16, 1, 0}, /* NEXT_PACKET_CNT */
00310     {2, 68, 0, 0, 16, 1, 0}, /* ADDR_CAPTURE_COUNT */
00311     {2, 70, 0, 0, 32, 1, 0}, /* TIMESTAMP */
00312     {2, 74, 0, 0, 4, 1, 0},  /* DBG_CHANN0_GAIN */
00313     {2, 74, 4, 0, 4, 1, 0},  /* DBG_CHANN1_GAIN */
00314     {2, 75, 0, 0, 4, 1, 0},  /* DBG_CHANN2_GAIN */
00315     {2, 75, 4, 0, 4, 1, 0},  /* DBG_CHANN3_GAIN */
00316     {2, 76, 0, 0, 4, 1, 0},  /* DBG_CHANN4_GAIN */
00317     {2, 76, 4, 0, 4, 1, 0},  /* DBG_CHANN5_GAIN */
00318     {2, 77, 0, 0, 4, 1, 0},  /* DBG_CHANN6_GAIN */
00319     {2, 77, 4, 0, 4, 1, 0},  /* DBG_CHANN7_GAIN */
00320     {2, 78, 0, 0, 4, 1, 0},  /* DBG_DEC_FILT_GAIN */
00321     {2, 79, 0, 0, 3, 1, 0},  /* SPI_DATA_FIFO_PTR */
00322     {2, 79, 3, 0, 3, 1, 0},  /* PACKET_DATA_FIFO_PTR */
00323     {2, 80, 0, 0, 8, 0, 0},  /* DBG_ARB_MCU_RAM_ADDR */
00324     {2, 81, 0, 0, 8, 0, 0},  /* DBG_AGC_MCU_RAM_ADDR */
00325     {2, 82, 0, 0, 1, 0, 0},  /* SPI_MASTER_CHIP_SELECT_POLARITY */
00326     {2, 82, 1, 0, 1, 0, 0},  /* SPI_MASTER_CPOL */
00327     {2, 82, 2, 0, 1, 0, 0},  /* SPI_MASTER_CPHA */
00328     {2, 83, 0, 0, 1, 0, 0},  /* SIG_GEN_ANALYSER_MUX_SEL */
00329     {2, 84, 0, 0, 1, 0, 0},  /* SIG_GEN_EN */
00330     {2, 84, 1, 0, 1, 0, 0},  /* SIG_ANALYSER_EN */
00331     {2, 84, 2, 0, 2, 0, 0},  /* SIG_ANALYSER_AVG_LEN */
00332     {2, 84, 4, 0, 3, 0, 0},  /* SIG_ANALYSER_PRECISION */
00333     {2, 84, 7, 0, 1, 1, 0},  /* SIG_ANALYSER_VALID_OUT */
00334     {2, 85, 0, 0, 8, 0, 0},  /* SIG_GEN_FREQ */
00335     {2, 86, 0, 0, 8, 0, 0},  /* SIG_ANALYSER_FREQ */
00336     {2, 87, 0, 0, 8, 1, 0},  /* SIG_ANALYSER_I_OUT */
00337     {2, 88, 0, 0, 8, 1, 0},  /* SIG_ANALYSER_Q_OUT */
00338     {2, 89, 0, 0, 1, 0, 0},  /* GPS_EN */
00339     {2, 89, 1, 0, 1, 0, 1},  /* GPS_POL */
00340     {2, 90, 0, 1, 8, 0, 0},  /* SW_TEST_REG1 */
00341     {2, 91, 2, 1, 6, 0, 0},  /* SW_TEST_REG2 */
00342     {2, 92, 0, 1, 16, 0, 0}, /* SW_TEST_REG3 */
00343     {2, 94, 0, 0, 4, 1, 0},  /* DATA_MNGT_STATUS */
00344     {2, 95, 0, 0, 5, 1, 0},  /* DATA_MNGT_CPT_FRAME_ALLOCATED */
00345     {2, 96, 0, 0, 5, 1, 0},  /* DATA_MNGT_CPT_FRAME_FINISHED */
00346     {2, 97, 0, 0, 5, 1, 0},  /* DATA_MNGT_CPT_FRAME_READEN */
00347     {1, 33, 0, 0, 8, 0, 0}   /* TX_TRIG_ALL (alias) */
00348 };
00349 
00350 /* -------------------------------------------------------------------------- */
00351 /* --- PRIVATE VARIABLES ---------------------------------------------------- */
00352 
00353 static int lgw_regpage = -1; /*! keep the value of the register page selected */
00354 
00355 /* -------------------------------------------------------------------------- */
00356 /* --- PRIVATE FUNCTIONS ---------------------------------------------------- */
00357 
00358 int page_switch(uint8_t target) {
00359     lgw_regpage = PAGE_MASK & target;
00360     Sx1308.spiWrite(PAGE_ADDR, (uint8_t)lgw_regpage);
00361     return LGW_REG_SUCCESS;
00362 }
00363 
00364 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
00365 
00366 /* soft-reset function */
00367 int lgw_soft_reset(void) {
00368     Sx1308.spiWrite(0, 0x80); /* 1 -> SOFT_RESET bit */
00369     lgw_regpage = 0; /* reset the paging static variable */
00370     return LGW_REG_SUCCESS;
00371 }
00372 
00373 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
00374 
00375 int reg_w_align32(void *spi_target, uint8_t spi_mux_mode, uint8_t spi_mux_target, struct lgw_reg_s r, int32_t reg_value) {
00376     int i, size_byte;
00377     uint8_t buf[4] = {0, 0, 0, 0};
00378 
00379     if ((r.leng == 8) && (r.offs == 0)) {
00380         /* direct write */
00381         Sx1308.spiWrite(r.addr, (uint8_t)reg_value);
00382     } else if ((r.offs + r.leng) <= 8) {
00383         /* single-byte read-modify-write, offs:[0-7], leng:[1-7] */
00384         buf[0] = Sx1308.spiRead(r.addr);
00385         buf[1] = ((1 << r.leng) - 1) << r.offs; /* bit mask */
00386         buf[2] = ((uint8_t)reg_value) << r.offs; /* new data offsetted */
00387         buf[3] = (~buf[1] & buf[0]) | (buf[1] & buf[2]); /* mixing old & new data */
00388         Sx1308.spiWrite(r.addr, (uint8_t)buf[3]);
00389     } else if ((r.offs == 0) && (r.leng > 0) && (r.leng <= 32)) {
00390         /* multi-byte direct write routine */
00391         size_byte = (r.leng + 7) / 8; /* add a byte if it's not an exact multiple of 8 */
00392         for (i = 0; i < size_byte; ++i) {
00393             /* big endian register file for a file on N bytes
00394             Least significant byte is stored in buf[0], most one in buf[N-1] */
00395             buf[i] = (uint8_t)(0x000000FF & reg_value);
00396             reg_value = (reg_value >> 8);
00397         }
00398         Sx1308.spiWriteBurst( r.addr, buf, size_byte);
00399     } else {
00400         /* register spanning multiple memory bytes but with an offset */
00401 
00402         return LGW_REG_ERROR;
00403     }
00404 
00405     return LGW_REG_SUCCESS;
00406 }
00407 
00408 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
00409 
00410 int reg_r_align32(void *spi_target, uint8_t spi_mux_mode, uint8_t spi_mux_target, struct lgw_reg_s r, int32_t *reg_value) {
00411     uint8_t bufu[4] = {0, 0, 0, 0};
00412     int8_t *bufs = (int8_t *)bufu;
00413     int i, size_byte;
00414     uint32_t u = 0;
00415 
00416     if ((r.offs + r.leng) <= 8) {
00417         /* read one byte, then shift and mask bits to get reg value with sign extension if needed */
00418         bufu[0] = Sx1308.spiRead(r.addr);
00419         bufu[1] = bufu[0] << (8 - r.leng - r.offs); /* left-align the data */
00420         if (r.sign == true) {
00421             bufs[2] = bufs[1] >> (8 - r.leng); /* right align the data with sign extension (ARITHMETIC right shift) */
00422             *reg_value = (int32_t)bufs[2]; /* signed pointer -> 32b sign extension */
00423         } else {
00424             bufu[2] = bufu[1] >> (8 - r.leng); /* right align the data, no sign extension */
00425             *reg_value = (int32_t)bufu[2]; /* unsigned pointer -> no sign extension */
00426         }
00427     } else if ((r.offs == 0) && (r.leng > 0) && (r.leng <= 32)) {
00428         size_byte = (r.leng + 7) / 8; /* add a byte if it's not an exact multiple of 8 */
00429         Sx1308.spiReadBurst(r.addr, bufu, size_byte);
00430         u = 0;
00431         for (i = (size_byte - 1); i >= 0; --i) {
00432             u = (uint32_t)bufu[i] + (u << 8); /* transform a 4-byte array into a 32 bit word */
00433         }
00434         if (r.sign == true) {
00435             u = u << (32 - r.leng); /* left-align the data */
00436             *reg_value = (int32_t)u >> (32 - r.leng); /* right-align the data with sign extension (ARITHMETIC right shift) */
00437         } else {
00438             *reg_value = (int32_t)u; /* unsigned value -> return 'as is' */
00439         }
00440     } else {
00441         /* register spanning multiple memory bytes but with an offset */
00442         return LGW_REG_ERROR;
00443     }
00444 
00445     return LGW_REG_SUCCESS;
00446 }
00447 
00448 /* -------------------------------------------------------------------------- */
00449 /* --- PUBLIC FUNCTIONS DEFINITION ------------------------------------------ */
00450 
00451 int lgw_connect(void) {
00452     Sx1308.init();
00453     Sx1308.spiWrite(LGW_PAGE_REG, 0);
00454     
00455     return LGW_REG_SUCCESS;
00456 }
00457 
00458 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
00459 
00460 int lgw_reg_w(uint16_t register_id, int32_t reg_value) {
00461     struct lgw_reg_s r;
00462 
00463     /* check input parameters */
00464     if (register_id >= LGW_TOTALREGS) {
00465         return LGW_REG_ERROR;
00466     }
00467 
00468     /* intercept direct access to PAGE_REG & SOFT_RESET */
00469     if (register_id == LGW_PAGE_REG) {
00470         page_switch(reg_value);
00471         return LGW_REG_SUCCESS;
00472     } else if (register_id == LGW_SOFT_RESET) {
00473         /* only reset if lsb is 1 */
00474         if ((reg_value & 0x01) != 0) {
00475             return LGW_REG_SUCCESS;
00476         }
00477     }
00478 
00479     /* get register struct from the struct array */
00480     r = loregs[register_id];
00481 
00482     /* reject write to read-only registers */
00483     if (r.rdon == 1) {
00484 
00485         return LGW_REG_ERROR;
00486     }
00487 
00488     /* select proper register page if needed */
00489     if ((r.page != -1)) {
00490         page_switch(r.page);
00491     }
00492 
00493     reg_w_align32(0, 0, 0, r, reg_value);
00494 
00495     return LGW_REG_SUCCESS;
00496 }
00497 
00498 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
00499 
00500 int lgw_reg_r(uint16_t register_id, int32_t *reg_value) {
00501     struct lgw_reg_s r;
00502 
00503     /* get register struct from the struct array */
00504     r = loregs[register_id];
00505 
00506     /* select proper register page if needed */
00507     if ((r.page != -1)) { // && (r.page != lgw_regpage)) {
00508         page_switch(r.page);
00509     }
00510 
00511     reg_r_align32(0, 0, 0, r, reg_value);
00512 
00513     return LGW_REG_SUCCESS;
00514 
00515 }
00516 
00517 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
00518 
00519 int lgw_reg_wb(uint16_t register_id, uint8_t *data, uint16_t size) {
00520     struct lgw_reg_s r;
00521 
00522     /* check input parameters */
00523     if (size == 0) {
00524 
00525         return LGW_REG_ERROR;
00526     }
00527     if (register_id >= LGW_TOTALREGS) {
00528 
00529         return LGW_REG_ERROR;
00530     }
00531 
00532     /* get register struct from the struct array */
00533     r = loregs[register_id];
00534 
00535     /* reject write to read-only registers */
00536     if (r.rdon == 1) {
00537 
00538         return LGW_REG_ERROR;
00539     }
00540 
00541     /* select proper register page if needed */
00542     if ((r.page != -1)) {
00543         page_switch(r.page);
00544     }
00545 
00546     /* do the burst write */
00547     Sx1308.spiWriteBurst(r.addr, data, size);
00548 
00549     return LGW_REG_SUCCESS;
00550 
00551 }
00552 
00553 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
00554 
00555 int lgw_reg_rb(uint16_t register_id, uint8_t *data, uint16_t size) {
00556     struct lgw_reg_s r;
00557 
00558     /* check input parameters */
00559     if (size == 0) {
00560 
00561         return LGW_REG_ERROR;
00562     }
00563     if (register_id >= LGW_TOTALREGS) {
00564 
00565         return LGW_REG_ERROR;
00566     }
00567 
00568     /* get register struct from the struct array */
00569     r = loregs[register_id];
00570 
00571     /* select proper register page if needed */
00572     if ((r.page != -1)) {
00573         page_switch(r.page);
00574     }
00575 
00576     /* do the burst read */
00577     Sx1308.spiReadBurst(r.addr, data, size);
00578 
00579     return LGW_REG_SUCCESS;
00580 }