1 /*
2 * Copyright 2016-2017 NXP
3 *
4 * Redistribution and use in source and binary forms, with or without modification,
5 * are permitted provided that the following conditions are met:
6 *
7 * o Redistributions of source code must retain the above copyright notice, this list
8 *   of conditions and the following disclaimer.
9 *
10 * o Redistributions in binary form must reproduce the above copyright notice, this
11 *   list of conditions and the following disclaimer in the documentation and/or
12 *   other materials provided with the distribution.
13 *
14 * o Neither the name of Freescale Semiconductor, Inc. nor the names of its
15 *   contributors may be used to endorse or promote products derived from this
16 *   software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
22 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
25 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29 
30 #include "fsl_device_registers.h"
31 #include "fsl_common.h"
32 #include "fsl_xcvr.h"
33 #include "fsl_xcvr_trim.h"
34 #include "dbg_ram_capture.h"
35 #include "math.h"
36 
37 /*******************************************************************************
38 * Definitions
39 ******************************************************************************/
40 
41 
42 /*******************************************************************************
43 * Prototypes
44 ******************************************************************************/
45 void DC_Measure_short(IQ_t chan, DAC_SWEEP_STEP2_t dcoc_init_val);
46 float calc_dcoc_dac_step(GAIN_CALC_TBL_ENTRY2_T * meas_ptr, GAIN_CALC_TBL_ENTRY2_T * baseline_meas_ptr );
47 extern float roundf (float);
48 
49 /*******************************************************************************
50 * Variables
51 ******************************************************************************/
52 const int8_t TsettleCal = 10;
53 static GAIN_CALC_TBL_ENTRY2_T measurement_tbl2[NUM_I_Q_CHAN][NUM_SWEEP_STEP_ENTRIES2];
54 static const int8_t sweep_step_values2[NUM_SWEEP_STEP_ENTRIES2] =
55 {
56     0, /* Baseline entry is first and not used in this table */
57     -16,
58     +16,
59     -4,
60     -4,
61     -4,
62     -4,
63     -4,
64     -4,
65     -4,
66     -4,
67     -4,
68     -4,
69     -4,
70     +4,
71     +4,
72     +4,
73     +4,
74     +4,
75     +4,
76     +4,
77     +4,
78     +4,
79     +4,
80     +4
81 };
82 
83 /*******************************************************************************
84  * Macros
85  ******************************************************************************/
86 #define ISIGN(x) !((uint16_t)x & 0x8000)
87 #define ABS(x) ((x) > 0 ? (x) : -(x))
88 
89 /*******************************************************************************
90  * Code
91  ******************************************************************************/
92 /*! *********************************************************************************
93  * \brief  This function performs a trim of the BBA DCOC DAC on the DUT
94  *
95  * \return status - 1 if passed, 0 if failed.
96  *
97  * \ingroup PublicAPIs
98  *
99  * \details
100  *   Requires the RX to be warmed up before this function is called.
101  *
102  ***********************************************************************************/
rx_bba_dcoc_dac_trim_shortIQ(void)103 uint8_t rx_bba_dcoc_dac_trim_shortIQ(void)
104 {
105     uint8_t i;
106     float temp_mi = 0;
107     float temp_mq = 0;
108     float temp_pi = 0;
109     float temp_pq = 0;
110     float temp_step = 0;
111     uint8_t bbf_dacinit_i, bbf_dacinit_q;
112 
113     uint32_t dcoc_init_reg_value_dcgain = 0x80802020; /* Used in 2nd & 3rd Generation DCOC Trims only. */
114     uint32_t bbf_dcoc_step;
115     uint32_t bbf_dcoc_step_rcp;
116     TZAdcocstep_t tza_dcoc_step[11];
117     uint8_t status = 0;
118 
119     /* Save register values. */
120     uint32_t dcoc_ctrl_0_stack;
121     uint32_t dcoc_ctrl_1_stack;
122     uint32_t agc_ctrl_1_stack;
123     uint32_t rx_dig_ctrl_stack;
124     uint32_t dcoc_cal_gain_state;
125 
126     XcvrCalDelay(1000);
127     dcoc_ctrl_0_stack = XCVR_RX_DIG->DCOC_CTRL_0; /* Save state of DCOC_CTRL_0 for later restore. */
128     dcoc_ctrl_1_stack = XCVR_RX_DIG->DCOC_CTRL_1; /* Save state of DCOC_CTRL_1 for later restore. */
129     rx_dig_ctrl_stack =  XCVR_RX_DIG->RX_DIG_CTRL; /* Save state of RX_DIG_CTRL for later restore. */
130     agc_ctrl_1_stack = XCVR_RX_DIG->AGC_CTRL_1; /* Save state of RX_DIG_CTRL for later restore. */
131     dcoc_cal_gain_state = XCVR_RX_DIG->DCOC_CAL_GAIN; /* Save state of DCOC_CAL_GAIN for later restore. */
132 
133     /* Ensure AGC, DCOC and RX_DIG_CTRL is in correct mode. */
134     XCVR_RX_DIG->RX_DIG_CTRL = (XCVR_RX_DIG->RX_DIG_CTRL & ~XCVR_RX_DIG_RX_DIG_CTRL_RX_AGC_EN_MASK) | XCVR_RX_DIG_RX_DIG_CTRL_RX_AGC_EN(0); /* Turn OFF AGC */
135 
136     XCVR_RX_DIG->AGC_CTRL_1 = (XCVR_RX_DIG->AGC_CTRL_1 & ~XCVR_RX_DIG_AGC_CTRL_1_USER_LNA_GAIN_EN_MASK) | XCVR_RX_DIG_AGC_CTRL_1_USER_LNA_GAIN_EN(1) ; /* Set LNA Manual Gain */
137     XCVR_RX_DIG->AGC_CTRL_1 = (XCVR_RX_DIG->AGC_CTRL_1 & ~XCVR_RX_DIG_AGC_CTRL_1_USER_BBA_GAIN_EN_MASK) | XCVR_RX_DIG_AGC_CTRL_1_USER_BBA_GAIN_EN(1) ; /* Set BBA Manual Gain */
138 
139     XCVR_RX_DIG->RX_DIG_CTRL = (XCVR_RX_DIG->RX_DIG_CTRL & ~XCVR_RX_DIG_RX_DIG_CTRL_RX_DCOC_CAL_EN_MASK) | XCVR_RX_DIG_RX_DIG_CTRL_RX_DCOC_CAL_EN(0); /* Enable HW DC Calibration -- Disable for SW-DCOC */
140     XCVR_RX_DIG->DCOC_CTRL_0 = (XCVR_RX_DIG->DCOC_CTRL_0 & ~XCVR_RX_DIG_DCOC_CTRL_0_DCOC_MAN_MASK) | XCVR_RX_DIG_DCOC_CTRL_0_DCOC_MAN(1); /* Enable  Manual DCOC */
141     /* DCOC_CTRL_0 @ 4005_C02C -- Define default DCOC DAC settings in manual mode. */
142     XCVR_RX_DIG->DCOC_DAC_INIT = XCVR_RX_DIG_DCOC_DAC_INIT_BBA_DCOC_INIT_I(0x20) | XCVR_RX_DIG_DCOC_DAC_INIT_BBA_DCOC_INIT_Q(0x20) |  XCVR_RX_DIG_DCOC_DAC_INIT_TZA_DCOC_INIT_I(0x80) | XCVR_RX_DIG_DCOC_DAC_INIT_TZA_DCOC_INIT_Q(0x80);
143     /* Set DCOC Tracking State. */
144     XCVR_RX_DIG->DCOC_CTRL_0 = (XCVR_RX_DIG->DCOC_CTRL_0 & ~XCVR_RX_DIG_DCOC_CTRL_0_DCOC_CORRECT_SRC_MASK) | XCVR_RX_DIG_DCOC_CTRL_0_DCOC_CORRECT_SRC(0); /* Disables DCOC Tracking when set to 0 */
145     /* Apply Manual Gain. */
146     XCVR_RX_DIG->AGC_CTRL_1 = XCVR_RX_DIG_AGC_CTRL_1_USER_LNA_GAIN_EN(1) | XCVR_RX_DIG_AGC_CTRL_1_USER_BBA_GAIN_EN(1) | XCVR_RX_DIG_AGC_CTRL_1_LNA_USER_GAIN(0x02) | XCVR_RX_DIG_AGC_CTRL_1_BBA_USER_GAIN(0x00) ;
147     XcvrCalDelay(TsettleCal);
148 
149     dcoc_init_reg_value_dcgain = XCVR_RX_DIG->DCOC_DAC_INIT; /* Capture DC null setting. */
150 
151     bbf_dacinit_i = (dcoc_init_reg_value_dcgain & 0x000000FFU);
152     bbf_dacinit_q = (dcoc_init_reg_value_dcgain & 0x0000FF00U) >> 8;
153 
154     DC_Measure_short(I_CHANNEL, NOMINAL2);
155     DC_Measure_short(Q_CHANNEL, NOMINAL2);
156 
157     /* SWEEP Q CHANNEL */
158     /* BBF NEG STEP */
159     XCVR_RX_DIG->DCOC_DAC_INIT = (XCVR_RX_DIG->DCOC_DAC_INIT & ~XCVR_RX_DIG_DCOC_DAC_INIT_BBA_DCOC_INIT_Q_MASK) | XCVR_RX_DIG_DCOC_DAC_INIT_BBA_DCOC_INIT_Q(bbf_dacinit_q - 16);
160     XcvrCalDelay(TsettleCal);
161     DC_Measure_short(Q_CHANNEL, BBF_NEG);
162 
163     /* BBF POS STEP */
164     XCVR_RX_DIG->DCOC_DAC_INIT = (XCVR_RX_DIG->DCOC_DAC_INIT & ~XCVR_RX_DIG_DCOC_DAC_INIT_BBA_DCOC_INIT_Q_MASK) | XCVR_RX_DIG_DCOC_DAC_INIT_BBA_DCOC_INIT_Q(bbf_dacinit_q + 16);
165     XcvrCalDelay(TsettleCal);
166     DC_Measure_short(Q_CHANNEL, BBF_POS);
167 
168     XCVR_RX_DIG->DCOC_DAC_INIT = dcoc_init_reg_value_dcgain; /* Return DAC setting to initial. */
169     XcvrCalDelay(TsettleCal);
170 
171     /* SWEEP I CHANNEL */
172     /* BBF NEG STEP */
173     XCVR_RX_DIG->DCOC_DAC_INIT = (XCVR_RX_DIG->DCOC_DAC_INIT & ~XCVR_RX_DIG_DCOC_DAC_INIT_BBA_DCOC_INIT_I_MASK) | XCVR_RX_DIG_DCOC_DAC_INIT_BBA_DCOC_INIT_I(bbf_dacinit_i - 16);
174     XcvrCalDelay(TsettleCal);
175     DC_Measure_short(I_CHANNEL, BBF_NEG);
176     /* BBF POS STEP  */
177     XCVR_RX_DIG->DCOC_DAC_INIT = (XCVR_RX_DIG->DCOC_DAC_INIT & ~XCVR_RX_DIG_DCOC_DAC_INIT_BBA_DCOC_INIT_I_MASK) | XCVR_RX_DIG_DCOC_DAC_INIT_BBA_DCOC_INIT_I(bbf_dacinit_i + 16);
178     XcvrCalDelay(TsettleCal);
179     DC_Measure_short(I_CHANNEL, BBF_POS);
180 
181     XCVR_RX_DIG->DCOC_DAC_INIT = dcoc_init_reg_value_dcgain; /* Return DACs to initial. */
182     XcvrCalDelay(TsettleCal);
183 
184     /* Calculate BBF DCOC STEPS, RECIPROCALS */
185     temp_mi = calc_dcoc_dac_step(&measurement_tbl2[I_CHANNEL][BBF_NEG], &measurement_tbl2[I_CHANNEL][NOMINAL2]);
186     temp_mq = calc_dcoc_dac_step(&measurement_tbl2[Q_CHANNEL][BBF_NEG], &measurement_tbl2[Q_CHANNEL][NOMINAL2]);
187     temp_pi = calc_dcoc_dac_step(&measurement_tbl2[I_CHANNEL][BBF_POS], &measurement_tbl2[I_CHANNEL][NOMINAL2]);
188     temp_pq = calc_dcoc_dac_step(&measurement_tbl2[Q_CHANNEL][BBF_POS], &measurement_tbl2[Q_CHANNEL][NOMINAL2]);
189 
190     temp_step = (temp_mi+temp_pi + temp_mq+temp_pq) / 4;
191 
192     bbf_dcoc_step = (uint32_t)roundf(temp_step * 8U);
193 
194     if ((bbf_dcoc_step > 265) & (bbf_dcoc_step < 305))
195     {
196         bbf_dcoc_step_rcp = (uint32_t)roundf((float)0x8000U / temp_step);
197 
198         /* Calculate TZA DCOC STEPS & RECIPROCALS and IQ_DC_GAIN_MISMATCH. */
199         for (i = TZA_STEP_N0; i <= TZA_STEP_N10; i++) /* Relying on enumeration ordering. */
200         {
201             /* Calculate TZA DCOC STEPSIZE & its RECIPROCAL. */
202             switch(i){
203             case TZA_STEP_N0:
204                 temp_step = (bbf_dcoc_step >> 3U) / 3.6F;
205                 break;
206             case TZA_STEP_N1:
207                 temp_step = temp_step * (xcvr_common_config.dcoc_tza_step_01_init >> 16)/(xcvr_common_config.dcoc_tza_step_00_init >> 16);
208                 break;
209             case TZA_STEP_N2:
210                 temp_step = temp_step * (xcvr_common_config.dcoc_tza_step_02_init >> 16)/(xcvr_common_config.dcoc_tza_step_01_init >> 16);
211                 break;
212             case TZA_STEP_N3:
213                 temp_step = temp_step * (xcvr_common_config.dcoc_tza_step_03_init >> 16)/(xcvr_common_config.dcoc_tza_step_02_init >> 16);
214                 break;
215             case TZA_STEP_N4:
216                 temp_step = temp_step * (xcvr_common_config.dcoc_tza_step_04_init >> 16)/(xcvr_common_config.dcoc_tza_step_03_init >> 16);
217                 break;
218             case TZA_STEP_N5:
219                 temp_step = temp_step * (xcvr_common_config.dcoc_tza_step_05_init >> 16)/(xcvr_common_config.dcoc_tza_step_04_init >> 16);
220                 break;
221             case TZA_STEP_N6:
222                 temp_step = temp_step * (xcvr_common_config.dcoc_tza_step_06_init >> 16)/(xcvr_common_config.dcoc_tza_step_05_init >> 16);
223                 break;
224             case TZA_STEP_N7:
225                 temp_step = temp_step * (xcvr_common_config.dcoc_tza_step_07_init >> 16)/(xcvr_common_config.dcoc_tza_step_06_init >> 16);
226                 break;
227             case TZA_STEP_N8:
228                 temp_step = temp_step * (xcvr_common_config.dcoc_tza_step_08_init >> 16)/(xcvr_common_config.dcoc_tza_step_07_init >> 16);
229                 break;
230             case TZA_STEP_N9:
231                 temp_step = temp_step * (xcvr_common_config.dcoc_tza_step_09_init >> 16)/(xcvr_common_config.dcoc_tza_step_08_init >> 16);
232                 break;
233             case TZA_STEP_N10:
234                 temp_step = temp_step * (xcvr_common_config.dcoc_tza_step_10_init >> 16)/(xcvr_common_config.dcoc_tza_step_09_init >> 16);
235                 break;
236             default:
237                 break;
238             }
239 
240             tza_dcoc_step[i-TZA_STEP_N0].dcoc_step = (uint32_t)roundf(temp_step * 8);
241             tza_dcoc_step[i-TZA_STEP_N0].dcoc_step_rcp = (uint32_t)roundf((float)0x8000 / temp_step);
242         }
243 
244         /* Make the trims active. */
245         XCVR_RX_DIG->DCOC_BBA_STEP = XCVR_RX_DIG_DCOC_BBA_STEP_BBA_DCOC_STEP(bbf_dcoc_step) | XCVR_RX_DIG_DCOC_BBA_STEP_BBA_DCOC_STEP_RECIP(bbf_dcoc_step_rcp) ;
246         XCVR_RX_DIG->DCOC_TZA_STEP_0 = XCVR_RX_DIG_DCOC_TZA_STEP_0_DCOC_TZA_STEP_GAIN_0(tza_dcoc_step[0].dcoc_step) | XCVR_RX_DIG_DCOC_TZA_STEP_0_DCOC_TZA_STEP_RCP_0(tza_dcoc_step[0].dcoc_step_rcp) ;
247         XCVR_RX_DIG->DCOC_TZA_STEP_1 = XCVR_RX_DIG_DCOC_TZA_STEP_1_DCOC_TZA_STEP_GAIN_1(tza_dcoc_step[1].dcoc_step) | XCVR_RX_DIG_DCOC_TZA_STEP_1_DCOC_TZA_STEP_RCP_1(tza_dcoc_step[1].dcoc_step_rcp) ;
248         XCVR_RX_DIG->DCOC_TZA_STEP_2 = XCVR_RX_DIG_DCOC_TZA_STEP_2_DCOC_TZA_STEP_GAIN_2(tza_dcoc_step[2].dcoc_step) | XCVR_RX_DIG_DCOC_TZA_STEP_2_DCOC_TZA_STEP_RCP_2(tza_dcoc_step[2].dcoc_step_rcp) ;
249         XCVR_RX_DIG->DCOC_TZA_STEP_3 = XCVR_RX_DIG_DCOC_TZA_STEP_3_DCOC_TZA_STEP_GAIN_3(tza_dcoc_step[3].dcoc_step) | XCVR_RX_DIG_DCOC_TZA_STEP_3_DCOC_TZA_STEP_RCP_3(tza_dcoc_step[3].dcoc_step_rcp) ;
250         XCVR_RX_DIG->DCOC_TZA_STEP_4 = XCVR_RX_DIG_DCOC_TZA_STEP_4_DCOC_TZA_STEP_GAIN_4(tza_dcoc_step[4].dcoc_step) | XCVR_RX_DIG_DCOC_TZA_STEP_4_DCOC_TZA_STEP_RCP_4(tza_dcoc_step[4].dcoc_step_rcp) ;
251         XCVR_RX_DIG->DCOC_TZA_STEP_5 = XCVR_RX_DIG_DCOC_TZA_STEP_5_DCOC_TZA_STEP_GAIN_5(tza_dcoc_step[5].dcoc_step) | XCVR_RX_DIG_DCOC_TZA_STEP_5_DCOC_TZA_STEP_RCP_5(tza_dcoc_step[5].dcoc_step_rcp) ;
252         XCVR_RX_DIG->DCOC_TZA_STEP_6 = XCVR_RX_DIG_DCOC_TZA_STEP_6_DCOC_TZA_STEP_GAIN_6(tza_dcoc_step[6].dcoc_step) | XCVR_RX_DIG_DCOC_TZA_STEP_6_DCOC_TZA_STEP_RCP_6(tza_dcoc_step[6].dcoc_step_rcp) ;
253         XCVR_RX_DIG->DCOC_TZA_STEP_7 = XCVR_RX_DIG_DCOC_TZA_STEP_7_DCOC_TZA_STEP_GAIN_7(tza_dcoc_step[7].dcoc_step) | XCVR_RX_DIG_DCOC_TZA_STEP_7_DCOC_TZA_STEP_RCP_7(tza_dcoc_step[7].dcoc_step_rcp) ;
254         XCVR_RX_DIG->DCOC_TZA_STEP_8 = XCVR_RX_DIG_DCOC_TZA_STEP_8_DCOC_TZA_STEP_GAIN_8(tza_dcoc_step[8].dcoc_step) | XCVR_RX_DIG_DCOC_TZA_STEP_8_DCOC_TZA_STEP_RCP_8(tza_dcoc_step[8].dcoc_step_rcp) ;
255         XCVR_RX_DIG->DCOC_TZA_STEP_9 = XCVR_RX_DIG_DCOC_TZA_STEP_9_DCOC_TZA_STEP_GAIN_9(tza_dcoc_step[9].dcoc_step) | XCVR_RX_DIG_DCOC_TZA_STEP_9_DCOC_TZA_STEP_RCP_9(tza_dcoc_step[9].dcoc_step_rcp) ;
256         XCVR_RX_DIG->DCOC_TZA_STEP_10 = XCVR_RX_DIG_DCOC_TZA_STEP_10_DCOC_TZA_STEP_GAIN_10(tza_dcoc_step[10].dcoc_step) | XCVR_RX_DIG_DCOC_TZA_STEP_10_DCOC_TZA_STEP_RCP_10(tza_dcoc_step[10].dcoc_step_rcp) ;
257 
258         status = 1; /* Success */
259     }
260     else
261     {
262         status = 0; /* Failure */
263     }
264 
265     /* Restore Registers. */
266     XCVR_RX_DIG->DCOC_CTRL_0 = dcoc_ctrl_0_stack; /* Restore DCOC_CTRL_0 state to prior settings. */
267     XCVR_RX_DIG->DCOC_CTRL_1 = dcoc_ctrl_1_stack; /* Restore DCOC_CTRL_1 state to prior settings. */
268     XCVR_RX_DIG->RX_DIG_CTRL = rx_dig_ctrl_stack; /* Restore RX_DIG_CTRL state to prior settings. */
269     XCVR_RX_DIG->DCOC_CAL_GAIN = dcoc_cal_gain_state; /* Restore DCOC_CAL_GAIN state to prior setting. */
270     XCVR_RX_DIG->AGC_CTRL_1 = agc_ctrl_1_stack; /* Save state of RX_DIG_CTRL for later restore. */
271 
272     return status;
273 }
274 
275 /*! *********************************************************************************
276  * \brief  This function performs one point of the DC GAIN calibration process on the DUT
277  *
278  * \param[in] chan - whether the I or Q channel is being tested.
279  * \param[in] stage - whether the BBF or TZA gain stage is being tested.
280  * \param[in] dcoc_init_val - the value being set in the ***DCOC_INIT_* register by the parent.
281  * \param[in] ext_measmt - the external measurement (in milliVolts) captured by the parent after the ***DCOC_INIT_* register was setup.
282  *
283  * \ingroup PublicAPIs
284  *
285  * \details
286  *   Relies on a static array to store each point of data for later processing in ::DC_GainCalc().
287  *
288  ***********************************************************************************/
DC_Measure_short(IQ_t chan,DAC_SWEEP_STEP2_t dcoc_init_val)289 void DC_Measure_short(IQ_t chan, DAC_SWEEP_STEP2_t dcoc_init_val)
290 {
291     int16_t dc_meas_i = 0;
292     int16_t dc_meas_q = 0;
293     int16_t sum_dc_meas_i = 0;
294     int16_t sum_dc_meas_q = 0;
295 
296     {
297         int8_t i;
298         const int8_t iterations = 1;
299         sum_dc_meas_i = 0;
300         sum_dc_meas_q = 0;
301 
302         for (i = 0; i < iterations; i++)
303         {
304             rx_dc_sample_average(&dc_meas_i, &dc_meas_q);
305             sum_dc_meas_i = sum_dc_meas_i + dc_meas_i;
306             sum_dc_meas_q = sum_dc_meas_q + dc_meas_q;
307         }
308         sum_dc_meas_i = sum_dc_meas_i / iterations;
309         sum_dc_meas_q = sum_dc_meas_q / iterations;
310     }
311 
312     measurement_tbl2[chan][dcoc_init_val].step_value = sweep_step_values2[dcoc_init_val];
313 
314     if (chan == I_CHANNEL)
315     {
316         measurement_tbl2[chan][dcoc_init_val].internal_measurement = dc_meas_i;
317     }
318     else
319     {
320         measurement_tbl2[chan][dcoc_init_val].internal_measurement = dc_meas_q;
321     }
322 }
323 
324 /*! *********************************************************************************
325  * \brief  This function calculates one point of DC DAC step based on digital samples of I or Q.
326  *
327  * \param[in] meas_ptr - pointer to the structure containing the measured data from internal measurement.
328  * \param[in] baseline_meas_ptr - pointer to the structure containing the baseline measured data from internal measurement.
329  *
330  * \return result of the calculation, the measurement DCOC DAC step value for this measurement point.
331  *
332  ***********************************************************************************/
calc_dcoc_dac_step(GAIN_CALC_TBL_ENTRY2_T * meas_ptr,GAIN_CALC_TBL_ENTRY2_T * baseline_meas_ptr)333 float calc_dcoc_dac_step(GAIN_CALC_TBL_ENTRY2_T * meas_ptr, GAIN_CALC_TBL_ENTRY2_T * baseline_meas_ptr )
334 {
335     static int16_t norm_dc_code;
336     static float dc_step;
337 
338     /* Normalize internal measurement */
339     norm_dc_code = meas_ptr->internal_measurement - baseline_meas_ptr->internal_measurement;
340     dc_step = (float)(norm_dc_code) / (float)(meas_ptr->step_value);
341     dc_step = (dc_step < 0)? -dc_step: dc_step;
342 
343     return dc_step;
344 }
345 
346 /*! *********************************************************************************
347  * \brief  Temporary delay function
348  *
349  * \param[in] none.
350  *
351  * \return none.
352  *
353  * \details
354  *
355  ***********************************************************************************/
XcvrCalDelay(uint32_t time)356 void XcvrCalDelay(uint32_t time)
357 {
358     while(time * 32 > 0) /* Time delay is roughly in uSec. */
359     {
360         time--;
361     }
362 }
363 
364 /*! *********************************************************************************
365  * \brief  This function calculates the average (DC value) based on a smaller set of digital samples of I and Q.
366  *
367  * \param[in] i_avg - pointer to the location for storing the calculated average for I channel samples.
368  * \param[in] q_avg - pointer to the location for storing the calculated average for Q channel samples.
369  *
370  ***********************************************************************************/
rx_dc_sample_average(int16_t * i_avg,int16_t * q_avg)371 void rx_dc_sample_average(int16_t * i_avg, int16_t * q_avg)
372 {
373     static uint32_t samples[128]; /* 544*2*2 (entire packet ram1/2 size) */
374     uint16_t i;
375     uint32_t rx_sample;
376     uint16_t * sample_ptr;
377     uint32_t temp, end_of_rx_wu;
378     uint32_t num_iq_samples;
379     float avg_i = 0;
380     float avg_q = 0;
381 
382     num_iq_samples = 128;
383 
384     /* Clear the entire allocated sample buffer */
385     for (i = 0; i < num_iq_samples; i++)
386     {
387         samples[i]=0;
388     }
389 
390     /* Assume this has been called *AFTER* RxWu has completed. */
391     /* XCVR_ForceRxWu(); */
392 
393     /* Wait for TSM to reach the end of warmup (unless you want to capture some samples during DCOC cal phase) */
394     temp = XCVR_TSM->END_OF_SEQ;
395     end_of_rx_wu = (temp & XCVR_TSM_END_OF_SEQ_END_OF_RX_WU_MASK) >> XCVR_TSM_END_OF_SEQ_END_OF_RX_WU_SHIFT;
396     while ((( XCVR_MISC->XCVR_STATUS & XCVR_CTRL_XCVR_STATUS_TSM_COUNT_MASK) >> XCVR_CTRL_XCVR_STATUS_TSM_COUNT_SHIFT ) != end_of_rx_wu) {};
397 
398     dbg_ram_init();
399     /* Argument below is # of bytes, so *2 (I+Q) and *2 (2bytes/sample) */
400 #if RADIO_IS_GEN_3P0
401     dbg_ram_start_capture(DBG_PAGE_RXDIGIQ, NO_START_TRIG, NO_STOP_TRIG);
402     dbg_ram_wait_for_complete();
403     dbg_ram_postproc_capture(DBG_PAGE_RXDIGIQ, num_iq_samples * 2 * 2, &samples[0]);
404     dbg_ram_release();
405 #else
406     (void)dbg_ram_capture(DBG_PAGE_RXDIGIQ, num_iq_samples * 2 * 2, &samples[0]);
407 #endif /* RADIO_IS_GEN_3P0 */
408 
409     /* Sign extend the IQ samples in place in the sample buffer. */
410     sample_ptr = (uint16_t *)(&samples[0]);
411     for (i = 0; i < num_iq_samples * 2; i++)
412     {
413         rx_sample = *sample_ptr;
414         rx_sample |= ((rx_sample & 0x800U) ? 0xF000U : 0x0U); /* Sign extend from 12 to 16 bits. */
415         *sample_ptr = rx_sample;
416         sample_ptr++;
417     }
418 
419     sample_ptr = (uint16_t *)(&samples[0]);
420     for (i = 0; i < num_iq_samples * 2; i += 2)
421     {
422         static int16_t i_value;
423         static int16_t q_value;
424 
425         /* Average I & Q channels separately. */
426         i_value = *(sample_ptr + i); /* Sign extend from 12 to 16 bits. */
427         q_value = *(sample_ptr + i + 1); /* Sign extend from 12 to 16 bits. */
428         avg_i += ((float)i_value - avg_i) / (float)(i + 1);  /* Rolling average I */
429         avg_q += ((float)q_value - avg_q) / (float)(i + 1);  /* Rolling average Q */
430     }
431     XcvrCalDelay(10);
432     *i_avg = (int16_t)avg_i;
433     *q_avg = (int16_t)avg_q;
434 }
435 
436 /*! *********************************************************************************
437  * \brief  This function calculates the average (DC value) based on a larger set of digital samples of I and Q.
438  *
439  * \param[in] i_avg - pointer to the location for storing the calculated average for I channel samples.
440  * \param[in] q_avg - pointer to the location for storing the calculated average for Q channel samples.
441  *
442  ***********************************************************************************/
rx_dc_sample_average_long(int16_t * i_avg,int16_t * q_avg)443 void rx_dc_sample_average_long(int16_t * i_avg, int16_t * q_avg)
444 {
445     static uint32_t samples[512]; /* 544*2*2 (entire packet ram1/2 size) */
446     uint16_t i;
447     uint32_t rx_sample;
448     uint16_t * sample_ptr;
449     uint32_t temp, end_of_rx_wu;
450     uint32_t num_iq_samples;
451     float avg_i = 0;
452     float avg_q = 0;
453 
454     num_iq_samples = 512;
455 
456     /* Clear the entire allocated sample buffer. */
457     for (i = 0; i < num_iq_samples; i++)
458     {
459         samples[i]=0;
460     }
461 
462     /* Assume this has been called *AFTER* RxWu has completed. */
463     /* XCVR_ForceRxWu(); */
464 
465     /* Wait for TSM to reach the end of warmup (unless you want to capture some samples during DCOC cal phase). */
466     temp = XCVR_TSM->END_OF_SEQ;
467     end_of_rx_wu = (temp & XCVR_TSM_END_OF_SEQ_END_OF_RX_WU_MASK) >> XCVR_TSM_END_OF_SEQ_END_OF_RX_WU_SHIFT;
468     while ((( XCVR_MISC->XCVR_STATUS & XCVR_CTRL_XCVR_STATUS_TSM_COUNT_MASK) >> XCVR_CTRL_XCVR_STATUS_TSM_COUNT_SHIFT ) != end_of_rx_wu) {};
469 
470     dbg_ram_init();
471     /* Argument below is # of bytes, so *2 (I+Q) and *2 (2bytes/sample) */
472 #if RADIO_IS_GEN_3P0
473     dbg_ram_start_capture(DBG_PAGE_RXDIGIQ, NO_START_TRIG, NO_STOP_TRIG);
474     dbg_ram_wait_for_complete();
475     dbg_ram_postproc_capture(DBG_PAGE_RXDIGIQ,num_iq_samples * 2 * 2, &samples[0]);
476     dbg_ram_release();
477 #else
478     (void)dbg_ram_capture(DBG_PAGE_RXDIGIQ, num_iq_samples * 2 * 2, &samples[0]);
479 #endif /* RADIO_IS_GEN_3P0 */
480 
481     /* Sign extend the IQ samples in place in the sample buffer. */
482 
483     sample_ptr = (uint16_t *)(&samples[0]);
484     for (i = 0; i < num_iq_samples * 2; i++)
485     {
486         rx_sample = *sample_ptr;
487         rx_sample |= ((rx_sample & 0x800U) ? 0xF000U : 0x0U); /* Sign extend from 12 to 16 bits. */
488         *sample_ptr = rx_sample;
489         sample_ptr++;
490     }
491 
492     sample_ptr = (uint16_t *)(&samples[0]);
493     for (i = 0; i < num_iq_samples * 2; i += 2)
494     {
495         static int16_t i_value;
496         static int16_t q_value;
497 
498         /* Average I & Q channels separately. */
499         i_value = *(sample_ptr + i); /* Sign extend from 12 to 16 bits */
500         q_value = *(sample_ptr + i + 1); /* Sign extend from 12 to 16 bits */
501         avg_i += ((float)i_value - avg_i) / (float)(i + 1); /* Rolling average I */
502         avg_q += ((float)q_value - avg_q) / (float)(i + 1); /* Rolling average Q */
503     }
504 
505     XcvrCalDelay(10);
506     *i_avg = (int16_t)avg_i;
507     *q_avg = (int16_t)avg_q;
508 }
509 
510 /*! *********************************************************************************
511  * rx_dc_est_average : Get DC EST values and return the Average
512  ***********************************************************************************/
rx_dc_est_average(int16_t * i_avg,int16_t * q_avg,uint16_t SampleNumber)513 void rx_dc_est_average(int16_t * i_avg, int16_t * q_avg, uint16_t SampleNumber)
514 {
515     float avg_i = 0;
516     float avg_q = 0;
517     uint16_t i = 0;
518     static uint32_t dc_temp, temp;
519     uint32_t end_of_rx_wu = 0;
520     static int16_t dc_meas_i;
521     static int16_t dc_meas_q;
522 
523      /* Wait for TSM to reach the end of warmup (unless you want to capture some samples during DCOC cal phase). */
524     temp = XCVR_TSM->END_OF_SEQ;
525     end_of_rx_wu = (temp & XCVR_TSM_END_OF_SEQ_END_OF_RX_WU_MASK) >> XCVR_TSM_END_OF_SEQ_END_OF_RX_WU_SHIFT;
526     while ((( XCVR_MISC->XCVR_STATUS & XCVR_CTRL_XCVR_STATUS_TSM_COUNT_MASK) >> XCVR_CTRL_XCVR_STATUS_TSM_COUNT_SHIFT ) != end_of_rx_wu) {};
527 
528     /* Read DCOC DC EST register. */
529     for (i = 0; i < SampleNumber; i++)
530     {
531         dc_temp = XCVR_RX_DIG->DCOC_DC_EST;
532         dc_meas_i = dc_temp & XCVR_RX_DIG_DCOC_DC_EST_DC_EST_I_MASK;
533         temp = dc_meas_i;
534         temp |= ((temp & 0x800U) ? 0xF000U : 0x0U); /* Sign extend from 12 to 16 bits. */
535         dc_meas_i = temp;
536         avg_i += (float) dc_meas_i;
537 
538         dc_meas_q = (dc_temp & XCVR_RX_DIG_DCOC_DC_EST_DC_EST_Q_MASK) >> XCVR_RX_DIG_DCOC_DC_EST_DC_EST_Q_SHIFT;
539         temp = dc_meas_q;
540         temp |= ((temp & 0x800U) ? 0xF000U : 0x0U); /* Sign extend from 12 to 16 bits. */
541         dc_meas_q = temp;
542         avg_q += (float) dc_meas_q;
543     }
544 
545     avg_i /= (float) SampleNumber;
546     avg_q /= (float) SampleNumber;
547 
548     *i_avg = (int16_t)avg_i;
549     *q_avg = (int16_t)avg_q;
550 }
551 
552 /*! *********************************************************************************
553  * \brief  This function performs a trim of the BBA DCOC DAC on the DUT
554  *
555  * \return status - 1 if passed, 0 if failed.
556  *
557  * \ingroup PublicAPIs
558  *
559  * \details
560  *   Requires the RX to be warmed up before this function is called.
561  *
562  ***********************************************************************************/
rx_bba_dcoc_dac_trim_DCest(void)563 uint8_t rx_bba_dcoc_dac_trim_DCest(void)
564 {
565     uint8_t i;
566     float temp_mi = 0;
567     float temp_mq = 0;
568     float temp_pi = 0;
569     float temp_pq = 0;
570     float temp_step = 0;
571 
572     uint32_t bbf_dcoc_step;
573     uint32_t bbf_dcoc_step_rcp;
574     TZAdcocstep_t tza_dcoc_step[11];
575     uint8_t status = 0;
576 
577     uint8_t bbf_dacinit_i, bbf_dacinit_q;
578     uint8_t tza_dacinit_i, tza_dacinit_q;
579     int16_t dc_meas_i;
580     int16_t dc_meas_q;
581     uint32_t dcoc_init_reg_value_dcgain = 0x80802020; /* Used in 2nd & 3rd Generation DCOC Trims only */
582     uint32_t temp;
583 
584     uint32_t dcoc_ctrl_0_stack;
585     uint32_t dcoc_ctrl_1_stack;
586     uint32_t agc_ctrl_1_stack;
587     uint32_t rx_dig_ctrl_stack;
588     uint32_t dcoc_cal_gain_state;
589 
590     /* Save register */
591     dcoc_ctrl_0_stack = XCVR_RX_DIG->DCOC_CTRL_0; /* Save state of DCOC_CTRL_0 for later restore */
592     dcoc_ctrl_1_stack = XCVR_RX_DIG->DCOC_CTRL_1; /* Save state of DCOC_CTRL_1 for later restore */
593     rx_dig_ctrl_stack =  XCVR_RX_DIG->RX_DIG_CTRL; /* Save state of RX_DIG_CTRL for later restore */
594     agc_ctrl_1_stack = XCVR_RX_DIG->AGC_CTRL_1; /* Save state of RX_DIG_CTRL for later restore */
595     dcoc_cal_gain_state = XCVR_RX_DIG->DCOC_CAL_GAIN; /* Save state of DCOC_CAL_GAIN for later restore */
596 
597     /* Register config */
598     /* Ensure AGC, DCOC and RX_DIG_CTRL is in correct mode */
599     temp = XCVR_RX_DIG->RX_DIG_CTRL;
600     temp &= ~XCVR_RX_DIG_RX_DIG_CTRL_RX_AGC_EN_MASK; /* Turn OFF AGC */
601     temp &= ~XCVR_RX_DIG_RX_DIG_CTRL_RX_DCOC_CAL_EN_MASK; /* Disable for SW control of DCOC */
602     temp &= ~XCVR_RX_DIG_RX_DIG_CTRL_RX_DC_RESID_EN_MASK; /* Disable for SW control of DCOC */
603     XCVR_RX_DIG->RX_DIG_CTRL = temp;
604 
605     XCVR_RX_DIG->AGC_CTRL_1 = XCVR_RX_DIG_AGC_CTRL_1_USER_LNA_GAIN_EN(1) | /* Enable LNA Manual Gain */
606                               XCVR_RX_DIG_AGC_CTRL_1_USER_BBA_GAIN_EN(1) | /* Enable BBA Manual Gain */
607                               XCVR_RX_DIG_AGC_CTRL_1_LNA_USER_GAIN(0x0) | /* Set LNA Manual Gain */
608                               XCVR_RX_DIG_AGC_CTRL_1_BBA_USER_GAIN(0x0); /* Set BBA Manual Gain */
609 
610     /* DCOC_CTRL_0 @ 4005_C02C -- Define default DCOC DAC settings in manual mode */
611     temp = XCVR_RX_DIG->DCOC_CTRL_0;
612     temp |=  XCVR_RX_DIG_DCOC_CTRL_0_DCOC_MAN(1); /* Enable  Manual DCOC */
613     temp |=  XCVR_RX_DIG_DCOC_CTRL_0_DCOC_CORRECT_SRC(1); /* Ensure DCOC Tracking is enabled */
614     temp |=  XCVR_RX_DIG_DCOC_CTRL_0_DCOC_TRK_EST_OVR(1); /* Enable DC Estimator */
615     temp |=  XCVR_RX_DIG_DCOC_CTRL_0_DCOC_CORRECT_EN(1); /* Ensure DC correction is enabled */
616     XCVR_RX_DIG->DCOC_CTRL_0 = temp;
617 
618     XCVR_RX_DIG->DCOC_DAC_INIT = XCVR_RX_DIG_DCOC_DAC_INIT_BBA_DCOC_INIT_I(0x20) |
619                                  XCVR_RX_DIG_DCOC_DAC_INIT_BBA_DCOC_INIT_Q(0x20) |
620                                  XCVR_RX_DIG_DCOC_DAC_INIT_TZA_DCOC_INIT_I(0x80) |
621                                  XCVR_RX_DIG_DCOC_DAC_INIT_TZA_DCOC_INIT_Q(0x80);
622 
623     XcvrCalDelay(TsettleCal);
624 
625     /* Set default DCOC DAC INIT Value */
626     dcoc_init_reg_value_dcgain = XCVR_RX_DIG->DCOC_DAC_INIT; /* Store DCOC DAC INIT values */
627     bbf_dacinit_i = (dcoc_init_reg_value_dcgain & 0x000000FFU);
628     bbf_dacinit_q = (dcoc_init_reg_value_dcgain & 0x0000FF00U)>>8;
629     tza_dacinit_i = (dcoc_init_reg_value_dcgain & 0x00FF0000U)>>16;
630     tza_dacinit_q = dcoc_init_reg_value_dcgain >> 24;
631 
632     XcvrCalDelay(TsettleCal * 4);
633     rx_dc_est_average(&dc_meas_i, &dc_meas_q, 64);
634     measurement_tbl2[I_CHANNEL][NOMINAL2].step_value = sweep_step_values2[NOMINAL2];
635     measurement_tbl2[Q_CHANNEL][NOMINAL2].step_value = sweep_step_values2[NOMINAL2];
636     measurement_tbl2[I_CHANNEL][NOMINAL2].internal_measurement = dc_meas_i;
637     measurement_tbl2[Q_CHANNEL][NOMINAL2].internal_measurement = dc_meas_q;
638 
639     /* SWEEP I/Q CHANNEL */
640     /* BBF NEG STEP */
641     XCVR_RX_DIG->DCOC_DAC_INIT = XCVR_RX_DIG_DCOC_DAC_INIT_BBA_DCOC_INIT_I(bbf_dacinit_i - 16) |
642                                  XCVR_RX_DIG_DCOC_DAC_INIT_BBA_DCOC_INIT_Q(bbf_dacinit_q - 16) |
643                                  XCVR_RX_DIG_DCOC_DAC_INIT_TZA_DCOC_INIT_I(tza_dacinit_i) |
644                                  XCVR_RX_DIG_DCOC_DAC_INIT_TZA_DCOC_INIT_Q(tza_dacinit_q);
645     XcvrCalDelay(TsettleCal * 2);
646 
647     rx_dc_est_average(&dc_meas_i, &dc_meas_q, 64);
648     measurement_tbl2[I_CHANNEL][BBF_NEG].step_value = -16;
649     measurement_tbl2[Q_CHANNEL][BBF_NEG].step_value = -16;
650     measurement_tbl2[I_CHANNEL][BBF_NEG].internal_measurement = dc_meas_i;
651     measurement_tbl2[Q_CHANNEL][BBF_NEG].internal_measurement = dc_meas_q;
652 
653 
654     /* BBF POS STEP */
655     XCVR_RX_DIG->DCOC_DAC_INIT = XCVR_RX_DIG_DCOC_DAC_INIT_BBA_DCOC_INIT_I(bbf_dacinit_i + 16) |
656                                  XCVR_RX_DIG_DCOC_DAC_INIT_BBA_DCOC_INIT_Q(bbf_dacinit_q + 16) |
657                                  XCVR_RX_DIG_DCOC_DAC_INIT_TZA_DCOC_INIT_I(tza_dacinit_i) |
658                                  XCVR_RX_DIG_DCOC_DAC_INIT_TZA_DCOC_INIT_Q(tza_dacinit_q);
659     XcvrCalDelay(TsettleCal * 2);
660     rx_dc_est_average(&dc_meas_i, &dc_meas_q, 64);
661     measurement_tbl2[I_CHANNEL][BBF_POS].step_value = +16;
662     measurement_tbl2[Q_CHANNEL][BBF_POS].step_value = +16;
663     measurement_tbl2[I_CHANNEL][BBF_POS].internal_measurement = dc_meas_i;
664     measurement_tbl2[Q_CHANNEL][BBF_POS].internal_measurement = dc_meas_q;
665 
666     XCVR_RX_DIG->DCOC_DAC_INIT = dcoc_init_reg_value_dcgain; /* Return DAC setting to initial */
667 
668     /* Calculate BBF DCOC STEPS, RECIPROCALS */
669     temp_mi = calc_dcoc_dac_step(&measurement_tbl2[I_CHANNEL][BBF_NEG], &measurement_tbl2[I_CHANNEL][NOMINAL2]);
670     temp_mq = calc_dcoc_dac_step(&measurement_tbl2[Q_CHANNEL][BBF_NEG], &measurement_tbl2[Q_CHANNEL][NOMINAL2]);
671     temp_pi = calc_dcoc_dac_step(&measurement_tbl2[I_CHANNEL][BBF_POS], &measurement_tbl2[I_CHANNEL][NOMINAL2]);
672     temp_pq = calc_dcoc_dac_step(&measurement_tbl2[Q_CHANNEL][BBF_POS], &measurement_tbl2[Q_CHANNEL][NOMINAL2]);
673 
674 	temp_step = (temp_mi + temp_pi + temp_mq + temp_pq) / 4;
675     bbf_dcoc_step = (uint32_t)roundf(temp_step * 8U);
676 
677     if ((bbf_dcoc_step > 265) & (bbf_dcoc_step < 305))
678     {
679         bbf_dcoc_step_rcp = (uint32_t)roundf((float)0x8000U / temp_step);
680 
681         /* Calculate TZA DCOC STEPS & RECIPROCALS and IQ_DC_GAIN_MISMATCH */
682         for (i = TZA_STEP_N0; i <= TZA_STEP_N10; i++)
683         {
684             /* Calculate TZA DCOC STEPSIZE & its RECIPROCAL */
685             switch(i){
686                 case TZA_STEP_N0:
687                     temp_step = (bbf_dcoc_step>>3U) / 3.6F;
688                     break;
689                 case TZA_STEP_N1:
690                     temp_step = temp_step * (xcvr_common_config.dcoc_tza_step_01_init >> 16) / (xcvr_common_config.dcoc_tza_step_00_init >> 16);
691                     break;
692                 case TZA_STEP_N2:
693                     temp_step = temp_step * (xcvr_common_config.dcoc_tza_step_02_init >> 16) / (xcvr_common_config.dcoc_tza_step_01_init >> 16);
694                     break;
695                 case TZA_STEP_N3:
696                     temp_step = temp_step * (xcvr_common_config.dcoc_tza_step_03_init >> 16) / (xcvr_common_config.dcoc_tza_step_02_init >> 16);
697                     break;
698                 case TZA_STEP_N4:
699                     temp_step = temp_step * (xcvr_common_config.dcoc_tza_step_04_init >> 16) / (xcvr_common_config.dcoc_tza_step_03_init >> 16);
700                     break;
701                 case TZA_STEP_N5:
702                     temp_step = temp_step * (xcvr_common_config.dcoc_tza_step_05_init >> 16) / (xcvr_common_config.dcoc_tza_step_04_init >> 16);
703                     break;
704                 case TZA_STEP_N6:
705                     temp_step = temp_step * (xcvr_common_config.dcoc_tza_step_06_init >> 16) / (xcvr_common_config.dcoc_tza_step_05_init >> 16);
706                     break;
707                 case TZA_STEP_N7:
708                     temp_step = temp_step * (xcvr_common_config.dcoc_tza_step_07_init >> 16) / (xcvr_common_config.dcoc_tza_step_06_init >> 16);
709                     break;
710                 case TZA_STEP_N8:
711                     temp_step = temp_step * (xcvr_common_config.dcoc_tza_step_08_init >> 16) / (xcvr_common_config.dcoc_tza_step_07_init >> 16);
712                     break;
713                 case TZA_STEP_N9:
714                     temp_step = temp_step * (xcvr_common_config.dcoc_tza_step_09_init >> 16) / (xcvr_common_config.dcoc_tza_step_08_init >> 16);
715                     break;
716                 case TZA_STEP_N10:
717                     temp_step = temp_step * (xcvr_common_config.dcoc_tza_step_10_init >> 16) / (xcvr_common_config.dcoc_tza_step_09_init >> 16);
718                     break;
719                 default:
720                     break;
721             }
722 
723             tza_dcoc_step[i-TZA_STEP_N0].dcoc_step = (uint32_t)roundf(temp_step * 8);
724             tza_dcoc_step[i-TZA_STEP_N0].dcoc_step_rcp = (uint32_t)roundf((float)0x8000 / temp_step);
725         }
726 
727         /* Make the trims active */
728         XCVR_RX_DIG->DCOC_BBA_STEP = XCVR_RX_DIG_DCOC_BBA_STEP_BBA_DCOC_STEP(bbf_dcoc_step) | XCVR_RX_DIG_DCOC_BBA_STEP_BBA_DCOC_STEP_RECIP(bbf_dcoc_step_rcp);
729         XCVR_RX_DIG->DCOC_TZA_STEP_0 = XCVR_RX_DIG_DCOC_TZA_STEP_0_DCOC_TZA_STEP_GAIN_0(tza_dcoc_step[0].dcoc_step) | XCVR_RX_DIG_DCOC_TZA_STEP_0_DCOC_TZA_STEP_RCP_0(tza_dcoc_step[0].dcoc_step_rcp);
730         XCVR_RX_DIG->DCOC_TZA_STEP_1 = XCVR_RX_DIG_DCOC_TZA_STEP_1_DCOC_TZA_STEP_GAIN_1(tza_dcoc_step[1].dcoc_step) | XCVR_RX_DIG_DCOC_TZA_STEP_1_DCOC_TZA_STEP_RCP_1(tza_dcoc_step[1].dcoc_step_rcp);
731         XCVR_RX_DIG->DCOC_TZA_STEP_2 = XCVR_RX_DIG_DCOC_TZA_STEP_2_DCOC_TZA_STEP_GAIN_2(tza_dcoc_step[2].dcoc_step) | XCVR_RX_DIG_DCOC_TZA_STEP_2_DCOC_TZA_STEP_RCP_2(tza_dcoc_step[2].dcoc_step_rcp);
732         XCVR_RX_DIG->DCOC_TZA_STEP_3 = XCVR_RX_DIG_DCOC_TZA_STEP_3_DCOC_TZA_STEP_GAIN_3(tza_dcoc_step[3].dcoc_step) | XCVR_RX_DIG_DCOC_TZA_STEP_3_DCOC_TZA_STEP_RCP_3(tza_dcoc_step[3].dcoc_step_rcp);
733         XCVR_RX_DIG->DCOC_TZA_STEP_4 = XCVR_RX_DIG_DCOC_TZA_STEP_4_DCOC_TZA_STEP_GAIN_4(tza_dcoc_step[4].dcoc_step) | XCVR_RX_DIG_DCOC_TZA_STEP_4_DCOC_TZA_STEP_RCP_4(tza_dcoc_step[4].dcoc_step_rcp);
734         XCVR_RX_DIG->DCOC_TZA_STEP_5 = XCVR_RX_DIG_DCOC_TZA_STEP_5_DCOC_TZA_STEP_GAIN_5(tza_dcoc_step[5].dcoc_step) | XCVR_RX_DIG_DCOC_TZA_STEP_5_DCOC_TZA_STEP_RCP_5(tza_dcoc_step[5].dcoc_step_rcp);
735         XCVR_RX_DIG->DCOC_TZA_STEP_6 = XCVR_RX_DIG_DCOC_TZA_STEP_6_DCOC_TZA_STEP_GAIN_6(tza_dcoc_step[6].dcoc_step) | XCVR_RX_DIG_DCOC_TZA_STEP_6_DCOC_TZA_STEP_RCP_6(tza_dcoc_step[6].dcoc_step_rcp);
736         XCVR_RX_DIG->DCOC_TZA_STEP_7 = XCVR_RX_DIG_DCOC_TZA_STEP_7_DCOC_TZA_STEP_GAIN_7(tza_dcoc_step[7].dcoc_step) | XCVR_RX_DIG_DCOC_TZA_STEP_7_DCOC_TZA_STEP_RCP_7(tza_dcoc_step[7].dcoc_step_rcp);
737         XCVR_RX_DIG->DCOC_TZA_STEP_8 = XCVR_RX_DIG_DCOC_TZA_STEP_8_DCOC_TZA_STEP_GAIN_8(tza_dcoc_step[8].dcoc_step) | XCVR_RX_DIG_DCOC_TZA_STEP_8_DCOC_TZA_STEP_RCP_8(tza_dcoc_step[8].dcoc_step_rcp);
738         XCVR_RX_DIG->DCOC_TZA_STEP_9 = XCVR_RX_DIG_DCOC_TZA_STEP_9_DCOC_TZA_STEP_GAIN_9(tza_dcoc_step[9].dcoc_step) | XCVR_RX_DIG_DCOC_TZA_STEP_9_DCOC_TZA_STEP_RCP_9(tza_dcoc_step[9].dcoc_step_rcp);
739         XCVR_RX_DIG->DCOC_TZA_STEP_10 = XCVR_RX_DIG_DCOC_TZA_STEP_10_DCOC_TZA_STEP_GAIN_10(tza_dcoc_step[10].dcoc_step) | XCVR_RX_DIG_DCOC_TZA_STEP_10_DCOC_TZA_STEP_RCP_10(tza_dcoc_step[10].dcoc_step_rcp);
740 
741         status = 1; /* Success */
742     }
743     else
744     {
745         status = 0; /* Failure */
746     }
747 
748     /* Restore Registers */
749     XCVR_RX_DIG->DCOC_CTRL_0 = dcoc_ctrl_0_stack; /* Restore DCOC_CTRL_0 state to prior settings */
750     XCVR_RX_DIG->DCOC_CTRL_1 = dcoc_ctrl_1_stack; /* Restore DCOC_CTRL_1 state to prior settings */
751     XCVR_RX_DIG->RX_DIG_CTRL = rx_dig_ctrl_stack; /* Restore RX_DIG_CTRL state to prior settings */
752     XCVR_RX_DIG->DCOC_CAL_GAIN = dcoc_cal_gain_state; /* Restore DCOC_CAL_GAIN state to prior setting */
753     XCVR_RX_DIG->AGC_CTRL_1 = agc_ctrl_1_stack; /* Save state of RX_DIG_CTRL for later restore */
754 
755    return status;
756 }
757 
758 /*! *********************************************************************************
759  * DCOC_DAC_INIT_Cal : slope sign seek depending on measure's sign
760  ***********************************************************************************/
DCOC_DAC_INIT_Cal(uint8_t standalone_operation)761 void DCOC_DAC_INIT_Cal(uint8_t standalone_operation)
762 {
763     int16_t dc_meas_i = 2000, dc_meas_i_p = 2000;
764     int16_t dc_meas_q = 2000, dc_meas_q_p = 2000;
765     uint8_t curr_tza_dac_i, curr_tza_dac_q;
766     uint8_t curr_bba_dac_i, curr_bba_dac_q;
767     uint8_t p_tza_dac_i = 0, p_tza_dac_q = 0;
768     uint8_t p_bba_dac_i = 0, p_bba_dac_q = 0;
769     uint8_t i = 0;
770     uint8_t bba_gain = 11;
771     bool TZA_I_OK = 0, TZA_Q_OK = 0, BBA_I_OK = 0, BBA_Q_OK = 0;
772 
773     uint32_t dcoc_ctrl_0_stack;
774     uint32_t dcoc_ctrl_1_stack;
775     uint32_t agc_ctrl_1_stack;
776     uint32_t rx_dig_ctrl_stack;
777     uint32_t dcoc_cal_gain_state;
778     uint32_t xcvr_ctrl_stack = 0;
779 
780     uint32_t temp;
781 
782     /* Save registers */
783     dcoc_ctrl_0_stack = XCVR_RX_DIG->DCOC_CTRL_0; /* Save state of DCOC_CTRL_0 for later restore */
784     dcoc_ctrl_1_stack = XCVR_RX_DIG->DCOC_CTRL_1; /* Save state of DCOC_CTRL_1 for later restore */
785     rx_dig_ctrl_stack =  XCVR_RX_DIG->RX_DIG_CTRL; /* Save state of RX_DIG_CTRL for later restore */
786     agc_ctrl_1_stack = XCVR_RX_DIG->AGC_CTRL_1; /* Save state of RX_DIG_CTRL for later restore */
787     dcoc_cal_gain_state = XCVR_RX_DIG->DCOC_CAL_GAIN; /* Save state of DCOC_CAL_GAIN for later restore */
788 
789     /* WarmUp */
790     if (standalone_operation)
791     {
792         temp = XCVR_MISC->XCVR_CTRL;
793         xcvr_ctrl_stack = temp;
794         temp &= ~(XCVR_CTRL_XCVR_CTRL_PROTOCOL_MASK);
795         temp |= XCVR_CTRL_XCVR_CTRL_PROTOCOL(0);
796         XCVR_MISC->XCVR_CTRL = temp;
797         XCVR_OverrideChannel(12, 1); /* Calibrate on channel #12, 2.426 GHz in BLE map */
798         XCVR_ForceRxWu();
799         XcvrCalDelay(2000);
800     }
801 
802     /* Register config */
803     /* Ensure AGC, DCOC and RX_DIG_CTRL is in correct mode */
804     temp = XCVR_RX_DIG->RX_DIG_CTRL;
805     temp &= ~XCVR_RX_DIG_RX_DIG_CTRL_RX_AGC_EN_MASK; /* Turn OFF AGC */
806     temp &= ~XCVR_RX_DIG_RX_DIG_CTRL_RX_DCOC_CAL_EN_MASK; /* Disable for SW control of DCOC */
807     temp &= ~XCVR_RX_DIG_RX_DIG_CTRL_RX_DC_RESID_EN_MASK; /* Disable for SW control of DCOC */
808     XCVR_RX_DIG->RX_DIG_CTRL = temp;
809 
810     XCVR_RX_DIG->AGC_CTRL_1 = XCVR_RX_DIG_AGC_CTRL_1_USER_LNA_GAIN_EN(1) | /* Enable LNA Manual Gain */
811                               XCVR_RX_DIG_AGC_CTRL_1_USER_BBA_GAIN_EN(1) | /* Enable BBA Manual Gain */
812                               XCVR_RX_DIG_AGC_CTRL_1_LNA_USER_GAIN(0x0) | /* Set LNA Manual Gain */
813                               XCVR_RX_DIG_AGC_CTRL_1_BBA_USER_GAIN(0x0); /* Set BBA Manual Gain */
814 
815     /* DCOC_CTRL_0 @ 4005_C02C -- Define default DCOC DAC settings in manual mode */
816     temp = XCVR_RX_DIG->DCOC_CTRL_0;
817     temp |= XCVR_RX_DIG_DCOC_CTRL_0_DCOC_MAN(1); /* Enable  Manual DCOC */
818     temp |= XCVR_RX_DIG_DCOC_CTRL_0_DCOC_CORRECT_SRC(1); /* Ensure DCOC Tracking is enabled */
819     temp |= XCVR_RX_DIG_DCOC_CTRL_0_DCOC_TRK_EST_OVR(1); /* Enable DC Estimator */
820     temp |= XCVR_RX_DIG_DCOC_CTRL_0_DCOC_CORRECT_EN(1); /* Ensure DC correction is enabled */
821     XCVR_RX_DIG->DCOC_CTRL_0 = temp;
822 
823     XcvrCalDelay(TsettleCal);
824 
825     /* Set default DCOC DAC INIT Value */
826     /* LNA and BBA DAC Sweep */
827     curr_bba_dac_i = 0x20;
828     curr_bba_dac_q = 0x20;
829     curr_tza_dac_i = 0x80;
830     curr_tza_dac_q = 0x80;
831 
832     /* Perform a first DC measurement to ensure that measurement is not clipping */
833     XCVR_RX_DIG->DCOC_DAC_INIT = XCVR_RX_DIG_DCOC_DAC_INIT_BBA_DCOC_INIT_I(curr_bba_dac_i) |
834                                  XCVR_RX_DIG_DCOC_DAC_INIT_BBA_DCOC_INIT_Q(curr_bba_dac_q) |
835                                  XCVR_RX_DIG_DCOC_DAC_INIT_TZA_DCOC_INIT_I(curr_tza_dac_i) |
836                                  XCVR_RX_DIG_DCOC_DAC_INIT_TZA_DCOC_INIT_Q(curr_tza_dac_q);
837 
838     do
839     {
840         bba_gain--;
841         /* Set DAC user gain */
842         XCVR_RX_DIG->AGC_CTRL_1 = XCVR_RX_DIG_AGC_CTRL_1_USER_LNA_GAIN_EN(1) |
843                                   XCVR_RX_DIG_AGC_CTRL_1_LNA_USER_GAIN(0) | /* 2 */
844                                   XCVR_RX_DIG_AGC_CTRL_1_USER_BBA_GAIN_EN(1) |
845                                   XCVR_RX_DIG_AGC_CTRL_1_BBA_USER_GAIN(bba_gain) ; /* 10 */
846         XcvrCalDelay(TsettleCal * 2);
847         rx_dc_est_average(&dc_meas_i, &dc_meas_q, 64);
848     } while ((ABS(dc_meas_i) > 1900) | (ABS(dc_meas_q) > 1900));
849 
850     for (i = 0; i < 0x0F; i++)
851     {
852         /* I channel :  */
853         if (!TZA_I_OK)
854         {
855             if ((ISIGN(dc_meas_i) != ISIGN(dc_meas_i_p)) && (i > 0))
856             {
857                 if (ABS(dc_meas_i) != MIN(ABS(dc_meas_i), ABS(dc_meas_i_p)))
858                 {
859                     curr_tza_dac_i = p_tza_dac_i;
860                 }
861 
862                 TZA_I_OK = 1;
863             }
864             else
865             {
866                 p_tza_dac_i = curr_tza_dac_i;
867 
868                 if (ISIGN(dc_meas_i)) /* If positif */
869                 {
870                     curr_tza_dac_i--;
871                 }
872                 else
873                 {
874                     curr_tza_dac_i++;
875                 }
876             }
877         }
878         else /* Sweep BBA I */
879         {
880             if (!BBA_I_OK)
881             {
882                 if ((ISIGN(dc_meas_i) != ISIGN(dc_meas_i_p)) && (curr_bba_dac_i != 0x20))
883                 {
884                     if (ABS(dc_meas_i) != MIN(ABS(dc_meas_i), ABS(dc_meas_i_p)))
885                     {
886                         curr_bba_dac_i = p_bba_dac_i;
887                     }
888 
889                     BBA_I_OK = 1;
890                 }
891                 else
892                 {
893                     p_bba_dac_i = curr_bba_dac_i;
894                     if (ISIGN(dc_meas_i)) /* If positif */
895                     {
896                         curr_bba_dac_i--;
897                     }
898                     else
899                     {
900                         curr_bba_dac_i++;
901                     }
902                 }
903             }
904         }
905 
906         /* Q channel : */
907         if (!TZA_Q_OK)
908         {
909             if ((ISIGN(dc_meas_q) != ISIGN(dc_meas_q_p)) && (i > 0))
910             {
911                 if (ABS(dc_meas_q) != MIN(ABS(dc_meas_q), ABS(dc_meas_q_p)))
912                 {
913                     curr_tza_dac_q = p_tza_dac_q;
914                 }
915                 TZA_Q_OK = 1;
916             }
917             else
918             {
919                 p_tza_dac_q = curr_tza_dac_q;
920                 if (ISIGN(dc_meas_q)) /* If positif */
921                 {
922                     curr_tza_dac_q--;
923                 }
924                 else
925                 {
926                     curr_tza_dac_q++;
927                 }
928             }
929         }
930         else  /* Sweep BBA Q */
931         {
932             if (!BBA_Q_OK)
933             {
934                 if ((ISIGN(dc_meas_q) != ISIGN(dc_meas_q_p)) && (curr_bba_dac_q != 0x20))
935                 {
936                     if (ABS(dc_meas_q) != MIN(ABS(dc_meas_q), ABS(dc_meas_q_p)))
937                     {
938                         curr_bba_dac_q = p_bba_dac_q;
939                     }
940                     BBA_Q_OK = 1;
941                  }
942                  else
943                  {
944                      p_bba_dac_q = curr_bba_dac_q;
945                      if (ISIGN(dc_meas_q)) /* If positif */
946                      {
947                        curr_bba_dac_q--;
948                      }
949                      else
950                      {
951                          curr_bba_dac_q++;
952                      }
953                  }
954             }
955         }
956 
957         /* DC OK break : */
958         if (TZA_I_OK && TZA_Q_OK && BBA_I_OK && BBA_Q_OK)
959         {
960             break;
961         }
962 
963         dc_meas_i_p = dc_meas_i; /* Store as previous value */
964         dc_meas_q_p = dc_meas_q; /* Store as previous value */
965         XCVR_RX_DIG->DCOC_DAC_INIT = XCVR_RX_DIG_DCOC_DAC_INIT_BBA_DCOC_INIT_I(curr_bba_dac_i) |
966                                      XCVR_RX_DIG_DCOC_DAC_INIT_BBA_DCOC_INIT_Q(curr_bba_dac_q) |
967                                      XCVR_RX_DIG_DCOC_DAC_INIT_TZA_DCOC_INIT_I(curr_tza_dac_i) |
968                                      XCVR_RX_DIG_DCOC_DAC_INIT_TZA_DCOC_INIT_Q(curr_tza_dac_q);
969         XcvrCalDelay(TsettleCal * 2);
970         rx_dc_est_average(&dc_meas_i, &dc_meas_q, 64);
971     }
972 
973     /* Apply optimized DCOC DAC INIT : */
974     XCVR_RX_DIG->DCOC_DAC_INIT = XCVR_RX_DIG_DCOC_DAC_INIT_BBA_DCOC_INIT_I(curr_bba_dac_i) |
975                                  XCVR_RX_DIG_DCOC_DAC_INIT_BBA_DCOC_INIT_Q(curr_bba_dac_q) |
976                                  XCVR_RX_DIG_DCOC_DAC_INIT_TZA_DCOC_INIT_I(curr_tza_dac_i) |
977                                  XCVR_RX_DIG_DCOC_DAC_INIT_TZA_DCOC_INIT_Q(curr_tza_dac_q);
978 
979     /* WarmDown */
980     if (standalone_operation)
981     {
982         XCVR_ForceRxWd(); /* Don't leave the receiver running. */
983         XcvrCalDelay(200);
984         XCVR_OverrideChannel(0xFF,1); /* Release channel overrides */
985         XCVR_MISC->XCVR_CTRL = xcvr_ctrl_stack;
986     }
987 
988     /* Restore register */
989     XCVR_RX_DIG->DCOC_CTRL_0 = dcoc_ctrl_0_stack; /* Restore DCOC_CTRL_0 state to prior settings */
990     XCVR_RX_DIG->DCOC_CTRL_1 = dcoc_ctrl_1_stack; /* Restore DCOC_CTRL_1 state to prior settings */
991     XCVR_RX_DIG->RX_DIG_CTRL = rx_dig_ctrl_stack; /* Restore RX_DIG_CTRL state to prior settings */
992     XCVR_RX_DIG->DCOC_CAL_GAIN = dcoc_cal_gain_state; /* Restore DCOC_CAL_GAIN state to prior setting */
993     XCVR_RX_DIG->AGC_CTRL_1 = agc_ctrl_1_stack; /* Save state of RX_DIG_CTRL for later restore */
994 }
995 
996