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