Post Go back to editing

How to Increase Sampling Rate For The EVAL-AD5940BIOZ Board (Impedance Measurements)

Hello, 

I was wondering how the sampling rate for the EVAL-AD5940BIOZ board can be changed or is there a buffer limit to the number of samples that can be taken?. I am currently using the IAR software program and SerialTerm Capture to record the outputting data. I ran a sample test with a 1kOhm resistor for 1 second and I was able to record 184 lines of data. I am aiming to increase the sampling rate to 2,000 samples/second. I have already changed certain lines of code given by Github to run the example project, I will include those changes down below.  Any suggestions or thoughts would be greatly appreciated. Thank you!. 

Parents
  • Hi,

    Inside the measure function, you may add the code snippet below, to know the max allowed ODR for a given configuration:

      AppBIACfg.MeasSeqCycleCount = AD5940_SEQCycleTime();

      AppBIACfg.MaxODR = 1/((( AppBIACfg.MeasSeqCycleCount + 10) / 16.0)* 1E-6)  ; //If Sysclk is16MHz

      if(AppBIACfg.AmpODR > AppBIACfg.MaxODR)

      {

      /* We have requested a sampling rate that cannot be achieved with the time it takes to acquire a sample.*/

    AppBIACfg.AmpODR = AppBIACfg.MaxODR;

      }

    Also in AD5940_SEQCycleTime() function definition in AD5940.c ,

                    

     Change “ for(i=0;i<SeqGenDB.RegCount;i++)  “   to  “for(i=0;i<SeqGenDB.SeqLen;i++)”.

  • Hello Akila, 

    Thank you for the response. Is the snippet code for the body impedance function or 2-wire BIOZ function? 

  • It can be used for all the projects in AD594x 

  • Hi Akila, 

    When you mentioned adding the code snippet in the measurement function, are you referring to the line below " ODR (Sample Rate) 5 Hz */ "?

    Also, you mentioned that it would allow me to determine the max sampling rate for the BIOZ configuration. Would the max sampling rate be outputted after I download and debug or run an actual experimental test and export the file from RealTerm Capture?. 

    Thank you!

  • Hi Akila, 

    Sorry to bother you again, I forgot to mention this from yesterday's comment but is the snippet code supposed to have the same exact spacing as you indicated in your reply? 

Reply Children
  • Add the code snippet:

    AppBIACfg.MeasSeqCycleCount = AD5940_SEQCycleTime();

    AppBIACfg.MaxODR = 1/((( AppBIACfg.MeasSeqCycleCount + 10) / 16.0)* 1E-6)  ; //If Sysclk is16MHz

      if(AppBIACfg.AmpODR > AppBIACfg.MaxODR)

      {

      /* We have requested a sampling rate that cannot be achieved with the time it takes to acquire a sample.*/

    AppBIACfg.AmpODR = AppBIACfg.MaxODR;

      }

    inside AppBIASeqMeasureGen() function 

  • Hi Akila, 

    So I used the same exact codes you have provided to me and inserted them in the "AppBIOZSeqMeasureGen() function" instead of the "AppBIASeqMeasureGen() function" that you pointed out in your previous post. I also changed the configurations of "AppBIACfg." to the "AppBIOZCfg." to match the 2-Wire BIOZ impedance example on IAR. When I rebuild the project I get the following errors: 

    I also want to mention that I am getting similar errors even when I add the snippet code to the "AppBIASeqMeasureGen() function". The error messages indicate that the "AppBIACfg." is undefined. Any suggestions? Thank you!

  • Hi,

    You have to add the relevant fields in bodyImpedance.h:

    SEQInfo_Type InitSeqInfo;
    SEQInfo_Type MeasureSeqInfo;
    BoolFlag StopRequired; /* After FIFO is ready, stop the measurement sequence */
    uint32_t FifoDataCount; /* Count how many times impedance have been measured */
    uint32_t MeasSeqCycleCount; /* How long the measurement sequence will take */
    float MaxODR; /* Max ODR for sampling in this config */
    /* End */
    }AppBIACfg_Type;

    Also change AmpODR to BiaODR

  • Hi Akila, 

    I have two questions:
    Q1: I inserted the above code snippet in the BIOZ-2Wire.c and printed the parameters using printf, see the images attached for the code snippets and output. The SysClkFreq prints 16MHz correctly, but the AD5940_SEQCycleTime() prints what appears to be a random or unassigned number (1.49e-154), making the calculation of the MAxODR incorrect or useless. Should AD5940_SEQCycleTime() be defined somewhere?
    Q2: Is it possible to get the number of samples for a specified measurement time - like a 1 second or 10 second time period?
    Thank you! 
  • Hi,

    AD5940_SEQCycleTime() is defined in AD5940.c

    uint32_t AD5940_SEQCycleTime(void)
    {
    uint32_t i, Cycles, Cmd;
    Cycles = 0;
    for(i=0;i<SeqGenDB.RegCount;i++)
    {
    Cmd = (SeqGenDB.pSeqBuff[i] >> 30) & 0x3;
    if (Cmd & 0x2)
    {
    /* A write command */
    Cycles += 1;
    }
    else
    {
    if (Cmd & 0x1)
    {
    /* Timeout Command */
    Cycles += 1;
    }
    else
    {
    /* Wait command */
    Cycles += SeqGenDB.pSeqBuff[i] & 0x3FFFFFFF;
    }
    }
    }
    return Cycles;
    }

  • Hello Akila, 

    I wanted to diverge the thread post regarding the increase in sampling frequency of the AD5940BIOZ board with the BIOZ-2Wire example here. The other customer's question about the AD5940 board was on a different example. 

    The original thread is here:  How to change AD5940's sampling frequency 

    So in your latest response in the thread above, you highlighted regions that need to be changed in the BIOZ-2Wire.c file, but I wondered what it should be changed to obtain the 1000hz sampling rate? 

    The regions that you have indicated are already present (unedited lines of code) in the BIOZ-2Wire.c file. I wanted the complete code modifications to get to a 1000Hz sampling rate, which would be similar to a benchtop Zurich instrument, which we would like to compare to. I don't have an extensive background in programming so clarity on this subject matter would be the utmost help. In addition, please provide the maximum sampling rate and ideally the loss in accuracy from the 4Hz example in the documentation and the desirable 1000Hz sampling rate.

    Thank you!

  • Hello, 

    Has this been looked at by any chance? Thank you. 

  • Hi,

    Since Bioz2Wire code uses sequences (which run only at 32KHz), max allowed ODR is 5HZ only.

    Max of 10HZ can be achieved when measuring only ADC raw data.

    Below is the code modified for this:

    /******************************************************************************
    Copyright (c) 2017-2019 Analog Devices, Inc. All Rights Reserved.
    
    This software is proprietary to Analog Devices, Inc. and its licensors.
    By using this software you agree to the terms of the associated
    Analog Devices Software License Agreement.
    
    *****************************************************************************/
    
    #include "BIOZ-2Wire.h"
    
    /**
    * @note This example is modified from BIOZ example. This one is for 2-wire impedance measuremnt.
    *       The default pins used are CE0 and AIN2. The differnce with BIOZ is that the body voltage
    *       Measurment is replaced with excitation voltage measurment and it's only measured once.
    */
    
    /* 
    Application configuration structure. Specified by user from template.
    The variables are usable in this whole application.
    It includes basic configuration for sequencer generator and application related parameters
    */
    AppBIOZCfg_Type AppBIOZCfg = 
    {
      .bParaChanged = bFALSE,
      .SeqStartAddr = 0,
      .MaxSeqLen = 0,
      
      .SeqStartAddrCal = 0,
      .MaxSeqLenCal = 0,
      
      .ReDoRtiaCal = bFALSE,
      .SysClkFreq = 16000000.0,
      .WuptClkFreq = 32000.0,
      .AdcClkFreq = 16000000.0,
      .BIOZODR = 20.0, /* 20.0 Hz*/
      .NumOfData = -1,
      .RcalVal = 10000.0, /* 10kOhm */
      
      .PwrMod = AFEPWR_LP,
      .HstiaRtiaSel = HSTIARTIA_10K,
      .CtiaSel = 16,
      .ExcitBufGain = EXCITBUFGAIN_2,
      .HsDacGain = HSDACGAIN_1,
      .HsDacUpdateRate = 7,
      .DacVoltPP = 600.0,
      
      .SinFreq = 50000.0, /* 5000Hz */
      
      .ADCPgaGain = ADCPGA_1P5,
      .ADCSinc3Osr = ADCSINC3OSR_2,
      .ADCSinc2Osr = ADCSINC2OSR_22,
      
      .DftNum = DFTNUM_8192,
      .DftSrc = DFTSRC_SINC3,
      .HanWinEn = bTRUE,
      
      .SweepCfg.SweepEn = bFALSE,
      .SweepCfg.SweepStart = 10000,
      .SweepCfg.SweepStop = 150000.0,
      .SweepCfg.SweepPoints = 100,
      .SweepCfg.SweepLog = bTRUE,
      .SweepCfg.SweepIndex = 0,
      
      .FifoThresh = 4,	/* Must be 4 when SweepEn = bTRUE*/
      .BIOZInited = bFALSE,
      .StopRequired = bFALSE,
    };
    
    /**
    This function is provided for upper controllers that want to change 
    application parameters specially for user defined parameters.
    */
    AD5940Err AppBIOZGetCfg(void *pCfg)
    {
      if(pCfg){
        *(AppBIOZCfg_Type**)pCfg = &AppBIOZCfg;
        return AD5940ERR_OK;
      }
      return AD5940ERR_PARA;
    }
    
    AD5940Err AppBIOZCtrl(int32_t BcmCtrl, void *pPara)
    {
      switch (BcmCtrl)
      {
      case BIOZCTRL_START:
        {
          WUPTCfg_Type wupt_cfg;
          if(AD5940_WakeUp(10) > 10)  /* Wakeup AFE by read register, read 10 times at most */
            return AD5940ERR_WAKEUP;  /* Wakeup Failed */
          if(AppBIOZCfg.BIOZInited == bFALSE)
            return AD5940ERR_APPERROR;
          /* Start the wakeup timer */
          wupt_cfg.WuptEn = bTRUE;
          wupt_cfg.WuptEndSeq = WUPTENDSEQ_A;
          wupt_cfg.WuptOrder[0] = SEQID_0;
          wupt_cfg.SeqxSleepTime[SEQID_0] = (uint32_t)(AppBIOZCfg.WuptClkFreq/AppBIOZCfg.BIOZODR)-2-1;
          wupt_cfg.SeqxWakeupTime[SEQID_0] = 1; /* The minimum value is 1. Do not set it to zero. Set it to 1 will spend 2 32kHz clock. */
          AD5940_WUPTCfg(&wupt_cfg);
          
          AppBIOZCfg.FifoDataCount = 0;  /* restart */
    #ifdef ADI_DEBUG
          ADI_Print("BIOZ Start...\n");
    #endif
          break;
        }
      case BIOZCTRL_STOPNOW:
        {
          if(AD5940_WakeUp(10) > 10)  /* Wakeup AFE by read register, read 10 times at most */
            return AD5940ERR_WAKEUP;  /* Wakeup Failed */
          /* Stop Wupt right now */
          AD5940_WUPTCtrl(bFALSE);
          AD5940_WUPTCtrl(bFALSE);
    #ifdef ADI_DEBUG
          ADI_Print("BIOZ Stop Now...\n");
    #endif
          break;
        }
      case BIOZCTRL_STOPSYNC:
        {
    #ifdef ADI_DEBUG
          ADI_Print("BIOZ Stop SYNC...\n");
    #endif
          AppBIOZCfg.StopRequired = bTRUE;
          break;
        }
      case BIOZCTRL_GETFREQ:
        if(pPara)
        {
          if(AppBIOZCfg.SweepCfg.SweepEn == bTRUE)
            *(float*)pPara = AppBIOZCfg.FreqofData;
          else
            *(float*)pPara = AppBIOZCfg.SinFreq;
        }
        break;
      case BIOZCTRL_SHUTDOWN:
        {
          AppBIOZCtrl(BIOZCTRL_STOPNOW, 0);  /* Stop the measurment if it's running. */
          /* Turn off LPloop related blocks which are not controlled automatically by sleep operation */
          AFERefCfg_Type aferef_cfg;
          LPLoopCfg_Type lp_loop;
          memset(&aferef_cfg, 0, sizeof(aferef_cfg));
          AD5940_REFCfgS(&aferef_cfg);
          memset(&lp_loop, 0, sizeof(lp_loop));
          AD5940_LPLoopCfgS(&lp_loop);
          AD5940_EnterSleepS();  /* Enter Hibernate */
    #ifdef ADI_DEBUG
          ADI_Print("BIOZ Shut down...\n");
    #endif
        }
        break;
      default:
        break;
      }
      return AD5940ERR_OK;
    }
    
    /* Generate init sequence */
    static AD5940Err AppBIOZSeqCfgGen(void)
    {
      AD5940Err error = AD5940ERR_OK;
      uint32_t const *pSeqCmd;
      uint32_t SeqLen;
      
      AFERefCfg_Type aferef_cfg;
      HSLoopCfg_Type hs_loop;
      DSPCfg_Type dsp_cfg;
      float sin_freq;
      
      /* Start sequence generator here */
      AD5940_SEQGenCtrl(bTRUE);
      
      aferef_cfg.HpBandgapEn = bTRUE;
      aferef_cfg.Hp1V1BuffEn = bTRUE;
      aferef_cfg.Hp1V8BuffEn = bTRUE;
      aferef_cfg.Disc1V1Cap = bFALSE;
      aferef_cfg.Disc1V8Cap = bFALSE;
      aferef_cfg.Hp1V8ThemBuff = bFALSE;
      aferef_cfg.Hp1V8Ilimit = bFALSE;
      aferef_cfg.Lp1V1BuffEn = bFALSE;
      aferef_cfg.Lp1V8BuffEn = bFALSE;
    	
      /* LP reference control - turn off them to save powr*/
      aferef_cfg.LpBandgapEn = bTRUE;
      aferef_cfg.LpRefBufEn = bTRUE;
      aferef_cfg.LpRefBoostEn = bFALSE;
      AD5940_REFCfgS(&aferef_cfg);	
      hs_loop.HsDacCfg.ExcitBufGain = AppBIOZCfg.ExcitBufGain;
      hs_loop.HsDacCfg.HsDacGain = AppBIOZCfg.HsDacGain;
      hs_loop.HsDacCfg.HsDacUpdateRate = AppBIOZCfg.HsDacUpdateRate;
      
      hs_loop.HsTiaCfg.DiodeClose = bFALSE;
      hs_loop.HsTiaCfg.HstiaBias = HSTIABIAS_1P1;
      hs_loop.HsTiaCfg.HstiaCtia = AppBIOZCfg.CtiaSel; /* 31pF + 2pF */
      hs_loop.HsTiaCfg.HstiaDeRload = HSTIADERLOAD_OPEN;
      hs_loop.HsTiaCfg.HstiaDeRtia = HSTIADERTIA_OPEN;
      hs_loop.HsTiaCfg.HstiaRtiaSel = AppBIOZCfg.HstiaRtiaSel;
      
      hs_loop.SWMatCfg.Dswitch = SWD_OPEN;
      hs_loop.SWMatCfg.Pswitch = SWP_PL|SWP_PL2;
      hs_loop.SWMatCfg.Nswitch = SWN_NL|SWN_NL2;
      hs_loop.SWMatCfg.Tswitch = SWT_TRTIA;
      
      hs_loop.WgCfg.WgType = WGTYPE_SIN;
      hs_loop.WgCfg.GainCalEn = bFALSE;
      hs_loop.WgCfg.OffsetCalEn = bFALSE;
      if(AppBIOZCfg.SweepCfg.SweepEn == bTRUE)
      {
        AppBIOZCfg.SweepCfg.SweepIndex = 0;
        AppBIOZCfg.FreqofData = AppBIOZCfg.SweepCfg.SweepStart;
        AppBIOZCfg.SweepCurrFreq = AppBIOZCfg.SweepCfg.SweepStart;
        AD5940_SweepNext(&AppBIOZCfg.SweepCfg, &AppBIOZCfg.SweepNextFreq);
        sin_freq = AppBIOZCfg.SweepCurrFreq;
      }
      else
      {
        sin_freq = AppBIOZCfg.SinFreq;
        AppBIOZCfg.FreqofData = sin_freq;
      }
      hs_loop.WgCfg.SinCfg.SinFreqWord = AD5940_WGFreqWordCal(sin_freq, AppBIOZCfg.SysClkFreq);
      hs_loop.WgCfg.SinCfg.SinAmplitudeWord = (uint32_t)(AppBIOZCfg.DacVoltPP/800.0f*2047 + 0.5f);
      hs_loop.WgCfg.SinCfg.SinOffsetWord = 0;
      hs_loop.WgCfg.SinCfg.SinPhaseWord = 0;
      AD5940_HSLoopCfgS(&hs_loop);
      
      dsp_cfg.ADCBaseCfg.ADCMuxN = ADCMUXN_HSTIA_N;
      dsp_cfg.ADCBaseCfg.ADCMuxP = ADCMUXP_HSTIA_P;
      dsp_cfg.ADCBaseCfg.ADCPga = AppBIOZCfg.ADCPgaGain;
      
      memset(&dsp_cfg.ADCDigCompCfg, 0, sizeof(dsp_cfg.ADCDigCompCfg));
      
      //dsp_cfg.ADCFilterCfg.ADCAvgNum = ADCAVGNUM_16;  /* Don't care becase it's disabled */
      dsp_cfg.ADCFilterCfg.ADCRate = ADCRATE_800KHZ;	/* Tell filter block clock rate of ADC*/
      dsp_cfg.ADCFilterCfg.ADCSinc2Osr = AppBIOZCfg.ADCSinc2Osr;
      dsp_cfg.ADCFilterCfg.ADCSinc3Osr = AppBIOZCfg.ADCSinc3Osr;
      dsp_cfg.ADCFilterCfg.BpSinc3 = bTRUE;//bFALSE;
      dsp_cfg.ADCFilterCfg.BpNotch = bTRUE;
      dsp_cfg.ADCFilterCfg.Sinc2NotchEnable = bTRUE;
      //dsp_cfg.DftCfg.DftNum = AppBIOZCfg.DftNum;
      //dsp_cfg.DftCfg.DftSrc = AppBIOZCfg.DftSrc;
      //dsp_cfg.DftCfg.HanWinEn = AppBIOZCfg.HanWinEn;
      
      memset(&dsp_cfg.StatCfg, 0, sizeof(dsp_cfg.StatCfg)); /* Don't care about Statistic */
      AD5940_DSPCfgS(&dsp_cfg);
      
      /* Enable all of them. They are automatically turned off during hibernate mode to save power */
      AD5940_AFECtrlS(AFECTRL_HPREFPWR|AFECTRL_HSTIAPWR|AFECTRL_INAMPPWR|AFECTRL_EXTBUFPWR|\
        AFECTRL_DACREFPWR|AFECTRL_HSDACPWR|\
          AFECTRL_SINC2NOTCH, bTRUE);
      AD5940_SEQGpioCtrlS(0/*AGPIO_Pin6|AGPIO_Pin5|AGPIO_Pin1*/);        //GP6->endSeq, GP5 -> AD8233=OFF, GP1->RLD=OFF .
      
      /* Sequence end. */
      AD5940_SEQGenInsert(SEQ_STOP()); /* Add one extral command to disable sequencer for initialization sequence because we only want it to run one time. */
      
      /* Stop here */
      error = AD5940_SEQGenFetchSeq(&pSeqCmd, &SeqLen);
      AD5940_SEQGenCtrl(bFALSE); /* Stop seuqncer generator */
      if(error == AD5940ERR_OK)
      {
        AppBIOZCfg.InitSeqInfo.SeqId = SEQID_1;
        AppBIOZCfg.InitSeqInfo.SeqRamAddr = AppBIOZCfg.SeqStartAddr;
        AppBIOZCfg.InitSeqInfo.pSeqCmd = pSeqCmd;
        AppBIOZCfg.InitSeqInfo.SeqLen = SeqLen;
        /* Write command to SRAM */
        AD5940_SEQCmdWrite(AppBIOZCfg.InitSeqInfo.SeqRamAddr, pSeqCmd, SeqLen);
      }
      else
        return error; /* Error */
      return AD5940ERR_OK;
    }
    
    static AD5940Err AppBIOZSeqMeasureGen(void)
    {
      AD5940Err error = AD5940ERR_OK;
      uint32_t const *pSeqCmd;
      uint32_t SeqLen;
      
      uint32_t WaitClks;
      SWMatrixCfg_Type sw_cfg;
      ClksCalInfo_Type clks_cal;
      
      clks_cal.DataType = DATATYPE_ADCRAW;//DATATYPE_DFT;
      //clks_cal.DftSrc = AppBIOZCfg.DftSrc;
      clks_cal.DataCount = 1L<<(AppBIOZCfg.DftNum+2); /* 2^(DFTNUMBER+2) */
      clks_cal.ADCSinc2Osr = AppBIOZCfg.ADCSinc2Osr;
      clks_cal.ADCSinc3Osr = AppBIOZCfg.ADCSinc3Osr;
      clks_cal.ADCAvgNum = 0;
      clks_cal.RatioSys2AdcClk = AppBIOZCfg.SysClkFreq/AppBIOZCfg.AdcClkFreq;
      AD5940_ClksCalculate(&clks_cal, &WaitClks);
      
      /* Start sequence generator here */
      AD5940_SEQGenCtrl(bTRUE);
      
      AD5940_SEQGpioCtrlS(AGPIO_Pin1/*|AGPIO_Pin5|AGPIO_Pin1*/);//GP6->endSeq, GP5 -> AD8233=OFF, GP1->RLD=OFF .
      
    	/* Configure switch matrix to connect the sensor */
      sw_cfg.Dswitch = AppBIOZCfg.DswitchSel;
      sw_cfg.Pswitch = AppBIOZCfg.PswitchSel;
      sw_cfg.Nswitch = AppBIOZCfg.NswitchSel;
      sw_cfg.Tswitch = AppBIOZCfg.TswitchSel|SWT_TRTIA;
      AD5940_SWMatrixCfgS(&sw_cfg);
      
      AD5940_SEQGenInsert(SEQ_WAIT(16*250));
      /* Step 1: Measure Current */
      AD5940_ADCMuxCfgS(ADCMUXP_HSTIA_P, ADCMUXN_HSTIA_N);
      AD5940_AFECtrlS(AFECTRL_WG|AFECTRL_ADCPWR, bTRUE);  /* Enable Waveform generator, ADC power */
      AD5940_SEQGenInsert(SEQ_WAIT(16*50));
      AD5940_AFECtrlS(AFECTRL_ADCCNV|AFECTRL_DFT, bTRUE);  /* Start ADC convert and DFT */
      AD5940_SEQGenInsert(SEQ_WAIT(WaitClks));  /* wait for first data ready */  
    	AD5940_SEQGenInsert(SEQ_WAIT(1));
      AD5940_AFECtrlS(AFECTRL_ADCCNV|AFECTRL_DFT|AFECTRL_WG|AFECTRL_ADCPWR, bFALSE);  /* Stop ADC convert and DFT */
      
      /* Step 2: Measure Voltage */
      AD5940_ADCMuxCfgS(ADCMUXP_VCE0, ADCMUXN_N_NODE);
      AD5940_AFECtrlS(AFECTRL_WG|AFECTRL_ADCPWR, bTRUE);  /* Enable Waveform generator, ADC power */
      AD5940_SEQGenInsert(SEQ_WAIT(16*50));
      AD5940_AFECtrlS(AFECTRL_ADCCNV|AFECTRL_DFT, bTRUE);  /* Start ADC convert and DFT */
      AD5940_SEQGenInsert(SEQ_WAIT(WaitClks));  /* wait for first data ready */  
    	AD5940_SEQGenInsert(SEQ_WAIT(1));
      AD5940_AFECtrlS(AFECTRL_ADCCNV|AFECTRL_DFT|AFECTRL_WG|AFECTRL_ADCPWR, bFALSE);  /* Stop ADC convert and DFT */
      
      sw_cfg.Dswitch = SWD_OPEN;
      sw_cfg.Pswitch = SWP_PL|SWP_PL2;
      sw_cfg.Nswitch = SWN_NL|SWN_NL2;
      sw_cfg.Tswitch = SWT_TRTIA;
      AD5940_SWMatrixCfgS(&sw_cfg); /* Float switches */
      
      AD5940_SEQGpioCtrlS(0/*AGPIO_Pin6|AGPIO_Pin5|AGPIO_Pin1*/);        //GP6->endSeq, GP5 -> AD8233=OFF, GP1->RLD=OFF .
      AD5940_EnterSleepS();/* Goto hibernate */
      /* Sequence end. */
      error = AD5940_SEQGenFetchSeq(&pSeqCmd, &SeqLen);
      AD5940_SEQGenCtrl(bFALSE); /* Stop seuqncer generator */
      
      AppBIOZCfg.MeasSeqCycleCount = AD5940_SEQCycleTime();
    
    AppBIOZCfg.MaxODR = 1/((( AppBIOZCfg.MeasSeqCycleCount + 10) / 32.0)* 1E-6)  ; //If Sysclk is16MHz
    
      if(AppBIOZCfg.BIOZODR > AppBIOZCfg.MaxODR)
    
      {
    
      /* We have requested a sampling rate that cannot be achieved with the time it takes to acquire a sample.*/
    
    AppBIOZCfg.BIOZODR = AppBIOZCfg.MaxODR;
    
      }
      
      if(error == AD5940ERR_OK)
      {
        AppBIOZCfg.MeasureSeqInfo.SeqId = SEQID_0;
        AppBIOZCfg.MeasureSeqInfo.SeqRamAddr = AppBIOZCfg.InitSeqInfo.SeqRamAddr + AppBIOZCfg.InitSeqInfo.SeqLen ;
        AppBIOZCfg.MeasureSeqInfo.pSeqCmd = pSeqCmd;
        AppBIOZCfg.MeasureSeqInfo.SeqLen = SeqLen;
        /* Write command to SRAM */
        AD5940_SEQCmdWrite(AppBIOZCfg.MeasureSeqInfo.SeqRamAddr, pSeqCmd, SeqLen);
      }
      else
        return error; /* Error */
      return AD5940ERR_OK;
    }
    
    static AD5940Err AppBIOZRtiaCal(void)
    {
      HSRTIACal_Type hsrtia_cal;
      FreqParams_Type freq_params;
      
      if(AppBIOZCfg.SweepCfg.SweepEn == bTRUE)
      {
        hsrtia_cal.fFreq = AppBIOZCfg.SweepCfg.SweepStart;
        freq_params = AD5940_GetFreqParameters(AppBIOZCfg.SweepCfg.SweepStart);
      }
      else
      {
        hsrtia_cal.fFreq = AppBIOZCfg.SinFreq;
        freq_params = AD5940_GetFreqParameters(AppBIOZCfg.SinFreq);
      }
      
      if(freq_params.HighPwrMode == bTRUE)
        hsrtia_cal.AdcClkFreq = 32e6; 
      else
        hsrtia_cal.AdcClkFreq = 16e6;
      hsrtia_cal.ADCSinc2Osr = freq_params.ADCSinc2Osr;
      hsrtia_cal.ADCSinc3Osr = freq_params.ADCSinc3Osr;
      hsrtia_cal.DftCfg.DftNum = freq_params.DftNum;
      hsrtia_cal.DftCfg.DftSrc = freq_params.DftSrc;
      hsrtia_cal.bPolarResult = bTRUE; /* We need magnitude and phase here */
      hsrtia_cal.DftCfg.HanWinEn = AppBIOZCfg.HanWinEn;
      hsrtia_cal.fRcal= AppBIOZCfg.RcalVal;
      hsrtia_cal.HsTiaCfg.DiodeClose = bFALSE;
      hsrtia_cal.HsTiaCfg.HstiaBias = HSTIABIAS_1P1;
      hsrtia_cal.HsTiaCfg.HstiaCtia = AppBIOZCfg.CtiaSel;
      hsrtia_cal.HsTiaCfg.HstiaDeRload = HSTIADERLOAD_OPEN;
      hsrtia_cal.HsTiaCfg.HstiaDeRtia = HSTIADERTIA_OPEN;
      hsrtia_cal.HsTiaCfg.HstiaRtiaSel = AppBIOZCfg.HstiaRtiaSel;
      hsrtia_cal.SysClkFreq = AppBIOZCfg.SysClkFreq;
      
      
      if(AppBIOZCfg.SweepCfg.SweepEn == bTRUE)
      {
        uint32_t i;
        AppBIOZCfg.SweepCfg.SweepIndex = 0;  /* Reset index */
        for(i=0;i<AppBIOZCfg.SweepCfg.SweepPoints;i++)
        {      
          AD5940_HSRtiaCal(&hsrtia_cal, &AppBIOZCfg.RtiaCalTable[i]);
    #ifdef ADI_DEBUG
          ADI_Print("Freq:%.2f, (%f, %f)Ohm\n", hsrtia_cal.fFreq, AppBIOZCfg.RtiaCalTable[i].Real, AppBIOZCfg.RtiaCalTable[i].Image);
    #endif
          AD5940_SweepNext(&AppBIOZCfg.SweepCfg, &hsrtia_cal.fFreq);
          freq_params = AD5940_GetFreqParameters(hsrtia_cal.fFreq);
          
          if(freq_params.HighPwrMode == bTRUE)
          {
            hsrtia_cal.AdcClkFreq = 32e6;
            /* Change clock to 32MHz oscillator */
            AD5940_HPModeEn(bTRUE);
          }
          else
          {
            hsrtia_cal.AdcClkFreq = 16e6;
            /* Change clock to 16MHz oscillator */
    	AD5940_HPModeEn(bFALSE);
          }
          hsrtia_cal.ADCSinc2Osr = freq_params.ADCSinc2Osr;
          hsrtia_cal.ADCSinc3Osr = freq_params.ADCSinc3Osr;
          hsrtia_cal.DftCfg.DftNum = freq_params.DftNum;
          hsrtia_cal.DftCfg.DftSrc = freq_params.DftSrc;
        }
        
        AppBIOZCfg.SweepCfg.SweepIndex = 0;  /* Reset index */
        AppBIOZCfg.RtiaCurrValue = AppBIOZCfg.RtiaCalTable[0];
      }
      else
      {
        AD5940_HSRtiaCal(&hsrtia_cal, &AppBIOZCfg.RtiaCurrValue);
    #ifdef ADI_DEBUG
        ADI_Print("Freq:%.2f, (%f, %f)Ohm\n", hsrtia_cal.fFreq, AppBIOZCfg.RtiaCurrValue.Real, AppBIOZCfg.RtiaCurrValue.Image);
    #endif
      }
      return AD5940ERR_OK;
    }
    
    /* This function provide application initialize.   */
    AD5940Err AppBIOZInit(uint32_t *pBuffer, uint32_t BufferSize)
    {
      AD5940Err error = AD5940ERR_OK;
      SEQCfg_Type seq_cfg;
      FIFOCfg_Type fifo_cfg;
      
      if(AD5940_WakeUp(10) > 10)  /* Wakeup AFE by read register, read 10 times at most */
        return AD5940ERR_WAKEUP;  /* Wakeup Failed */
      
      /* Configure sequencer and stop it */
      seq_cfg.SeqMemSize = SEQMEMSIZE_2KB;  /* 2kB SRAM is used for sequencer, others for data FIFO */
      seq_cfg.SeqBreakEn = bFALSE;
      seq_cfg.SeqIgnoreEn = bFALSE;
      seq_cfg.SeqCntCRCClr = bTRUE;
      seq_cfg.SeqEnable = bFALSE;
      seq_cfg.SeqWrTimer = 0;
      AD5940_SEQCfg(&seq_cfg);
      
      /* Do RTIA calibration */
      if((AppBIOZCfg.ReDoRtiaCal == bTRUE) || \
        AppBIOZCfg.BIOZInited == bFALSE)  /* Do calibration on the first initializaion */
      {
        AppBIOZRtiaCal();
        AppBIOZCfg.ReDoRtiaCal = bFALSE;
      }
      /* Reconfigure FIFO */
      AD5940_FIFOCtrlS(FIFOSRC_DFT, bFALSE);									/* Disable FIFO firstly */
      fifo_cfg.FIFOEn = bTRUE;
      fifo_cfg.FIFOMode = FIFOMODE_FIFO;
      fifo_cfg.FIFOSize = FIFOSIZE_4KB;                       /* 4kB for FIFO, The reset 2kB for sequencer */
      fifo_cfg.FIFOSrc = FIFOSRC_DFT;
      fifo_cfg.FIFOThresh = AppBIOZCfg.FifoThresh;              /* DFT result. One pair for RCAL, another for Rz. One DFT result have real part and imaginary part */
      AD5940_FIFOCfg(&fifo_cfg);
      
      AD5940_INTCClrFlag(AFEINTSRC_ALLINT);
      
      /* Start sequence generator */
      /* Initialize sequencer generator */
      if((AppBIOZCfg.BIOZInited == bFALSE)||\
        (AppBIOZCfg.bParaChanged == bTRUE))
      {
        if(pBuffer == 0)  return AD5940ERR_PARA;
        if(BufferSize == 0) return AD5940ERR_PARA;   
        AD5940_SEQGenInit(pBuffer, BufferSize);
        
        /* Generate initialize sequence */
        error = AppBIOZSeqCfgGen(); /* Application initialization sequence using either MCU or sequencer */
        if(error != AD5940ERR_OK) return error;
        
        /* Generate measurement sequence */
        error = AppBIOZSeqMeasureGen();
        if(error != AD5940ERR_OK) return error;
        
        AppBIOZCfg.bParaChanged = bFALSE; /* Clear this flag as we already implemented the new configuration */
      }
      
      /* Initialization sequencer  */
      AppBIOZCfg.InitSeqInfo.WriteSRAM = bFALSE;
      AD5940_SEQInfoCfg(&AppBIOZCfg.InitSeqInfo);
      seq_cfg.SeqEnable = bTRUE;
      AD5940_SEQCfg(&seq_cfg);  /* Enable sequencer */
      AD5940_SEQMmrTrig(AppBIOZCfg.InitSeqInfo.SeqId);
      while(AD5940_INTCTestFlag(AFEINTC_1, AFEINTSRC_ENDSEQ) == bFALSE);
      AD5940_INTCClrFlag(AFEINTSRC_ALLINT);
    
      /* Measurment sequence  */
      AppBIOZCfg.MeasureSeqInfo.WriteSRAM = bFALSE;
      AD5940_SEQInfoCfg(&AppBIOZCfg.MeasureSeqInfo);
      
      AppBIOZCheckFreq(AppBIOZCfg.FreqofData);
      seq_cfg.SeqEnable = bTRUE;
      AD5940_SEQCfg(&seq_cfg);  /* Enable sequencer, and wait for trigger */
      AD5940_ClrMCUIntFlag();   /* Clear interrupt flag generated before */
      
      AppBIOZCfg.BIOZInited = bTRUE;  /* BIOZ application has been initialized. */
      return AD5940ERR_OK;
    }
    
    /* Depending on frequency of Sin wave set optimum filter settings */
    AD5940Err AppBIOZCheckFreq(float freq)
    {
      ADCFilterCfg_Type filter_cfg;
      DFTCfg_Type dft_cfg;
      HSDACCfg_Type hsdac_cfg;
      uint32_t WaitClks;
      ClksCalInfo_Type clks_cal;
      FreqParams_Type freq_params;
      uint32_t SeqCmdBuff[2];
      uint32_t SRAMAddr = 0;;
      /* Step 1: Check Frequency */
      freq_params = AD5940_GetFreqParameters(freq);
      
    	/* Set power mode */
      if(freq_params.HighPwrMode == bTRUE)
      {
        /* Update HSDAC update rate */     
        hsdac_cfg.ExcitBufGain = AppBIOZCfg.ExcitBufGain;
        hsdac_cfg.HsDacGain = AppBIOZCfg.HsDacGain;
        hsdac_cfg.HsDacUpdateRate = 0x7;
        AD5940_HSDacCfgS(&hsdac_cfg);
        
        /*Update ADC rate */
        filter_cfg.ADCRate = ADCRATE_1P6MHZ;
        AppBIOZCfg.AdcClkFreq = 32e6;
        
        /* Change clock to 32MHz oscillator */
        AD5940_HPModeEn(bTRUE);
      }else
    	{
        /* Update HSDAC update rate */
        hsdac_cfg.ExcitBufGain = AppBIOZCfg.ExcitBufGain;
        hsdac_cfg.HsDacGain = AppBIOZCfg.HsDacGain;
        hsdac_cfg.HsDacUpdateRate = 0x1B;
        AD5940_HSDacCfgS(&hsdac_cfg);
        /* Update ADC rate */
        filter_cfg.ADCRate = ADCRATE_800KHZ;
        AppBIOZCfg.AdcClkFreq = 16e6;
        
    		/* Change clock to 16MHz oscillator */
        AD5940_HPModeEn(bFALSE);
      }
      
      /* Step 2: Adjust ADCFILTERCON and DFTCON to set optimumn SINC3, SINC2 and DFTNUM settings  */
      filter_cfg.ADCAvgNum = ADCAVGNUM_16;  /* Don't care because it's disabled */ 
      filter_cfg.ADCSinc2Osr = freq_params.ADCSinc2Osr;
      filter_cfg.ADCSinc3Osr = freq_params.ADCSinc3Osr;
      filter_cfg.BpSinc3 = bFALSE;
      filter_cfg.BpNotch = bTRUE;
      filter_cfg.Sinc2NotchEnable = bTRUE;
      dft_cfg.DftNum = freq_params.DftNum;
      dft_cfg.DftSrc = freq_params.DftSrc;
      dft_cfg.HanWinEn = AppBIOZCfg.HanWinEn;
      AD5940_ADCFilterCfgS(&filter_cfg);
      AD5940_DFTCfgS(&dft_cfg);
      
      /* Step 3: Calculate clocks needed to get result to FIFO and update sequencer wait command */
      clks_cal.DataType = DATATYPE_DFT;
      clks_cal.DftSrc = freq_params.DftSrc;
      clks_cal.DataCount = 1L<<(freq_params.DftNum+2); /* 2^(DFTNUMBER+2) */
      clks_cal.ADCSinc2Osr = freq_params.ADCSinc2Osr;
      clks_cal.ADCSinc3Osr = freq_params.ADCSinc3Osr;
      clks_cal.ADCAvgNum = 0;
      clks_cal.RatioSys2AdcClk = AppBIOZCfg.SysClkFreq/AppBIOZCfg.AdcClkFreq;
      AD5940_ClksCalculate(&clks_cal, &WaitClks);		
    	
    	/* Maximum number of clocks is 0x3FFFFFFF. More are needed if the frequency is low */
    	if(WaitClks > 0x3FFFFFFF)
    	{
    		WaitClks /=2;
    		SRAMAddr = AppBIOZCfg.MeasureSeqInfo.SeqRamAddr;
    		SeqCmdBuff[0] = SEQ_WAIT(WaitClks);
    		AD5940_SEQCmdWrite(SRAMAddr+11, SeqCmdBuff, 1);
    		AD5940_SEQCmdWrite(SRAMAddr+12, SeqCmdBuff, 1);
    		AD5940_SEQCmdWrite(SRAMAddr+18, SeqCmdBuff, 1);
    		AD5940_SEQCmdWrite(SRAMAddr+19, SeqCmdBuff, 1);
    	}
    	else
    	{
    		SRAMAddr = AppBIOZCfg.MeasureSeqInfo.SeqRamAddr;
    		SeqCmdBuff[0] = SEQ_WAIT(WaitClks);
    		AD5940_SEQCmdWrite(SRAMAddr+11, SeqCmdBuff, 1);
    		AD5940_SEQCmdWrite(SRAMAddr+18, SeqCmdBuff, 1);
    	}
     
      return AD5940ERR_OK;
    }
    
    /* Modify registers when AFE wakeup */
    static AD5940Err AppBIOZRegModify(int32_t * const pData, uint32_t *pDataCount)
    {
      if(AppBIOZCfg.NumOfData > 0)
      {
        AppBIOZCfg.FifoDataCount += *pDataCount/4;
        if(AppBIOZCfg.FifoDataCount >= AppBIOZCfg.NumOfData)
        {
          AD5940_WUPTCtrl(bFALSE);
          return AD5940ERR_OK;
        }
      }
      if(AppBIOZCfg.StopRequired == bTRUE)
      {
        AD5940_WUPTCtrl(bFALSE);
        return AD5940ERR_OK;
      }
      if(AppBIOZCfg.SweepCfg.SweepEn) /* Need to set new frequency and set power mode */
      {
        AppBIOZCheckFreq(AppBIOZCfg.SweepNextFreq);
        AD5940_WGFreqCtrlS(AppBIOZCfg.SweepNextFreq, AppBIOZCfg.SysClkFreq);
      }
      return AD5940ERR_OK;
    }
    
    /* Depending on the data type, do appropriate data pre-process before return back to controller */
    static AD5940Err AppBIOZDataProcess(int32_t * const pData, uint32_t *pDataCount)
    {
      uint32_t DataCount = *pDataCount;
      uint32_t ImpResCount = DataCount/4;
      
      fImpCar_Type * pOut = (fImpCar_Type*)pData;
      iImpCar_Type * pSrcData = (iImpCar_Type*)pData;
      
      *pDataCount = 0;
      
      DataCount = (DataCount/4)*4; /* One DFT result has two data in FIFO, real part and imaginary part. Each measurement has 2 DFT results, one for voltage measurement, one for current */
      
      /* Convert DFT result to int32_t type */
      for(uint32_t i=0; i<DataCount; i++)
      {
        pData[i] &= 0x3ffff;
        if(pData[i]&(1<<17)) /* Bit17 is sign bit */
        {
          pData[i] |= 0xfffc0000; /* Data is 18bit in two's complement, bit17 is the sign bit */
        }
      }
      for(uint32_t i=0; i<ImpResCount; i++)
      {
        fImpCar_Type DftCurr, DftVolt;
        fImpCar_Type res;
        
        DftCurr.Real = (float)pSrcData[i].Real;
        DftCurr.Image = (float)pSrcData[i].Image;
        DftVolt.Real = (float)pSrcData[i+1].Real;
        DftVolt.Image = (float)pSrcData[i+1].Image;
        
        DftCurr.Real = -DftCurr.Real;
        DftCurr.Image = -DftCurr.Image;
        DftVolt.Real = DftVolt.Real;
        DftVolt.Image = DftVolt.Image;
        res = AD5940_ComplexDivFloat(&DftCurr, &AppBIOZCfg.RtiaCurrValue);           /* I=Vrtia/Zrtia */
        res = AD5940_ComplexDivFloat(&DftVolt, &res);
        pOut[i] = res;
      }
      *pDataCount = ImpResCount; 
      /* Calculate next frequency point */
      if(AppBIOZCfg.SweepCfg.SweepEn == bTRUE)
      {
        AppBIOZCfg.FreqofData = AppBIOZCfg.SweepCurrFreq;
        AppBIOZCfg.SweepCurrFreq = AppBIOZCfg.SweepNextFreq;
        AppBIOZCfg.RtiaCurrValue = AppBIOZCfg.RtiaCalTable[AppBIOZCfg.SweepCfg.SweepIndex];
        AD5940_SweepNext(&AppBIOZCfg.SweepCfg, &AppBIOZCfg.SweepNextFreq);
      }
      return AD5940ERR_OK;
    }
    
    /**
    
    */
    AD5940Err AppBIOZISR(void *pBuff, uint32_t *pCount)
    {
      uint32_t BuffCount;
      uint32_t FifoCnt;
      if(AppBIOZCfg.BIOZInited == bFALSE)
        return AD5940ERR_APPERROR;
      if(AD5940_WakeUp(10) > 10)  /* Wakeup AFE by read register, read 10 times at most */
        return AD5940ERR_WAKEUP;  /* Wakeup Failed */
    	
      AD5940_SleepKeyCtrlS(SLPKEY_LOCK);  /* Don't enter hibernate */
      *pCount = 0;
      
      if(AD5940_INTCTestFlag(AFEINTC_0, AFEINTSRC_DATAFIFOTHRESH) == bTRUE)
      {
        /* Now there should be 4 data in FIFO */
        FifoCnt = (AD5940_FIFOGetCnt()/4)*4;
        AD5940_FIFORd((uint32_t *)pBuff, FifoCnt);
        AD5940_INTCClrFlag(AFEINTSRC_DATAFIFOTHRESH);
        AppBIOZRegModify(pBuff, &FifoCnt);   /* If there is need to do AFE re-configure, do it here when AFE is in active state */
        AD5940_EnterSleepS();  /* Manually put AFE back to hibernate mode to save power. */
        AD5940_SleepKeyCtrlS(SLPKEY_UNLOCK);  /* Allow AFE to enter hibernate mode */
        /* Process data */ 
        AppBIOZDataProcess((int32_t*)pBuff,&FifoCnt); 
        *pCount = FifoCnt;
        return 0;
      }
      
      return 0;
    } 
    
    /**
    * @}
    */
    
    

    For achieving 1000Hz, the code should be written without sequences. 

  • Hi,

    Sinc2 setting

    (ADC SINC2 Filter Oversampling rate)

    Sinc3 setting

    (ADC SINC3 Filter Oversampling rate)

    DFT points

    Avg Num setting

    (No. of inputs taken to do average)

    Max ODR

    (max allowed Output data rate in Hz)

    22

    2

    16384

    16

    1.21643219E+1

    22

    4

    16384

    16

    6.0924482344

    22

    5

    16384

    16

    4.87560796

    22

    2

    8192

    16

    2.42438202E+1

    22

    2

    4096

    16

    4.8151870722E+1

    22

    2

    2048

    16

    9.4988182E+1

    22

    2

    1024

    16

    1.8492407222E+2

    22

    2

    512

    16

    3.5116983033E+2

    22

    2

    256

    16

    6.37907653E+2

    22

    2

    128

    16

    1.07802185E+3

    22

    2

    64

    16

    1.6457519533E+3

    22

    2

    32

    16

    2.23401294E+3

    22

    2

    16

    16

    2.72016333E+3

    22

    2

    8

    16

    3.05227002E+3

    22

    2

    4

    16

    3.2507111811E+3

    44

    2

    4

    16

    3.2507111811E+3

    89

    2

    4

    16

    3.2507111811E+3

    178

    2

    4

    16

    3.2507111811E+3

    267

    2

    4

    16

    3.2507111811E+3

    533

    2

    4

    16

    3.2507111811E+3

    640

    2

    4

    16

    3.2507111811E+3

    667

    2

    4

    16

    3.2507111811E+3

    800

    2

    4

    16

    3.2507111811E+3

    889

    2

    4

    16

    3.2507111811E+3

    1067

    2

    4

    16

    3.2507111811E+3

    1333

    2

    4

    16

    3.2507111811E+3

    22

    2

    4

    8

    3.2507111811E+3

    22

    2

    4

    4

    3.2507111811E+3

    22

    2

    4

    2

    3.2507111811E+3