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.
Impedance.c
00001 /*! 00002 ***************************************************************************** 00003 @file: Impedance.c 00004 @author: Neo Xu 00005 @brief: standard 4-wire or 2-wire impedance measurement sequences. 00006 ----------------------------------------------------------------------------- 00007 00008 Copyright (c) 2017-2019 Analog Devices, Inc. All Rights Reserved. 00009 00010 This software is proprietary to Analog Devices, Inc. and its licensors. 00011 By using this software you agree to the terms of the associated 00012 Analog Devices Software License Agreement. 00013 00014 *****************************************************************************/ 00015 #include "ad5940.h" 00016 #include <stdio.h> 00017 #include "string.h" 00018 #include "math.h" 00019 #include "Impedance.h" 00020 00021 /* Default LPDAC resolution(2.5V internal reference). */ 00022 #define DAC12BITVOLT_1LSB (2200.0f/4095) //mV 00023 #define DAC6BITVOLT_1LSB (DAC12BITVOLT_1LSB*64) //mV 00024 00025 /* 00026 Application configuration structure. Specified by user from template. 00027 The variables are usable in this whole application. 00028 It includes basic configuration for sequencer generator and application related parameters 00029 */ 00030 AppIMPCfg_Type AppIMPCfg = 00031 { 00032 .bParaChanged = bFALSE, 00033 .SeqStartAddr = 0, 00034 .MaxSeqLen = 0, 00035 00036 .SeqStartAddrCal = 0, 00037 .MaxSeqLenCal = 0, 00038 00039 .ImpODR = 20.0, /* 20.0 Hz*/ 00040 .NumOfData = -1, 00041 .SysClkFreq = 16000000.0, 00042 .WuptClkFreq = 32000.0, 00043 .AdcClkFreq = 16000000.0, 00044 .RcalVal = 10000.0, 00045 00046 .DswitchSel = SWD_CE0, 00047 .PswitchSel = SWP_CE0, 00048 .NswitchSel = SWN_AIN1, 00049 .TswitchSel = SWT_AIN1, 00050 00051 .PwrMod = AFEPWR_HP, 00052 00053 .HstiaRtiaSel = HSTIARTIA_5K, 00054 .ExcitBufGain = EXCITBUFGAIN_2, 00055 .HsDacGain = HSDACGAIN_1, 00056 .HsDacUpdateRate = 7, 00057 .DacVoltPP = 800.0, 00058 .BiasVolt = -0.0f, 00059 00060 .SinFreq = 100000.0, /* 1000Hz */ 00061 00062 .DftNum = DFTNUM_16384, 00063 .DftSrc = DFTSRC_SINC3, 00064 .HanWinEn = bTRUE, 00065 00066 .AdcPgaGain = ADCPGA_1, 00067 .ADCSinc3Osr = ADCSINC3OSR_2, 00068 .ADCSinc2Osr = ADCSINC2OSR_22, 00069 00070 .ADCAvgNum = ADCAVGNUM_16, 00071 00072 .SweepCfg.SweepEn = bTRUE, 00073 .SweepCfg.SweepStart = 1000, 00074 .SweepCfg.SweepStop = 100000.0, 00075 .SweepCfg.SweepPoints = 101, 00076 .SweepCfg.SweepLog = bFALSE, 00077 .SweepCfg.SweepIndex = 0, 00078 00079 .FifoThresh = 4, 00080 .IMPInited = bFALSE, 00081 .StopRequired = bFALSE, 00082 }; 00083 00084 /** 00085 This function is provided for upper controllers that want to change 00086 application parameters specially for user defined parameters. 00087 */ 00088 int32_t AppIMPGetCfg(void *pCfg) 00089 { 00090 if(pCfg) 00091 { 00092 *(AppIMPCfg_Type**)pCfg = &AppIMPCfg; 00093 return AD5940ERR_OK; 00094 } 00095 return AD5940ERR_PARA; 00096 } 00097 00098 int32_t AppIMPCtrl(uint32_t Command, void *pPara) 00099 { 00100 00101 switch (Command) 00102 { 00103 case IMPCTRL_START: 00104 { 00105 WUPTCfg_Type wupt_cfg; 00106 00107 if(AD5940_WakeUp(10) > 10) /* Wakeup AFE by read register, read 10 times at most */ 00108 return AD5940ERR_WAKEUP; /* Wakeup Failed */ 00109 if(AppIMPCfg.IMPInited == bFALSE) 00110 return AD5940ERR_APPERROR; 00111 /* Start it */ 00112 wupt_cfg.WuptEn = bTRUE; 00113 wupt_cfg.WuptEndSeq = WUPTENDSEQ_A; 00114 wupt_cfg.WuptOrder[0] = SEQID_0; 00115 wupt_cfg.SeqxSleepTime[SEQID_0] = 4; 00116 wupt_cfg.SeqxWakeupTime[SEQID_0] = (uint32_t)(AppIMPCfg.WuptClkFreq/AppIMPCfg.ImpODR)-4; 00117 AD5940_WUPTCfg(&wupt_cfg); 00118 00119 AppIMPCfg.FifoDataCount = 0; /* restart */ 00120 break; 00121 } 00122 case IMPCTRL_STOPNOW: 00123 { 00124 if(AD5940_WakeUp(10) > 10) /* Wakeup AFE by read register, read 10 times at most */ 00125 return AD5940ERR_WAKEUP; /* Wakeup Failed */ 00126 /* Start Wupt right now */ 00127 AD5940_WUPTCtrl(bFALSE); 00128 /* There is chance this operation will fail because sequencer could put AFE back 00129 to hibernate mode just after waking up. Use STOPSYNC is better. */ 00130 AD5940_WUPTCtrl(bFALSE); 00131 break; 00132 } 00133 case IMPCTRL_STOPSYNC: 00134 { 00135 AppIMPCfg.StopRequired = bTRUE; 00136 break; 00137 } 00138 case IMPCTRL_GETFREQ: 00139 { 00140 if(pPara == 0) 00141 return AD5940ERR_PARA; 00142 if(AppIMPCfg.SweepCfg.SweepEn == bTRUE) 00143 *(float*)pPara = AppIMPCfg.FreqofData; 00144 else 00145 *(float*)pPara = AppIMPCfg.SinFreq; 00146 } 00147 break; 00148 case IMPCTRL_SHUTDOWN: 00149 { 00150 AppIMPCtrl(IMPCTRL_STOPNOW, 0); /* Stop the measurement if it's running. */ 00151 /* Turn off LPloop related blocks which are not controlled automatically by hibernate operation */ 00152 AFERefCfg_Type aferef_cfg; 00153 LPLoopCfg_Type lp_loop; 00154 memset(&aferef_cfg, 0, sizeof(aferef_cfg)); 00155 AD5940_REFCfgS(&aferef_cfg); 00156 memset(&lp_loop, 0, sizeof(lp_loop)); 00157 AD5940_LPLoopCfgS(&lp_loop); 00158 AD5940_EnterSleepS(); /* Enter Hibernate */ 00159 } 00160 break; 00161 default: 00162 break; 00163 } 00164 return AD5940ERR_OK; 00165 } 00166 00167 /* generated code snnipet */ 00168 float AppIMPGetCurrFreq(void) 00169 { 00170 if(AppIMPCfg.SweepCfg.SweepEn == bTRUE) 00171 return AppIMPCfg.FreqofData; 00172 else 00173 return AppIMPCfg.SinFreq; 00174 } 00175 00176 /* Application initialization */ 00177 static AD5940Err AppIMPSeqCfgGen(void) 00178 { 00179 AD5940Err error = AD5940ERR_OK; 00180 const uint32_t *pSeqCmd; 00181 uint32_t SeqLen; 00182 AFERefCfg_Type aferef_cfg; 00183 HSLoopCfg_Type HsLoopCfg; 00184 DSPCfg_Type dsp_cfg; 00185 float sin_freq; 00186 00187 /* Start sequence generator here */ 00188 AD5940_SEQGenCtrl(bTRUE); 00189 00190 AD5940_AFECtrlS(AFECTRL_ALL, bFALSE); /* Init all to disable state */ 00191 00192 aferef_cfg.HpBandgapEn = bTRUE; 00193 aferef_cfg.Hp1V1BuffEn = bTRUE; 00194 aferef_cfg.Hp1V8BuffEn = bTRUE; 00195 aferef_cfg.Disc1V1Cap = bFALSE; 00196 aferef_cfg.Disc1V8Cap = bFALSE; 00197 aferef_cfg.Hp1V8ThemBuff = bFALSE; 00198 aferef_cfg.Hp1V8Ilimit = bFALSE; 00199 aferef_cfg.Lp1V1BuffEn = bFALSE; 00200 aferef_cfg.Lp1V8BuffEn = bFALSE; 00201 /* LP reference control - turn off them to save power*/ 00202 if(AppIMPCfg.BiasVolt != 0.0f) /* With bias voltage */ 00203 { 00204 aferef_cfg.LpBandgapEn = bTRUE; 00205 aferef_cfg.LpRefBufEn = bTRUE; 00206 } 00207 else 00208 { 00209 aferef_cfg.LpBandgapEn = bFALSE; 00210 aferef_cfg.LpRefBufEn = bFALSE; 00211 } 00212 aferef_cfg.LpRefBoostEn = bFALSE; 00213 AD5940_REFCfgS(&aferef_cfg); 00214 HsLoopCfg.HsDacCfg.ExcitBufGain = AppIMPCfg.ExcitBufGain; 00215 HsLoopCfg.HsDacCfg.HsDacGain = AppIMPCfg.HsDacGain; 00216 HsLoopCfg.HsDacCfg.HsDacUpdateRate = AppIMPCfg.HsDacUpdateRate; 00217 00218 HsLoopCfg.HsTiaCfg.DiodeClose = bFALSE; 00219 if(AppIMPCfg.BiasVolt != 0.0f) /* With bias voltage */ 00220 HsLoopCfg.HsTiaCfg.HstiaBias = HSTIABIAS_VZERO0; 00221 else 00222 HsLoopCfg.HsTiaCfg.HstiaBias = HSTIABIAS_1P1; 00223 HsLoopCfg.HsTiaCfg.HstiaCtia = 31; /* 31pF + 2pF */ 00224 HsLoopCfg.HsTiaCfg.HstiaDeRload = HSTIADERLOAD_OPEN; 00225 HsLoopCfg.HsTiaCfg.HstiaDeRtia = HSTIADERTIA_OPEN; 00226 HsLoopCfg.HsTiaCfg.HstiaRtiaSel = AppIMPCfg.HstiaRtiaSel; 00227 00228 HsLoopCfg.SWMatCfg.Dswitch = AppIMPCfg.DswitchSel; 00229 HsLoopCfg.SWMatCfg.Pswitch = AppIMPCfg.PswitchSel; 00230 HsLoopCfg.SWMatCfg.Nswitch = AppIMPCfg.NswitchSel; 00231 HsLoopCfg.SWMatCfg.Tswitch = SWT_TRTIA|AppIMPCfg.TswitchSel; 00232 00233 HsLoopCfg.WgCfg.WgType = WGTYPE_SIN; 00234 HsLoopCfg.WgCfg.GainCalEn = bTRUE; 00235 HsLoopCfg.WgCfg.OffsetCalEn = bTRUE; 00236 if(AppIMPCfg.SweepCfg.SweepEn == bTRUE) 00237 { 00238 AppIMPCfg.FreqofData = AppIMPCfg.SweepCfg.SweepStart; 00239 AppIMPCfg.SweepCurrFreq = AppIMPCfg.SweepCfg.SweepStart; 00240 AD5940_SweepNext(&AppIMPCfg.SweepCfg, &AppIMPCfg.SweepNextFreq); 00241 sin_freq = AppIMPCfg.SweepCurrFreq; 00242 } 00243 else 00244 { 00245 sin_freq = AppIMPCfg.SinFreq; 00246 AppIMPCfg.FreqofData = sin_freq; 00247 } 00248 HsLoopCfg.WgCfg.SinCfg.SinFreqWord = AD5940_WGFreqWordCal(sin_freq, AppIMPCfg.SysClkFreq); 00249 HsLoopCfg.WgCfg.SinCfg.SinAmplitudeWord = (uint32_t)(AppIMPCfg.DacVoltPP/800.0f*2047 + 0.5f); 00250 HsLoopCfg.WgCfg.SinCfg.SinOffsetWord = 0; 00251 HsLoopCfg.WgCfg.SinCfg.SinPhaseWord = 0; 00252 AD5940_HSLoopCfgS(&HsLoopCfg); 00253 if(AppIMPCfg.BiasVolt != 0.0f) /* With bias voltage */ 00254 { 00255 LPDACCfg_Type lpdac_cfg; 00256 00257 lpdac_cfg.LpdacSel = LPDAC0; 00258 lpdac_cfg.LpDacVbiasMux = LPDACVBIAS_12BIT; /* Use Vbias to tuning BiasVolt. */ 00259 lpdac_cfg.LpDacVzeroMux = LPDACVZERO_6BIT; /* Vbias-Vzero = BiasVolt */ 00260 lpdac_cfg.DacData6Bit = 0x40>>1; /* Set Vzero to middle scale. */ 00261 if(AppIMPCfg.BiasVolt<-1100.0f) AppIMPCfg.BiasVolt = -1100.0f + DAC12BITVOLT_1LSB; 00262 if(AppIMPCfg.BiasVolt> 1100.0f) AppIMPCfg.BiasVolt = 1100.0f - DAC12BITVOLT_1LSB; 00263 lpdac_cfg.DacData12Bit = (uint32_t)((AppIMPCfg.BiasVolt + 1100.0f)/DAC12BITVOLT_1LSB); 00264 lpdac_cfg.DataRst = bFALSE; /* Do not reset data register */ 00265 lpdac_cfg.LpDacSW = LPDACSW_VBIAS2LPPA|LPDACSW_VBIAS2PIN|LPDACSW_VZERO2LPTIA|LPDACSW_VZERO2PIN|LPDACSW_VZERO2HSTIA; 00266 lpdac_cfg.LpDacRef = LPDACREF_2P5; 00267 lpdac_cfg.LpDacSrc = LPDACSRC_MMR; /* Use MMR data, we use LPDAC to generate bias voltage for LPTIA - the Vzero */ 00268 lpdac_cfg.PowerEn = bTRUE; /* Power up LPDAC */ 00269 AD5940_LPDACCfgS(&lpdac_cfg); 00270 } 00271 dsp_cfg.ADCBaseCfg.ADCMuxN = ADCMUXN_HSTIA_N; 00272 dsp_cfg.ADCBaseCfg.ADCMuxP = ADCMUXP_HSTIA_P; 00273 dsp_cfg.ADCBaseCfg.ADCPga = AppIMPCfg.AdcPgaGain; 00274 00275 memset(&dsp_cfg.ADCDigCompCfg, 0, sizeof(dsp_cfg.ADCDigCompCfg)); 00276 00277 dsp_cfg.ADCFilterCfg.ADCAvgNum = AppIMPCfg.ADCAvgNum; 00278 dsp_cfg.ADCFilterCfg.ADCRate = ADCRATE_800KHZ; /* Tell filter block clock rate of ADC*/ 00279 dsp_cfg.ADCFilterCfg.ADCSinc2Osr = AppIMPCfg.ADCSinc2Osr; 00280 dsp_cfg.ADCFilterCfg.ADCSinc3Osr = AppIMPCfg.ADCSinc3Osr; 00281 dsp_cfg.ADCFilterCfg.BpNotch = bTRUE; 00282 dsp_cfg.ADCFilterCfg.BpSinc3 = bFALSE; 00283 dsp_cfg.ADCFilterCfg.Sinc2NotchEnable = bTRUE; 00284 dsp_cfg.DftCfg.DftNum = AppIMPCfg.DftNum; 00285 dsp_cfg.DftCfg.DftSrc = AppIMPCfg.DftSrc; 00286 dsp_cfg.DftCfg.HanWinEn = AppIMPCfg.HanWinEn; 00287 00288 memset(&dsp_cfg.StatCfg, 0, sizeof(dsp_cfg.StatCfg)); 00289 AD5940_DSPCfgS(&dsp_cfg); 00290 00291 /* Enable all of them. They are automatically turned off during hibernate mode to save power */ 00292 if(AppIMPCfg.BiasVolt == 0.0f) 00293 AD5940_AFECtrlS(AFECTRL_HSTIAPWR|AFECTRL_INAMPPWR|AFECTRL_EXTBUFPWR|\ 00294 AFECTRL_WG|AFECTRL_DACREFPWR|AFECTRL_HSDACPWR|\ 00295 AFECTRL_SINC2NOTCH, bTRUE); 00296 else 00297 AD5940_AFECtrlS(AFECTRL_HSTIAPWR|AFECTRL_INAMPPWR|AFECTRL_EXTBUFPWR|\ 00298 AFECTRL_WG|AFECTRL_DACREFPWR|AFECTRL_HSDACPWR|\ 00299 AFECTRL_SINC2NOTCH|AFECTRL_DCBUFPWR, bTRUE); 00300 /* Sequence end. */ 00301 AD5940_SEQGenInsert(SEQ_STOP()); /* Add one extra command to disable sequencer for initialization sequence because we only want it to run one time. */ 00302 00303 /* Stop here */ 00304 error = AD5940_SEQGenFetchSeq(&pSeqCmd, &SeqLen); 00305 AD5940_SEQGenCtrl(bFALSE); /* Stop sequencer generator */ 00306 if(error == AD5940ERR_OK) 00307 { 00308 AppIMPCfg.InitSeqInfo.SeqId = SEQID_1; 00309 AppIMPCfg.InitSeqInfo.SeqRamAddr = AppIMPCfg.SeqStartAddr; 00310 AppIMPCfg.InitSeqInfo.pSeqCmd = pSeqCmd; 00311 AppIMPCfg.InitSeqInfo.SeqLen = SeqLen; 00312 /* Write command to SRAM */ 00313 AD5940_SEQCmdWrite(AppIMPCfg.InitSeqInfo.SeqRamAddr, pSeqCmd, SeqLen); 00314 } 00315 else 00316 return error; /* Error */ 00317 return AD5940ERR_OK; 00318 } 00319 00320 00321 static AD5940Err AppIMPSeqMeasureGen(void) 00322 { 00323 AD5940Err error = AD5940ERR_OK; 00324 const uint32_t *pSeqCmd; 00325 uint32_t SeqLen; 00326 00327 uint32_t WaitClks; 00328 SWMatrixCfg_Type sw_cfg; 00329 ClksCalInfo_Type clks_cal; 00330 00331 clks_cal.DataType = DATATYPE_DFT; 00332 clks_cal.DftSrc = AppIMPCfg.DftSrc; 00333 clks_cal.DataCount = 1L<<(AppIMPCfg.DftNum+2); /* 2^(DFTNUMBER+2) */ 00334 clks_cal.ADCSinc2Osr = AppIMPCfg.ADCSinc2Osr; 00335 clks_cal.ADCSinc3Osr = AppIMPCfg.ADCSinc3Osr; 00336 clks_cal.ADCAvgNum = AppIMPCfg.ADCAvgNum; 00337 clks_cal.RatioSys2AdcClk = AppIMPCfg.SysClkFreq/AppIMPCfg.AdcClkFreq; 00338 AD5940_ClksCalculate(&clks_cal, &WaitClks); 00339 00340 AD5940_SEQGenCtrl(bTRUE); 00341 AD5940_SEQGpioCtrlS(AGPIO_Pin2); /* Set GPIO1, clear others that under control */ 00342 AD5940_SEQGenInsert(SEQ_WAIT(16*250)); /* @todo wait 250us? */ 00343 sw_cfg.Dswitch = SWD_RCAL0; 00344 sw_cfg.Pswitch = SWP_RCAL0; 00345 sw_cfg.Nswitch = SWN_RCAL1; 00346 sw_cfg.Tswitch = SWT_RCAL1|SWT_TRTIA; 00347 AD5940_SWMatrixCfgS(&sw_cfg); 00348 AD5940_AFECtrlS(AFECTRL_HSTIAPWR|AFECTRL_INAMPPWR|AFECTRL_EXTBUFPWR|\ 00349 AFECTRL_WG|AFECTRL_DACREFPWR|AFECTRL_HSDACPWR|\ 00350 AFECTRL_SINC2NOTCH, bTRUE); 00351 AD5940_AFECtrlS(AFECTRL_WG|AFECTRL_ADCPWR, bTRUE); /* Enable Waveform generator */ 00352 //delay for signal settling DFT_WAIT 00353 AD5940_SEQGenInsert(SEQ_WAIT(16*10)); 00354 AD5940_AFECtrlS(AFECTRL_ADCCNV|AFECTRL_DFT, bTRUE); /* Start ADC convert and DFT */ 00355 AD5940_SEQGenInsert(SEQ_WAIT(WaitClks)); 00356 //wait for first data ready 00357 AD5940_AFECtrlS(AFECTRL_ADCPWR|AFECTRL_ADCCNV|AFECTRL_DFT|AFECTRL_WG, bFALSE); /* Stop ADC convert and DFT */ 00358 00359 /* Configure matrix for external Rz */ 00360 sw_cfg.Dswitch = AppIMPCfg.DswitchSel; 00361 sw_cfg.Pswitch = AppIMPCfg.PswitchSel; 00362 sw_cfg.Nswitch = AppIMPCfg.NswitchSel; 00363 sw_cfg.Tswitch = SWT_TRTIA|AppIMPCfg.TswitchSel; 00364 AD5940_SWMatrixCfgS(&sw_cfg); 00365 AD5940_AFECtrlS(AFECTRL_ADCPWR|AFECTRL_WG, bTRUE); /* Enable Waveform generator */ 00366 AD5940_SEQGenInsert(SEQ_WAIT(16*10)); //delay for signal settling DFT_WAIT 00367 AD5940_AFECtrlS(AFECTRL_ADCCNV|AFECTRL_DFT, bTRUE); /* Start ADC convert and DFT */ 00368 AD5940_SEQGenInsert(SEQ_WAIT(WaitClks)); /* wait for first data ready */ 00369 AD5940_AFECtrlS(AFECTRL_ADCCNV|AFECTRL_DFT|AFECTRL_WG|AFECTRL_ADCPWR, bFALSE); /* Stop ADC convert and DFT */ 00370 AD5940_AFECtrlS(AFECTRL_HSTIAPWR|AFECTRL_INAMPPWR|AFECTRL_EXTBUFPWR|\ 00371 AFECTRL_WG|AFECTRL_DACREFPWR|AFECTRL_HSDACPWR|\ 00372 AFECTRL_SINC2NOTCH, bFALSE); 00373 AD5940_SEQGpioCtrlS(0); /* Clr GPIO1 */ 00374 00375 AD5940_EnterSleepS();/* Goto hibernate */ 00376 00377 /* Sequence end. */ 00378 error = AD5940_SEQGenFetchSeq(&pSeqCmd, &SeqLen); 00379 AD5940_SEQGenCtrl(bFALSE); /* Stop sequencer generator */ 00380 00381 if(error == AD5940ERR_OK) 00382 { 00383 AppIMPCfg.MeasureSeqInfo.SeqId = SEQID_0; 00384 AppIMPCfg.MeasureSeqInfo.SeqRamAddr = AppIMPCfg.InitSeqInfo.SeqRamAddr + AppIMPCfg.InitSeqInfo.SeqLen ; 00385 AppIMPCfg.MeasureSeqInfo.pSeqCmd = pSeqCmd; 00386 AppIMPCfg.MeasureSeqInfo.SeqLen = SeqLen; 00387 /* Write command to SRAM */ 00388 AD5940_SEQCmdWrite(AppIMPCfg.MeasureSeqInfo.SeqRamAddr, pSeqCmd, SeqLen); 00389 } 00390 else 00391 return error; /* Error */ 00392 return AD5940ERR_OK; 00393 } 00394 00395 00396 /* This function provide application initialize. It can also enable Wupt that will automatically trigger sequence. Or it can configure */ 00397 int32_t AppIMPInit(uint32_t *pBuffer, uint32_t BufferSize) 00398 { 00399 AD5940Err error = AD5940ERR_OK; 00400 SEQCfg_Type seq_cfg; 00401 FIFOCfg_Type fifo_cfg; 00402 00403 if(AD5940_WakeUp(10) > 10) /* Wakeup AFE by read register, read 10 times at most */ 00404 return AD5940ERR_WAKEUP; /* Wakeup Failed */ 00405 00406 /* Configure sequencer and stop it */ 00407 seq_cfg.SeqMemSize = SEQMEMSIZE_2KB; /* 2kB SRAM is used for sequencer, others for data FIFO */ 00408 seq_cfg.SeqBreakEn = bFALSE; 00409 seq_cfg.SeqIgnoreEn = bTRUE; 00410 seq_cfg.SeqCntCRCClr = bTRUE; 00411 seq_cfg.SeqEnable = bFALSE; 00412 seq_cfg.SeqWrTimer = 0; 00413 AD5940_SEQCfg(&seq_cfg); 00414 00415 /* Reconfigure FIFO */ 00416 AD5940_FIFOCtrlS(FIFOSRC_DFT, bFALSE); /* Disable FIFO firstly */ 00417 fifo_cfg.FIFOEn = bTRUE; 00418 fifo_cfg.FIFOMode = FIFOMODE_FIFO; 00419 fifo_cfg.FIFOSize = FIFOSIZE_4KB; /* 4kB for FIFO, The reset 2kB for sequencer */ 00420 fifo_cfg.FIFOSrc = FIFOSRC_DFT; 00421 fifo_cfg.FIFOThresh = AppIMPCfg.FifoThresh; /* DFT result. One pair for RCAL, another for Rz. One DFT result have real part and imaginary part */ 00422 AD5940_FIFOCfg(&fifo_cfg); 00423 AD5940_INTCClrFlag(AFEINTSRC_ALLINT); 00424 00425 /* Start sequence generator */ 00426 /* Initialize sequencer generator */ 00427 if((AppIMPCfg.IMPInited == bFALSE)||\ 00428 (AppIMPCfg.bParaChanged == bTRUE)) 00429 { 00430 if(pBuffer == 0) return AD5940ERR_PARA; 00431 if(BufferSize == 0) return AD5940ERR_PARA; 00432 AD5940_SEQGenInit(pBuffer, BufferSize); 00433 00434 /* Generate initialize sequence */ 00435 error = AppIMPSeqCfgGen(); /* Application initialization sequence using either MCU or sequencer */ 00436 if(error != AD5940ERR_OK) return error; 00437 00438 /* Generate measurement sequence */ 00439 error = AppIMPSeqMeasureGen(); 00440 if(error != AD5940ERR_OK) return error; 00441 00442 AppIMPCfg.bParaChanged = bFALSE; /* Clear this flag as we already implemented the new configuration */ 00443 } 00444 00445 /* Initialization sequencer */ 00446 AppIMPCfg.InitSeqInfo.WriteSRAM = bFALSE; 00447 AD5940_SEQInfoCfg(&AppIMPCfg.InitSeqInfo); 00448 seq_cfg.SeqEnable = bTRUE; 00449 AD5940_SEQCfg(&seq_cfg); /* Enable sequencer */ 00450 AD5940_SEQMmrTrig(AppIMPCfg.InitSeqInfo.SeqId); 00451 while(AD5940_INTCTestFlag(AFEINTC_1, AFEINTSRC_ENDSEQ) == bFALSE); 00452 00453 /* Measurement sequence */ 00454 AppIMPCfg.MeasureSeqInfo.WriteSRAM = bFALSE; 00455 AD5940_SEQInfoCfg(&AppIMPCfg.MeasureSeqInfo); 00456 00457 seq_cfg.SeqEnable = bTRUE; 00458 AD5940_SEQCfg(&seq_cfg); /* Enable sequencer, and wait for trigger */ 00459 AD5940_ClrMCUIntFlag(); /* Clear interrupt flag generated before */ 00460 00461 AD5940_AFEPwrBW(AppIMPCfg.PwrMod, AFEBW_250KHZ); 00462 00463 AppIMPCfg.IMPInited = bTRUE; /* IMP application has been initialized. */ 00464 return AD5940ERR_OK; 00465 } 00466 00467 /* Modify registers when AFE wakeup */ 00468 int32_t AppIMPRegModify(int32_t * const pData, uint32_t *pDataCount) 00469 { 00470 if(AppIMPCfg.NumOfData > 0) 00471 { 00472 AppIMPCfg.FifoDataCount += *pDataCount/4; 00473 if(AppIMPCfg.FifoDataCount >= AppIMPCfg.NumOfData) 00474 { 00475 AD5940_WUPTCtrl(bFALSE); 00476 return AD5940ERR_OK; 00477 } 00478 } 00479 if(AppIMPCfg.StopRequired == bTRUE) 00480 { 00481 AD5940_WUPTCtrl(bFALSE); 00482 return AD5940ERR_OK; 00483 } 00484 if(AppIMPCfg.SweepCfg.SweepEn) /* Need to set new frequency and set power mode */ 00485 { 00486 AD5940_WGFreqCtrlS(AppIMPCfg.SweepNextFreq, AppIMPCfg.SysClkFreq); 00487 } 00488 return AD5940ERR_OK; 00489 } 00490 00491 /* Depending on the data type, do appropriate data pre-process before return back to controller */ 00492 int32_t AppIMPDataProcess(int32_t * const pData, uint32_t *pDataCount) 00493 { 00494 uint32_t DataCount = *pDataCount; 00495 uint32_t ImpResCount = DataCount/4; 00496 00497 fImpPol_Type * const pOut = (fImpPol_Type*)pData; 00498 iImpCar_Type * pSrcData = (iImpCar_Type*)pData; 00499 00500 *pDataCount = 0; 00501 00502 DataCount = (DataCount/4)*4;/* We expect RCAL data together with Rz data. One DFT result has two data in FIFO, real part and imaginary part. */ 00503 00504 /* Convert DFT result to int32_t type */ 00505 for(uint32_t i=0; i<DataCount; i++) 00506 { 00507 pData[i] &= 0x3ffff; /* @todo option to check ECC */ 00508 if(pData[i]&(1L<<17)) /* Bit17 is sign bit */ 00509 { 00510 pData[i] |= 0xfffc0000; /* Data is 18bit in two's complement, bit17 is the sign bit */ 00511 } 00512 } 00513 for(uint32_t i=0; i<ImpResCount; i++) 00514 { 00515 iImpCar_Type *pDftRcal, *pDftRz; 00516 00517 pDftRcal = pSrcData++; 00518 pDftRz = pSrcData++; 00519 float RzMag,RzPhase; 00520 float RcalMag, RcalPhase; 00521 00522 RcalMag = sqrt((float)pDftRcal->Real*pDftRcal->Real+(float)pDftRcal->Image*pDftRcal->Image); 00523 RcalPhase = atan2(-pDftRcal->Image,pDftRcal->Real); 00524 RzMag = sqrt((float)pDftRz->Real*pDftRz->Real+(float)pDftRz->Image*pDftRz->Image); 00525 RzPhase = atan2(-pDftRz->Image,pDftRz->Real); 00526 00527 RzMag = RcalMag/RzMag*AppIMPCfg.RcalVal; 00528 RzPhase = RcalPhase - RzPhase; 00529 //printf("V:%d,%d,I:%d,%d ",pDftRcal->Real,pDftRcal->Image, pDftRz->Real, pDftRz->Image); 00530 00531 pOut[i].Magnitude = RzMag; 00532 pOut[i].Phase = RzPhase; 00533 } 00534 *pDataCount = ImpResCount; 00535 AppIMPCfg.FreqofData = AppIMPCfg.SweepCurrFreq; 00536 /* Calculate next frequency point */ 00537 if(AppIMPCfg.SweepCfg.SweepEn == bTRUE) 00538 { 00539 AppIMPCfg.FreqofData = AppIMPCfg.SweepCurrFreq; 00540 AppIMPCfg.SweepCurrFreq = AppIMPCfg.SweepNextFreq; 00541 AD5940_SweepNext(&AppIMPCfg.SweepCfg, &AppIMPCfg.SweepNextFreq); 00542 } 00543 00544 return 0; 00545 } 00546 00547 /** 00548 00549 */ 00550 int32_t AppIMPISR (void *pBuff, uint32_t *pCount) 00551 { 00552 uint32_t BuffCount; 00553 uint32_t FifoCnt; 00554 BuffCount = *pCount; 00555 00556 *pCount = 0; 00557 00558 if(AD5940_WakeUp(10) > 10) /* Wakeup AFE by read register, read 10 times at most */ 00559 return AD5940ERR_WAKEUP; /* Wakeup Failed */ 00560 AD5940_SleepKeyCtrlS(SLPKEY_LOCK); /* Prohibit AFE to enter sleep mode. */ 00561 00562 if(AD5940_INTCTestFlag(AFEINTC_0, AFEINTSRC_DATAFIFOTHRESH) == bTRUE) 00563 { 00564 /* Now there should be 4 data in FIFO */ 00565 FifoCnt = (AD5940_FIFOGetCnt()/4)*4; 00566 00567 if(FifoCnt > BuffCount) 00568 { 00569 ///@todo buffer is limited. 00570 } 00571 AD5940_FIFORd((uint32_t *)pBuff, FifoCnt); 00572 AD5940_INTCClrFlag(AFEINTSRC_DATAFIFOTHRESH); 00573 AppIMPRegModify(pBuff, &FifoCnt); /* If there is need to do AFE re-configure, do it here when AFE is in active state */ 00574 //AD5940_EnterSleepS(); /* Manually put AFE back to hibernate mode. This operation only takes effect when register value is ACTIVE previously */ 00575 AD5940_SleepKeyCtrlS(SLPKEY_UNLOCK); /* Allow AFE to enter sleep mode. */ 00576 /* Process data */ 00577 AppIMPDataProcess((int32_t*)pBuff,&FifoCnt); 00578 *pCount = FifoCnt; 00579 return 0; 00580 } 00581 00582 return 0; 00583 } 00584 00585
Generated on Tue Jul 12 2022 21:32:08 by
 1.7.2
 1.7.2