Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
fsl_xcvr_trim.c
00001 /* 00002 * Copyright 2016-2017 NXP 00003 * 00004 * Redistribution and use in source and binary forms, with or without modification, 00005 * are permitted provided that the following conditions are met: 00006 * 00007 * o Redistributions of source code must retain the above copyright notice, this list 00008 * of conditions and the following disclaimer. 00009 * 00010 * o Redistributions in binary form must reproduce the above copyright notice, this 00011 * list of conditions and the following disclaimer in the documentation and/or 00012 * other materials provided with the distribution. 00013 * 00014 * o Neither the name of Freescale Semiconductor, Inc. nor the names of its 00015 * contributors may be used to endorse or promote products derived from this 00016 * software without specific prior written permission. 00017 * 00018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 00019 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00020 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00021 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 00022 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00023 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00024 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 00025 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00026 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00027 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00028 */ 00029 00030 #include "fsl_device_registers.h" 00031 #include "fsl_common.h" 00032 #include "fsl_xcvr.h " 00033 #include "fsl_xcvr_trim.h " 00034 #include "dbg_ram_capture.h " 00035 #include "math.h" 00036 00037 /******************************************************************************* 00038 * Definitions 00039 ******************************************************************************/ 00040 00041 00042 /******************************************************************************* 00043 * Prototypes 00044 ******************************************************************************/ 00045 void DC_Measure_short(IQ_t chan, DAC_SWEEP_STEP2_t dcoc_init_val); 00046 float calc_dcoc_dac_step(GAIN_CALC_TBL_ENTRY2_T * meas_ptr, GAIN_CALC_TBL_ENTRY2_T * baseline_meas_ptr ); 00047 extern float roundf (float); 00048 00049 /******************************************************************************* 00050 * Variables 00051 ******************************************************************************/ 00052 const int8_t TsettleCal = 10; 00053 static GAIN_CALC_TBL_ENTRY2_T measurement_tbl2[NUM_I_Q_CHAN][NUM_SWEEP_STEP_ENTRIES2]; 00054 static const int8_t sweep_step_values2[NUM_SWEEP_STEP_ENTRIES2] = 00055 { 00056 0, /* Baseline entry is first and not used in this table */ 00057 -16, 00058 +16, 00059 -4, 00060 -4, 00061 -4, 00062 -4, 00063 -4, 00064 -4, 00065 -4, 00066 -4, 00067 -4, 00068 -4, 00069 -4, 00070 +4, 00071 +4, 00072 +4, 00073 +4, 00074 +4, 00075 +4, 00076 +4, 00077 +4, 00078 +4, 00079 +4, 00080 +4 00081 }; 00082 00083 /******************************************************************************* 00084 * Macros 00085 ******************************************************************************/ 00086 #define ISIGN(x) !((uint16_t)x & 0x8000) 00087 #define ABS(x) ((x) > 0 ? (x) : -(x)) 00088 00089 /******************************************************************************* 00090 * Code 00091 ******************************************************************************/ 00092 /*! ********************************************************************************* 00093 * \brief This function performs a trim of the BBA DCOC DAC on the DUT 00094 * 00095 * \return status - 1 if passed, 0 if failed. 00096 * 00097 * \ingroup PublicAPIs 00098 * 00099 * \details 00100 * Requires the RX to be warmed up before this function is called. 00101 * 00102 ***********************************************************************************/ 00103 uint8_t rx_bba_dcoc_dac_trim_shortIQ(void) 00104 { 00105 uint8_t i; 00106 float temp_mi = 0; 00107 float temp_mq = 0; 00108 float temp_pi = 0; 00109 float temp_pq = 0; 00110 float temp_step = 0; 00111 uint8_t bbf_dacinit_i, bbf_dacinit_q; 00112 00113 uint32_t dcoc_init_reg_value_dcgain = 0x80802020; /* Used in 2nd & 3rd Generation DCOC Trims only. */ 00114 uint32_t bbf_dcoc_step; 00115 uint32_t bbf_dcoc_step_rcp; 00116 TZAdcocstep_t tza_dcoc_step[11]; 00117 uint8_t status = 0; 00118 00119 /* Save register values. */ 00120 uint32_t dcoc_ctrl_0_stack; 00121 uint32_t dcoc_ctrl_1_stack; 00122 uint32_t agc_ctrl_1_stack; 00123 uint32_t rx_dig_ctrl_stack; 00124 uint32_t dcoc_cal_gain_state; 00125 00126 XcvrCalDelay(1000); 00127 dcoc_ctrl_0_stack = XCVR_RX_DIG->DCOC_CTRL_0; /* Save state of DCOC_CTRL_0 for later restore. */ 00128 dcoc_ctrl_1_stack = XCVR_RX_DIG->DCOC_CTRL_1; /* Save state of DCOC_CTRL_1 for later restore. */ 00129 rx_dig_ctrl_stack = XCVR_RX_DIG->RX_DIG_CTRL; /* Save state of RX_DIG_CTRL for later restore. */ 00130 agc_ctrl_1_stack = XCVR_RX_DIG->AGC_CTRL_1; /* Save state of RX_DIG_CTRL for later restore. */ 00131 dcoc_cal_gain_state = XCVR_RX_DIG->DCOC_CAL_GAIN; /* Save state of DCOC_CAL_GAIN for later restore. */ 00132 00133 /* Ensure AGC, DCOC and RX_DIG_CTRL is in correct mode. */ 00134 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 */ 00135 00136 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 */ 00137 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 */ 00138 00139 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 */ 00140 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 */ 00141 /* DCOC_CTRL_0 @ 4005_C02C -- Define default DCOC DAC settings in manual mode. */ 00142 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); 00143 /* Set DCOC Tracking State. */ 00144 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 */ 00145 /* Apply Manual Gain. */ 00146 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) ; 00147 XcvrCalDelay(TsettleCal); 00148 00149 dcoc_init_reg_value_dcgain = XCVR_RX_DIG->DCOC_DAC_INIT; /* Capture DC null setting. */ 00150 00151 bbf_dacinit_i = (dcoc_init_reg_value_dcgain & 0x000000FFU); 00152 bbf_dacinit_q = (dcoc_init_reg_value_dcgain & 0x0000FF00U) >> 8; 00153 00154 DC_Measure_short(I_CHANNEL, NOMINAL2); 00155 DC_Measure_short(Q_CHANNEL, NOMINAL2); 00156 00157 /* SWEEP Q CHANNEL */ 00158 /* BBF NEG STEP */ 00159 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); 00160 XcvrCalDelay(TsettleCal); 00161 DC_Measure_short(Q_CHANNEL, BBF_NEG); 00162 00163 /* BBF POS STEP */ 00164 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); 00165 XcvrCalDelay(TsettleCal); 00166 DC_Measure_short(Q_CHANNEL, BBF_POS); 00167 00168 XCVR_RX_DIG->DCOC_DAC_INIT = dcoc_init_reg_value_dcgain; /* Return DAC setting to initial. */ 00169 XcvrCalDelay(TsettleCal); 00170 00171 /* SWEEP I CHANNEL */ 00172 /* BBF NEG STEP */ 00173 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); 00174 XcvrCalDelay(TsettleCal); 00175 DC_Measure_short(I_CHANNEL, BBF_NEG); 00176 /* BBF POS STEP */ 00177 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); 00178 XcvrCalDelay(TsettleCal); 00179 DC_Measure_short(I_CHANNEL, BBF_POS); 00180 00181 XCVR_RX_DIG->DCOC_DAC_INIT = dcoc_init_reg_value_dcgain; /* Return DACs to initial. */ 00182 XcvrCalDelay(TsettleCal); 00183 00184 /* Calculate BBF DCOC STEPS, RECIPROCALS */ 00185 temp_mi = calc_dcoc_dac_step(&measurement_tbl2[I_CHANNEL][BBF_NEG], &measurement_tbl2[I_CHANNEL][NOMINAL2]); 00186 temp_mq = calc_dcoc_dac_step(&measurement_tbl2[Q_CHANNEL][BBF_NEG], &measurement_tbl2[Q_CHANNEL][NOMINAL2]); 00187 temp_pi = calc_dcoc_dac_step(&measurement_tbl2[I_CHANNEL][BBF_POS], &measurement_tbl2[I_CHANNEL][NOMINAL2]); 00188 temp_pq = calc_dcoc_dac_step(&measurement_tbl2[Q_CHANNEL][BBF_POS], &measurement_tbl2[Q_CHANNEL][NOMINAL2]); 00189 00190 temp_step = (temp_mi+temp_pi + temp_mq+temp_pq) / 4; 00191 00192 bbf_dcoc_step = (uint32_t)roundf(temp_step * 8U); 00193 00194 if ((bbf_dcoc_step > 265) & (bbf_dcoc_step < 305)) 00195 { 00196 bbf_dcoc_step_rcp = (uint32_t)roundf((float)0x8000U / temp_step); 00197 00198 /* Calculate TZA DCOC STEPS & RECIPROCALS and IQ_DC_GAIN_MISMATCH. */ 00199 for (i = TZA_STEP_N0; i <= TZA_STEP_N10; i++) /* Relying on enumeration ordering. */ 00200 { 00201 /* Calculate TZA DCOC STEPSIZE & its RECIPROCAL. */ 00202 switch(i){ 00203 case TZA_STEP_N0: 00204 temp_step = (bbf_dcoc_step >> 3U) / 3.6F; 00205 break; 00206 case TZA_STEP_N1: 00207 temp_step = temp_step * (xcvr_common_config.dcoc_tza_step_01_init >> 16)/(xcvr_common_config.dcoc_tza_step_00_init >> 16); 00208 break; 00209 case TZA_STEP_N2: 00210 temp_step = temp_step * (xcvr_common_config.dcoc_tza_step_02_init >> 16)/(xcvr_common_config.dcoc_tza_step_01_init >> 16); 00211 break; 00212 case TZA_STEP_N3: 00213 temp_step = temp_step * (xcvr_common_config.dcoc_tza_step_03_init >> 16)/(xcvr_common_config.dcoc_tza_step_02_init >> 16); 00214 break; 00215 case TZA_STEP_N4: 00216 temp_step = temp_step * (xcvr_common_config.dcoc_tza_step_04_init >> 16)/(xcvr_common_config.dcoc_tza_step_03_init >> 16); 00217 break; 00218 case TZA_STEP_N5: 00219 temp_step = temp_step * (xcvr_common_config.dcoc_tza_step_05_init >> 16)/(xcvr_common_config.dcoc_tza_step_04_init >> 16); 00220 break; 00221 case TZA_STEP_N6: 00222 temp_step = temp_step * (xcvr_common_config.dcoc_tza_step_06_init >> 16)/(xcvr_common_config.dcoc_tza_step_05_init >> 16); 00223 break; 00224 case TZA_STEP_N7: 00225 temp_step = temp_step * (xcvr_common_config.dcoc_tza_step_07_init >> 16)/(xcvr_common_config.dcoc_tza_step_06_init >> 16); 00226 break; 00227 case TZA_STEP_N8: 00228 temp_step = temp_step * (xcvr_common_config.dcoc_tza_step_08_init >> 16)/(xcvr_common_config.dcoc_tza_step_07_init >> 16); 00229 break; 00230 case TZA_STEP_N9: 00231 temp_step = temp_step * (xcvr_common_config.dcoc_tza_step_09_init >> 16)/(xcvr_common_config.dcoc_tza_step_08_init >> 16); 00232 break; 00233 case TZA_STEP_N10: 00234 temp_step = temp_step * (xcvr_common_config.dcoc_tza_step_10_init >> 16)/(xcvr_common_config.dcoc_tza_step_09_init >> 16); 00235 break; 00236 default: 00237 break; 00238 } 00239 00240 tza_dcoc_step[i-TZA_STEP_N0].dcoc_step = (uint32_t)roundf(temp_step * 8); 00241 tza_dcoc_step[i-TZA_STEP_N0].dcoc_step_rcp = (uint32_t)roundf((float)0x8000 / temp_step); 00242 } 00243 00244 /* Make the trims active. */ 00245 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) ; 00246 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) ; 00247 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) ; 00248 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) ; 00249 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) ; 00250 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) ; 00251 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) ; 00252 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) ; 00253 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) ; 00254 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) ; 00255 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) ; 00256 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) ; 00257 00258 status = 1; /* Success */ 00259 } 00260 else 00261 { 00262 status = 0; /* Failure */ 00263 } 00264 00265 /* Restore Registers. */ 00266 XCVR_RX_DIG->DCOC_CTRL_0 = dcoc_ctrl_0_stack; /* Restore DCOC_CTRL_0 state to prior settings. */ 00267 XCVR_RX_DIG->DCOC_CTRL_1 = dcoc_ctrl_1_stack; /* Restore DCOC_CTRL_1 state to prior settings. */ 00268 XCVR_RX_DIG->RX_DIG_CTRL = rx_dig_ctrl_stack; /* Restore RX_DIG_CTRL state to prior settings. */ 00269 XCVR_RX_DIG->DCOC_CAL_GAIN = dcoc_cal_gain_state; /* Restore DCOC_CAL_GAIN state to prior setting. */ 00270 XCVR_RX_DIG->AGC_CTRL_1 = agc_ctrl_1_stack; /* Save state of RX_DIG_CTRL for later restore. */ 00271 00272 return status; 00273 } 00274 00275 /*! ********************************************************************************* 00276 * \brief This function performs one point of the DC GAIN calibration process on the DUT 00277 * 00278 * \param[in] chan - whether the I or Q channel is being tested. 00279 * \param[in] stage - whether the BBF or TZA gain stage is being tested. 00280 * \param[in] dcoc_init_val - the value being set in the ***DCOC_INIT_* register by the parent. 00281 * \param[in] ext_measmt - the external measurement (in milliVolts) captured by the parent after the ***DCOC_INIT_* register was setup. 00282 * 00283 * \ingroup PublicAPIs 00284 * 00285 * \details 00286 * Relies on a static array to store each point of data for later processing in ::DC_GainCalc(). 00287 * 00288 ***********************************************************************************/ 00289 void DC_Measure_short(IQ_t chan, DAC_SWEEP_STEP2_t dcoc_init_val) 00290 { 00291 int16_t dc_meas_i = 0; 00292 int16_t dc_meas_q = 0; 00293 int16_t sum_dc_meas_i = 0; 00294 int16_t sum_dc_meas_q = 0; 00295 00296 { 00297 int8_t i; 00298 const int8_t iterations = 1; 00299 sum_dc_meas_i = 0; 00300 sum_dc_meas_q = 0; 00301 00302 for (i = 0; i < iterations; i++) 00303 { 00304 rx_dc_sample_average(&dc_meas_i, &dc_meas_q); 00305 sum_dc_meas_i = sum_dc_meas_i + dc_meas_i; 00306 sum_dc_meas_q = sum_dc_meas_q + dc_meas_q; 00307 } 00308 sum_dc_meas_i = sum_dc_meas_i / iterations; 00309 sum_dc_meas_q = sum_dc_meas_q / iterations; 00310 } 00311 00312 measurement_tbl2[chan][dcoc_init_val].step_value = sweep_step_values2[dcoc_init_val]; 00313 00314 if (chan == I_CHANNEL) 00315 { 00316 measurement_tbl2[chan][dcoc_init_val].internal_measurement = dc_meas_i; 00317 } 00318 else 00319 { 00320 measurement_tbl2[chan][dcoc_init_val].internal_measurement = dc_meas_q; 00321 } 00322 } 00323 00324 /*! ********************************************************************************* 00325 * \brief This function calculates one point of DC DAC step based on digital samples of I or Q. 00326 * 00327 * \param[in] meas_ptr - pointer to the structure containing the measured data from internal measurement. 00328 * \param[in] baseline_meas_ptr - pointer to the structure containing the baseline measured data from internal measurement. 00329 * 00330 * \return result of the calculation, the measurement DCOC DAC step value for this measurement point. 00331 * 00332 ***********************************************************************************/ 00333 float calc_dcoc_dac_step(GAIN_CALC_TBL_ENTRY2_T * meas_ptr, GAIN_CALC_TBL_ENTRY2_T * baseline_meas_ptr ) 00334 { 00335 static int16_t norm_dc_code; 00336 static float dc_step; 00337 00338 /* Normalize internal measurement */ 00339 norm_dc_code = meas_ptr->internal_measurement - baseline_meas_ptr->internal_measurement; 00340 dc_step = (float)(norm_dc_code) / (float)(meas_ptr->step_value); 00341 dc_step = (dc_step < 0)? -dc_step: dc_step; 00342 00343 return dc_step; 00344 } 00345 00346 /*! ********************************************************************************* 00347 * \brief Temporary delay function 00348 * 00349 * \param[in] none. 00350 * 00351 * \return none. 00352 * 00353 * \details 00354 * 00355 ***********************************************************************************/ 00356 void XcvrCalDelay(uint32_t time) 00357 { 00358 while(time * 32 > 0) /* Time delay is roughly in uSec. */ 00359 { 00360 time--; 00361 } 00362 } 00363 00364 /*! ********************************************************************************* 00365 * \brief This function calculates the average (DC value) based on a smaller set of digital samples of I and Q. 00366 * 00367 * \param[in] i_avg - pointer to the location for storing the calculated average for I channel samples. 00368 * \param[in] q_avg - pointer to the location for storing the calculated average for Q channel samples. 00369 * 00370 ***********************************************************************************/ 00371 void rx_dc_sample_average(int16_t * i_avg, int16_t * q_avg) 00372 { 00373 static uint32_t samples[128]; /* 544*2*2 (entire packet ram1/2 size) */ 00374 uint16_t i; 00375 uint32_t rx_sample; 00376 uint16_t * sample_ptr; 00377 uint32_t temp, end_of_rx_wu; 00378 uint32_t num_iq_samples; 00379 float avg_i = 0; 00380 float avg_q = 0; 00381 00382 num_iq_samples = 128; 00383 00384 /* Clear the entire allocated sample buffer */ 00385 for (i = 0; i < num_iq_samples; i++) 00386 { 00387 samples[i]=0; 00388 } 00389 00390 /* Assume this has been called *AFTER* RxWu has completed. */ 00391 /* XCVR_ForceRxWu(); */ 00392 00393 /* Wait for TSM to reach the end of warmup (unless you want to capture some samples during DCOC cal phase) */ 00394 temp = XCVR_TSM->END_OF_SEQ; 00395 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; 00396 while ((( XCVR_MISC->XCVR_STATUS & XCVR_CTRL_XCVR_STATUS_TSM_COUNT_MASK) >> XCVR_CTRL_XCVR_STATUS_TSM_COUNT_SHIFT ) != end_of_rx_wu) {}; 00397 00398 dbg_ram_init(); 00399 /* Argument below is # of bytes, so *2 (I+Q) and *2 (2bytes/sample) */ 00400 #if RADIO_IS_GEN_3P0 00401 dbg_ram_start_capture(DBG_PAGE_RXDIGIQ, NO_START_TRIG, NO_STOP_TRIG); 00402 dbg_ram_wait_for_complete(); 00403 dbg_ram_postproc_capture(DBG_PAGE_RXDIGIQ, num_iq_samples * 2 * 2, &samples[0]); 00404 dbg_ram_release(); 00405 #else 00406 (void)dbg_ram_capture(DBG_PAGE_RXDIGIQ, num_iq_samples * 2 * 2, &samples[0]); 00407 #endif /* RADIO_IS_GEN_3P0 */ 00408 00409 /* Sign extend the IQ samples in place in the sample buffer. */ 00410 sample_ptr = (uint16_t *)(&samples[0]); 00411 for (i = 0; i < num_iq_samples * 2; i++) 00412 { 00413 rx_sample = *sample_ptr; 00414 rx_sample |= ((rx_sample & 0x800U) ? 0xF000U : 0x0U); /* Sign extend from 12 to 16 bits. */ 00415 *sample_ptr = rx_sample; 00416 sample_ptr++; 00417 } 00418 00419 sample_ptr = (uint16_t *)(&samples[0]); 00420 for (i = 0; i < num_iq_samples * 2; i += 2) 00421 { 00422 static int16_t i_value; 00423 static int16_t q_value; 00424 00425 /* Average I & Q channels separately. */ 00426 i_value = *(sample_ptr + i); /* Sign extend from 12 to 16 bits. */ 00427 q_value = *(sample_ptr + i + 1); /* Sign extend from 12 to 16 bits. */ 00428 avg_i += ((float)i_value - avg_i) / (float)(i + 1); /* Rolling average I */ 00429 avg_q += ((float)q_value - avg_q) / (float)(i + 1); /* Rolling average Q */ 00430 } 00431 XcvrCalDelay(10); 00432 *i_avg = (int16_t)avg_i; 00433 *q_avg = (int16_t)avg_q; 00434 } 00435 00436 /*! ********************************************************************************* 00437 * \brief This function calculates the average (DC value) based on a larger set of digital samples of I and Q. 00438 * 00439 * \param[in] i_avg - pointer to the location for storing the calculated average for I channel samples. 00440 * \param[in] q_avg - pointer to the location for storing the calculated average for Q channel samples. 00441 * 00442 ***********************************************************************************/ 00443 void rx_dc_sample_average_long(int16_t * i_avg, int16_t * q_avg) 00444 { 00445 static uint32_t samples[512]; /* 544*2*2 (entire packet ram1/2 size) */ 00446 uint16_t i; 00447 uint32_t rx_sample; 00448 uint16_t * sample_ptr; 00449 uint32_t temp, end_of_rx_wu; 00450 uint32_t num_iq_samples; 00451 float avg_i = 0; 00452 float avg_q = 0; 00453 00454 num_iq_samples = 512; 00455 00456 /* Clear the entire allocated sample buffer. */ 00457 for (i = 0; i < num_iq_samples; i++) 00458 { 00459 samples[i]=0; 00460 } 00461 00462 /* Assume this has been called *AFTER* RxWu has completed. */ 00463 /* XCVR_ForceRxWu(); */ 00464 00465 /* Wait for TSM to reach the end of warmup (unless you want to capture some samples during DCOC cal phase). */ 00466 temp = XCVR_TSM->END_OF_SEQ; 00467 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; 00468 while ((( XCVR_MISC->XCVR_STATUS & XCVR_CTRL_XCVR_STATUS_TSM_COUNT_MASK) >> XCVR_CTRL_XCVR_STATUS_TSM_COUNT_SHIFT ) != end_of_rx_wu) {}; 00469 00470 dbg_ram_init(); 00471 /* Argument below is # of bytes, so *2 (I+Q) and *2 (2bytes/sample) */ 00472 #if RADIO_IS_GEN_3P0 00473 dbg_ram_start_capture(DBG_PAGE_RXDIGIQ, NO_START_TRIG, NO_STOP_TRIG); 00474 dbg_ram_wait_for_complete(); 00475 dbg_ram_postproc_capture(DBG_PAGE_RXDIGIQ,num_iq_samples * 2 * 2, &samples[0]); 00476 dbg_ram_release(); 00477 #else 00478 (void)dbg_ram_capture(DBG_PAGE_RXDIGIQ, num_iq_samples * 2 * 2, &samples[0]); 00479 #endif /* RADIO_IS_GEN_3P0 */ 00480 00481 /* Sign extend the IQ samples in place in the sample buffer. */ 00482 00483 sample_ptr = (uint16_t *)(&samples[0]); 00484 for (i = 0; i < num_iq_samples * 2; i++) 00485 { 00486 rx_sample = *sample_ptr; 00487 rx_sample |= ((rx_sample & 0x800U) ? 0xF000U : 0x0U); /* Sign extend from 12 to 16 bits. */ 00488 *sample_ptr = rx_sample; 00489 sample_ptr++; 00490 } 00491 00492 sample_ptr = (uint16_t *)(&samples[0]); 00493 for (i = 0; i < num_iq_samples * 2; i += 2) 00494 { 00495 static int16_t i_value; 00496 static int16_t q_value; 00497 00498 /* Average I & Q channels separately. */ 00499 i_value = *(sample_ptr + i); /* Sign extend from 12 to 16 bits */ 00500 q_value = *(sample_ptr + i + 1); /* Sign extend from 12 to 16 bits */ 00501 avg_i += ((float)i_value - avg_i) / (float)(i + 1); /* Rolling average I */ 00502 avg_q += ((float)q_value - avg_q) / (float)(i + 1); /* Rolling average Q */ 00503 } 00504 00505 XcvrCalDelay(10); 00506 *i_avg = (int16_t)avg_i; 00507 *q_avg = (int16_t)avg_q; 00508 } 00509 00510 /*! ********************************************************************************* 00511 * rx_dc_est_average : Get DC EST values and return the Average 00512 ***********************************************************************************/ 00513 void rx_dc_est_average (int16_t * i_avg, int16_t * q_avg, uint16_t SampleNumber) 00514 { 00515 float avg_i = 0; 00516 float avg_q = 0; 00517 uint16_t i = 0; 00518 static uint32_t dc_temp, temp; 00519 uint32_t end_of_rx_wu = 0; 00520 static int16_t dc_meas_i; 00521 static int16_t dc_meas_q; 00522 00523 /* Wait for TSM to reach the end of warmup (unless you want to capture some samples during DCOC cal phase). */ 00524 temp = XCVR_TSM->END_OF_SEQ; 00525 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; 00526 while ((( XCVR_MISC->XCVR_STATUS & XCVR_CTRL_XCVR_STATUS_TSM_COUNT_MASK) >> XCVR_CTRL_XCVR_STATUS_TSM_COUNT_SHIFT ) != end_of_rx_wu) {}; 00527 00528 /* Read DCOC DC EST register. */ 00529 for (i = 0; i < SampleNumber; i++) 00530 { 00531 dc_temp = XCVR_RX_DIG->DCOC_DC_EST; 00532 dc_meas_i = dc_temp & XCVR_RX_DIG_DCOC_DC_EST_DC_EST_I_MASK; 00533 temp = dc_meas_i; 00534 temp |= ((temp & 0x800U) ? 0xF000U : 0x0U); /* Sign extend from 12 to 16 bits. */ 00535 dc_meas_i = temp; 00536 avg_i += (float) dc_meas_i; 00537 00538 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; 00539 temp = dc_meas_q; 00540 temp |= ((temp & 0x800U) ? 0xF000U : 0x0U); /* Sign extend from 12 to 16 bits. */ 00541 dc_meas_q = temp; 00542 avg_q += (float) dc_meas_q; 00543 } 00544 00545 avg_i /= (float) SampleNumber; 00546 avg_q /= (float) SampleNumber; 00547 00548 *i_avg = (int16_t)avg_i; 00549 *q_avg = (int16_t)avg_q; 00550 } 00551 00552 /*! ********************************************************************************* 00553 * \brief This function performs a trim of the BBA DCOC DAC on the DUT 00554 * 00555 * \return status - 1 if passed, 0 if failed. 00556 * 00557 * \ingroup PublicAPIs 00558 * 00559 * \details 00560 * Requires the RX to be warmed up before this function is called. 00561 * 00562 ***********************************************************************************/ 00563 uint8_t rx_bba_dcoc_dac_trim_DCest(void) 00564 { 00565 uint8_t i; 00566 float temp_mi = 0; 00567 float temp_mq = 0; 00568 float temp_pi = 0; 00569 float temp_pq = 0; 00570 float temp_step = 0; 00571 00572 uint32_t bbf_dcoc_step; 00573 uint32_t bbf_dcoc_step_rcp; 00574 TZAdcocstep_t tza_dcoc_step[11]; 00575 uint8_t status = 0; 00576 00577 uint8_t bbf_dacinit_i, bbf_dacinit_q; 00578 uint8_t tza_dacinit_i, tza_dacinit_q; 00579 int16_t dc_meas_i; 00580 int16_t dc_meas_q; 00581 uint32_t dcoc_init_reg_value_dcgain = 0x80802020; /* Used in 2nd & 3rd Generation DCOC Trims only */ 00582 uint32_t temp; 00583 00584 uint32_t dcoc_ctrl_0_stack; 00585 uint32_t dcoc_ctrl_1_stack; 00586 uint32_t agc_ctrl_1_stack; 00587 uint32_t rx_dig_ctrl_stack; 00588 uint32_t dcoc_cal_gain_state; 00589 00590 /* Save register */ 00591 dcoc_ctrl_0_stack = XCVR_RX_DIG->DCOC_CTRL_0; /* Save state of DCOC_CTRL_0 for later restore */ 00592 dcoc_ctrl_1_stack = XCVR_RX_DIG->DCOC_CTRL_1; /* Save state of DCOC_CTRL_1 for later restore */ 00593 rx_dig_ctrl_stack = XCVR_RX_DIG->RX_DIG_CTRL; /* Save state of RX_DIG_CTRL for later restore */ 00594 agc_ctrl_1_stack = XCVR_RX_DIG->AGC_CTRL_1; /* Save state of RX_DIG_CTRL for later restore */ 00595 dcoc_cal_gain_state = XCVR_RX_DIG->DCOC_CAL_GAIN; /* Save state of DCOC_CAL_GAIN for later restore */ 00596 00597 /* Register config */ 00598 /* Ensure AGC, DCOC and RX_DIG_CTRL is in correct mode */ 00599 temp = XCVR_RX_DIG->RX_DIG_CTRL; 00600 temp &= ~XCVR_RX_DIG_RX_DIG_CTRL_RX_AGC_EN_MASK; /* Turn OFF AGC */ 00601 temp &= ~XCVR_RX_DIG_RX_DIG_CTRL_RX_DCOC_CAL_EN_MASK; /* Disable for SW control of DCOC */ 00602 temp &= ~XCVR_RX_DIG_RX_DIG_CTRL_RX_DC_RESID_EN_MASK; /* Disable for SW control of DCOC */ 00603 XCVR_RX_DIG->RX_DIG_CTRL = temp; 00604 00605 XCVR_RX_DIG->AGC_CTRL_1 = XCVR_RX_DIG_AGC_CTRL_1_USER_LNA_GAIN_EN(1) | /* Enable LNA Manual Gain */ 00606 XCVR_RX_DIG_AGC_CTRL_1_USER_BBA_GAIN_EN(1) | /* Enable BBA Manual Gain */ 00607 XCVR_RX_DIG_AGC_CTRL_1_LNA_USER_GAIN(0x0) | /* Set LNA Manual Gain */ 00608 XCVR_RX_DIG_AGC_CTRL_1_BBA_USER_GAIN(0x0); /* Set BBA Manual Gain */ 00609 00610 /* DCOC_CTRL_0 @ 4005_C02C -- Define default DCOC DAC settings in manual mode */ 00611 temp = XCVR_RX_DIG->DCOC_CTRL_0; 00612 temp |= XCVR_RX_DIG_DCOC_CTRL_0_DCOC_MAN(1); /* Enable Manual DCOC */ 00613 temp |= XCVR_RX_DIG_DCOC_CTRL_0_DCOC_CORRECT_SRC(1); /* Ensure DCOC Tracking is enabled */ 00614 temp |= XCVR_RX_DIG_DCOC_CTRL_0_DCOC_TRK_EST_OVR(1); /* Enable DC Estimator */ 00615 temp |= XCVR_RX_DIG_DCOC_CTRL_0_DCOC_CORRECT_EN(1); /* Ensure DC correction is enabled */ 00616 XCVR_RX_DIG->DCOC_CTRL_0 = temp; 00617 00618 XCVR_RX_DIG->DCOC_DAC_INIT = XCVR_RX_DIG_DCOC_DAC_INIT_BBA_DCOC_INIT_I(0x20) | 00619 XCVR_RX_DIG_DCOC_DAC_INIT_BBA_DCOC_INIT_Q(0x20) | 00620 XCVR_RX_DIG_DCOC_DAC_INIT_TZA_DCOC_INIT_I(0x80) | 00621 XCVR_RX_DIG_DCOC_DAC_INIT_TZA_DCOC_INIT_Q(0x80); 00622 00623 XcvrCalDelay(TsettleCal); 00624 00625 /* Set default DCOC DAC INIT Value */ 00626 dcoc_init_reg_value_dcgain = XCVR_RX_DIG->DCOC_DAC_INIT; /* Store DCOC DAC INIT values */ 00627 bbf_dacinit_i = (dcoc_init_reg_value_dcgain & 0x000000FFU); 00628 bbf_dacinit_q = (dcoc_init_reg_value_dcgain & 0x0000FF00U)>>8; 00629 tza_dacinit_i = (dcoc_init_reg_value_dcgain & 0x00FF0000U)>>16; 00630 tza_dacinit_q = dcoc_init_reg_value_dcgain >> 24; 00631 00632 XcvrCalDelay(TsettleCal * 4); 00633 rx_dc_est_average (&dc_meas_i, &dc_meas_q, 64); 00634 measurement_tbl2[I_CHANNEL][NOMINAL2].step_value = sweep_step_values2[NOMINAL2]; 00635 measurement_tbl2[Q_CHANNEL][NOMINAL2].step_value = sweep_step_values2[NOMINAL2]; 00636 measurement_tbl2[I_CHANNEL][NOMINAL2].internal_measurement = dc_meas_i; 00637 measurement_tbl2[Q_CHANNEL][NOMINAL2].internal_measurement = dc_meas_q; 00638 00639 /* SWEEP I/Q CHANNEL */ 00640 /* BBF NEG STEP */ 00641 XCVR_RX_DIG->DCOC_DAC_INIT = XCVR_RX_DIG_DCOC_DAC_INIT_BBA_DCOC_INIT_I(bbf_dacinit_i - 16) | 00642 XCVR_RX_DIG_DCOC_DAC_INIT_BBA_DCOC_INIT_Q(bbf_dacinit_q - 16) | 00643 XCVR_RX_DIG_DCOC_DAC_INIT_TZA_DCOC_INIT_I(tza_dacinit_i) | 00644 XCVR_RX_DIG_DCOC_DAC_INIT_TZA_DCOC_INIT_Q(tza_dacinit_q); 00645 XcvrCalDelay(TsettleCal * 2); 00646 00647 rx_dc_est_average (&dc_meas_i, &dc_meas_q, 64); 00648 measurement_tbl2[I_CHANNEL][BBF_NEG].step_value = -16; 00649 measurement_tbl2[Q_CHANNEL][BBF_NEG].step_value = -16; 00650 measurement_tbl2[I_CHANNEL][BBF_NEG].internal_measurement = dc_meas_i; 00651 measurement_tbl2[Q_CHANNEL][BBF_NEG].internal_measurement = dc_meas_q; 00652 00653 00654 /* BBF POS STEP */ 00655 XCVR_RX_DIG->DCOC_DAC_INIT = XCVR_RX_DIG_DCOC_DAC_INIT_BBA_DCOC_INIT_I(bbf_dacinit_i + 16) | 00656 XCVR_RX_DIG_DCOC_DAC_INIT_BBA_DCOC_INIT_Q(bbf_dacinit_q + 16) | 00657 XCVR_RX_DIG_DCOC_DAC_INIT_TZA_DCOC_INIT_I(tza_dacinit_i) | 00658 XCVR_RX_DIG_DCOC_DAC_INIT_TZA_DCOC_INIT_Q(tza_dacinit_q); 00659 XcvrCalDelay(TsettleCal * 2); 00660 rx_dc_est_average (&dc_meas_i, &dc_meas_q, 64); 00661 measurement_tbl2[I_CHANNEL][BBF_POS].step_value = +16; 00662 measurement_tbl2[Q_CHANNEL][BBF_POS].step_value = +16; 00663 measurement_tbl2[I_CHANNEL][BBF_POS].internal_measurement = dc_meas_i; 00664 measurement_tbl2[Q_CHANNEL][BBF_POS].internal_measurement = dc_meas_q; 00665 00666 XCVR_RX_DIG->DCOC_DAC_INIT = dcoc_init_reg_value_dcgain; /* Return DAC setting to initial */ 00667 00668 /* Calculate BBF DCOC STEPS, RECIPROCALS */ 00669 temp_mi = calc_dcoc_dac_step(&measurement_tbl2[I_CHANNEL][BBF_NEG], &measurement_tbl2[I_CHANNEL][NOMINAL2]); 00670 temp_mq = calc_dcoc_dac_step(&measurement_tbl2[Q_CHANNEL][BBF_NEG], &measurement_tbl2[Q_CHANNEL][NOMINAL2]); 00671 temp_pi = calc_dcoc_dac_step(&measurement_tbl2[I_CHANNEL][BBF_POS], &measurement_tbl2[I_CHANNEL][NOMINAL2]); 00672 temp_pq = calc_dcoc_dac_step(&measurement_tbl2[Q_CHANNEL][BBF_POS], &measurement_tbl2[Q_CHANNEL][NOMINAL2]); 00673 00674 temp_step = (temp_mi + temp_pi + temp_mq + temp_pq) / 4; 00675 bbf_dcoc_step = (uint32_t)roundf(temp_step * 8U); 00676 00677 if ((bbf_dcoc_step > 265) & (bbf_dcoc_step < 305)) 00678 { 00679 bbf_dcoc_step_rcp = (uint32_t)roundf((float)0x8000U / temp_step); 00680 00681 /* Calculate TZA DCOC STEPS & RECIPROCALS and IQ_DC_GAIN_MISMATCH */ 00682 for (i = TZA_STEP_N0; i <= TZA_STEP_N10; i++) 00683 { 00684 /* Calculate TZA DCOC STEPSIZE & its RECIPROCAL */ 00685 switch(i){ 00686 case TZA_STEP_N0: 00687 temp_step = (bbf_dcoc_step>>3U) / 3.6F; 00688 break; 00689 case TZA_STEP_N1: 00690 temp_step = temp_step * (xcvr_common_config.dcoc_tza_step_01_init >> 16) / (xcvr_common_config.dcoc_tza_step_00_init >> 16); 00691 break; 00692 case TZA_STEP_N2: 00693 temp_step = temp_step * (xcvr_common_config.dcoc_tza_step_02_init >> 16) / (xcvr_common_config.dcoc_tza_step_01_init >> 16); 00694 break; 00695 case TZA_STEP_N3: 00696 temp_step = temp_step * (xcvr_common_config.dcoc_tza_step_03_init >> 16) / (xcvr_common_config.dcoc_tza_step_02_init >> 16); 00697 break; 00698 case TZA_STEP_N4: 00699 temp_step = temp_step * (xcvr_common_config.dcoc_tza_step_04_init >> 16) / (xcvr_common_config.dcoc_tza_step_03_init >> 16); 00700 break; 00701 case TZA_STEP_N5: 00702 temp_step = temp_step * (xcvr_common_config.dcoc_tza_step_05_init >> 16) / (xcvr_common_config.dcoc_tza_step_04_init >> 16); 00703 break; 00704 case TZA_STEP_N6: 00705 temp_step = temp_step * (xcvr_common_config.dcoc_tza_step_06_init >> 16) / (xcvr_common_config.dcoc_tza_step_05_init >> 16); 00706 break; 00707 case TZA_STEP_N7: 00708 temp_step = temp_step * (xcvr_common_config.dcoc_tza_step_07_init >> 16) / (xcvr_common_config.dcoc_tza_step_06_init >> 16); 00709 break; 00710 case TZA_STEP_N8: 00711 temp_step = temp_step * (xcvr_common_config.dcoc_tza_step_08_init >> 16) / (xcvr_common_config.dcoc_tza_step_07_init >> 16); 00712 break; 00713 case TZA_STEP_N9: 00714 temp_step = temp_step * (xcvr_common_config.dcoc_tza_step_09_init >> 16) / (xcvr_common_config.dcoc_tza_step_08_init >> 16); 00715 break; 00716 case TZA_STEP_N10: 00717 temp_step = temp_step * (xcvr_common_config.dcoc_tza_step_10_init >> 16) / (xcvr_common_config.dcoc_tza_step_09_init >> 16); 00718 break; 00719 default: 00720 break; 00721 } 00722 00723 tza_dcoc_step[i-TZA_STEP_N0].dcoc_step = (uint32_t)roundf(temp_step * 8); 00724 tza_dcoc_step[i-TZA_STEP_N0].dcoc_step_rcp = (uint32_t)roundf((float)0x8000 / temp_step); 00725 } 00726 00727 /* Make the trims active */ 00728 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); 00729 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); 00730 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); 00731 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); 00732 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); 00733 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); 00734 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); 00735 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); 00736 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); 00737 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); 00738 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); 00739 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); 00740 00741 status = 1; /* Success */ 00742 } 00743 else 00744 { 00745 status = 0; /* Failure */ 00746 } 00747 00748 /* Restore Registers */ 00749 XCVR_RX_DIG->DCOC_CTRL_0 = dcoc_ctrl_0_stack; /* Restore DCOC_CTRL_0 state to prior settings */ 00750 XCVR_RX_DIG->DCOC_CTRL_1 = dcoc_ctrl_1_stack; /* Restore DCOC_CTRL_1 state to prior settings */ 00751 XCVR_RX_DIG->RX_DIG_CTRL = rx_dig_ctrl_stack; /* Restore RX_DIG_CTRL state to prior settings */ 00752 XCVR_RX_DIG->DCOC_CAL_GAIN = dcoc_cal_gain_state; /* Restore DCOC_CAL_GAIN state to prior setting */ 00753 XCVR_RX_DIG->AGC_CTRL_1 = agc_ctrl_1_stack; /* Save state of RX_DIG_CTRL for later restore */ 00754 00755 return status; 00756 } 00757 00758 /*! ********************************************************************************* 00759 * DCOC_DAC_INIT_Cal : slope sign seek depending on measure's sign 00760 ***********************************************************************************/ 00761 void DCOC_DAC_INIT_Cal (uint8_t standalone_operation) 00762 { 00763 int16_t dc_meas_i = 2000, dc_meas_i_p = 2000; 00764 int16_t dc_meas_q = 2000, dc_meas_q_p = 2000; 00765 uint8_t curr_tza_dac_i, curr_tza_dac_q; 00766 uint8_t curr_bba_dac_i, curr_bba_dac_q; 00767 uint8_t p_tza_dac_i = 0, p_tza_dac_q = 0; 00768 uint8_t p_bba_dac_i = 0, p_bba_dac_q = 0; 00769 uint8_t i = 0; 00770 uint8_t bba_gain = 11; 00771 bool TZA_I_OK = 0, TZA_Q_OK = 0, BBA_I_OK = 0, BBA_Q_OK = 0; 00772 00773 uint32_t dcoc_ctrl_0_stack; 00774 uint32_t dcoc_ctrl_1_stack; 00775 uint32_t agc_ctrl_1_stack; 00776 uint32_t rx_dig_ctrl_stack; 00777 uint32_t dcoc_cal_gain_state; 00778 uint32_t xcvr_ctrl_stack = 0; 00779 00780 uint32_t temp; 00781 00782 /* Save registers */ 00783 dcoc_ctrl_0_stack = XCVR_RX_DIG->DCOC_CTRL_0; /* Save state of DCOC_CTRL_0 for later restore */ 00784 dcoc_ctrl_1_stack = XCVR_RX_DIG->DCOC_CTRL_1; /* Save state of DCOC_CTRL_1 for later restore */ 00785 rx_dig_ctrl_stack = XCVR_RX_DIG->RX_DIG_CTRL; /* Save state of RX_DIG_CTRL for later restore */ 00786 agc_ctrl_1_stack = XCVR_RX_DIG->AGC_CTRL_1; /* Save state of RX_DIG_CTRL for later restore */ 00787 dcoc_cal_gain_state = XCVR_RX_DIG->DCOC_CAL_GAIN; /* Save state of DCOC_CAL_GAIN for later restore */ 00788 00789 /* WarmUp */ 00790 if (standalone_operation) 00791 { 00792 temp = XCVR_MISC->XCVR_CTRL; 00793 xcvr_ctrl_stack = temp; 00794 temp &= ~(XCVR_CTRL_XCVR_CTRL_PROTOCOL_MASK); 00795 temp |= XCVR_CTRL_XCVR_CTRL_PROTOCOL(0); 00796 XCVR_MISC->XCVR_CTRL = temp; 00797 XCVR_OverrideChannel(12, 1); /* Calibrate on channel #12, 2.426 GHz in BLE map */ 00798 XCVR_ForceRxWu(); 00799 XcvrCalDelay(2000); 00800 } 00801 00802 /* Register config */ 00803 /* Ensure AGC, DCOC and RX_DIG_CTRL is in correct mode */ 00804 temp = XCVR_RX_DIG->RX_DIG_CTRL; 00805 temp &= ~XCVR_RX_DIG_RX_DIG_CTRL_RX_AGC_EN_MASK; /* Turn OFF AGC */ 00806 temp &= ~XCVR_RX_DIG_RX_DIG_CTRL_RX_DCOC_CAL_EN_MASK; /* Disable for SW control of DCOC */ 00807 temp &= ~XCVR_RX_DIG_RX_DIG_CTRL_RX_DC_RESID_EN_MASK; /* Disable for SW control of DCOC */ 00808 XCVR_RX_DIG->RX_DIG_CTRL = temp; 00809 00810 XCVR_RX_DIG->AGC_CTRL_1 = XCVR_RX_DIG_AGC_CTRL_1_USER_LNA_GAIN_EN(1) | /* Enable LNA Manual Gain */ 00811 XCVR_RX_DIG_AGC_CTRL_1_USER_BBA_GAIN_EN(1) | /* Enable BBA Manual Gain */ 00812 XCVR_RX_DIG_AGC_CTRL_1_LNA_USER_GAIN(0x0) | /* Set LNA Manual Gain */ 00813 XCVR_RX_DIG_AGC_CTRL_1_BBA_USER_GAIN(0x0); /* Set BBA Manual Gain */ 00814 00815 /* DCOC_CTRL_0 @ 4005_C02C -- Define default DCOC DAC settings in manual mode */ 00816 temp = XCVR_RX_DIG->DCOC_CTRL_0; 00817 temp |= XCVR_RX_DIG_DCOC_CTRL_0_DCOC_MAN(1); /* Enable Manual DCOC */ 00818 temp |= XCVR_RX_DIG_DCOC_CTRL_0_DCOC_CORRECT_SRC(1); /* Ensure DCOC Tracking is enabled */ 00819 temp |= XCVR_RX_DIG_DCOC_CTRL_0_DCOC_TRK_EST_OVR(1); /* Enable DC Estimator */ 00820 temp |= XCVR_RX_DIG_DCOC_CTRL_0_DCOC_CORRECT_EN(1); /* Ensure DC correction is enabled */ 00821 XCVR_RX_DIG->DCOC_CTRL_0 = temp; 00822 00823 XcvrCalDelay(TsettleCal); 00824 00825 /* Set default DCOC DAC INIT Value */ 00826 /* LNA and BBA DAC Sweep */ 00827 curr_bba_dac_i = 0x20; 00828 curr_bba_dac_q = 0x20; 00829 curr_tza_dac_i = 0x80; 00830 curr_tza_dac_q = 0x80; 00831 00832 /* Perform a first DC measurement to ensure that measurement is not clipping */ 00833 XCVR_RX_DIG->DCOC_DAC_INIT = XCVR_RX_DIG_DCOC_DAC_INIT_BBA_DCOC_INIT_I(curr_bba_dac_i) | 00834 XCVR_RX_DIG_DCOC_DAC_INIT_BBA_DCOC_INIT_Q(curr_bba_dac_q) | 00835 XCVR_RX_DIG_DCOC_DAC_INIT_TZA_DCOC_INIT_I(curr_tza_dac_i) | 00836 XCVR_RX_DIG_DCOC_DAC_INIT_TZA_DCOC_INIT_Q(curr_tza_dac_q); 00837 00838 do 00839 { 00840 bba_gain--; 00841 /* Set DAC user gain */ 00842 XCVR_RX_DIG->AGC_CTRL_1 = XCVR_RX_DIG_AGC_CTRL_1_USER_LNA_GAIN_EN(1) | 00843 XCVR_RX_DIG_AGC_CTRL_1_LNA_USER_GAIN(0) | /* 2 */ 00844 XCVR_RX_DIG_AGC_CTRL_1_USER_BBA_GAIN_EN(1) | 00845 XCVR_RX_DIG_AGC_CTRL_1_BBA_USER_GAIN(bba_gain) ; /* 10 */ 00846 XcvrCalDelay(TsettleCal * 2); 00847 rx_dc_est_average (&dc_meas_i, &dc_meas_q, 64); 00848 } while ((ABS(dc_meas_i) > 1900) | (ABS(dc_meas_q) > 1900)); 00849 00850 for (i = 0; i < 0x0F; i++) 00851 { 00852 /* I channel : */ 00853 if (!TZA_I_OK) 00854 { 00855 if ((ISIGN(dc_meas_i) != ISIGN(dc_meas_i_p)) && (i > 0)) 00856 { 00857 if (ABS(dc_meas_i) != MIN(ABS(dc_meas_i), ABS(dc_meas_i_p))) 00858 { 00859 curr_tza_dac_i = p_tza_dac_i; 00860 } 00861 00862 TZA_I_OK = 1; 00863 } 00864 else 00865 { 00866 p_tza_dac_i = curr_tza_dac_i; 00867 00868 if (ISIGN(dc_meas_i)) /* If positif */ 00869 { 00870 curr_tza_dac_i--; 00871 } 00872 else 00873 { 00874 curr_tza_dac_i++; 00875 } 00876 } 00877 } 00878 else /* Sweep BBA I */ 00879 { 00880 if (!BBA_I_OK) 00881 { 00882 if ((ISIGN(dc_meas_i) != ISIGN(dc_meas_i_p)) && (curr_bba_dac_i != 0x20)) 00883 { 00884 if (ABS(dc_meas_i) != MIN(ABS(dc_meas_i), ABS(dc_meas_i_p))) 00885 { 00886 curr_bba_dac_i = p_bba_dac_i; 00887 } 00888 00889 BBA_I_OK = 1; 00890 } 00891 else 00892 { 00893 p_bba_dac_i = curr_bba_dac_i; 00894 if (ISIGN(dc_meas_i)) /* If positif */ 00895 { 00896 curr_bba_dac_i--; 00897 } 00898 else 00899 { 00900 curr_bba_dac_i++; 00901 } 00902 } 00903 } 00904 } 00905 00906 /* Q channel : */ 00907 if (!TZA_Q_OK) 00908 { 00909 if ((ISIGN(dc_meas_q) != ISIGN(dc_meas_q_p)) && (i > 0)) 00910 { 00911 if (ABS(dc_meas_q) != MIN(ABS(dc_meas_q), ABS(dc_meas_q_p))) 00912 { 00913 curr_tza_dac_q = p_tza_dac_q; 00914 } 00915 TZA_Q_OK = 1; 00916 } 00917 else 00918 { 00919 p_tza_dac_q = curr_tza_dac_q; 00920 if (ISIGN(dc_meas_q)) /* If positif */ 00921 { 00922 curr_tza_dac_q--; 00923 } 00924 else 00925 { 00926 curr_tza_dac_q++; 00927 } 00928 } 00929 } 00930 else /* Sweep BBA Q */ 00931 { 00932 if (!BBA_Q_OK) 00933 { 00934 if ((ISIGN(dc_meas_q) != ISIGN(dc_meas_q_p)) && (curr_bba_dac_q != 0x20)) 00935 { 00936 if (ABS(dc_meas_q) != MIN(ABS(dc_meas_q), ABS(dc_meas_q_p))) 00937 { 00938 curr_bba_dac_q = p_bba_dac_q; 00939 } 00940 BBA_Q_OK = 1; 00941 } 00942 else 00943 { 00944 p_bba_dac_q = curr_bba_dac_q; 00945 if (ISIGN(dc_meas_q)) /* If positif */ 00946 { 00947 curr_bba_dac_q--; 00948 } 00949 else 00950 { 00951 curr_bba_dac_q++; 00952 } 00953 } 00954 } 00955 } 00956 00957 /* DC OK break : */ 00958 if (TZA_I_OK && TZA_Q_OK && BBA_I_OK && BBA_Q_OK) 00959 { 00960 break; 00961 } 00962 00963 dc_meas_i_p = dc_meas_i; /* Store as previous value */ 00964 dc_meas_q_p = dc_meas_q; /* Store as previous value */ 00965 XCVR_RX_DIG->DCOC_DAC_INIT = XCVR_RX_DIG_DCOC_DAC_INIT_BBA_DCOC_INIT_I(curr_bba_dac_i) | 00966 XCVR_RX_DIG_DCOC_DAC_INIT_BBA_DCOC_INIT_Q(curr_bba_dac_q) | 00967 XCVR_RX_DIG_DCOC_DAC_INIT_TZA_DCOC_INIT_I(curr_tza_dac_i) | 00968 XCVR_RX_DIG_DCOC_DAC_INIT_TZA_DCOC_INIT_Q(curr_tza_dac_q); 00969 XcvrCalDelay(TsettleCal * 2); 00970 rx_dc_est_average (&dc_meas_i, &dc_meas_q, 64); 00971 } 00972 00973 /* Apply optimized DCOC DAC INIT : */ 00974 XCVR_RX_DIG->DCOC_DAC_INIT = XCVR_RX_DIG_DCOC_DAC_INIT_BBA_DCOC_INIT_I(curr_bba_dac_i) | 00975 XCVR_RX_DIG_DCOC_DAC_INIT_BBA_DCOC_INIT_Q(curr_bba_dac_q) | 00976 XCVR_RX_DIG_DCOC_DAC_INIT_TZA_DCOC_INIT_I(curr_tza_dac_i) | 00977 XCVR_RX_DIG_DCOC_DAC_INIT_TZA_DCOC_INIT_Q(curr_tza_dac_q); 00978 00979 /* WarmDown */ 00980 if (standalone_operation) 00981 { 00982 XCVR_ForceRxWd(); /* Don't leave the receiver running. */ 00983 XcvrCalDelay(200); 00984 XCVR_OverrideChannel(0xFF,1); /* Release channel overrides */ 00985 XCVR_MISC->XCVR_CTRL = xcvr_ctrl_stack; 00986 } 00987 00988 /* Restore register */ 00989 XCVR_RX_DIG->DCOC_CTRL_0 = dcoc_ctrl_0_stack; /* Restore DCOC_CTRL_0 state to prior settings */ 00990 XCVR_RX_DIG->DCOC_CTRL_1 = dcoc_ctrl_1_stack; /* Restore DCOC_CTRL_1 state to prior settings */ 00991 XCVR_RX_DIG->RX_DIG_CTRL = rx_dig_ctrl_stack; /* Restore RX_DIG_CTRL state to prior settings */ 00992 XCVR_RX_DIG->DCOC_CAL_GAIN = dcoc_cal_gain_state; /* Restore DCOC_CAL_GAIN state to prior setting */ 00993 XCVR_RX_DIG->AGC_CTRL_1 = agc_ctrl_1_stack; /* Save state of RX_DIG_CTRL for later restore */ 00994 } 00995
Generated on Wed Jul 13 2022 07:46:57 by
1.7.2