Igor Stepura / kw41z-rf-driver Featured
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers fsl_xcvr_trim.c Source File

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