James Reynolds / AD594x Driver
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Impedance.c Source File

Impedance.c

Go to the documentation of this file.
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