732 lines
21 KiB
C
732 lines
21 KiB
C
// File: Impedance.c
|
|
#include "ad5940.h"
|
|
#include <stdio.h>
|
|
#include "string.h"
|
|
#include "math.h"
|
|
#include "Impedance.h"
|
|
|
|
/* Default LPDAC resolution(2.5V internal reference). */
|
|
#define DAC12BITVOLT_1LSB (2200.0f/4095) //mV
|
|
#define DAC6BITVOLT_1LSB (DAC12BITVOLT_1LSB*64) //mV
|
|
|
|
AppIMPCfg_Type AppIMPCfg =
|
|
{
|
|
.bParaChanged = bFALSE,
|
|
.SeqStartAddr = 0,
|
|
.MaxSeqLen = 0,
|
|
|
|
.SeqStartAddrCal = 0,
|
|
.MaxSeqLenCal = 0,
|
|
|
|
.ImpODR = 20.0, /* 20.0 Hz = 50ms period */
|
|
.NumOfData = -1,
|
|
.RealDataCount = -1, /* Default to no filtering */
|
|
.SysClkFreq = 16000000.0,
|
|
.WuptClkFreq = 32000.0,
|
|
.AdcClkFreq = 16000000.0,
|
|
.RcalVal = 10000.0,
|
|
.RtiaVal = 200.0,
|
|
|
|
.DswitchSel = SWD_CE0,
|
|
.PswitchSel = SWP_CE0,
|
|
.NswitchSel = SWN_SE0,
|
|
.TswitchSel = SWT_TRTIA,
|
|
|
|
.PwrMod = AFEPWR_HP,
|
|
|
|
.HstiaRtiaSel = HSTIARTIA_200,
|
|
.ExtRtia = 0,
|
|
.ExcitBufGain = EXCITBUFGAIN_0P25,
|
|
.HsDacGain = HSDACGAIN_0P2,
|
|
.HsDacUpdateRate = 7,
|
|
.DacVoltPP = 600.0,
|
|
.BiasVolt = -0.0f,
|
|
|
|
.SinFreq = 1000.0,
|
|
|
|
.DftNum = DFTNUM_16384,
|
|
.DftSrc = DFTSRC_SINC3,
|
|
.HanWinEn = bTRUE,
|
|
|
|
.AdcPgaGain = ADCPGA_1P5,
|
|
.ADCSinc3Osr = ADCSINC3OSR_2,
|
|
.ADCSinc2Osr = ADCSINC2OSR_22,
|
|
|
|
.ADCAvgNum = ADCAVGNUM_16,
|
|
|
|
.SweepCfg.SweepEn = bTRUE,
|
|
.SweepCfg.SweepStart = 1000,
|
|
.SweepCfg.SweepStop = 100000.0,
|
|
.SweepCfg.SweepPoints = 101,
|
|
.SweepCfg.SweepLog = bFALSE,
|
|
.SweepCfg.SweepIndex = 0,
|
|
|
|
.FifoThresh = 6, /* 3 measurements * 2 (Real/Imag) = 6 words */
|
|
.IMPInited = bFALSE,
|
|
.StopRequired = bFALSE,
|
|
};
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
/* Helper Functions */
|
|
/* ----------------------------------------------------------------------- */
|
|
|
|
void AppIMPCleanup(void) {
|
|
// Ensure chip is awake before sending commands
|
|
if(AD5940_WakeUp(10) > 10) return;
|
|
|
|
// 1. Stop Sequencer and Wakeup Timer
|
|
AD5940_WUPTCtrl(bFALSE);
|
|
AD5940_SEQCtrlS(bFALSE);
|
|
|
|
// 2. Stop any active conversions/WG, but KEEP Reference/LDOs ON
|
|
AD5940_AFECtrlS(AFECTRL_ADCCNV|AFECTRL_DFT|AFECTRL_WG, bFALSE);
|
|
|
|
// 3. Reset FIFO
|
|
FIFOCfg_Type fifo_cfg;
|
|
fifo_cfg.FIFOEn = bFALSE;
|
|
AD5940_FIFOCfg(&fifo_cfg);
|
|
|
|
fifo_cfg.FIFOEn = bTRUE;
|
|
fifo_cfg.FIFOMode = FIFOMODE_FIFO;
|
|
fifo_cfg.FIFOSize = FIFOSIZE_4KB;
|
|
fifo_cfg.FIFOSrc = FIFOSRC_DFT;
|
|
fifo_cfg.FIFOThresh = 6;
|
|
AD5940_FIFOCfg(&fifo_cfg);
|
|
|
|
// 4. Clear Interrupts
|
|
AD5940_INTCClrFlag(AFEINTSRC_ALLINT);
|
|
}
|
|
|
|
void AppIMPCalibrateLFO(void) {
|
|
LFOSCMeasure_Type cal_cfg;
|
|
cal_cfg.CalDuration = 1000.0; // 1000ms for high accuracy
|
|
cal_cfg.CalSeqAddr = 0; // Use start of SRAM for calibration sequence
|
|
cal_cfg.SystemClkFreq = 16000000.0;
|
|
|
|
float freq;
|
|
// Use SDK function to measure LFOSC
|
|
if(AD5940_LFOSCMeasure(&cal_cfg, &freq) == AD5940ERR_OK) {
|
|
AppIMPCfg.WuptClkFreq = freq;
|
|
}
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
|
|
int32_t AppIMPGetCfg(void *pCfg)
|
|
{
|
|
if(pCfg)
|
|
{
|
|
*(AppIMPCfg_Type**)pCfg = &AppIMPCfg;
|
|
return AD5940ERR_OK;
|
|
}
|
|
return AD5940ERR_PARA;
|
|
}
|
|
|
|
int32_t AppIMPCtrl(uint32_t Command, void *pPara)
|
|
{
|
|
switch (Command)
|
|
{
|
|
case IMPCTRL_START:
|
|
{
|
|
// Unified Start Logic: Always use Manual Trigger + ENDSEQ Interrupt
|
|
AD5940_WUPTCtrl(bFALSE);
|
|
|
|
AD5940_INTCCfg(AFEINTC_1, AFEINTSRC_ENDSEQ, bTRUE);
|
|
AD5940_INTCCfg(AFEINTC_1, AFEINTSRC_DATAFIFOTHRESH, bFALSE);
|
|
AD5940_INTCClrFlag(AFEINTSRC_ALLINT);
|
|
|
|
AppIMPCfg.FifoDataCount = 0;
|
|
AppIMPCfg.StopRequired = bFALSE;
|
|
|
|
// Trigger first sequence manually
|
|
AD5940_SEQMmrTrig(SEQID_0);
|
|
break;
|
|
}
|
|
case IMPCTRL_STOPNOW:
|
|
{
|
|
if(AD5940_WakeUp(10) > 10) return AD5940ERR_WAKEUP;
|
|
AD5940_WUPTCtrl(bFALSE);
|
|
AD5940_SEQCtrlS(bFALSE);
|
|
break;
|
|
}
|
|
case IMPCTRL_STOPSYNC:
|
|
{
|
|
AppIMPCfg.StopRequired = bTRUE;
|
|
break;
|
|
}
|
|
case IMPCTRL_GETFREQ:
|
|
{
|
|
if(pPara == 0) return AD5940ERR_PARA;
|
|
if(AppIMPCfg.SweepCfg.SweepEn == bTRUE)
|
|
*(float*)pPara = AppIMPCfg.FreqofData;
|
|
else
|
|
*(float*)pPara = AppIMPCfg.SinFreq;
|
|
break;
|
|
}
|
|
case IMPCTRL_SHUTDOWN:
|
|
{
|
|
AppIMPCtrl(IMPCTRL_STOPNOW, 0);
|
|
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();
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return AD5940ERR_OK;
|
|
}
|
|
|
|
float AppIMPGetCurrFreq(void)
|
|
{
|
|
if(AppIMPCfg.SweepCfg.SweepEn == bTRUE)
|
|
return AppIMPCfg.FreqofData;
|
|
else
|
|
return AppIMPCfg.SinFreq;
|
|
}
|
|
|
|
static AD5940Err AppIMPSeqCfgGen(void)
|
|
{
|
|
AD5940Err error = AD5940ERR_OK;
|
|
const uint32_t *pSeqCmd;
|
|
uint32_t SeqLen;
|
|
AFERefCfg_Type aferef_cfg;
|
|
HSLoopCfg_Type HsLoopCfg;
|
|
DSPCfg_Type dsp_cfg;
|
|
float sin_freq;
|
|
|
|
AD5940_SEQGenCtrl(bTRUE);
|
|
AD5940_AFECtrlS(AFECTRL_ALL, bFALSE);
|
|
|
|
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;
|
|
aferef_cfg.LpBandgapEn = bTRUE;
|
|
aferef_cfg.LpRefBufEn = bTRUE;
|
|
aferef_cfg.LpRefBoostEn = bFALSE;
|
|
AD5940_REFCfgS(&aferef_cfg);
|
|
|
|
HsLoopCfg.HsDacCfg.ExcitBufGain = AppIMPCfg.ExcitBufGain;
|
|
HsLoopCfg.HsDacCfg.HsDacGain = AppIMPCfg.HsDacGain;
|
|
HsLoopCfg.HsDacCfg.HsDacUpdateRate = AppIMPCfg.HsDacUpdateRate;
|
|
|
|
HsLoopCfg.HsTiaCfg.DiodeClose = bFALSE;
|
|
HsLoopCfg.HsTiaCfg.HstiaBias = HSTIABIAS_1P1;
|
|
HsLoopCfg.HsTiaCfg.HstiaCtia = 31;
|
|
HsLoopCfg.HsTiaCfg.HstiaDeRload = HSTIADERLOAD_OPEN;
|
|
HsLoopCfg.HsTiaCfg.HstiaDeRtia = HSTIADERTIA_OPEN;
|
|
HsLoopCfg.HsTiaCfg.HstiaRtiaSel = AppIMPCfg.HstiaRtiaSel;
|
|
HsLoopCfg.HsTiaCfg.ExtRtia = AppIMPCfg.ExtRtia;
|
|
|
|
HsLoopCfg.SWMatCfg.Dswitch = AppIMPCfg.DswitchSel;
|
|
HsLoopCfg.SWMatCfg.Pswitch = AppIMPCfg.PswitchSel;
|
|
HsLoopCfg.SWMatCfg.Nswitch = AppIMPCfg.NswitchSel;
|
|
HsLoopCfg.SWMatCfg.Tswitch = SWT_TRTIA|AppIMPCfg.TswitchSel;
|
|
|
|
HsLoopCfg.WgCfg.WgType = WGTYPE_SIN;
|
|
HsLoopCfg.WgCfg.GainCalEn = bTRUE;
|
|
HsLoopCfg.WgCfg.OffsetCalEn = bTRUE;
|
|
|
|
if(AppIMPCfg.SweepCfg.SweepEn == bTRUE)
|
|
{
|
|
AppIMPCfg.FreqofData = AppIMPCfg.SweepCfg.SweepStart;
|
|
AppIMPCfg.SweepCurrFreq = AppIMPCfg.SweepCfg.SweepStart;
|
|
AD5940_SweepNext(&AppIMPCfg.SweepCfg, &AppIMPCfg.SweepNextFreq);
|
|
sin_freq = AppIMPCfg.SweepCurrFreq;
|
|
}
|
|
else
|
|
{
|
|
sin_freq = AppIMPCfg.SinFreq;
|
|
AppIMPCfg.FreqofData = sin_freq;
|
|
}
|
|
|
|
HsLoopCfg.WgCfg.SinCfg.SinFreqWord = AD5940_WGFreqWordCal(sin_freq, AppIMPCfg.SysClkFreq);
|
|
HsLoopCfg.WgCfg.SinCfg.SinAmplitudeWord = (uint32_t)(AppIMPCfg.DacVoltPP/800.0f*2047 + 0.5f);
|
|
HsLoopCfg.WgCfg.SinCfg.SinOffsetWord = 0;
|
|
HsLoopCfg.WgCfg.SinCfg.SinPhaseWord = 0;
|
|
AD5940_HSLoopCfgS(&HsLoopCfg);
|
|
|
|
dsp_cfg.ADCBaseCfg.ADCMuxN = ADCMUXN_HSTIA_N;
|
|
dsp_cfg.ADCBaseCfg.ADCMuxP = ADCMUXP_HSTIA_P;
|
|
dsp_cfg.ADCBaseCfg.ADCPga = AppIMPCfg.AdcPgaGain;
|
|
|
|
memset(&dsp_cfg.ADCDigCompCfg, 0, sizeof(dsp_cfg.ADCDigCompCfg));
|
|
|
|
dsp_cfg.ADCFilterCfg.ADCAvgNum = AppIMPCfg.ADCAvgNum;
|
|
dsp_cfg.ADCFilterCfg.ADCRate = ADCRATE_800KHZ;
|
|
dsp_cfg.ADCFilterCfg.ADCSinc2Osr = AppIMPCfg.ADCSinc2Osr;
|
|
dsp_cfg.ADCFilterCfg.ADCSinc3Osr = AppIMPCfg.ADCSinc3Osr;
|
|
dsp_cfg.ADCFilterCfg.BpNotch = bTRUE;
|
|
dsp_cfg.ADCFilterCfg.BpSinc3 = bFALSE;
|
|
dsp_cfg.ADCFilterCfg.Sinc2NotchEnable = bTRUE;
|
|
dsp_cfg.DftCfg.DftNum = AppIMPCfg.DftNum;
|
|
dsp_cfg.DftCfg.DftSrc = AppIMPCfg.DftSrc;
|
|
dsp_cfg.DftCfg.HanWinEn = AppIMPCfg.HanWinEn;
|
|
|
|
memset(&dsp_cfg.StatCfg, 0, sizeof(dsp_cfg.StatCfg));
|
|
AD5940_DSPCfgS(&dsp_cfg);
|
|
|
|
AD5940_AFECtrlS(AFECTRL_HSTIAPWR|AFECTRL_INAMPPWR|AFECTRL_EXTBUFPWR|\
|
|
AFECTRL_WG|AFECTRL_DACREFPWR|AFECTRL_HSDACPWR|\
|
|
AFECTRL_SINC2NOTCH, bTRUE);
|
|
|
|
AD5940_SEQGenInsert(SEQ_STOP());
|
|
|
|
error = AD5940_SEQGenFetchSeq(&pSeqCmd, &SeqLen);
|
|
AD5940_SEQGenCtrl(bFALSE);
|
|
if(error == AD5940ERR_OK)
|
|
{
|
|
AppIMPCfg.InitSeqInfo.SeqId = SEQID_1;
|
|
AppIMPCfg.InitSeqInfo.SeqRamAddr = AppIMPCfg.SeqStartAddr;
|
|
AppIMPCfg.InitSeqInfo.pSeqCmd = pSeqCmd;
|
|
AppIMPCfg.InitSeqInfo.SeqLen = SeqLen;
|
|
AD5940_SEQCmdWrite(AppIMPCfg.InitSeqInfo.SeqRamAddr, pSeqCmd, SeqLen);
|
|
}
|
|
else
|
|
return error;
|
|
return AD5940ERR_OK;
|
|
}
|
|
|
|
static AD5940Err AppIMPSeqMeasureGen(void)
|
|
{
|
|
AD5940Err error = AD5940ERR_OK;
|
|
const uint32_t *pSeqCmd;
|
|
uint32_t SeqLen;
|
|
uint32_t WaitClks;
|
|
SWMatrixCfg_Type sw_cfg;
|
|
ClksCalInfo_Type clks_cal;
|
|
|
|
clks_cal.DataType = DATATYPE_DFT;
|
|
clks_cal.DftSrc = AppIMPCfg.DftSrc;
|
|
clks_cal.DataCount = 1L<<(AppIMPCfg.DftNum+2);
|
|
clks_cal.ADCSinc2Osr = AppIMPCfg.ADCSinc2Osr;
|
|
clks_cal.ADCSinc3Osr = AppIMPCfg.ADCSinc3Osr;
|
|
clks_cal.ADCAvgNum = AppIMPCfg.ADCAvgNum;
|
|
clks_cal.RatioSys2AdcClk = AppIMPCfg.SysClkFreq/AppIMPCfg.AdcClkFreq;
|
|
AD5940_ClksCalculate(&clks_cal, &WaitClks);
|
|
|
|
AD5940_SEQGenCtrl(bTRUE);
|
|
AD5940_SEQGpioCtrlS(AGPIO_Pin2);
|
|
AD5940_SEQGenInsert(SEQ_WAIT(16*250));
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
/* Measurement 1: RCAL (Current) */
|
|
/* ----------------------------------------------------------------------- */
|
|
sw_cfg.Dswitch = SWD_RCAL0;
|
|
sw_cfg.Pswitch = SWP_RCAL0;
|
|
sw_cfg.Nswitch = SWN_RCAL1;
|
|
sw_cfg.Tswitch = SWT_RCAL1|SWT_TRTIA;
|
|
AD5940_SWMatrixCfgS(&sw_cfg);
|
|
|
|
/* ADC Mux for Current (HSTIA) */
|
|
AD5940_ADCMuxCfgS(ADCMUXP_HSTIA_P, ADCMUXN_HSTIA_N);
|
|
|
|
AD5940_AFECtrlS(AFECTRL_HSTIAPWR|AFECTRL_INAMPPWR|AFECTRL_EXTBUFPWR|\
|
|
AFECTRL_WG|AFECTRL_DACREFPWR|AFECTRL_HSDACPWR|\
|
|
AFECTRL_SINC2NOTCH, bTRUE);
|
|
AD5940_AFECtrlS(AFECTRL_WG|AFECTRL_ADCPWR, bTRUE);
|
|
AD5940_SEQGenInsert(SEQ_WAIT(16*2000));
|
|
AD5940_AFECtrlS(AFECTRL_ADCCNV|AFECTRL_DFT, bTRUE);
|
|
|
|
AD5940_SEQGenFetchSeq(NULL, &AppIMPCfg.SeqWaitAddr[0]);
|
|
AD5940_SEQGenInsert(SEQ_WAIT(WaitClks/2));
|
|
AD5940_SEQGenInsert(SEQ_WAIT(WaitClks/2));
|
|
|
|
// Stop ADC/DFT first, wait 10us, then stop WG
|
|
AD5940_AFECtrlS(AFECTRL_ADCCNV|AFECTRL_DFT, bFALSE);
|
|
AD5940_SEQGenInsert(SEQ_WAIT(16*10));
|
|
AD5940_AFECtrlS(AFECTRL_WG, bFALSE);
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
/* Measurement 2: Sensor Current (I) */
|
|
/* ----------------------------------------------------------------------- */
|
|
sw_cfg.Dswitch = AppIMPCfg.DswitchSel;
|
|
sw_cfg.Pswitch = AppIMPCfg.PswitchSel;
|
|
sw_cfg.Nswitch = AppIMPCfg.NswitchSel;
|
|
sw_cfg.Tswitch = SWT_TRTIA|AppIMPCfg.TswitchSel;
|
|
AD5940_SWMatrixCfgS(&sw_cfg);
|
|
|
|
/* ADC Mux for Current (HSTIA) */
|
|
AD5940_ADCMuxCfgS(ADCMUXP_HSTIA_P, ADCMUXN_HSTIA_N);
|
|
|
|
AD5940_AFECtrlS(AFECTRL_ADCPWR|AFECTRL_WG, bTRUE);
|
|
AD5940_SEQGenInsert(SEQ_WAIT(16*2000));
|
|
AD5940_AFECtrlS(AFECTRL_ADCCNV|AFECTRL_DFT, bTRUE);
|
|
|
|
AD5940_SEQGenFetchSeq(NULL, &AppIMPCfg.SeqWaitAddr[1]);
|
|
AD5940_SEQGenInsert(SEQ_WAIT(WaitClks/2));
|
|
AD5940_SEQGenInsert(SEQ_WAIT(WaitClks/2));
|
|
|
|
// Stop ADC/DFT first, wait 10us, then stop WG
|
|
AD5940_AFECtrlS(AFECTRL_ADCCNV|AFECTRL_DFT, bFALSE);
|
|
AD5940_SEQGenInsert(SEQ_WAIT(16*10));
|
|
AD5940_AFECtrlS(AFECTRL_WG, bFALSE);
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
/* Measurement 3: Sensor Voltage (V) */
|
|
/* ----------------------------------------------------------------------- */
|
|
/* Switches remain same (Force path active) */
|
|
|
|
/* ADC Mux for Voltage (AIN2/AIN3) */
|
|
AD5940_ADCMuxCfgS(ADCMUXP_AIN2, ADCMUXN_AIN3);
|
|
|
|
AD5940_AFECtrlS(AFECTRL_ADCPWR|AFECTRL_WG, bTRUE);
|
|
AD5940_SEQGenInsert(SEQ_WAIT(16*2000));
|
|
AD5940_AFECtrlS(AFECTRL_ADCCNV|AFECTRL_DFT, bTRUE);
|
|
|
|
AD5940_SEQGenFetchSeq(NULL, &AppIMPCfg.SeqWaitAddr[2]);
|
|
AD5940_SEQGenInsert(SEQ_WAIT(WaitClks/2));
|
|
AD5940_SEQGenInsert(SEQ_WAIT(WaitClks/2));
|
|
|
|
// Stop ADC/DFT first, wait 10us, then stop WG and ADC Power
|
|
AD5940_AFECtrlS(AFECTRL_ADCCNV|AFECTRL_DFT, bFALSE);
|
|
AD5940_SEQGenInsert(SEQ_WAIT(16*10));
|
|
AD5940_AFECtrlS(AFECTRL_WG|AFECTRL_ADCPWR, bFALSE);
|
|
|
|
AD5940_AFECtrlS(AFECTRL_HSTIAPWR|AFECTRL_INAMPPWR|AFECTRL_EXTBUFPWR|\
|
|
AFECTRL_WG|AFECTRL_DACREFPWR|AFECTRL_HSDACPWR|\
|
|
AFECTRL_SINC2NOTCH, bFALSE);
|
|
AD5940_SEQGpioCtrlS(0);
|
|
|
|
AD5940_SEQGenInsert(SEQ_STOP());
|
|
|
|
error = AD5940_SEQGenFetchSeq(&pSeqCmd, &SeqLen);
|
|
AD5940_SEQGenCtrl(bFALSE);
|
|
|
|
if(error == AD5940ERR_OK)
|
|
{
|
|
AppIMPCfg.MeasureSeqInfo.SeqId = SEQID_0;
|
|
AppIMPCfg.MeasureSeqInfo.SeqRamAddr = AppIMPCfg.InitSeqInfo.SeqRamAddr + AppIMPCfg.InitSeqInfo.SeqLen ;
|
|
AppIMPCfg.MeasureSeqInfo.pSeqCmd = pSeqCmd;
|
|
AppIMPCfg.MeasureSeqInfo.SeqLen = SeqLen;
|
|
AD5940_SEQCmdWrite(AppIMPCfg.MeasureSeqInfo.SeqRamAddr, pSeqCmd, SeqLen);
|
|
}
|
|
else
|
|
return error;
|
|
return AD5940ERR_OK;
|
|
}
|
|
|
|
AD5940Err AppIMPCheckFreq(float freq)
|
|
{
|
|
ADCFilterCfg_Type filter_cfg;
|
|
DFTCfg_Type dft_cfg;
|
|
uint32_t WaitClks;
|
|
ClksCalInfo_Type clks_cal;
|
|
FreqParams_Type freq_params;
|
|
uint32_t SeqCmdBuff[32];
|
|
uint32_t SRAMAddr = 0;
|
|
|
|
freq_params = AD5940_GetFreqParameters(freq);
|
|
|
|
// Update ADC Filter and DFT settings based on frequency
|
|
filter_cfg.ADCAvgNum = ADCAVGNUM_16;
|
|
filter_cfg.ADCSinc2Osr = freq_params.ADCSinc2Osr;
|
|
filter_cfg.ADCSinc3Osr = freq_params.ADCSinc3Osr;
|
|
filter_cfg.BpSinc3 = bFALSE;
|
|
filter_cfg.BpNotch = bTRUE;
|
|
filter_cfg.Sinc2NotchEnable = bTRUE;
|
|
filter_cfg.ADCRate = ADCRATE_800KHZ; // Fixed ADC Rate for stability
|
|
|
|
dft_cfg.DftNum = freq_params.DftNum;
|
|
dft_cfg.DftSrc = freq_params.DftSrc;
|
|
dft_cfg.HanWinEn = AppIMPCfg.HanWinEn;
|
|
|
|
AD5940_ADCFilterCfgS(&filter_cfg);
|
|
AD5940_DFTCfgS(&dft_cfg);
|
|
|
|
// Calculate new WaitClks for the sequence
|
|
clks_cal.DataType = DATATYPE_DFT;
|
|
clks_cal.DftSrc = freq_params.DftSrc;
|
|
clks_cal.DataCount = 1L<<(freq_params.DftNum+2);
|
|
clks_cal.ADCSinc2Osr = freq_params.ADCSinc2Osr;
|
|
clks_cal.ADCSinc3Osr = freq_params.ADCSinc3Osr;
|
|
clks_cal.ADCAvgNum = 0;
|
|
clks_cal.RatioSys2AdcClk = AppIMPCfg.SysClkFreq/AppIMPCfg.AdcClkFreq;
|
|
AD5940_ClksCalculate(&clks_cal, &WaitClks);
|
|
|
|
// Add safety margin
|
|
WaitClks += 200;
|
|
|
|
// Update Wait Times in SRAM for all 3 measurements
|
|
for (int i = 0; i < 3; i++) {
|
|
if (AppIMPCfg.SeqWaitAddr[i] == 0) continue;
|
|
|
|
SRAMAddr = AppIMPCfg.MeasureSeqInfo.SeqRamAddr + AppIMPCfg.SeqWaitAddr[i];
|
|
|
|
// Split wait time into two commands to handle large values
|
|
uint32_t finalWait = WaitClks/2;
|
|
|
|
SeqCmdBuff[0] = SEQ_WAIT(finalWait);
|
|
SeqCmdBuff[1] = SEQ_WAIT(finalWait);
|
|
AD5940_SEQCmdWrite(SRAMAddr, SeqCmdBuff, 2);
|
|
}
|
|
|
|
return AD5940ERR_OK;
|
|
}
|
|
|
|
int32_t AppIMPInit(uint32_t *pBuffer, uint32_t BufferSize)
|
|
{
|
|
AD5940Err error = AD5940ERR_OK;
|
|
SEQCfg_Type seq_cfg;
|
|
FIFOCfg_Type fifo_cfg;
|
|
|
|
if(AD5940_WakeUp(10) > 10) return AD5940ERR_WAKEUP;
|
|
|
|
// CRITICAL: Stop WUPT and Sequencer before reconfiguration
|
|
AD5940_WUPTCtrl(bFALSE);
|
|
AD5940_SEQCtrlS(bFALSE);
|
|
|
|
seq_cfg.SeqMemSize = SEQMEMSIZE_2KB;
|
|
seq_cfg.SeqBreakEn = bFALSE;
|
|
seq_cfg.SeqIgnoreEn = bTRUE;
|
|
seq_cfg.SeqCntCRCClr = bTRUE;
|
|
seq_cfg.SeqEnable = bFALSE;
|
|
seq_cfg.SeqWrTimer = 0;
|
|
AD5940_SEQCfg(&seq_cfg);
|
|
|
|
AD5940_FIFOCtrlS(FIFOSRC_DFT, bFALSE);
|
|
fifo_cfg.FIFOEn = bTRUE;
|
|
fifo_cfg.FIFOMode = FIFOMODE_FIFO;
|
|
fifo_cfg.FIFOSize = FIFOSIZE_4KB;
|
|
fifo_cfg.FIFOSrc = FIFOSRC_DFT;
|
|
fifo_cfg.FIFOThresh = AppIMPCfg.FifoThresh;
|
|
AD5940_FIFOCfg(&fifo_cfg);
|
|
AD5940_INTCClrFlag(AFEINTSRC_ALLINT);
|
|
|
|
if((AppIMPCfg.IMPInited == bFALSE)||(AppIMPCfg.bParaChanged == bTRUE))
|
|
{
|
|
if(pBuffer == 0) return AD5940ERR_PARA;
|
|
if(BufferSize == 0) return AD5940ERR_PARA;
|
|
AD5940_SEQGenInit(pBuffer, BufferSize);
|
|
|
|
error = AppIMPSeqCfgGen();
|
|
if(error != AD5940ERR_OK) return error;
|
|
|
|
error = AppIMPSeqMeasureGen();
|
|
if(error != AD5940ERR_OK) return error;
|
|
|
|
AppIMPCfg.bParaChanged = bFALSE;
|
|
}
|
|
|
|
AppIMPCfg.InitSeqInfo.WriteSRAM = bFALSE;
|
|
AD5940_SEQInfoCfg(&AppIMPCfg.InitSeqInfo);
|
|
seq_cfg.SeqEnable = bTRUE;
|
|
AD5940_SEQCfg(&seq_cfg);
|
|
AD5940_SEQMmrTrig(AppIMPCfg.InitSeqInfo.SeqId);
|
|
|
|
AD5940_INTCCfg(AFEINTC_1, AFEINTSRC_ENDSEQ, bTRUE);
|
|
|
|
// Safety timeout for Init Sequence
|
|
int timeout = 100000;
|
|
while(AD5940_INTCTestFlag(AFEINTC_1, AFEINTSRC_ENDSEQ) == bFALSE) {
|
|
if(--timeout <= 0) {
|
|
return AD5940ERR_TIMEOUT;
|
|
}
|
|
}
|
|
AD5940_INTCClrFlag(AFEINTSRC_ALLINT);
|
|
|
|
AppIMPCfg.MeasureSeqInfo.WriteSRAM = bFALSE;
|
|
AD5940_SEQInfoCfg(&AppIMPCfg.MeasureSeqInfo);
|
|
|
|
// Set initial frequency parameters
|
|
AppIMPCheckFreq(AppIMPCfg.FreqofData);
|
|
|
|
seq_cfg.SeqEnable = bTRUE;
|
|
AD5940_SEQCfg(&seq_cfg);
|
|
AD5940_ClrMCUIntFlag();
|
|
|
|
AppIMPCfg.IMPInited = bTRUE;
|
|
return AD5940ERR_OK;
|
|
}
|
|
|
|
int32_t AppIMPRegModify(int32_t * const pData, uint32_t *pDataCount)
|
|
{
|
|
if(AppIMPCfg.NumOfData > 0)
|
|
{
|
|
AppIMPCfg.FifoDataCount += *pDataCount/6;
|
|
if(AppIMPCfg.FifoDataCount >= AppIMPCfg.NumOfData)
|
|
{
|
|
AD5940_WUPTCtrl(bFALSE);
|
|
AD5940_SEQCtrlS(bFALSE);
|
|
return AD5940ERR_OK;
|
|
}
|
|
}
|
|
if(AppIMPCfg.StopRequired == bTRUE)
|
|
{
|
|
AD5940_WUPTCtrl(bFALSE);
|
|
return AD5940ERR_OK;
|
|
}
|
|
if(AppIMPCfg.SweepCfg.SweepEn)
|
|
{
|
|
// Update Filters and Wait Times in SRAM
|
|
AppIMPCheckFreq(AppIMPCfg.SweepNextFreq);
|
|
|
|
// Update WG Frequency
|
|
AD5940_WGFreqCtrlS(AppIMPCfg.SweepNextFreq, AppIMPCfg.SysClkFreq);
|
|
}
|
|
return AD5940ERR_OK;
|
|
}
|
|
|
|
int32_t AppIMPDataProcess(int32_t * const pData, uint32_t *pDataCount)
|
|
{
|
|
uint32_t DataCount = *pDataCount;
|
|
uint32_t ImpResCount = DataCount/6;
|
|
|
|
fImpPol_Type * const pOut = (fImpPol_Type*)pData;
|
|
iImpCar_Type * pSrcData = (iImpCar_Type*)pData;
|
|
|
|
*pDataCount = 0;
|
|
|
|
for(uint32_t i=0; i<DataCount; i++)
|
|
{
|
|
pData[i] &= 0x3ffff;
|
|
if(pData[i]&(1L<<17))
|
|
{
|
|
pData[i] |= 0xfffc0000;
|
|
}
|
|
}
|
|
|
|
for(uint32_t i=0; i<ImpResCount; i++)
|
|
{
|
|
iImpCar_Type *pDftRcal, *pDftI, *pDftV;
|
|
|
|
pDftRcal = pSrcData++;
|
|
pDftI = pSrcData++;
|
|
pDftV = pSrcData++;
|
|
|
|
float MagI, PhaseI;
|
|
float MagV, PhaseV;
|
|
float ZMag, ZPhase;
|
|
|
|
MagI = sqrt((float)pDftI->Real*pDftI->Real + (float)pDftI->Image*pDftI->Image);
|
|
PhaseI = atan2(-pDftI->Image, pDftI->Real);
|
|
|
|
MagV = sqrt((float)pDftV->Real*pDftV->Real + (float)pDftV->Image*pDftV->Image);
|
|
PhaseV = atan2(-pDftV->Image, pDftV->Real);
|
|
|
|
if(MagI > 1e-9)
|
|
ZMag = (MagV / MagI) * AppIMPCfg.RtiaVal;
|
|
else
|
|
ZMag = 0;
|
|
|
|
ZPhase = PhaseV - PhaseI + MATH_PI;
|
|
|
|
while(ZPhase > MATH_PI) ZPhase -= 2*MATH_PI;
|
|
while(ZPhase < -MATH_PI) ZPhase += 2*MATH_PI;
|
|
|
|
pOut[i].Magnitude = ZMag;
|
|
pOut[i].Phase = ZPhase;
|
|
}
|
|
*pDataCount = ImpResCount;
|
|
AppIMPCfg.FreqofData = AppIMPCfg.SweepCurrFreq;
|
|
|
|
if(AppIMPCfg.SweepCfg.SweepEn == bTRUE)
|
|
{
|
|
AppIMPCfg.FreqofData = AppIMPCfg.SweepCurrFreq;
|
|
AppIMPCfg.SweepCurrFreq = AppIMPCfg.SweepNextFreq;
|
|
AD5940_SweepNext(&AppIMPCfg.SweepCfg, &AppIMPCfg.SweepNextFreq);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int32_t AppIMPISR(void *pBuff, uint32_t *pCount)
|
|
{
|
|
uint32_t BuffCount;
|
|
uint32_t FifoCnt;
|
|
BuffCount = *pCount;
|
|
|
|
*pCount = 0;
|
|
|
|
if(AD5940_WakeUp(10) > 10) return AD5940ERR_WAKEUP;
|
|
AD5940_SleepKeyCtrlS(SLPKEY_LOCK);
|
|
|
|
uint32_t IntFlag = AD5940_INTCGetFlag(AFEINTC_1);
|
|
|
|
if (IntFlag & (AFEINTSRC_DATAFIFOOF | AFEINTSRC_DATAFIFOUF)) {
|
|
AD5940_INTCClrFlag(AFEINTSRC_DATAFIFOOF | AFEINTSRC_DATAFIFOUF);
|
|
FIFOCfg_Type fifo_cfg;
|
|
fifo_cfg.FIFOEn = bFALSE;
|
|
AD5940_FIFOCfg(&fifo_cfg);
|
|
fifo_cfg.FIFOEn = bTRUE;
|
|
fifo_cfg.FIFOMode = FIFOMODE_FIFO;
|
|
fifo_cfg.FIFOSize = FIFOSIZE_4KB;
|
|
fifo_cfg.FIFOSrc = FIFOSRC_DFT;
|
|
fifo_cfg.FIFOThresh = AppIMPCfg.FifoThresh;
|
|
AD5940_FIFOCfg(&fifo_cfg);
|
|
|
|
AD5940_SleepKeyCtrlS(SLPKEY_UNLOCK);
|
|
return AD5940ERR_FIFO;
|
|
}
|
|
|
|
if(IntFlag & AFEINTSRC_ENDSEQ)
|
|
{
|
|
int timeout = 200;
|
|
while(AD5940_FIFOGetCnt() < 6 && timeout-- > 0)
|
|
{
|
|
AD5940_Delay10us(10);
|
|
}
|
|
|
|
FifoCnt = (AD5940_FIFOGetCnt()/6)*6;
|
|
if(FifoCnt > BuffCount) FifoCnt = BuffCount;
|
|
|
|
AD5940_FIFORd((uint32_t *)pBuff, FifoCnt);
|
|
AD5940_INTCClrFlag(AFEINTSRC_ENDSEQ);
|
|
|
|
if (FifoCnt > 0)
|
|
{
|
|
AD5940_SEQCtrlS(bFALSE);
|
|
|
|
if (AppIMPRegModify(pBuff, &FifoCnt) == AD5940ERR_OK)
|
|
{
|
|
if(AppIMPCfg.FifoDataCount < AppIMPCfg.NumOfData || AppIMPCfg.NumOfData == -1)
|
|
{
|
|
if(AppIMPCfg.StopRequired == bFALSE)
|
|
{
|
|
AD5940_Delay10us(20);
|
|
|
|
AD5940_WriteReg(REG_AFE_SEQCNT, 0);
|
|
AD5940_SEQCtrlS(bTRUE);
|
|
AD5940_SEQMmrTrig(SEQID_0);
|
|
}
|
|
}
|
|
}
|
|
|
|
AD5940_SleepKeyCtrlS(SLPKEY_UNLOCK);
|
|
AppIMPDataProcess((int32_t*)pBuff, &FifoCnt);
|
|
|
|
// DUMMY POINT FILTERING
|
|
// If we are in sweep mode and have exceeded the user's requested count,
|
|
// discard this data packet so the host doesn't see the artifact.
|
|
if (AppIMPCfg.SweepCfg.SweepEn && AppIMPCfg.RealDataCount > 0) {
|
|
if (AppIMPCfg.FifoDataCount > AppIMPCfg.RealDataCount) {
|
|
*pCount = 0; // Discard
|
|
} else {
|
|
*pCount = FifoCnt;
|
|
}
|
|
} else {
|
|
*pCount = FifoCnt;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
AD5940_SleepKeyCtrlS(SLPKEY_UNLOCK);
|
|
*pCount = 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
AD5940_INTCClrFlag(AFEINTSRC_ALLINT);
|
|
AD5940_SleepKeyCtrlS(SLPKEY_UNLOCK);
|
|
return 0;
|
|
} |