495 lines
17 KiB
C
495 lines
17 KiB
C
// Amperometric.c
|
|
/*!
|
|
*****************************************************************************
|
|
@file: Amperometric.c
|
|
@author: $Author: mlambe $
|
|
@brief: Amperometric measurement.
|
|
@version: $Revision: 766 $
|
|
@date: $Date: 2018-03-21 14:09:35 +0100 (Wed, 21 Mar 2018) $
|
|
-----------------------------------------------------------------------------
|
|
|
|
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 "Amperometric.h"
|
|
|
|
#define AD5940ERR_STOP 10
|
|
|
|
/*
|
|
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
|
|
*/
|
|
AppAMPCfg_Type AppAMPCfg =
|
|
{
|
|
.bParaChanged = bFALSE,
|
|
.SeqStartAddr = 0,
|
|
.MaxSeqLen = 0,
|
|
|
|
.SeqStartAddrCal = 0,
|
|
.MaxSeqLenCal = 0,
|
|
.FifoThresh = 5, /* Number of points for FIFO */
|
|
|
|
.SysClkFreq = 16000000.0,
|
|
.WuptClkFreq = 32000.0,
|
|
.AdcClkFreq = 16000000.0,
|
|
.AmpODR = 1.0, /* Sample time in seconds. I.e. every 5 seconds make a measurement */
|
|
.NumOfData = -1,
|
|
.RcalVal = 100.0, /* RCAL = 100 Ohms */
|
|
.PwrMod = AFEPWR_LP,
|
|
.AMPInited = bFALSE,
|
|
.StopRequired = bFALSE,
|
|
|
|
/* LPTIA Configure */
|
|
.ExtRtia = bFALSE, /* Set to true if using external RTIA */
|
|
.LptiaRtiaSel = LPTIARTIA_4K, /* COnfigure RTIA */
|
|
.LpTiaRf = LPTIARF_1M, /* Configure LPF resistor */
|
|
.LpTiaRl = LPTIARLOAD_100R,
|
|
.ReDoRtiaCal = bTRUE,
|
|
.RtiaCalValue = 0,
|
|
.ExtRtiaVal = 0,
|
|
|
|
/*LPDAC Configure */
|
|
.Vzero = 1100, /* Sets voltage on SE0 and LPTIA */
|
|
.SensorBias = 500, /* Sets voltage between RE0 and SE0 */
|
|
|
|
/* ADC Configure*/
|
|
.ADCPgaGain = ADCPGA_1P5,
|
|
.ADCSinc3Osr = ADCSINC3OSR_4,
|
|
.ADCSinc2Osr = ADCSINC2OSR_22,
|
|
.DataFifoSrc = FIFOSRC_SINC2NOTCH,
|
|
.ADCRefVolt = 1.8162, /* Measure voltage on ADCRefVolt pin and enter here*/
|
|
};
|
|
|
|
/**
|
|
This function is provided for upper controllers that want to change
|
|
application parameters specially for user defined parameters.
|
|
*/
|
|
AD5940Err AppAMPGetCfg(void *pCfg)
|
|
{
|
|
if(pCfg){
|
|
*(AppAMPCfg_Type**)pCfg = &AppAMPCfg;
|
|
return AD5940ERR_OK;
|
|
}
|
|
return AD5940ERR_PARA;
|
|
}
|
|
|
|
AD5940Err AppAMPCtrl(int32_t AmpCtrl, void *pPara)
|
|
{
|
|
switch (AmpCtrl)
|
|
{
|
|
case AMPCTRL_START:
|
|
{
|
|
WUPTCfg_Type wupt_cfg;
|
|
|
|
AD5940_ReadReg(REG_AFE_ADCDAT); /* Any SPI Operation can wakeup AFE */
|
|
if(AppAMPCfg.AMPInited == bFALSE)
|
|
return AD5940ERR_APPERROR;
|
|
/* Start it */
|
|
wupt_cfg.WuptEn = bTRUE;
|
|
wupt_cfg.WuptEndSeq = WUPTENDSEQ_A;
|
|
wupt_cfg.WuptOrder[0] = SEQID_0;
|
|
wupt_cfg.SeqxSleepTime[SEQID_0] = 4-1;
|
|
wupt_cfg.SeqxWakeupTime[SEQID_0] = (uint32_t)(AppAMPCfg.WuptClkFreq*AppAMPCfg.AmpODR)-4-1;
|
|
AD5940_WUPTCfg(&wupt_cfg);
|
|
|
|
AppAMPCfg.FifoDataCount = 0; /* restart */
|
|
break;
|
|
}
|
|
case AMPCTRL_STOPNOW:
|
|
{
|
|
AD5940_ReadReg(REG_AFE_ADCDAT); /* Any SPI Operation can wakeup AFE */
|
|
/* Start Wupt right now */
|
|
AD5940_WUPTCtrl(bFALSE);
|
|
/* There is chance this operation will fail because sequencer could put AFE back
|
|
to hibernate mode just after waking up. Use STOPSYNC is better. */
|
|
AD5940_WUPTCtrl(bFALSE);
|
|
break;
|
|
}
|
|
case AMPCTRL_STOPSYNC:
|
|
{
|
|
AppAMPCfg.StopRequired = bTRUE;
|
|
break;
|
|
}
|
|
case AMPCTRL_SHUTDOWN:
|
|
{
|
|
AppAMPCtrl(AMPCTRL_STOPNOW, 0); /* Stop the measurement 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 */
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return AD5940ERR_OK;
|
|
}
|
|
|
|
/* Generate init sequence */
|
|
static AD5940Err AppAMPSeqCfgGen(void)
|
|
{
|
|
AD5940Err error = AD5940ERR_OK;
|
|
uint32_t const *pSeqCmd;
|
|
uint32_t SeqLen;
|
|
|
|
AFERefCfg_Type aferef_cfg;
|
|
LPLoopCfg_Type lp_loop;
|
|
DSPCfg_Type dsp_cfg;
|
|
SWMatrixCfg_Type sw_cfg;
|
|
/* Start sequence generator here */
|
|
AD5940_SEQGenCtrl(bTRUE);
|
|
|
|
//AD5940_AFECtrlS(AFECTRL_ALL, bFALSE); /* Init all to disable state */
|
|
|
|
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 = bTRUE;
|
|
aferef_cfg.Lp1V8BuffEn = bTRUE;
|
|
/* LP reference control - turn off them to save power*/
|
|
aferef_cfg.LpBandgapEn = bTRUE;
|
|
aferef_cfg.LpRefBufEn = bTRUE;
|
|
aferef_cfg.LpRefBoostEn = bFALSE;
|
|
AD5940_REFCfgS(&aferef_cfg);
|
|
|
|
lp_loop.LpDacCfg.LpdacSel = LPDAC0;
|
|
lp_loop.LpDacCfg.LpDacSrc = LPDACSRC_MMR;
|
|
lp_loop.LpDacCfg.LpDacSW = LPDACSW_VBIAS2LPPA|LPDACSW_VBIAS2PIN|LPDACSW_VZERO2LPTIA|LPDACSW_VZERO2PIN;
|
|
lp_loop.LpDacCfg.LpDacVzeroMux = LPDACVZERO_6BIT;
|
|
lp_loop.LpDacCfg.LpDacVbiasMux = LPDACVBIAS_12BIT;
|
|
lp_loop.LpDacCfg.LpDacRef = LPDACREF_2P5;
|
|
lp_loop.LpDacCfg.DataRst = bFALSE;
|
|
lp_loop.LpDacCfg.PowerEn = bTRUE;
|
|
lp_loop.LpDacCfg.DacData6Bit = (uint32_t)((AppAMPCfg.Vzero-200)/DAC6BITVOLT_1LSB);
|
|
lp_loop.LpDacCfg.DacData12Bit =(int32_t)((AppAMPCfg.SensorBias)/DAC12BITVOLT_1LSB) + lp_loop.LpDacCfg.DacData6Bit*64;
|
|
if(lp_loop.LpDacCfg.DacData12Bit>lp_loop.LpDacCfg.DacData6Bit*64)
|
|
lp_loop.LpDacCfg.DacData12Bit--;
|
|
lp_loop.LpAmpCfg.LpAmpSel = LPAMP0;
|
|
lp_loop.LpAmpCfg.LpAmpPwrMod = LPAMPPWR_NORM;
|
|
lp_loop.LpAmpCfg.LpPaPwrEn = bTRUE;
|
|
lp_loop.LpAmpCfg.LpTiaPwrEn = bTRUE;
|
|
lp_loop.LpAmpCfg.LpTiaRf = AppAMPCfg.LpTiaRf;
|
|
lp_loop.LpAmpCfg.LpTiaRload = AppAMPCfg.LpTiaRl;
|
|
if(AppAMPCfg.ExtRtia == bTRUE)
|
|
{
|
|
lp_loop.LpAmpCfg.LpTiaRtia = LPTIARTIA_OPEN;
|
|
lp_loop.LpAmpCfg.LpTiaSW = LPTIASW(9)|LPTIASW(2)|LPTIASW(4)|LPTIASW(5)|LPTIASW(12)|LPTIASW(13);
|
|
}else
|
|
{
|
|
lp_loop.LpAmpCfg.LpTiaRtia = AppAMPCfg.LptiaRtiaSel;
|
|
lp_loop.LpAmpCfg.LpTiaSW = LPTIASW(5)|LPTIASW(2)|LPTIASW(4)|LPTIASW(12)|LPTIASW(13);
|
|
}
|
|
AD5940_LPLoopCfgS(&lp_loop);
|
|
|
|
|
|
dsp_cfg.ADCBaseCfg.ADCMuxN = ADCMUXN_VZERO0;
|
|
dsp_cfg.ADCBaseCfg.ADCMuxP = ADCMUXP_AIN4;
|
|
dsp_cfg.ADCBaseCfg.ADCPga = AppAMPCfg.ADCPgaGain;
|
|
|
|
memset(&dsp_cfg.ADCDigCompCfg, 0, sizeof(dsp_cfg.ADCDigCompCfg));
|
|
memset(&dsp_cfg.DftCfg, 0, sizeof(dsp_cfg.DftCfg));
|
|
dsp_cfg.ADCFilterCfg.ADCAvgNum = ADCAVGNUM_16; /* Don't care because it's disabled */
|
|
dsp_cfg.ADCFilterCfg.ADCRate = ADCRATE_800KHZ; /* Tell filter block clock rate of ADC*/
|
|
dsp_cfg.ADCFilterCfg.ADCSinc2Osr = AppAMPCfg.ADCSinc2Osr;
|
|
dsp_cfg.ADCFilterCfg.ADCSinc3Osr = AppAMPCfg.ADCSinc3Osr;
|
|
dsp_cfg.ADCFilterCfg.BpSinc3 = bFALSE;
|
|
dsp_cfg.ADCFilterCfg.BpNotch = bFALSE;
|
|
dsp_cfg.ADCFilterCfg.Sinc2NotchEnable = bTRUE;
|
|
|
|
memset(&dsp_cfg.StatCfg, 0, sizeof(dsp_cfg.StatCfg)); /* Don't care about Statistic */
|
|
AD5940_DSPCfgS(&dsp_cfg);
|
|
|
|
sw_cfg.Dswitch = 0;
|
|
sw_cfg.Pswitch = 0;
|
|
sw_cfg.Nswitch = 0;
|
|
sw_cfg.Tswitch = 0;
|
|
AD5940_SWMatrixCfgS(&sw_cfg);
|
|
|
|
/* Enable all of them. They are automatically turned off during hibernate mode to save power */
|
|
AD5940_AFECtrlS(AFECTRL_HPREFPWR|AFECTRL_SINC2NOTCH, bTRUE);
|
|
AD5940_AFECtrlS(AFECTRL_SINC2NOTCH, bFALSE);
|
|
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 extra 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 sequencer generator */
|
|
if(error == AD5940ERR_OK)
|
|
{
|
|
AppAMPCfg.InitSeqInfo.SeqId = SEQID_1;
|
|
AppAMPCfg.InitSeqInfo.SeqRamAddr = AppAMPCfg.SeqStartAddr;
|
|
AppAMPCfg.InitSeqInfo.pSeqCmd = pSeqCmd;
|
|
AppAMPCfg.InitSeqInfo.SeqLen = SeqLen;
|
|
/* Write command to SRAM */
|
|
AD5940_SEQCmdWrite(AppAMPCfg.InitSeqInfo.SeqRamAddr, pSeqCmd, SeqLen);
|
|
}
|
|
else
|
|
return error; /* Error */
|
|
return AD5940ERR_OK;
|
|
}
|
|
|
|
static AD5940Err AppAMPSeqMeasureGen(void)
|
|
{
|
|
AD5940Err error = AD5940ERR_OK;
|
|
uint32_t const *pSeqCmd;
|
|
uint32_t SeqLen;
|
|
|
|
uint32_t WaitClks;
|
|
ClksCalInfo_Type clks_cal;
|
|
|
|
clks_cal.DataType = DATATYPE_SINC2;
|
|
clks_cal.DataCount = 1;
|
|
clks_cal.ADCSinc2Osr = AppAMPCfg.ADCSinc2Osr;
|
|
clks_cal.ADCSinc3Osr = AppAMPCfg.ADCSinc3Osr;
|
|
clks_cal.ADCAvgNum = 0;
|
|
clks_cal.RatioSys2AdcClk = AppAMPCfg.SysClkFreq/AppAMPCfg.AdcClkFreq;
|
|
AD5940_ClksCalculate(&clks_cal, &WaitClks);
|
|
WaitClks += 15;
|
|
AD5940_SEQGenCtrl(bTRUE);
|
|
AD5940_SEQGpioCtrlS(AGPIO_Pin2);
|
|
AD5940_AFECtrlS(AFECTRL_ADCPWR|AFECTRL_SINC2NOTCH, bTRUE);
|
|
AD5940_SEQGenInsert(SEQ_WAIT(16*250)); /* wait 250us */
|
|
AD5940_AFECtrlS(AFECTRL_ADCCNV, bTRUE); /* Start ADC convert*/
|
|
AD5940_SEQGenInsert(SEQ_WAIT(WaitClks)); /* wait for first data ready */
|
|
AD5940_AFECtrlS(AFECTRL_ADCPWR|AFECTRL_ADCCNV|AFECTRL_SINC2NOTCH, bFALSE); /* Stop ADC */
|
|
AD5940_SEQGpioCtrlS(0);
|
|
AD5940_EnterSleepS();/* Goto hibernate */
|
|
/* Sequence end. */
|
|
error = AD5940_SEQGenFetchSeq(&pSeqCmd, &SeqLen);
|
|
AD5940_SEQGenCtrl(bFALSE); /* Stop sequencer generator */
|
|
|
|
if(error == AD5940ERR_OK)
|
|
{
|
|
AppAMPCfg.MeasureSeqInfo.SeqId = SEQID_0;
|
|
AppAMPCfg.MeasureSeqInfo.SeqRamAddr = AppAMPCfg.InitSeqInfo.SeqRamAddr + AppAMPCfg.InitSeqInfo.SeqLen ;
|
|
AppAMPCfg.MeasureSeqInfo.pSeqCmd = pSeqCmd;
|
|
AppAMPCfg.MeasureSeqInfo.SeqLen = SeqLen;
|
|
/* Write command to SRAM */
|
|
AD5940_SEQCmdWrite(AppAMPCfg.MeasureSeqInfo.SeqRamAddr, pSeqCmd, SeqLen);
|
|
}
|
|
else
|
|
return error; /* Error */
|
|
return AD5940ERR_OK;
|
|
}
|
|
static AD5940Err AppAMPRtiaCal(void)
|
|
{
|
|
fImpPol_Type RtiaCalValue; /* Calibration result */
|
|
LPRTIACal_Type lprtia_cal;
|
|
AD5940_StructInit(&lprtia_cal, sizeof(lprtia_cal));
|
|
|
|
lprtia_cal.bPolarResult = bTRUE; /* Magnitude + Phase */
|
|
lprtia_cal.AdcClkFreq = AppAMPCfg.AdcClkFreq;
|
|
lprtia_cal.SysClkFreq = AppAMPCfg.SysClkFreq;
|
|
lprtia_cal.ADCSinc3Osr = ADCSINC3OSR_4;
|
|
lprtia_cal.ADCSinc2Osr = ADCSINC2OSR_22; /* Use SINC2 data as DFT data source */
|
|
lprtia_cal.DftCfg.DftNum = DFTNUM_2048; /* Maximum DFT number */
|
|
lprtia_cal.DftCfg.DftSrc = DFTSRC_SINC2NOTCH; /* For frequency under 12Hz, need to optimize DFT source. Use SINC3 data as DFT source */
|
|
lprtia_cal.DftCfg.HanWinEn = bTRUE;
|
|
lprtia_cal.fFreq = AppAMPCfg.AdcClkFreq/4/22/2048*3; /* Sample 3 period of signal, 13.317Hz here. Do not use DC method, because it needs ADC/PGA calibrated firstly(but it's faster) */
|
|
lprtia_cal.fRcal = AppAMPCfg.RcalVal;
|
|
lprtia_cal.LpTiaRtia = AppAMPCfg.LptiaRtiaSel;
|
|
lprtia_cal.LpAmpPwrMod = LPAMPPWR_NORM;
|
|
lprtia_cal.bWithCtia = bFALSE;
|
|
AD5940_LPRtiaCal(&lprtia_cal, &RtiaCalValue);
|
|
AppAMPCfg.RtiaCalValue = RtiaCalValue;
|
|
|
|
return AD5940ERR_OK;
|
|
}
|
|
/* This function provide application initialize. */
|
|
AD5940Err AppAMPInit(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(((AppAMPCfg.ReDoRtiaCal == bTRUE) || \
|
|
AppAMPCfg.AMPInited == bFALSE) && AppAMPCfg.ExtRtia == bFALSE) /* Do calibration on the first initializaion */
|
|
{
|
|
AppAMPRtiaCal();
|
|
AppAMPCfg.ReDoRtiaCal = bFALSE;
|
|
}else
|
|
AppAMPCfg.RtiaCalValue.Magnitude = AppAMPCfg.ExtRtiaVal;
|
|
|
|
/* Reconfigure FIFO */
|
|
AD5940_FIFOCtrlS(DFTSRC_SINC3, 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 = AppAMPCfg.DataFifoSrc;
|
|
fifo_cfg.FIFOThresh = AppAMPCfg.FifoThresh;
|
|
AD5940_FIFOCfg(&fifo_cfg);
|
|
|
|
AD5940_INTCClrFlag(AFEINTSRC_ALLINT);
|
|
|
|
/* Start sequence generator */
|
|
/* Initialize sequencer generator */
|
|
if((AppAMPCfg.AMPInited == bFALSE)||\
|
|
(AppAMPCfg.bParaChanged == bTRUE))
|
|
{
|
|
if(pBuffer == 0) return AD5940ERR_PARA;
|
|
if(BufferSize == 0) return AD5940ERR_PARA;
|
|
AD5940_SEQGenInit(pBuffer, BufferSize);
|
|
|
|
/* Generate initialize sequence */
|
|
error = AppAMPSeqCfgGen(); /* Application initialization sequence using either MCU or sequencer */
|
|
if(error != AD5940ERR_OK) return error;
|
|
|
|
/* Generate measurement sequence */
|
|
error = AppAMPSeqMeasureGen();
|
|
if(error != AD5940ERR_OK) return error;
|
|
|
|
AppAMPCfg.bParaChanged = bFALSE; /* Clear this flag as we already implemented the new configuration */
|
|
}
|
|
/* Initialization sequencer */
|
|
AppAMPCfg.InitSeqInfo.WriteSRAM = bFALSE;
|
|
AD5940_SEQInfoCfg(&AppAMPCfg.InitSeqInfo);
|
|
seq_cfg.SeqEnable = bTRUE;
|
|
AD5940_SEQCfg(&seq_cfg); /* Enable sequencer */
|
|
AD5940_SEQMmrTrig(AppAMPCfg.InitSeqInfo.SeqId);
|
|
while(AD5940_INTCTestFlag(AFEINTC_1, AFEINTSRC_ENDSEQ) == bFALSE);
|
|
|
|
/* Measurement sequence */
|
|
AppAMPCfg.MeasureSeqInfo.WriteSRAM = bFALSE;
|
|
AD5940_SEQInfoCfg(&AppAMPCfg.MeasureSeqInfo);
|
|
|
|
// seq_cfg.SeqEnable = bTRUE;
|
|
// AD5940_SEQCfg(&seq_cfg); /* Enable sequencer, and wait for trigger */
|
|
AD5940_SEQCtrlS(bTRUE); /* Enable sequencer, and wait for trigger. It's disabled in initialization sequence */
|
|
AD5940_ClrMCUIntFlag(); /* Clear interrupt flag generated before */
|
|
|
|
AD5940_AFEPwrBW(AppAMPCfg.PwrMod, AFEBW_250KHZ);
|
|
AppAMPCfg.AMPInited = bTRUE; /* AMP application has been initialized. */
|
|
return AD5940ERR_OK;
|
|
}
|
|
|
|
/* Modify registers when AFE wakeup */
|
|
static AD5940Err AppAMPRegModify(int32_t * const pData, uint32_t *pDataCount)
|
|
{
|
|
if(AppAMPCfg.NumOfData > 0)
|
|
{
|
|
AppAMPCfg.FifoDataCount += *pDataCount/4;
|
|
if(AppAMPCfg.FifoDataCount >= AppAMPCfg.NumOfData)
|
|
{
|
|
AD5940_WUPTCtrl(bFALSE);
|
|
return AD5940ERR_STOP; // Return STOP code
|
|
}
|
|
}
|
|
if(AppAMPCfg.StopRequired == bTRUE)
|
|
{
|
|
AD5940_WUPTCtrl(bFALSE);
|
|
return AD5940ERR_OK;
|
|
}
|
|
|
|
return AD5940ERR_OK;
|
|
}
|
|
|
|
/* Depending on the data type, do appropriate data pre-process before return back to controller */
|
|
static AD5940Err AppAMPDataProcess(int32_t * const pData, uint32_t *pDataCount)
|
|
{
|
|
uint32_t i, datacount;
|
|
datacount = *pDataCount;
|
|
float *pOut = (float *)pData;
|
|
for(i=0;i<datacount;i++)
|
|
{
|
|
pData[i] &= 0xffff;
|
|
pOut[i] = AppAMPCalcCurrent(pData[i]);
|
|
}
|
|
return AD5940ERR_OK;
|
|
}
|
|
|
|
/**
|
|
|
|
*/
|
|
AD5940Err AppAMPISR(void *pBuff, uint32_t *pCount)
|
|
{
|
|
uint32_t FifoCnt;
|
|
if(AD5940_WakeUp(10) > 10) /* Wakeup AFE by read register, read 10 times at most */
|
|
return AD5940ERR_WAKEUP; /* Wakeup Failed */
|
|
AD5940_SleepKeyCtrlS(SLPKEY_LOCK);
|
|
|
|
*pCount = 0;
|
|
if(AD5940_INTCTestFlag(AFEINTC_0, AFEINTSRC_DATAFIFOTHRESH) == bTRUE)
|
|
{
|
|
FifoCnt = AD5940_FIFOGetCnt();
|
|
AD5940_FIFORd((uint32_t *)pBuff, FifoCnt);
|
|
AD5940_INTCClrFlag(AFEINTSRC_DATAFIFOTHRESH);
|
|
|
|
AD5940Err status = AppAMPRegModify(pBuff, &FifoCnt); /* If there is need to do AFE re-configure, do it here when AFE is in active state */
|
|
AD5940_SleepKeyCtrlS(SLPKEY_UNLOCK);
|
|
//AD5940_EnterSleepS(); /* Manually put AFE back to hibernate mode. This operation only takes effect when register value is ACTIVE previously */
|
|
|
|
/* Process data */
|
|
AppAMPDataProcess((int32_t*)pBuff,&FifoCnt);
|
|
*pCount = FifoCnt;
|
|
|
|
if (status == AD5940ERR_STOP) return AD5940ERR_STOP;
|
|
return 0;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Calculate voltage */
|
|
float AppAMPCalcVoltage(uint32_t ADCcode)
|
|
{
|
|
float kFactor = 1.835/1.82;
|
|
float fVolt = 0.0;
|
|
int32_t tmp = 0;
|
|
tmp = ADCcode - 32768;
|
|
switch(AppAMPCfg.ADCPgaGain)
|
|
{
|
|
case ADCPGA_1:
|
|
fVolt = ((float)(tmp)/32768)*(AppAMPCfg.ADCRefVolt/1)*kFactor;
|
|
break;
|
|
case ADCPGA_1P5:
|
|
fVolt = ((float)(tmp)/32768)*(AppAMPCfg.ADCRefVolt/1.5f)*kFactor;
|
|
break;
|
|
case ADCPGA_2:
|
|
fVolt = ((float)(tmp)/32768)*(AppAMPCfg.ADCRefVolt/2)*kFactor;
|
|
break;
|
|
case ADCPGA_4:
|
|
fVolt = ((float)(tmp)/32768)*(AppAMPCfg.ADCRefVolt/4)*kFactor;
|
|
break;
|
|
case ADCPGA_9:
|
|
fVolt = ((float)(tmp)/32768)*(AppAMPCfg.ADCRefVolt/9)*kFactor;
|
|
break;
|
|
}
|
|
return fVolt;
|
|
}
|
|
/* Calculate current in uA */
|
|
float AppAMPCalcCurrent(uint32_t ADCcode)
|
|
{
|
|
float fCurrent, fVoltage = 0.0;
|
|
fVoltage = AppAMPCalcVoltage(ADCcode);
|
|
fCurrent = fVoltage/AppAMPCfg.RtiaCalValue.Magnitude;
|
|
|
|
return -fCurrent*1000000;
|
|
} |