working again a bit

This commit is contained in:
pszsh 2026-02-13 15:13:56 -08:00
parent 5723e89a1a
commit 794f71ccaf
22 changed files with 2701 additions and 2456 deletions

2
.gitignore vendored
View File

@ -6,7 +6,7 @@ build
*.swp *.swp
*.cmake *.cmake
requirements.txt requirements.txt
ad5940.* ad5940
pico_sdk_import.cmake pico_sdk_import.cmake
build* build*
*.png *.png

File diff suppressed because it is too large Load Diff

View File

@ -2,359 +2,367 @@
#include "App_Common.h" #include "App_Common.h"
void AD5941_InitAll(void) { void AD5941_InitAll(void) {
AD5940_HWReset(); AD5940_HWReset();
AD5940_MCUResourceInit(0); AD5940_MCUResourceInit(0);
AD5940_Initialize(); AD5940_Initialize();
// CRITICAL: Re-enable Platform Interrupts/GPIOs after HW Reset // CRITICAL: Re-enable Platform Interrupts/GPIOs after HW Reset
AD5940PlatformCfg(); AD5940PlatformCfg();
} }
void AD5940ImpedanceStructInit(void) { void AD5940ImpedanceStructInit(void) {
AppIMPCfg_Type *pImpedanceCfg; AppIMPCfg_Type *pImpedanceCfg;
AppIMPGetCfg(&pImpedanceCfg); AppIMPGetCfg(&pImpedanceCfg);
pImpedanceCfg->IMPInited = bFALSE; pImpedanceCfg->IMPInited = bFALSE;
pImpedanceCfg->SeqStartAddr = 0; pImpedanceCfg->SeqStartAddr = 0;
pImpedanceCfg->MaxSeqLen = 512; pImpedanceCfg->MaxSeqLen = 512;
pImpedanceCfg->RcalVal = 100.0; pImpedanceCfg->RcalVal = 100.0;
pImpedanceCfg->RtiaVal = CalibratedHstiaVal; pImpedanceCfg->RtiaVal = CalibratedHstiaVal;
pImpedanceCfg->SinFreq = 1000.0; pImpedanceCfg->SinFreq = 1000.0;
pImpedanceCfg->FifoThresh = 6; pImpedanceCfg->FifoThresh = 6;
pImpedanceCfg->DacVoltPP = 600.0; pImpedanceCfg->DacVoltPP = 600.0;
pImpedanceCfg->ExcitBufGain = EXCITBUFGAIN_0P25; pImpedanceCfg->ExcitBufGain = EXCITBUFGAIN_0P25;
pImpedanceCfg->HsDacGain = HSDACGAIN_0P2; pImpedanceCfg->HsDacGain = HSDACGAIN_0P2;
pImpedanceCfg->HsDacUpdateRate = 7; pImpedanceCfg->HsDacUpdateRate = 7;
// --- Switch Matrix Configuration --- // --- Switch Matrix Configuration ---
// D-Switch: Connect DAC to CE0 (Force +) // D-Switch: Connect DAC to CE0 (Force +)
pImpedanceCfg->DswitchSel = SWD_CE0; pImpedanceCfg->DswitchSel = SWD_CE0;
// P-Switch: Connect CE0 to P-Bus (Optional, but standard) // P-Switch: Connect CE0 to P-Bus (Optional, but standard)
pImpedanceCfg->PswitchSel = SWP_CE0; pImpedanceCfg->PswitchSel = SWP_CE0;
// N-Switch: Connect SE0 to N-Bus (Force - / Current Input) // N-Switch: Connect SE0 to N-Bus (Force - / Current Input)
// This is the CRITICAL path for HSTIA current measurement. // This is the CRITICAL path for HSTIA current measurement.
pImpedanceCfg->NswitchSel = SWN_SE0; pImpedanceCfg->NswitchSel = SWN_SE0;
// T-Switch: Only connect the Feedback Resistor (TRTIA). // T-Switch: Only connect the Feedback Resistor (TRTIA).
// DO NOT connect SWT_SE0 (T11), as it may short SE0 to RE0/LPTIA nodes. // DO NOT connect SWT_SE0 (T11), as it may short SE0 to RE0/LPTIA nodes.
pImpedanceCfg->TswitchSel = 0; // Impedance.c adds SWT_TRTIA automatically pImpedanceCfg->TswitchSel = SWT_SE0LOAD; // Restoring Legacy Config (Commit
// 4266c4b). Connects SE0 to T-Node.
pImpedanceCfg->HstiaRtiaSel = GetHSTIARtia(ConfigHstiaVal); pImpedanceCfg->HstiaRtiaSel = GetHSTIARtia(ConfigHstiaVal);
pImpedanceCfg->BiasVolt = 0.0; pImpedanceCfg->BiasVolt = 0.0;
pImpedanceCfg->SweepCfg.SweepEn = bFALSE; pImpedanceCfg->SweepCfg.SweepEn = bFALSE;
pImpedanceCfg->SweepCfg.SweepStart = 100.0f; pImpedanceCfg->SweepCfg.SweepStart = 100.0f;
pImpedanceCfg->SweepCfg.SweepStop = 100000.0f; pImpedanceCfg->SweepCfg.SweepStop = 100000.0f;
pImpedanceCfg->SweepCfg.SweepPoints = 50; pImpedanceCfg->SweepCfg.SweepPoints = 50;
pImpedanceCfg->SweepCfg.SweepLog = bTRUE; pImpedanceCfg->SweepCfg.SweepLog = bTRUE;
pImpedanceCfg->PwrMod = AFEPWR_LP; pImpedanceCfg->PwrMod = AFEPWR_LP;
pImpedanceCfg->ADCSinc3Osr = ADCSINC3OSR_4; pImpedanceCfg->ADCSinc3Osr = ADCSINC3OSR_4;
pImpedanceCfg->DftNum = DFTNUM_16384; pImpedanceCfg->DftNum = DFTNUM_16384;
pImpedanceCfg->DftSrc = DFTSRC_SINC3; pImpedanceCfg->DftSrc = DFTSRC_SINC3;
pImpedanceCfg->ShortRe0Se0 = GlobalShortRe0Se0; pImpedanceCfg->ShortRe0Se0 = GlobalShortRe0Se0;
} }
void AD5940AMPStructInit(void) { void AD5940AMPStructInit(void) {
AppAMPCfg_Type *pAMPCfg; AppAMPCfg_Type *pAMPCfg;
AppAMPGetCfg(&pAMPCfg); AppAMPGetCfg(&pAMPCfg);
pAMPCfg->AMPInited = bFALSE; pAMPCfg->AMPInited = bFALSE;
pAMPCfg->WuptClkFreq = LFOSCFreq; pAMPCfg->WuptClkFreq = LFOSCFreq;
pAMPCfg->SeqStartAddr = 0; pAMPCfg->SeqStartAddr = 0;
pAMPCfg->MaxSeqLen = 512; pAMPCfg->MaxSeqLen = 512;
pAMPCfg->RcalVal = 100.0; pAMPCfg->RcalVal = 100.0;
pAMPCfg->NumOfData = -1; pAMPCfg->NumOfData = -1;
pAMPCfg->AmpODR = 1.0; pAMPCfg->AmpODR = 1.0;
pAMPCfg->FifoThresh = 4; pAMPCfg->FifoThresh = 4;
pAMPCfg->SensorBias = 0; pAMPCfg->SensorBias = 0;
pAMPCfg->LptiaRtiaSel = GetLPTIARtia(ConfigLptiaVal); pAMPCfg->LptiaRtiaSel = GetLPTIARtia(ConfigLptiaVal);
pAMPCfg->LpTiaRl = ConfigRLoad; pAMPCfg->LpTiaRl = ConfigRLoad;
pAMPCfg->LpTiaRf = CurrentLpTiaRf; pAMPCfg->LpTiaRf = CurrentLpTiaRf;
pAMPCfg->Vzero = 1100; pAMPCfg->Vzero = 1100;
pAMPCfg->ADCRefVolt = 1.82; pAMPCfg->ADCRefVolt = 1.82;
pAMPCfg->RtiaCalValue.Magnitude = CalibratedLptiaVal; pAMPCfg->RtiaCalValue.Magnitude = CalibratedLptiaVal;
pAMPCfg->ShortRe0Se0 = GlobalShortRe0Se0; pAMPCfg->ShortRe0Se0 = GlobalShortRe0Se0;
} }
void AD5940RampStructInit(void) { void AD5940RampStructInit(void) {
AppRAMPCfg_Type *pRampCfg; AppRAMPCfg_Type *pRampCfg;
AppRAMPGetCfg(&pRampCfg); AppRAMPGetCfg(&pRampCfg);
pRampCfg->RAMPInited = bFALSE; pRampCfg->RAMPInited = bFALSE;
pRampCfg->SeqStartAddr = 0; pRampCfg->SeqStartAddr = 0;
pRampCfg->MaxSeqLen = 1024; pRampCfg->MaxSeqLen = 1024;
pRampCfg->RcalVal = 100.0; pRampCfg->RcalVal = 100.0;
pRampCfg->ADCRefVolt = 1820.0f; pRampCfg->ADCRefVolt = 1820.0f;
pRampCfg->FifoThresh = 4; pRampCfg->FifoThresh = 4;
pRampCfg->SysClkFreq = 16000000.0f; pRampCfg->SysClkFreq = 16000000.0f;
pRampCfg->LFOSCClkFreq = LFOSCFreq; pRampCfg->LFOSCClkFreq = LFOSCFreq;
pRampCfg->RampStartVolt = -500.0f; pRampCfg->RampStartVolt = -500.0f;
pRampCfg->RampPeakVolt = +500.0f; pRampCfg->RampPeakVolt = +500.0f;
pRampCfg->VzeroStart = 1100.0f; pRampCfg->VzeroStart = 1100.0f;
pRampCfg->VzeroPeak = 1100.0f; pRampCfg->VzeroPeak = 1100.0f;
pRampCfg->StepNumber = 100; pRampCfg->StepNumber = 100;
pRampCfg->RampDuration = 10000; pRampCfg->RampDuration = 10000;
pRampCfg->SampleDelay = 1.0f; pRampCfg->SampleDelay = 1.0f;
pRampCfg->LPTIARtiaSel = GetLPTIARtia(ConfigLptiaVal); pRampCfg->LPTIARtiaSel = GetLPTIARtia(ConfigLptiaVal);
pRampCfg->LPTIARloadSel = ConfigRLoad; pRampCfg->LPTIARloadSel = ConfigRLoad;
pRampCfg->LpTiaRf = CurrentLpTiaRf; pRampCfg->LpTiaRf = CurrentLpTiaRf;
pRampCfg->AdcPgaGain = ADCPGA_1P5; pRampCfg->AdcPgaGain = ADCPGA_1P5;
pRampCfg->RtiaValue.Magnitude = CalibratedLptiaVal; pRampCfg->RtiaValue.Magnitude = CalibratedLptiaVal;
pRampCfg->ShortRe0Se0 = GlobalShortRe0Se0; pRampCfg->ShortRe0Se0 = GlobalShortRe0Se0;
} }
void Config_LPLOOP(float bias_mv) { void Config_LPLOOP(float bias_mv) {
uint32_t vzero_code = 32; uint32_t vzero_code = 32;
float vzero_volts = vzero_code * (2200.0f / 64.0f); float vzero_volts = vzero_code * (2200.0f / 64.0f);
float vbias_volts = vzero_volts + bias_mv; float vbias_volts = vzero_volts + bias_mv;
uint32_t vbias_code = (uint32_t)(vbias_volts / (2200.0f / 4095.0f)); uint32_t vbias_code = (uint32_t)(vbias_volts / (2200.0f / 4095.0f));
if(vbias_code > 4095) vbias_code = 4095; if (vbias_code > 4095)
vbias_code = 4095;
LPDACCfg_Type lpdac_cfg; LPDACCfg_Type lpdac_cfg;
lpdac_cfg.LpdacSel = LPDAC0; lpdac_cfg.LpdacSel = LPDAC0;
lpdac_cfg.LpDacVbiasMux = LPDACVBIAS_12BIT; lpdac_cfg.LpDacVbiasMux = LPDACVBIAS_12BIT;
lpdac_cfg.LpDacVzeroMux = LPDACVZERO_6BIT; lpdac_cfg.LpDacVzeroMux = LPDACVZERO_6BIT;
lpdac_cfg.DacData6Bit = vzero_code; lpdac_cfg.DacData6Bit = vzero_code;
lpdac_cfg.DacData12Bit = vbias_code; lpdac_cfg.DacData12Bit = vbias_code;
lpdac_cfg.DataRst = bFALSE; lpdac_cfg.DataRst = bFALSE;
lpdac_cfg.LpDacSW = LPDACSW_VBIAS2LPPA | LPDACSW_VBIAS2PIN | LPDACSW_VZERO2LPTIA | LPDACSW_VZERO2PIN; lpdac_cfg.LpDacSW = LPDACSW_VBIAS2LPPA | LPDACSW_VBIAS2PIN |
lpdac_cfg.LpDacRef = LPDACREF_2P5; LPDACSW_VZERO2LPTIA | LPDACSW_VZERO2PIN;
lpdac_cfg.LpDacSrc = LPDACSRC_MMR; lpdac_cfg.LpDacRef = LPDACREF_2P5;
lpdac_cfg.PowerEn = bTRUE; lpdac_cfg.LpDacSrc = LPDACSRC_MMR;
AD5940_LPDACCfgS(&lpdac_cfg); lpdac_cfg.PowerEn = bTRUE;
AD5940_LPDACCfgS(&lpdac_cfg);
LPLoopCfg_Type lp_loop; LPLoopCfg_Type lp_loop;
lp_loop.LpAmpCfg.LpAmpSel = LPAMP0; lp_loop.LpAmpCfg.LpAmpSel = LPAMP0;
lp_loop.LpAmpCfg.LpAmpPwrMod = LPAMPPWR_NORM; lp_loop.LpAmpCfg.LpAmpPwrMod = LPAMPPWR_NORM;
lp_loop.LpAmpCfg.LpPaPwrEn = bTRUE; lp_loop.LpAmpCfg.LpPaPwrEn = bTRUE;
lp_loop.LpAmpCfg.LpTiaPwrEn = bTRUE; lp_loop.LpAmpCfg.LpTiaPwrEn = bTRUE;
lp_loop.LpAmpCfg.LpTiaRf = CurrentLpTiaRf; lp_loop.LpAmpCfg.LpTiaRf = CurrentLpTiaRf;
lp_loop.LpAmpCfg.LpTiaRload = ConfigRLoad; lp_loop.LpAmpCfg.LpTiaRload = ConfigRLoad;
lp_loop.LpAmpCfg.LpTiaRtia = GetLPTIARtia(ConfigLptiaVal); lp_loop.LpAmpCfg.LpTiaRtia = GetLPTIARtia(ConfigLptiaVal);
// Base Switches // Base Switches
lp_loop.LpAmpCfg.LpTiaSW = LPTIASW(5)|LPTIASW(2)|LPTIASW(4)|LPTIASW(12)|LPTIASW(13); lp_loop.LpAmpCfg.LpTiaSW =
LPTIASW(5) | LPTIASW(2) | LPTIASW(4) | LPTIASW(12) | LPTIASW(13);
// Apply Short Option // Apply Short Option
if(GlobalShortRe0Se0) { if (GlobalShortRe0Se0) {
lp_loop.LpAmpCfg.LpTiaSW |= LPTIASW(11); lp_loop.LpAmpCfg.LpTiaSW |= LPTIASW(11);
} }
AD5940_LPLoopCfgS(&lp_loop); AD5940_LPLoopCfgS(&lp_loop);
} }
void Calibrate_HSDAC(float freq) { void Calibrate_HSDAC(float freq) {
HSDACCal_Type hsdac_cal; HSDACCal_Type hsdac_cal;
ADCPGACal_Type adcpga_cal; ADCPGACal_Type adcpga_cal;
CLKCfg_Type clk_cfg; CLKCfg_Type clk_cfg;
// Configure Clock based on frequency (matches Do_WaveGen logic) // Configure Clock based on frequency (matches Do_WaveGen logic)
clk_cfg.ADCClkDiv = ADCCLKDIV_1; clk_cfg.ADCClkDiv = ADCCLKDIV_1;
clk_cfg.ADCCLkSrc = ADCCLKSRC_HFOSC; clk_cfg.ADCCLkSrc = ADCCLKSRC_HFOSC;
clk_cfg.SysClkDiv = SYSCLKDIV_1; clk_cfg.SysClkDiv = SYSCLKDIV_1;
clk_cfg.SysClkSrc = SYSCLKSRC_HFOSC; clk_cfg.SysClkSrc = SYSCLKSRC_HFOSC;
clk_cfg.HFXTALEn = bFALSE; clk_cfg.HFXTALEn = bFALSE;
clk_cfg.LFOSCEn = bTRUE; clk_cfg.LFOSCEn = bTRUE;
if(freq > 80000) { if (freq > 80000) {
clk_cfg.HfOSC32MHzMode = bTRUE; clk_cfg.HfOSC32MHzMode = bTRUE;
clk_cfg.HFOSCEn = bTRUE; clk_cfg.HFOSCEn = bTRUE;
AD5940_CLKCfg(&clk_cfg); AD5940_CLKCfg(&clk_cfg);
AD5940_HPModeEn(bTRUE); AD5940_HPModeEn(bTRUE);
} else { } else {
clk_cfg.HfOSC32MHzMode = bFALSE; clk_cfg.HfOSC32MHzMode = bFALSE;
clk_cfg.HFOSCEn = bTRUE; clk_cfg.HFOSCEn = bTRUE;
AD5940_CLKCfg(&clk_cfg); AD5940_CLKCfg(&clk_cfg);
AD5940_HPModeEn(bFALSE); AD5940_HPModeEn(bFALSE);
} }
AD5940_AFEPwrBW(AFEPWR_LP, AFEBW_250KHZ); AD5940_AFEPwrBW(AFEPWR_LP, AFEBW_250KHZ);
adcpga_cal.AdcClkFreq = 16000000; adcpga_cal.AdcClkFreq = 16000000;
adcpga_cal.ADCPga = ADCPGA_1P5; adcpga_cal.ADCPga = ADCPGA_1P5;
adcpga_cal.ADCSinc2Osr = ADCSINC2OSR_1333; adcpga_cal.ADCSinc2Osr = ADCSINC2OSR_1333;
adcpga_cal.ADCSinc3Osr = ADCSINC3OSR_4; adcpga_cal.ADCSinc3Osr = ADCSINC3OSR_4;
adcpga_cal.PGACalType = PGACALTYPE_OFFSET; adcpga_cal.PGACalType = PGACALTYPE_OFFSET;
adcpga_cal.TimeOut10us = 1000; adcpga_cal.TimeOut10us = 1000;
adcpga_cal.VRef1p11 = 1.11; adcpga_cal.VRef1p11 = 1.11;
adcpga_cal.VRef1p82 = 1.82; adcpga_cal.VRef1p82 = 1.82;
AD5940_ADCPGACal(&adcpga_cal); AD5940_ADCPGACal(&adcpga_cal);
hsdac_cal.ExcitBufGain = EXCITBUFGAIN_2; hsdac_cal.ExcitBufGain = EXCITBUFGAIN_2;
hsdac_cal.HsDacGain = HSDACGAIN_1; hsdac_cal.HsDacGain = HSDACGAIN_1;
hsdac_cal.AfePwrMode = AFEPWR_LP; hsdac_cal.AfePwrMode = AFEPWR_LP;
hsdac_cal.ADCSinc2Osr = ADCSINC2OSR_1333; hsdac_cal.ADCSinc2Osr = ADCSINC2OSR_1333;
hsdac_cal.ADCSinc3Osr = ADCSINC3OSR_4; hsdac_cal.ADCSinc3Osr = ADCSINC3OSR_4;
AD5940_HSDACCal(&hsdac_cal); AD5940_HSDACCal(&hsdac_cal);
hsdac_cal.ExcitBufGain = EXCITBUFGAIN_2; hsdac_cal.ExcitBufGain = EXCITBUFGAIN_2;
hsdac_cal.HsDacGain = HSDACGAIN_0P2; hsdac_cal.HsDacGain = HSDACGAIN_0P2;
AD5940_HSDACCal(&hsdac_cal); AD5940_HSDACCal(&hsdac_cal);
hsdac_cal.ExcitBufGain = EXCITBUFGAIN_0P25; hsdac_cal.ExcitBufGain = EXCITBUFGAIN_0P25;
hsdac_cal.HsDacGain = HSDACGAIN_1; hsdac_cal.HsDacGain = HSDACGAIN_1;
AD5940_HSDACCal(&hsdac_cal); AD5940_HSDACCal(&hsdac_cal);
hsdac_cal.ExcitBufGain = EXCITBUFGAIN_0P25; hsdac_cal.ExcitBufGain = EXCITBUFGAIN_0P25;
hsdac_cal.HsDacGain = HSDACGAIN_0P2; hsdac_cal.HsDacGain = HSDACGAIN_0P2;
AD5940_HSDACCal(&hsdac_cal); AD5940_HSDACCal(&hsdac_cal);
} }
void Configure_Filters(float freq) { void Configure_Filters(float freq) {
ADCFilterCfg_Type adc_filter; ADCFilterCfg_Type adc_filter;
DFTCfg_Type dft_cfg; DFTCfg_Type dft_cfg;
FIFOCfg_Type fifo_cfg; FIFOCfg_Type fifo_cfg;
fifo_cfg.FIFOEn = bFALSE; fifo_cfg.FIFOEn = bFALSE;
fifo_cfg.FIFOMode = FIFOMODE_FIFO; fifo_cfg.FIFOMode = FIFOMODE_FIFO;
fifo_cfg.FIFOSize = FIFOSIZE_4KB; fifo_cfg.FIFOSize = FIFOSIZE_4KB;
fifo_cfg.FIFOSrc = FIFOSRC_DFT; fifo_cfg.FIFOSrc = FIFOSRC_DFT;
fifo_cfg.FIFOThresh = 2; fifo_cfg.FIFOThresh = 2;
AD5940_FIFOCfg(&fifo_cfg); AD5940_FIFOCfg(&fifo_cfg);
fifo_cfg.FIFOEn = bTRUE; fifo_cfg.FIFOEn = bTRUE;
AD5940_FIFOCfg(&fifo_cfg); AD5940_FIFOCfg(&fifo_cfg);
AD5940_ADCMuxCfgS(ADCMUXP_HSTIA_P, ADCMUXN_HSTIA_N); AD5940_ADCMuxCfgS(ADCMUXP_HSTIA_P, ADCMUXN_HSTIA_N);
AD5940_StructInit(&adc_filter, sizeof(adc_filter)); AD5940_StructInit(&adc_filter, sizeof(adc_filter));
AD5940_StructInit(&dft_cfg, sizeof(dft_cfg)); AD5940_StructInit(&dft_cfg, sizeof(dft_cfg));
if (freq < 0.51f) { if (freq < 0.51f) {
adc_filter.ADCAvgNum = ADCAVGNUM_16; adc_filter.ADCAvgNum = ADCAVGNUM_16;
adc_filter.ADCSinc2Osr = ADCSINC2OSR_267; adc_filter.ADCSinc2Osr = ADCSINC2OSR_267;
adc_filter.ADCSinc3Osr = ADCSINC3OSR_5; adc_filter.ADCSinc3Osr = ADCSINC3OSR_5;
adc_filter.BpNotch = bTRUE; adc_filter.BpNotch = bTRUE;
adc_filter.BpSinc3 = bFALSE; adc_filter.BpSinc3 = bFALSE;
adc_filter.Sinc2NotchEnable = bTRUE; adc_filter.Sinc2NotchEnable = bTRUE;
adc_filter.ADCRate = ADCRATE_800KHZ; adc_filter.ADCRate = ADCRATE_800KHZ;
dft_cfg.DftNum = DFTNUM_8192; dft_cfg.DftNum = DFTNUM_8192;
dft_cfg.DftSrc = DFTSRC_SINC2NOTCH; dft_cfg.DftSrc = DFTSRC_SINC2NOTCH;
} else if(freq < 5.0f) { } else if (freq < 5.0f) {
adc_filter.ADCAvgNum = ADCAVGNUM_16; adc_filter.ADCAvgNum = ADCAVGNUM_16;
adc_filter.ADCSinc2Osr = ADCSINC2OSR_178; adc_filter.ADCSinc2Osr = ADCSINC2OSR_178;
adc_filter.ADCSinc3Osr = ADCSINC3OSR_4; adc_filter.ADCSinc3Osr = ADCSINC3OSR_4;
adc_filter.BpNotch = bTRUE; adc_filter.BpNotch = bTRUE;
adc_filter.BpSinc3 = bFALSE; adc_filter.BpSinc3 = bFALSE;
adc_filter.Sinc2NotchEnable = bTRUE; adc_filter.Sinc2NotchEnable = bTRUE;
adc_filter.ADCRate = ADCRATE_800KHZ; adc_filter.ADCRate = ADCRATE_800KHZ;
dft_cfg.DftNum = DFTNUM_8192; dft_cfg.DftNum = DFTNUM_8192;
dft_cfg.DftSrc = DFTSRC_SINC2NOTCH; dft_cfg.DftSrc = DFTSRC_SINC2NOTCH;
} else if(freq < 450.0f) { } else if (freq < 450.0f) {
adc_filter.ADCAvgNum = ADCAVGNUM_16; adc_filter.ADCAvgNum = ADCAVGNUM_16;
adc_filter.ADCSinc2Osr = ADCSINC2OSR_44; adc_filter.ADCSinc2Osr = ADCSINC2OSR_44;
adc_filter.ADCSinc3Osr = ADCSINC3OSR_4; adc_filter.ADCSinc3Osr = ADCSINC3OSR_4;
adc_filter.BpNotch = bTRUE; adc_filter.BpNotch = bTRUE;
adc_filter.BpSinc3 = bFALSE; adc_filter.BpSinc3 = bFALSE;
adc_filter.Sinc2NotchEnable = bTRUE; adc_filter.Sinc2NotchEnable = bTRUE;
adc_filter.ADCRate = ADCRATE_800KHZ; adc_filter.ADCRate = ADCRATE_800KHZ;
dft_cfg.DftNum = DFTNUM_4096; dft_cfg.DftNum = DFTNUM_4096;
dft_cfg.DftSrc = DFTSRC_SINC2NOTCH; dft_cfg.DftSrc = DFTSRC_SINC2NOTCH;
} else if(freq < 80000.0f) { } else if (freq < 80000.0f) {
adc_filter.ADCAvgNum = ADCAVGNUM_16; adc_filter.ADCAvgNum = ADCAVGNUM_16;
adc_filter.ADCSinc2Osr = ADCSINC2OSR_178; adc_filter.ADCSinc2Osr = ADCSINC2OSR_178;
adc_filter.ADCSinc3Osr = ADCSINC3OSR_4; adc_filter.ADCSinc3Osr = ADCSINC3OSR_4;
adc_filter.BpNotch = bTRUE; adc_filter.BpNotch = bTRUE;
adc_filter.BpSinc3 = bFALSE; adc_filter.BpSinc3 = bFALSE;
adc_filter.Sinc2NotchEnable = bFALSE; adc_filter.Sinc2NotchEnable = bFALSE;
adc_filter.ADCRate = ADCRATE_800KHZ; adc_filter.ADCRate = ADCRATE_800KHZ;
dft_cfg.DftNum = DFTNUM_16384; dft_cfg.DftNum = DFTNUM_16384;
dft_cfg.DftSrc = DFTSRC_SINC3; dft_cfg.DftSrc = DFTSRC_SINC3;
} else { } else {
adc_filter.ADCAvgNum = ADCAVGNUM_16; adc_filter.ADCAvgNum = ADCAVGNUM_16;
adc_filter.ADCSinc2Osr = ADCSINC2OSR_178; adc_filter.ADCSinc2Osr = ADCSINC2OSR_178;
adc_filter.ADCSinc3Osr = ADCSINC3OSR_2; adc_filter.ADCSinc3Osr = ADCSINC3OSR_2;
adc_filter.BpNotch = bTRUE; adc_filter.BpNotch = bTRUE;
adc_filter.BpSinc3 = bFALSE; adc_filter.BpSinc3 = bFALSE;
adc_filter.Sinc2NotchEnable = bFALSE; adc_filter.Sinc2NotchEnable = bFALSE;
adc_filter.ADCRate = ADCRATE_1P6MHZ; adc_filter.ADCRate = ADCRATE_1P6MHZ;
dft_cfg.DftNum = DFTNUM_16384; dft_cfg.DftNum = DFTNUM_16384;
dft_cfg.DftSrc = DFTSRC_SINC3; dft_cfg.DftSrc = DFTSRC_SINC3;
} }
dft_cfg.HanWinEn = bTRUE; dft_cfg.HanWinEn = bTRUE;
AD5940_ADCFilterCfgS(&adc_filter); AD5940_ADCFilterCfgS(&adc_filter);
AD5940_DFTCfgS(&dft_cfg); AD5940_DFTCfgS(&dft_cfg);
} }
void Do_WaveGen(float freq) { void Do_WaveGen(float freq) {
CLKCfg_Type clk_cfg; CLKCfg_Type clk_cfg;
AFERefCfg_Type aferef_cfg; AFERefCfg_Type aferef_cfg;
HSLoopCfg_Type HpLoopCfg; HSLoopCfg_Type HpLoopCfg;
ADCBaseCfg_Type adc_base; ADCBaseCfg_Type adc_base;
clk_cfg.ADCClkDiv = ADCCLKDIV_1; clk_cfg.ADCClkDiv = ADCCLKDIV_1;
clk_cfg.ADCCLkSrc = ADCCLKSRC_HFOSC; clk_cfg.ADCCLkSrc = ADCCLKSRC_HFOSC;
clk_cfg.SysClkDiv = SYSCLKDIV_1; clk_cfg.SysClkDiv = SYSCLKDIV_1;
clk_cfg.SysClkSrc = SYSCLKSRC_HFOSC; clk_cfg.SysClkSrc = SYSCLKSRC_HFOSC;
clk_cfg.HFXTALEn = bFALSE; clk_cfg.HFXTALEn = bFALSE;
clk_cfg.LFOSCEn = bTRUE; clk_cfg.LFOSCEn = bTRUE;
if(freq > 80000) { if (freq > 80000) {
clk_cfg.HfOSC32MHzMode = bTRUE; clk_cfg.HfOSC32MHzMode = bTRUE;
clk_cfg.HFOSCEn = bTRUE; clk_cfg.HFOSCEn = bTRUE;
AD5940_CLKCfg(&clk_cfg); AD5940_CLKCfg(&clk_cfg);
AD5940_HPModeEn(bTRUE); AD5940_HPModeEn(bTRUE);
} else { } else {
clk_cfg.HfOSC32MHzMode = bFALSE; clk_cfg.HfOSC32MHzMode = bFALSE;
clk_cfg.HFOSCEn = bTRUE; clk_cfg.HFOSCEn = bTRUE;
AD5940_CLKCfg(&clk_cfg); AD5940_CLKCfg(&clk_cfg);
AD5940_HPModeEn(bFALSE); AD5940_HPModeEn(bFALSE);
} }
aferef_cfg.HpBandgapEn = bTRUE; aferef_cfg.HpBandgapEn = bTRUE;
aferef_cfg.Hp1V1BuffEn = bTRUE; aferef_cfg.Hp1V1BuffEn = bTRUE;
aferef_cfg.Hp1V8BuffEn = bTRUE; aferef_cfg.Hp1V8BuffEn = bTRUE;
aferef_cfg.Disc1V1Cap = bFALSE; aferef_cfg.Disc1V1Cap = bFALSE;
aferef_cfg.Disc1V8Cap = bFALSE; aferef_cfg.Disc1V8Cap = bFALSE;
aferef_cfg.Hp1V8ThemBuff = bFALSE; aferef_cfg.Hp1V8ThemBuff = bFALSE;
aferef_cfg.Hp1V8Ilimit = bFALSE; aferef_cfg.Hp1V8Ilimit = bFALSE;
aferef_cfg.Lp1V1BuffEn = bFALSE; aferef_cfg.Lp1V1BuffEn = bFALSE;
aferef_cfg.Lp1V8BuffEn = bFALSE; aferef_cfg.Lp1V8BuffEn = bFALSE;
aferef_cfg.LpBandgapEn = bTRUE; aferef_cfg.LpBandgapEn = bTRUE;
aferef_cfg.LpRefBufEn = bTRUE; aferef_cfg.LpRefBufEn = bTRUE;
aferef_cfg.LpRefBoostEn = bFALSE; aferef_cfg.LpRefBoostEn = bFALSE;
AD5940_REFCfgS(&aferef_cfg); AD5940_REFCfgS(&aferef_cfg);
HpLoopCfg.HsDacCfg.ExcitBufGain = EXCITBUFGAIN_2; HpLoopCfg.HsDacCfg.ExcitBufGain = EXCITBUFGAIN_2;
HpLoopCfg.HsDacCfg.HsDacGain = HSDACGAIN_1; HpLoopCfg.HsDacCfg.HsDacGain = HSDACGAIN_1;
HpLoopCfg.HsDacCfg.HsDacUpdateRate = (freq > 80000) ? 0x07 : 0x1B; HpLoopCfg.HsDacCfg.HsDacUpdateRate = (freq > 80000) ? 0x07 : 0x1B;
HpLoopCfg.HsTiaCfg.DiodeClose = bFALSE; HpLoopCfg.HsTiaCfg.DiodeClose = bFALSE;
HpLoopCfg.HsTiaCfg.HstiaBias = HSTIABIAS_1P1; HpLoopCfg.HsTiaCfg.HstiaBias = HSTIABIAS_1P1;
HpLoopCfg.HsTiaCfg.HstiaCtia = 16; HpLoopCfg.HsTiaCfg.HstiaCtia = 16;
HpLoopCfg.HsTiaCfg.HstiaDeRload = HSTIADERLOAD_OPEN; HpLoopCfg.HsTiaCfg.HstiaDeRload = HSTIADERLOAD_OPEN;
HpLoopCfg.HsTiaCfg.HstiaDeRtia = HSTIADERTIA_TODE; HpLoopCfg.HsTiaCfg.HstiaDeRtia = HSTIADERTIA_TODE;
HpLoopCfg.HsTiaCfg.HstiaRtiaSel = GetHSTIARtia(ConfigHstiaVal); HpLoopCfg.HsTiaCfg.HstiaRtiaSel = GetHSTIARtia(ConfigHstiaVal);
adc_base.ADCPga = ADCPGA_1P5; adc_base.ADCPga = ADCPGA_1P5;
AD5940_ADCBaseCfgS(&adc_base); AD5940_ADCBaseCfgS(&adc_base);
// --- Switch Matrix Configuration (Manual Sweep) --- // --- Switch Matrix Configuration (Manual Sweep) ---
HpLoopCfg.SWMatCfg.Dswitch = SWD_CE0; HpLoopCfg.SWMatCfg.Dswitch = SWD_CE0;
HpLoopCfg.SWMatCfg.Pswitch = SWP_CE0; HpLoopCfg.SWMatCfg.Pswitch = SWP_CE0;
HpLoopCfg.SWMatCfg.Nswitch = SWN_SE0; HpLoopCfg.SWMatCfg.Nswitch = SWN_SE0;
// FIX: Only use TRTIA (Feedback). Do NOT use SWT_SE0. // FIX: Only use TRTIA (Feedback). Do NOT use SWT_SE0.
HpLoopCfg.SWMatCfg.Tswitch = SWT_TRTIA; HpLoopCfg.SWMatCfg.Tswitch = SWT_TRTIA;
AD5940_AFECtrlS(AFECTRL_WG, bFALSE); AD5940_AFECtrlS(AFECTRL_WG, bFALSE);
HpLoopCfg.WgCfg.WgType = WGTYPE_SIN; HpLoopCfg.WgCfg.WgType = WGTYPE_SIN;
HpLoopCfg.WgCfg.GainCalEn = bFALSE; HpLoopCfg.WgCfg.GainCalEn = bFALSE;
HpLoopCfg.WgCfg.OffsetCalEn = bFALSE; HpLoopCfg.WgCfg.OffsetCalEn = bFALSE;
HpLoopCfg.WgCfg.SinCfg.SinFreqWord = AD5940_WGFreqWordCal(freq, (freq > 80000) ? 32000000.0 : 16000000.0); HpLoopCfg.WgCfg.SinCfg.SinFreqWord =
AD5940_WGFreqWordCal(freq, (freq > 80000) ? 32000000.0 : 16000000.0);
// Reduced Amplitude: 50mV peak (100mV pp) to prevent saturation // Reduced Amplitude: 50mV peak (100mV pp) to prevent saturation
// Range is +/- 607mV with Gain 2/1. // Range is +/- 607mV with Gain 2/1.
// 50 / 607 * 2047 = ~168 // 50 / 607 * 2047 = ~168
HpLoopCfg.WgCfg.SinCfg.SinAmplitudeWord = (uint32_t)(50.0f/607.0f*2047 + 0.5f); HpLoopCfg.WgCfg.SinCfg.SinAmplitudeWord =
HpLoopCfg.WgCfg.SinCfg.SinOffsetWord = 0; (uint32_t)(50.0f / 607.0f * 2047 + 0.5f);
HpLoopCfg.WgCfg.SinCfg.SinPhaseWord = 0; HpLoopCfg.WgCfg.SinCfg.SinOffsetWord = 0;
AD5940_HSLoopCfgS(&HpLoopCfg); HpLoopCfg.WgCfg.SinCfg.SinPhaseWord = 0;
AD5940_HSLoopCfgS(&HpLoopCfg);
AD5940_AFECtrlS(AFECTRL_DACREFPWR, bTRUE); AD5940_AFECtrlS(AFECTRL_DACREFPWR, bTRUE);
AD5940_AFECtrlS(AFECTRL_EXTBUFPWR | AFECTRL_INAMPPWR | AFECTRL_HSTIAPWR | AFECTRL_HSDACPWR, bTRUE); AD5940_AFECtrlS(AFECTRL_EXTBUFPWR | AFECTRL_INAMPPWR | AFECTRL_HSTIAPWR |
AD5940_AFECtrlS(AFECTRL_WG, bTRUE); AFECTRL_HSDACPWR,
AD5940_AFECtrlS(AFECTRL_DCBUFPWR, bTRUE); bTRUE);
AD5940_AFEPwrBW(AFEPWR_LP, AFEBW_250KHZ); AD5940_AFECtrlS(AFECTRL_WG, bTRUE);
AD5940_AFECtrlS(AFECTRL_DCBUFPWR, bTRUE);
AD5940_AFEPwrBW(AFEPWR_LP, AFEBW_250KHZ);
} }

View File

@ -2,201 +2,231 @@
#include "App_Common.h" #include "App_Common.h"
void Routine_CalibrateLFO(void) { void Routine_CalibrateLFO(void) {
printf(">> Calibrating LFOSC...\n"); printf(">> Calibrating LFOSC...\n");
if (CurrentMode == MODE_IMPEDANCE) AppIMPCleanup(); if (CurrentMode == MODE_IMPEDANCE)
else if (CurrentMode == MODE_AMPEROMETRIC) AppAMPCtrl(AMPCTRL_SHUTDOWN, 0); AppIMPCleanup();
else if (CurrentMode == MODE_RAMP) AppRAMPCtrl(APPCTRL_SHUTDOWN, 0); else if (CurrentMode == MODE_AMPEROMETRIC)
AppAMPCtrl(AMPCTRL_SHUTDOWN, 0);
else if (CurrentMode == MODE_RAMP)
AppRAMPCtrl(APPCTRL_SHUTDOWN, 0);
LFOSCMeasure_Type cal_cfg; LFOSCMeasure_Type cal_cfg;
cal_cfg.CalDuration = 1000.0; cal_cfg.CalDuration = 1000.0;
cal_cfg.CalSeqAddr = 0; cal_cfg.CalSeqAddr = 0;
cal_cfg.SystemClkFreq = 16000000.0; cal_cfg.SystemClkFreq = 16000000.0;
if(AD5940_LFOSCMeasure(&cal_cfg, &LFOSCFreq) == AD5940ERR_OK) { if (AD5940_LFOSCMeasure(&cal_cfg, &LFOSCFreq) == AD5940ERR_OK) {
printf(">> LFOSC Calibrated: %.2f Hz\n", LFOSCFreq); printf(">> LFOSC Calibrated: %.2f Hz\n", LFOSCFreq);
} else { } else {
printf(">> LFOSC Calibration Failed.\n"); printf(">> LFOSC Calibration Failed.\n");
} }
} }
void Routine_Measure(float freq) { void Routine_Measure(float freq) {
if (CurrentMode == MODE_AMPEROMETRIC) AppAMPCtrl(AMPCTRL_SHUTDOWN, 0); if (CurrentMode == MODE_AMPEROMETRIC)
else if (CurrentMode == MODE_RAMP) AppRAMPCtrl(APPCTRL_SHUTDOWN, 0); AppAMPCtrl(AMPCTRL_SHUTDOWN, 0);
CurrentMode = MODE_IMPEDANCE; else if (CurrentMode == MODE_RAMP)
AppRAMPCtrl(APPCTRL_SHUTDOWN, 0);
CurrentMode = MODE_IMPEDANCE;
AppIMPCfg_Type *pCfg; AppIMPCfg_Type *pCfg;
AppIMPGetCfg(&pCfg); AppIMPGetCfg(&pCfg);
AppIMPCleanup(); AppIMPCleanup();
AD5940ImpedanceStructInit(); // Reload config with current HP settings AD5940ImpedanceStructInit(); // Reload config with current HP settings
pCfg->WuptClkFreq = LFOSCFreq; pCfg->WuptClkFreq = LFOSCFreq;
pCfg->SweepCfg.SweepEn = bFALSE; pCfg->SweepCfg.SweepEn = bFALSE;
pCfg->SinFreq = freq; pCfg->SinFreq = freq;
pCfg->NumOfData = -1; pCfg->NumOfData = -1;
pCfg->RealDataCount = -1; pCfg->RealDataCount = -1;
pCfg->bParaChanged = bTRUE;
if(AppIMPInit(AppBuff, APPBUFF_SIZE) == AD5940ERR_OK) { // Apply Global Settings
AppIMPCtrl(IMPCTRL_START, 0); pCfg->ShortRe0Se0 = GlobalShortRe0Se0;
} else { pCfg->HstiaRtiaSel = GetHSTIARtia(ConfigHstiaVal);
printf("ERROR: Init Failed\n"); pCfg->RtiaVal = (float)ConfigHstiaVal;
}
pCfg->bParaChanged = bTRUE;
if (AppIMPInit(AppBuff, APPBUFF_SIZE) == AD5940ERR_OK) {
AppIMPCtrl(IMPCTRL_START, 0);
} else {
printf("ERROR: Init Failed\n");
}
} }
void Routine_Sweep(float start, float end, int steps) { void Routine_Sweep(float start, float end, int steps) {
if (CurrentMode == MODE_AMPEROMETRIC) AppAMPCtrl(AMPCTRL_SHUTDOWN, 0); if (CurrentMode == MODE_AMPEROMETRIC)
else if (CurrentMode == MODE_RAMP) AppRAMPCtrl(APPCTRL_SHUTDOWN, 0); AppAMPCtrl(AMPCTRL_SHUTDOWN, 0);
CurrentMode = MODE_IMPEDANCE; else if (CurrentMode == MODE_RAMP)
AppRAMPCtrl(APPCTRL_SHUTDOWN, 0);
CurrentMode = MODE_IMPEDANCE;
AppIMPCfg_Type *pCfg; AppIMPCfg_Type *pCfg;
AppIMPGetCfg(&pCfg); AppIMPGetCfg(&pCfg);
AppIMPCleanup(); AppIMPCleanup();
AD5940ImpedanceStructInit(); // Reload config with current HP settings AD5940ImpedanceStructInit(); // Reload config with current HP settings
pCfg->WuptClkFreq = LFOSCFreq; pCfg->WuptClkFreq = LFOSCFreq;
pCfg->SweepCfg.SweepEn = bTRUE; pCfg->SweepCfg.SweepEn = bTRUE;
pCfg->SweepCfg.SweepStart = start; pCfg->SweepCfg.SweepStart = start;
pCfg->SweepCfg.SweepStop = end; pCfg->SweepCfg.SweepStop = end;
pCfg->SweepCfg.SweepPoints = steps + 1; pCfg->SweepCfg.SweepPoints = steps + 1;
pCfg->NumOfData = steps + 1; pCfg->NumOfData = steps + 1;
pCfg->RealDataCount = steps; pCfg->RealDataCount = steps;
pCfg->SweepCfg.SweepLog = bTRUE; pCfg->SweepCfg.SweepLog = bTRUE;
pCfg->bParaChanged = bTRUE;
if(AppIMPInit(AppBuff, APPBUFF_SIZE) == AD5940ERR_OK) { // Apply Global Settings
AppIMPCtrl(IMPCTRL_START, 0); pCfg->ShortRe0Se0 = GlobalShortRe0Se0;
} else { pCfg->HstiaRtiaSel = GetHSTIARtia(ConfigHstiaVal);
printf("ERROR: Init Failed\n"); pCfg->RtiaVal = (float)ConfigHstiaVal;
}
pCfg->bParaChanged = bTRUE;
if (AppIMPInit(AppBuff, APPBUFF_SIZE) == AD5940ERR_OK) {
AppIMPCtrl(IMPCTRL_START, 0);
} else {
printf("ERROR: Init Failed\n");
}
} }
void Routine_Amperometric(float bias_mv) { void Routine_Amperometric(float bias_mv) {
if (CurrentMode == MODE_IMPEDANCE) AppIMPCleanup(); if (CurrentMode == MODE_IMPEDANCE)
else if (CurrentMode == MODE_RAMP) AppRAMPCtrl(APPCTRL_SHUTDOWN, 0); AppIMPCleanup();
CurrentMode = MODE_AMPEROMETRIC; else if (CurrentMode == MODE_RAMP)
AppRAMPCtrl(APPCTRL_SHUTDOWN, 0);
CurrentMode = MODE_AMPEROMETRIC;
printf(">> Starting Amperometry (Bias: %.1f mV, LP Range: %d)...\n", bias_mv, ConfigLptiaVal); printf(">> Starting Amperometry (Bias: %.1f mV, LP Range: %d)...\n", bias_mv,
ConfigLptiaVal);
AppAMPCfg_Type *pCfg; AppAMPCfg_Type *pCfg;
AppAMPGetCfg(&pCfg); AppAMPGetCfg(&pCfg);
AD5940AMPStructInit(); // Reload config with current LP settings AD5940AMPStructInit(); // Reload config with current LP settings
pCfg->SensorBias = bias_mv; pCfg->SensorBias = bias_mv;
pCfg->ReDoRtiaCal = bFALSE; // Use pre-calibrated value pCfg->ReDoRtiaCal = bFALSE; // Use pre-calibrated value
if(AppAMPInit(AppBuff, APPBUFF_SIZE) == AD5940ERR_OK) { if (AppAMPInit(AppBuff, APPBUFF_SIZE) == AD5940ERR_OK) {
AppAMPCtrl(AMPCTRL_START, 0); AppAMPCtrl(AMPCTRL_START, 0);
} else { } else {
printf("ERROR: AMP Init Failed\n"); printf("ERROR: AMP Init Failed\n");
} }
} }
void Routine_LSV(float start_mv, float end_mv, int steps, int duration_ms) { void Routine_LSV(float start_mv, float end_mv, int steps, int duration_ms) {
if (CurrentMode == MODE_IMPEDANCE) AppIMPCleanup(); if (CurrentMode == MODE_IMPEDANCE)
else if (CurrentMode == MODE_AMPEROMETRIC) AppAMPCtrl(AMPCTRL_SHUTDOWN, 0); AppIMPCleanup();
CurrentMode = MODE_RAMP; else if (CurrentMode == MODE_AMPEROMETRIC)
AppAMPCtrl(AMPCTRL_SHUTDOWN, 0);
CurrentMode = MODE_RAMP;
printf(">> Starting LSV (%.1f to %.1f mV, %d steps, %d ms, LP Range: %d)...\n", start_mv, end_mv, steps, duration_ms, ConfigLptiaVal); printf(
">> Starting LSV (%.1f to %.1f mV, %d steps, %d ms, LP Range: %d)...\n",
start_mv, end_mv, steps, duration_ms, ConfigLptiaVal);
AppRAMPCfg_Type *pCfg; AppRAMPCfg_Type *pCfg;
AppRAMPGetCfg(&pCfg); AppRAMPGetCfg(&pCfg);
AD5940RampStructInit(); // Reload config with current LP settings AD5940RampStructInit(); // Reload config with current LP settings
pCfg->RampStartVolt = start_mv; pCfg->RampStartVolt = start_mv;
pCfg->RampPeakVolt = end_mv; pCfg->RampPeakVolt = end_mv;
pCfg->StepNumber = steps; pCfg->StepNumber = steps;
pCfg->RampDuration = duration_ms; pCfg->RampDuration = duration_ms;
pCfg->bRampOneDir = bTRUE; pCfg->bRampOneDir = bTRUE;
pCfg->bParaChanged = bTRUE; pCfg->bParaChanged = bTRUE;
if(AppRAMPInit(AppBuff, APPBUFF_SIZE) == AD5940ERR_OK) { if (AppRAMPInit(AppBuff, APPBUFF_SIZE) == AD5940ERR_OK) {
AppRAMPCtrl(APPCTRL_START, 0); AppRAMPCtrl(APPCTRL_START, 0);
} else { } else {
printf("ERROR: RAMP Init Failed\n"); printf("ERROR: RAMP Init Failed\n");
} }
} }
void Routine_CalibrateSystem(void) { void Routine_CalibrateSystem(void) {
if (CurrentMode == MODE_AMPEROMETRIC) AppAMPCtrl(AMPCTRL_SHUTDOWN, 0); if (CurrentMode == MODE_AMPEROMETRIC)
else if (CurrentMode == MODE_RAMP) AppRAMPCtrl(APPCTRL_SHUTDOWN, 0); AppAMPCtrl(AMPCTRL_SHUTDOWN, 0);
CurrentMode = MODE_IMPEDANCE; else if (CurrentMode == MODE_RAMP)
AppRAMPCtrl(APPCTRL_SHUTDOWN, 0);
CurrentMode = MODE_IMPEDANCE;
AppIMPCfg_Type *pCfg; AppIMPCfg_Type *pCfg;
AppIMPGetCfg(&pCfg); AppIMPGetCfg(&pCfg);
AppIMPCleanup(); AppIMPCleanup();
ADCPGACal_Type adcpga_cal; ADCPGACal_Type adcpga_cal;
adcpga_cal.AdcClkFreq = 16000000.0; adcpga_cal.AdcClkFreq = 16000000.0;
adcpga_cal.SysClkFreq = 16000000.0; adcpga_cal.SysClkFreq = 16000000.0;
adcpga_cal.ADCSinc3Osr = ADCSINC3OSR_4; adcpga_cal.ADCSinc3Osr = ADCSINC3OSR_4;
adcpga_cal.ADCSinc2Osr = ADCSINC2OSR_22; adcpga_cal.ADCSinc2Osr = ADCSINC2OSR_22;
adcpga_cal.ADCPga = ADCPGA_1P5; adcpga_cal.ADCPga = ADCPGA_1P5;
adcpga_cal.PGACalType = PGACALTYPE_OFFSET; adcpga_cal.PGACalType = PGACALTYPE_OFFSET;
adcpga_cal.TimeOut10us = 1000; adcpga_cal.TimeOut10us = 1000;
adcpga_cal.VRef1p11 = 1.11; adcpga_cal.VRef1p11 = 1.11;
adcpga_cal.VRef1p82 = 1.82; adcpga_cal.VRef1p82 = 1.82;
printf(">> Calibrating ADC Offset...\n"); printf(">> Calibrating ADC Offset...\n");
AD5940_ADCPGACal(&adcpga_cal); AD5940_ADCPGACal(&adcpga_cal);
// --- 1. Calibrate LPTIA (Low Power Loop) --- // --- 1. Calibrate LPTIA (Low Power Loop) ---
LPRTIACal_Type lprtia_cal; LPRTIACal_Type lprtia_cal;
fImpPol_Type LpRes; fImpPol_Type LpRes;
memset(&lprtia_cal, 0, sizeof(lprtia_cal)); memset(&lprtia_cal, 0, sizeof(lprtia_cal));
lprtia_cal.AdcClkFreq = 16000000.0; lprtia_cal.AdcClkFreq = 16000000.0;
lprtia_cal.SysClkFreq = 16000000.0; lprtia_cal.SysClkFreq = 16000000.0;
lprtia_cal.ADCSinc3Osr = ADCSINC3OSR_4; lprtia_cal.ADCSinc3Osr = ADCSINC3OSR_4;
lprtia_cal.ADCSinc2Osr = ADCSINC2OSR_22; lprtia_cal.ADCSinc2Osr = ADCSINC2OSR_22;
lprtia_cal.bPolarResult = bTRUE; lprtia_cal.bPolarResult = bTRUE;
lprtia_cal.fRcal = 100.0; lprtia_cal.fRcal = 100.0;
lprtia_cal.LpTiaRtia = GetLPTIARtia(ConfigLptiaVal); lprtia_cal.LpTiaRtia = GetLPTIARtia(ConfigLptiaVal);
lprtia_cal.LpAmpPwrMod = LPAMPPWR_NORM; lprtia_cal.LpAmpPwrMod = LPAMPPWR_NORM;
lprtia_cal.bWithCtia = bFALSE; lprtia_cal.bWithCtia = bFALSE;
// Use a low frequency for LPTIA calibration // Use a low frequency for LPTIA calibration
lprtia_cal.fFreq = 100.0f; lprtia_cal.fFreq = 100.0f;
lprtia_cal.DftCfg.DftNum = DFTNUM_2048; lprtia_cal.DftCfg.DftNum = DFTNUM_2048;
lprtia_cal.DftCfg.DftSrc = DFTSRC_SINC3; lprtia_cal.DftCfg.DftSrc = DFTSRC_SINC3;
lprtia_cal.DftCfg.HanWinEn = bTRUE; lprtia_cal.DftCfg.HanWinEn = bTRUE;
printf(">> Calibrating LPTIA %d Ohm...\n", ConfigLptiaVal); printf(">> Calibrating LPTIA %d Ohm...\n", ConfigLptiaVal);
if (AD5940_LPRtiaCal(&lprtia_cal, &LpRes) == AD5940ERR_OK) { if (AD5940_LPRtiaCal(&lprtia_cal, &LpRes) == AD5940ERR_OK) {
printf("Calibrated LPTIA: Mag = %f Ohm, Phase = %f\n", LpRes.Magnitude, LpRes.Phase); printf("Calibrated LPTIA: Mag = %f Ohm, Phase = %f\n", LpRes.Magnitude,
CalibratedLptiaVal = LpRes.Magnitude; LpRes.Phase);
} else { CalibratedLptiaVal = LpRes.Magnitude;
printf("LPTIA Calibration Failed\n"); } else {
} printf("LPTIA Calibration Failed\n");
}
// --- 2. Calibrate HSTIA (High Speed Loop) --- // --- 2. Calibrate HSTIA (High Speed Loop) ---
HSDACCfg_Type hsdac_cfg; HSDACCfg_Type hsdac_cfg;
hsdac_cfg.ExcitBufGain = EXCITBUFGAIN_0P25; hsdac_cfg.ExcitBufGain = EXCITBUFGAIN_0P25;
hsdac_cfg.HsDacGain = HSDACGAIN_0P2; hsdac_cfg.HsDacGain = HSDACGAIN_0P2;
hsdac_cfg.HsDacUpdateRate = 7; hsdac_cfg.HsDacUpdateRate = 7;
AD5940_HSDacCfgS(&hsdac_cfg); AD5940_HSDacCfgS(&hsdac_cfg);
HSRTIACal_Type hsrtia_cal; HSRTIACal_Type hsrtia_cal;
fImpPol_Type HsRes; fImpPol_Type HsRes;
memset(&hsrtia_cal, 0, sizeof(hsrtia_cal)); memset(&hsrtia_cal, 0, sizeof(hsrtia_cal));
hsrtia_cal.fFreq = 1000.0f; hsrtia_cal.fFreq = 1000.0f;
hsrtia_cal.AdcClkFreq = 16000000.0; hsrtia_cal.AdcClkFreq = 16000000.0;
hsrtia_cal.SysClkFreq = 16000000.0; hsrtia_cal.SysClkFreq = 16000000.0;
hsrtia_cal.ADCSinc3Osr = ADCSINC3OSR_4; hsrtia_cal.ADCSinc3Osr = ADCSINC3OSR_4;
hsrtia_cal.ADCSinc2Osr = ADCSINC2OSR_22; hsrtia_cal.ADCSinc2Osr = ADCSINC2OSR_22;
hsrtia_cal.bPolarResult = bTRUE; hsrtia_cal.bPolarResult = bTRUE;
hsrtia_cal.fRcal = 100.0; hsrtia_cal.fRcal = 100.0;
hsrtia_cal.HsTiaCfg.DiodeClose = bFALSE; hsrtia_cal.HsTiaCfg.DiodeClose = bFALSE;
hsrtia_cal.HsTiaCfg.HstiaBias = HSTIABIAS_1P1; hsrtia_cal.HsTiaCfg.HstiaBias = HSTIABIAS_1P1;
hsrtia_cal.HsTiaCfg.HstiaCtia = 31; hsrtia_cal.HsTiaCfg.HstiaCtia = 31;
hsrtia_cal.HsTiaCfg.HstiaRtiaSel = GetHSTIARtia(ConfigHstiaVal); hsrtia_cal.HsTiaCfg.HstiaRtiaSel = GetHSTIARtia(ConfigHstiaVal);
hsrtia_cal.HsTiaCfg.HstiaDeRtia = HSTIADERTIA_OPEN; hsrtia_cal.HsTiaCfg.HstiaDeRtia = HSTIADERTIA_OPEN;
hsrtia_cal.HsTiaCfg.HstiaDeRload = HSTIADERLOAD_OPEN; hsrtia_cal.HsTiaCfg.HstiaDeRload = HSTIADERLOAD_OPEN;
hsrtia_cal.DftCfg.DftNum = DFTNUM_16384; hsrtia_cal.DftCfg.DftNum = DFTNUM_16384;
hsrtia_cal.DftCfg.DftSrc = DFTSRC_SINC3; hsrtia_cal.DftCfg.DftSrc = DFTSRC_SINC3;
printf(">> Calibrating HSTIA %d Ohm...\n", ConfigHstiaVal); printf(">> Calibrating HSTIA %d Ohm...\n", ConfigHstiaVal);
if (AD5940_HSRtiaCal(&hsrtia_cal, &HsRes) == AD5940ERR_OK) { if (AD5940_HSRtiaCal(&hsrtia_cal, &HsRes) == AD5940ERR_OK) {
printf("Calibrated HSTIA: Mag = %f Ohm, Phase = %f\n", HsRes.Magnitude, HsRes.Phase); printf("Calibrated HSTIA: Mag = %f Ohm, Phase = %f\n", HsRes.Magnitude,
CalibratedHstiaVal = HsRes.Magnitude; HsRes.Phase);
} else { CalibratedHstiaVal = HsRes.Magnitude;
printf("HSTIA Calibration Failed\n"); } else {
} printf("HSTIA Calibration Failed\n");
}
} }

415
ad5940.h.shortlist.md Normal file
View File

@ -0,0 +1,415 @@
# Call Graph: ad5940
## Common Infrastructure
> Functions called > 5 times. Shown once here.
### AD5940_ReadAfeResult
└── AD5940_ReadAfeResult
└── #FF4500 **AD5940_ReadReg** ->>
### __AD5940_TakeMeasurement
└── #00FFFF **__AD5940_TakeMeasurement**
├── #008000 **AD5940_AFECtrlS** ->>
├── #FFD700 **AD5940_Delay10us** ->>
├── AD5940_INTCClrFlag ->>
├── AD5940_INTCTestFlag ->>
└── AD5940_ReadAfeResult ->>
### AD5940_HSLoopCfgS
└── AD5940_HSLoopCfgS
├── AD5940_HSDacCfgS
│ └── #FF0000 **AD5940_WriteReg** ->>
├── AD5940_HSTIACfgS
│ ├── #FF0000 **AD5940_WriteReg** ->>
│ └── __AD5940_SetDExRTIA
│ └── #FF0000 **AD5940_WriteReg** ->>
├── AD5940_SWMatrixCfgS
│ └── #FF0000 **AD5940_WriteReg** ->>
└── AD5940_WGCfgS
└── #FF0000 **AD5940_WriteReg** ->>
### AD5940_ADCFilterCfgS
└── AD5940_ADCFilterCfgS
├── #008000 **AD5940_AFECtrlS** ->>
├── #FF4500 **AD5940_ReadReg** ->>
└── #FF0000 **AD5940_WriteReg** ->>
### AD5940_ReadReg
└── #FF4500 **AD5940_ReadReg**
├── AD5940_D2DReadReg
├── AD5940_SEQReadReg
│ ├── AD5940_SEQGenGetRegDefault
│ │ ├── AD5940_D2DReadReg
│ │ └── AD5940_SPIReadReg
│ │ ├── AD5940_CsClr ->>
│ │ ├── AD5940_CsSet ->>
│ │ ├── AD5940_ReadWrite16B ->>
│ │ ├── AD5940_ReadWrite32B ->>
│ │ └── AD5940_ReadWrite8B ->>
│ ├── AD5940_SEQGenSearchReg
│ └── AD5940_SEQRegInfoInsert
└── AD5940_SPIReadReg
├── AD5940_CsClr ->>
├── AD5940_CsSet ->>
├── AD5940_ReadWrite16B ->>
├── AD5940_ReadWrite32B ->>
└── AD5940_ReadWrite8B ->>
### AD5940_WriteReg
└── #FF0000 **AD5940_WriteReg**
├── AD5940_D2DWriteReg
├── AD5940_SEQWriteReg
│ ├── AD5940_SEQGenInsert
│ ├── AD5940_SEQGenSearchReg
│ └── AD5940_SEQRegInfoInsert
└── AD5940_SPIWriteReg
├── AD5940_CsClr ->>
├── AD5940_CsSet ->>
├── AD5940_ReadWrite16B ->>
├── AD5940_ReadWrite32B ->>
└── AD5940_ReadWrite8B ->>
### AD5940_ADCMuxCfgS
└── AD5940_ADCMuxCfgS
├── #FF4500 **AD5940_ReadReg** ->>
└── #FF0000 **AD5940_WriteReg** ->>
### AD5940_INTCGetCfg
└── AD5940_INTCGetCfg
└── #FF4500 **AD5940_ReadReg** ->>
### AD5940_AFECtrlS
└── #008000 **AD5940_AFECtrlS**
├── #FF4500 **AD5940_ReadReg** ->>
└── #FF0000 **AD5940_WriteReg** ->>
### AD5940_INTCCfg
└── #0000FF **AD5940_INTCCfg**
├── #FF4500 **AD5940_ReadReg** ->>
└── #FF0000 **AD5940_WriteReg** ->>
### AD5940_ReadWrite16B
└── AD5940_ReadWrite16B
└── AD5940_ReadWriteNBytes
### AD5940_ReadWrite8B
└── AD5940_ReadWrite8B
└── AD5940_ReadWriteNBytes
### __AD5940_ReferenceON
└── __AD5940_ReferenceON
└── AD5940_REFCfgS
├── #FF4500 **AD5940_ReadReg** ->>
└── #FF0000 **AD5940_WriteReg** ->>
### AD5940_INTCTestFlag
└── AD5940_INTCTestFlag
└── #FF4500 **AD5940_ReadReg** ->>
### AD5940_INTCClrFlag
└── AD5940_INTCClrFlag
└── #FF0000 **AD5940_WriteReg** ->>
### AD5940_ADCBaseCfgS
└── #8B00FF **AD5940_ADCBaseCfgS**
└── #FF0000 **AD5940_WriteReg** ->>
### AD5940_ReadWrite32B
└── AD5940_ReadWrite32B
└── AD5940_ReadWriteNBytes
## Execution Tree
└── AD5940_ADCPGACal
├── #8B00FF **AD5940_ADCBaseCfgS** ->>
├── #008000 **AD5940_AFECtrlS** ->>
├── #FFD700 **AD5940_Delay10us** ->>
├── #0000FF **AD5940_INTCCfg** ->>
├── #FF4500 **AD5940_ReadReg** ->>
├── #FF0000 **AD5940_WriteReg** ->>
├── #00FFFF **__AD5940_TakeMeasurement** ->>
├── AD5940_ADCConvtCtrlS
│ ├── #FF4500 **AD5940_ReadReg** ->>
│ └── #FF0000 **AD5940_WriteReg** ->>
├── AD5940_ADCFilterCfgS ->>
├── AD5940_HSLoopCfgS ->>
├── AD5940_INTCGetCfg ->>
└── __AD5940_ReferenceON ->>
└── AD5940_ADCPowerCtrlS
├── #FF4500 **AD5940_ReadReg** ->>
└── #FF0000 **AD5940_WriteReg** ->>
└── AD5940_ADCRepeatCfgS
└── #FF0000 **AD5940_WriteReg** ->>
└── AD5940_AGPIOCfg
├── #FF0000 **AD5940_WriteReg** ->>
├── AD5940_AGPIOFuncCfg
│ └── #FF0000 **AD5940_WriteReg** ->>
├── AD5940_AGPIOIen
│ └── #FF0000 **AD5940_WriteReg** ->>
├── AD5940_AGPIOOen
│ └── #FF0000 **AD5940_WriteReg** ->>
└── AD5940_AGPIOPen
└── #FF0000 **AD5940_WriteReg** ->>
└── AD5940_AGPIOClr
└── #FF0000 **AD5940_WriteReg** ->>
└── AD5940_AGPIOIn
└── #FF4500 **AD5940_ReadReg** ->>
└── AD5940_AGPIOSet
└── #FF0000 **AD5940_WriteReg** ->>
└── AD5940_AGPIOToggle
└── #FF0000 **AD5940_WriteReg** ->>
└── AD5940_ClksCalculate
├── AD5940_Notch50HzAvailable
│ └── _is_value_in_table ->>
└── AD5940_Notch60HzAvailable
└── _is_value_in_table ->>
└── AD5940_FIFOCfg
├── #FF4500 **AD5940_ReadReg** ->>
└── #FF0000 **AD5940_WriteReg** ->>
└── AD5940_FIFOCtrlS
└── #FF0000 **AD5940_WriteReg** ->>
└── AD5940_FIFOGetCfg
└── #FF4500 **AD5940_ReadReg** ->>
└── AD5940_FIFOGetCnt
└── #FF4500 **AD5940_ReadReg** ->>
└── AD5940_FIFORd
├── AD5940_CsClr ->>
├── AD5940_CsSet ->>
├── AD5940_ReadWrite16B ->>
├── AD5940_ReadWrite32B ->>
└── AD5940_ReadWrite8B ->>
└── AD5940_FIFOThrshSet
└── #FF0000 **AD5940_WriteReg** ->>
└── AD5940_GetADIID
└── #FF4500 **AD5940_ReadReg** ->>
└── AD5940_GetChipID
└── #FF4500 **AD5940_ReadReg** ->>
└── AD5940_HPModeEn
├── #FF4500 **AD5940_ReadReg** ->>
├── AD5940_AFEPwrBW
│ └── #FF0000 **AD5940_WriteReg** ->>
└── AD5940_CLKCfg
├── #FFD700 **AD5940_Delay10us** ->>
├── #FF4500 **AD5940_ReadReg** ->>
├── #FF0000 **AD5940_WriteReg** ->>
└── AD5940_HFOSC32MHzCtrl
├── #FF4500 **AD5940_ReadReg** ->>
└── #FF0000 **AD5940_WriteReg** ->>
└── AD5940_HSDACCal
├── #8B00FF **AD5940_ADCBaseCfgS** ->>
├── #008000 **AD5940_AFECtrlS** ->>
├── #FFD700 **AD5940_Delay10us** ->>
├── #0000FF **AD5940_INTCCfg** ->>
├── #FF0000 **AD5940_WriteReg** ->>
├── #00FFFF **__AD5940_TakeMeasurement** ->>
├── AD5940_ADCCode2Volt
├── AD5940_ADCConvtCtrlS
│ ├── #FF4500 **AD5940_ReadReg** ->>
│ └── #FF0000 **AD5940_WriteReg** ->>
├── AD5940_ADCFilterCfgS ->>
├── AD5940_HSLoopCfgS ->>
├── AD5940_LPLoopCfgS
│ ├── AD5940_LPAMPCfgS
│ │ └── #FF0000 **AD5940_WriteReg** ->>
│ └── AD5940_LPDACCfgS
│ ├── #FF0000 **AD5940_WriteReg** ->>
│ ├── AD5940_LPDAC0WriteS
│ │ └── #FF0000 **AD5940_WriteReg** ->>
│ └── AD5940_LPDAC1WriteS
│ └── #FF0000 **AD5940_WriteReg** ->>
└── __AD5940_ReferenceON ->>
└── AD5940_HSRTIACfgS
├── #FF4500 **AD5940_ReadReg** ->>
└── #FF0000 **AD5940_WriteReg** ->>
└── AD5940_HSRtiaCal
├── #008000 **AD5940_AFECtrlS** ->>
├── #FFD700 **AD5940_Delay10us** ->>
├── #0000FF **AD5940_INTCCfg** ->>
├── AD5940_ADCMuxCfgS ->>
├── AD5940_ComplexDivInt
├── AD5940_ComplexMag
├── AD5940_ComplexPhase
├── AD5940_DSPCfgS
│ ├── #8B00FF **AD5940_ADCBaseCfgS** ->>
│ ├── AD5940_ADCDigCompCfgS
│ │ └── #FF0000 **AD5940_WriteReg** ->>
│ ├── AD5940_ADCFilterCfgS ->>
│ ├── AD5940_DFTCfgS
│ │ ├── #FF4500 **AD5940_ReadReg** ->>
│ │ └── #FF0000 **AD5940_WriteReg** ->>
│ └── AD5940_StatisticCfgS
│ └── #FF0000 **AD5940_WriteReg** ->>
├── AD5940_HSLoopCfgS ->>
├── AD5940_INTCClrFlag ->>
├── AD5940_INTCGetCfg ->>
├── AD5940_INTCTestFlag ->>
├── AD5940_REFCfgS
│ ├── #FF4500 **AD5940_ReadReg** ->>
│ └── #FF0000 **AD5940_WriteReg** ->>
├── AD5940_ReadAfeResult ->>
├── AD5940_StructInit ->>
└── AD5940_WGFreqWordCal
└── AD5940_HWReset
├── #FFD700 **AD5940_Delay10us** ->>
├── AD5940_RstClr
└── AD5940_RstSet
└── AD5940_INTCGetFlag
└── #FF4500 **AD5940_ReadReg** ->>
└── AD5940_Initialize
├── #FF4500 **AD5940_ReadReg** ->>
├── #FF0000 **AD5940_WriteReg** ->>
└── AD5940_CsSet ->>
└── AD5940_LFOSCMeasure
├── #0000FF **AD5940_INTCCfg** ->>
├── AD5940_INTCClrFlag ->>
├── AD5940_INTCGetCfg ->>
├── AD5940_INTCTestFlag ->>
├── AD5940_SEQCfg
│ ├── #FF4500 **AD5940_ReadReg** ->>
│ └── #FF0000 **AD5940_WriteReg** ->>
├── AD5940_SEQCtrlS
│ ├── #FF4500 **AD5940_ReadReg** ->>
│ └── #FF0000 **AD5940_WriteReg** ->>
├── AD5940_SEQGetCfg
│ └── #FF4500 **AD5940_ReadReg** ->>
├── AD5940_SEQInfoCfg
│ ├── #FF0000 **AD5940_WriteReg** ->>
│ └── AD5940_SEQCmdWrite
│ └── #FF0000 **AD5940_WriteReg** ->>
├── AD5940_SEQTimeOutRd
│ └── #FF4500 **AD5940_ReadReg** ->>
├── AD5940_WUPTCfg
│ └── #FF0000 **AD5940_WriteReg** ->>
├── AD5940_WUPTCtrl
│ ├── #FF4500 **AD5940_ReadReg** ->>
│ └── #FF0000 **AD5940_WriteReg** ->>
└── AD5940_WUPTTime
└── #FF0000 **AD5940_WriteReg** ->>
└── AD5940_LPDACCal
├── #8B00FF **AD5940_ADCBaseCfgS** ->>
├── #008000 **AD5940_AFECtrlS** ->>
├── #FFD700 **AD5940_Delay10us** ->>
├── #0000FF **AD5940_INTCCfg** ->>
├── #00FFFF **__AD5940_TakeMeasurement** ->>
├── AD5940_ADCConvtCtrlS
│ ├── #FF4500 **AD5940_ReadReg** ->>
│ └── #FF0000 **AD5940_WriteReg** ->>
├── AD5940_ADCFilterCfgS ->>
├── AD5940_ADCMuxCfgS ->>
├── AD5940_INTCGetCfg ->>
├── AD5940_LPDACCfgS
│ ├── #FF0000 **AD5940_WriteReg** ->>
│ ├── AD5940_LPDAC0WriteS
│ │ └── #FF0000 **AD5940_WriteReg** ->>
│ └── AD5940_LPDAC1WriteS
│ └── #FF0000 **AD5940_WriteReg** ->>
├── AD5940_LPDACWriteS
│ └── #FF0000 **AD5940_WriteReg** ->>
└── __AD5940_ReferenceON ->>
└── AD5940_LPModeClkS
└── #FF0000 **AD5940_WriteReg** ->>
└── AD5940_LPModeCtrlS
├── #FF4500 **AD5940_ReadReg** ->>
└── #FF0000 **AD5940_WriteReg** ->>
└── AD5940_LPModeEnS
└── #FF0000 **AD5940_WriteReg** ->>
└── AD5940_LPRtiaCal
├── #8B00FF **AD5940_ADCBaseCfgS** ->>
├── #008000 **AD5940_AFECtrlS** ->>
├── #FFD700 **AD5940_Delay10us** ->>
├── #0000FF **AD5940_INTCCfg** ->>
├── #FF4500 **AD5940_ReadReg** ->>
├── #FF0000 **AD5940_WriteReg** ->>
├── #00FFFF **__AD5940_TakeMeasurement** ->>
├── AD5940_ComplexDivInt
├── AD5940_ComplexMag
├── AD5940_ComplexPhase
├── AD5940_DSPCfgS
│ ├── #8B00FF **AD5940_ADCBaseCfgS** ->>
│ ├── AD5940_ADCDigCompCfgS
│ │ └── #FF0000 **AD5940_WriteReg** ->>
│ ├── AD5940_ADCFilterCfgS ->>
│ ├── AD5940_DFTCfgS
│ │ ├── #FF4500 **AD5940_ReadReg** ->>
│ │ └── #FF0000 **AD5940_WriteReg** ->>
│ └── AD5940_StatisticCfgS
│ └── #FF0000 **AD5940_WriteReg** ->>
├── AD5940_HSLoopCfgS ->>
├── AD5940_INTCClrFlag ->>
├── AD5940_INTCGetCfg ->>
├── AD5940_INTCTestFlag ->>
├── AD5940_LPLoopCfgS
│ ├── AD5940_LPAMPCfgS
│ │ └── #FF0000 **AD5940_WriteReg** ->>
│ └── AD5940_LPDACCfgS
│ ├── #FF0000 **AD5940_WriteReg** ->>
│ ├── AD5940_LPDAC0WriteS
│ │ └── #FF0000 **AD5940_WriteReg** ->>
│ └── AD5940_LPDAC1WriteS
│ └── #FF0000 **AD5940_WriteReg** ->>
├── AD5940_ReadAfeResult ->>
├── AD5940_SWMatrixCfgS
│ └── #FF0000 **AD5940_WriteReg** ->>
├── AD5940_StructInit ->>
├── AD5940_WGDACCodeS
│ └── #FF0000 **AD5940_WriteReg** ->>
├── AD5940_WGFreqWordCal
└── __AD5940_ReferenceON ->>
└── AD5940_LPTIAOffsetCal
├── #8B00FF **AD5940_ADCBaseCfgS** ->>
├── #008000 **AD5940_AFECtrlS** ->>
├── #FFD700 **AD5940_Delay10us** ->>
├── #0000FF **AD5940_INTCCfg** ->>
├── #FF0000 **AD5940_WriteReg** ->>
├── #00FFFF **__AD5940_TakeMeasurement** ->>
├── AD5940_ADCConvtCtrlS
│ ├── #FF4500 **AD5940_ReadReg** ->>
│ └── #FF0000 **AD5940_WriteReg** ->>
├── AD5940_ADCFilterCfgS ->>
├── AD5940_INTCGetCfg ->>
├── AD5940_LPLoopCfgS
│ ├── AD5940_LPAMPCfgS
│ │ └── #FF0000 **AD5940_WriteReg** ->>
│ └── AD5940_LPDACCfgS
│ ├── #FF0000 **AD5940_WriteReg** ->>
│ ├── AD5940_LPDAC0WriteS
│ │ └── #FF0000 **AD5940_WriteReg** ->>
│ └── AD5940_LPDAC1WriteS
│ └── #FF0000 **AD5940_WriteReg** ->>
└── __AD5940_ReferenceON ->>
└── AD5940_SEQGpioCtrlS
└── #FF0000 **AD5940_WriteReg** ->>
└── AD5940_SEQGpioTrigCfg
├── #FF4500 **AD5940_ReadReg** ->>
└── #FF0000 **AD5940_WriteReg** ->>
└── AD5940_SEQHaltS
└── #FF0000 **AD5940_WriteReg** ->>
└── AD5940_SEQInfoGet
└── #FF4500 **AD5940_ReadReg** ->>
└── AD5940_SEQMmrTrig
└── #FF0000 **AD5940_WriteReg** ->>
└── AD5940_ShutDownS
├── AD5940_EnterSleepS
│ └── #FF0000 **AD5940_WriteReg** ->>
├── AD5940_LPLoopCfgS
│ ├── AD5940_LPAMPCfgS
│ │ └── #FF0000 **AD5940_WriteReg** ->>
│ └── AD5940_LPDACCfgS
│ ├── #FF0000 **AD5940_WriteReg** ->>
│ ├── AD5940_LPDAC0WriteS
│ │ └── #FF0000 **AD5940_WriteReg** ->>
│ └── AD5940_LPDAC1WriteS
│ └── #FF0000 **AD5940_WriteReg** ->>
├── AD5940_REFCfgS
│ ├── #FF4500 **AD5940_ReadReg** ->>
│ └── #FF0000 **AD5940_WriteReg** ->>
├── AD5940_SleepKeyCtrlS
│ └── #FF0000 **AD5940_WriteReg** ->>
└── AD5940_StructInit ->>
└── AD5940_SoftRst
├── #FFD700 **AD5940_Delay10us** ->>
└── #FF0000 **AD5940_WriteReg** ->>
└── AD5940_WGFreqCtrlS
├── #FF0000 **AD5940_WriteReg** ->>
└── AD5940_WGFreqWordCal
└── AD5940_WakeUp
└── #FF4500 **AD5940_ReadReg** ->>

View File

@ -1,103 +0,0 @@
/*!
*****************************************************************************
@file: AD5940_ADCMeanFIFO.c
@author: $Author: nxu2 $
@brief: Use FIFO to read statistic block mean result.
@version: $Revision: 766 $
@date: $Date: 2017-08-21 14:09:35 +0100 (Mon, 21 Aug 2017) $
-----------------------------------------------------------------------------
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.
*****************************************************************************/
/** @addtogroup AD5940_Standard_Examples
* @{
@defgroup ADC_MEAN_FIFO_Example
@{
*/
#include "ad5940.h"
#include <stdio.h>
uint32_t ADCBuff[256];
void AD5940_Main(void)
{
ADCBaseCfg_Type adc_base;
ADCFilterCfg_Type adc_filter;
StatCfg_Type stat_cfg;
FIFOCfg_Type fifo_cfg;
/* Use hardware reset */
AD5940_HWReset();
/* Firstly call this function after reset to initialize AFE registers. */
AD5940_Initialize();
/* Configure AFE power mode and bandwidth */
AD5940_AFEPwrBW(AFEPWR_LP, AFEBW_250KHZ);
/* Initialize ADC basic function */
adc_base.ADCMuxP = ADCMUXP_AVDD_2;
adc_base.ADCMuxN = ADCMUXN_VSET1P1;
adc_base.ADCPga = ADCPGA_1;
AD5940_ADCBaseCfgS(&adc_base);
/* Initialize ADC filters ADCRawData-->SINC3-->SINC2+NOTCH-->StatisticBlock */
adc_filter.ADCSinc3Osr = ADCSINC3OSR_4;
adc_filter.ADCSinc2Osr = ADCSINC2OSR_1333;
adc_filter.ADCAvgNum = ADCAVGNUM_2; /* Don't care about it. Average function is only used for DFT */
adc_filter.ADCRate = ADCRATE_800KHZ; /* If ADC clock is 32MHz, then set it to ADCRATE_1P6MHZ. Default is 16MHz, use ADCRATE_800KHZ. */
adc_filter.BpNotch = bTRUE; /* SINC2+Notch is one block, when bypass notch filter, we can get fresh data from SINC2 filter. */
adc_filter.BpSinc3 = bFALSE; /* We use SINC3 filter. */
adc_filter.Sinc2NotchEnable = bTRUE; /* Enable the SINC2+Notch block. You can also use function AD5940_AFECtrlS */
AD5940_ADCFilterCfgS(&adc_filter);
/**
* Statistic block receive data from SINC2+Notch block. Note the diagram in datasheet page 51 PrM.
* The SINC3 can be bypassed optionally. SINC2 cannot be bypassed.
* */
stat_cfg.StatDev = STATDEV_1; /* Not used. */
stat_cfg.StatEnable = bTRUE;
stat_cfg.StatSample = STATSAMPLE_128; /* Sample 128 points and calculate mean. */
AD5940_StatisticCfgS(&stat_cfg);
fifo_cfg.FIFOEn = bTRUE;
fifo_cfg.FIFOMode = FIFOMODE_FIFO;
fifo_cfg.FIFOSize = FIFOSIZE_4KB;
fifo_cfg.FIFOSrc = FIFOSRC_MEAN;
fifo_cfg.FIFOThresh = 2;
AD5940_FIFOCfg(&fifo_cfg);
/* Enable all interrupt at Interrupt Controller 1. So we can check the interrupt flag */
AD5940_INTCCfg(AFEINTC_1, AFEINTSRC_ALLINT, bTRUE);
AD5940_INTCCfg(AFEINTC_0, AFEINTSRC_DATAFIFOTHRESH, bTRUE); /* Enable FIFO threshold interrupt. */
AD5940_INTCClrFlag(AFEINTSRC_ALLINT);
AD5940_ClrMCUIntFlag(); /* Clear the MCU interrupt flag which will be set in ISR. */
AD5940_AFECtrlS(AFECTRL_ADCPWR|AFECTRL_SINC2NOTCH, bTRUE);
AD5940_AFECtrlS(AFECTRL_ADCCNV, bTRUE);
while(1)
{
uint32_t FifoCnt;
if(AD5940_GetMCUIntFlag())
{
AD5940_ClrMCUIntFlag(); /* Clear this flag */
if(AD5940_INTCTestFlag(AFEINTC_0, AFEINTSRC_DATAFIFOTHRESH) == bTRUE)
{
FifoCnt = AD5940_FIFOGetCnt();
AD5940_FIFORd((uint32_t *)ADCBuff, FifoCnt);
AD5940_INTCClrFlag(AFEINTSRC_DATAFIFOTHRESH);
printf("Get %d data, ADC Code[0]:%d\n",FifoCnt, ADCBuff[0]&0xffff);
/*!!!!!NOTE!!!!!*/
/* The mean result already removed 32768. So to calculate the voltage, assume mean result is n, use below equation.
Voltage = n/32768*Vref
*/
}
}
}
}
/**
* @}
* @}
* */

View File

@ -1,205 +0,0 @@
/*!
*****************************************************************************
@file: AD5940_ADCNotchTest.c
@author: Neo Xu
@brief: Notch filter test.
-----------------------------------------------------------------------------
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.
*****************************************************************************/
/** @addtogroup AD5940_Standard_Examples
* @{
@defgroup ADC_Notch_Test_Example
@{
*/
#include "ad5940.h"
#include <stdio.h>
#ifdef ADI_DEBUG
#undef ADI_DEBUG
#endif
void ad5940_sequencer_init(uint8_t adc_rate, uint8_t sinc3osr, uint8_t sinc2osr){
FIFOCfg_Type fifo_cfg;
SEQCfg_Type seq_cfg;
/* Step2. Configure FIFO and Sequencer*/
fifo_cfg.FIFOEn = bFALSE;
fifo_cfg.FIFOMode = FIFOMODE_FIFO;
fifo_cfg.FIFOSize = FIFOSIZE_4KB; /* 4kB for FIFO, The reset 2kB for sequencer */
fifo_cfg.FIFOSrc = FIFOSRC_SINC2NOTCH;
fifo_cfg.FIFOThresh = 1;
AD5940_FIFOCfg(&fifo_cfg); /* Disable to reset FIFO. */
fifo_cfg.FIFOEn = bTRUE;
AD5940_FIFOCfg(&fifo_cfg); /* Enable FIFO here */
/* Configure sequencer and stop it */
seq_cfg.SeqMemSize = SEQMEMSIZE_2KB;
seq_cfg.SeqBreakEn = bFALSE;
seq_cfg.SeqIgnoreEn = bFALSE;
seq_cfg.SeqCntCRCClr = bTRUE;
seq_cfg.SeqEnable = bFALSE;
seq_cfg.SeqWrTimer = 0;
AD5940_SEQCfg(&seq_cfg);
uint32_t WaitClks;
uint8_t dl_60, dl_50, dl=0;
ADCFilterCfg_Type filter;
filter.ADCSinc3Osr = sinc3osr;
filter.ADCSinc2Osr = sinc2osr;
filter.ADCRate = adc_rate;
const uint32_t sinc2osr_table[] = {22,44,89,178,267,533,640,667,800,889,1067,1333,0};
const uint32_t sinc3osr_table[] = {5,4,2,0};
printf("SINC3:OSR%d, SINC2:OSR%d, ", sinc3osr_table[sinc3osr], sinc2osr_table[sinc2osr]);
if(AD5940_Notch50HzAvailable(&filter, &dl_50)){
printf("NOTCH50: DL:%d, %dHz ", dl_50, (uint32_t)((adc_rate==ADCRATE_1P6MHZ?1.6e6:800000.0)/sinc3osr_table[sinc3osr]/sinc2osr_table[sinc2osr]/dl_50 + .5));
dl += dl_50-1;
}
if(AD5940_Notch60HzAvailable(&filter, &dl_60)){
printf("NOTCH60: DL:%d, %dHz ", dl_60, (uint32_t)((adc_rate==ADCRATE_1P6MHZ?1.6e6:800000.0)/sinc3osr_table[sinc3osr]/sinc2osr_table[sinc2osr]/dl_60 + .5));
dl += dl_60-1;
}
ClksCalInfo_Type clks_cal;
clks_cal.DataType = DATATYPE_NOTCH;
clks_cal.ADCRate = adc_rate;
clks_cal.DataCount = 1; /* Sample one data when wakeup */
clks_cal.ADCSinc2Osr = sinc2osr;
clks_cal.ADCSinc3Osr = sinc3osr;
clks_cal.ADCAvgNum = 0;
clks_cal.RatioSys2AdcClk = adc_rate==ADCRATE_1P6MHZ?.5:1;
AD5940_ClksCalculate(&clks_cal, &WaitClks);
static uint32_t buff[128];
AD5940_SEQGenInit(buff, 128);
AD5940_SEQGenCtrl(bTRUE);
AD5940_SEQGpioCtrlS(AGPIO_Pin1);
AD5940_AFECtrlS(AFECTRL_ADCPWR, bTRUE);
AD5940_SEQGenInsert(SEQ_WAIT(16*250));
AD5940_AFECtrlS(AFECTRL_ADCCNV|AFECTRL_SINC2NOTCH, bTRUE); /* Start ADC convert */
AD5940_SEQGenInsert(SEQ_WAIT(WaitClks));
//wait for first data ready
AD5940_AFECtrlS(AFECTRL_ADCCNV|AFECTRL_ADCPWR|AFECTRL_SINC2NOTCH, bFALSE); /* Stop ADC convert and DFT */
AD5940_SEQGpioCtrlS(0);
AD5940_SEQGenCtrl(bFALSE); /* Stop sequencer generator */
SEQInfo_Type seqinfo;
AD5940_SEQGenFetchSeq(&seqinfo.pSeqCmd, &seqinfo.SeqLen);
seqinfo.SeqId = SEQID_0;
seqinfo.SeqRamAddr = 0;
seqinfo.WriteSRAM = bTRUE;
AD5940_SEQInfoCfg(&seqinfo);
AGPIOCfg_Type gpio_cfg;
gpio_cfg.FuncSet = GP6_SYNC|GP5_SYNC|GP2_TRIG|GP1_SYNC|GP0_INT;
gpio_cfg.InputEnSet = AGPIO_Pin2;
gpio_cfg.OutputEnSet = AGPIO_Pin0|AGPIO_Pin1|AGPIO_Pin5|AGPIO_Pin6;
gpio_cfg.OutVal = 0;
gpio_cfg.PullEnSet = AGPIO_Pin2;
AD5940_AGPIOCfg(&gpio_cfg);
}
uint32_t ad5940_notch_test(uint8_t adc_rate, uint8_t sinc3osr, uint8_t sinc2osr){
ADCBaseCfg_Type adc_base;
ADCFilterCfg_Type adc_filter;
/* Use hardware reset */
AD5940_HWReset();
/* Firstly call this function after reset to initialize AFE registers. */
AD5940_Initialize();
CLKCfg_Type clk_cfg;
clk_cfg.ADCClkDiv = ADCCLKDIV_1;
clk_cfg.ADCCLkSrc = ADCCLKSRC_HFOSC;
clk_cfg.SysClkDiv = adc_rate==ADCRATE_1P6MHZ?SYSCLKDIV_2:SYSCLKDIV_1;
clk_cfg.SysClkSrc = SYSCLKSRC_HFOSC;
clk_cfg.HfOSC32MHzMode = adc_rate==ADCRATE_1P6MHZ?bTRUE:bFALSE;
clk_cfg.HFOSCEn = bTRUE;
clk_cfg.HFXTALEn = bFALSE;
clk_cfg.LFOSCEn = bTRUE;
AD5940_CLKCfg(&clk_cfg);
/* Configure AFE power mode and bandwidth */
AD5940_AFEPwrBW(AFEPWR_LP, AFEBW_250KHZ);
/* Initialize ADC basic function */
adc_base.ADCMuxP = ADCMUXP_VREF1P8DAC;
adc_base.ADCMuxN = ADCMUXN_VSET1P1;
adc_base.ADCPga = ADCPGA_1P5;
AD5940_ADCBaseCfgS(&adc_base);
AD5940_AFECtrlS(AFECTRL_DACREFPWR|AFECTRL_HSDACPWR, bTRUE);
/* Initialize ADC filters ADCRawData-->SINC3-->SINC2+NOTCH */
adc_filter.ADCSinc3Osr = sinc3osr;
adc_filter.ADCSinc2Osr = sinc2osr;
adc_filter.ADCAvgNum = ADCAVGNUM_2; /* Don't care about it. Average function is only used for DFT */
adc_filter.ADCRate = adc_rate; /* If ADC clock is 32MHz, then set it to ADCRATE_1P6MHZ. Default is 16MHz, use ADCRATE_800KHZ. */
adc_filter.BpNotch = bFALSE; /* SINC2+Notch is one block, when bypass notch filter, we can get fresh data from SINC2 filter. */
adc_filter.BpSinc3 = bFALSE; /* We use SINC3 filter. */
adc_filter.Sinc2NotchEnable = bTRUE; /* Enable the SINC2+Notch block. You can also use function AD5940_AFECtrlS */
AD5940_ADCFilterCfgS(&adc_filter);
/* Enable all interrupt at Interrupt Controller 1. So we can check the interrupt flag */
AD5940_INTCCfg(AFEINTC_1, AFEINTSRC_ALLINT, bTRUE);
AD5940_INTCCfg(AFEINTC_0, AFEINTSRC_DATAFIFOTHRESH, bTRUE);
ad5940_sequencer_init(adc_rate, sinc3osr, sinc2osr);
AD5940_INTCClrFlag(AFEINTSRC_ALLINT);
AD5940_SEQCtrlS(bTRUE);
AD5940_ClrMCUIntFlag();
AD5940_SEQMmrTrig(SEQID_0);
while(1)
{
{int32_t i = 1000000;while(i--);}
if(AD5940_GetMCUIntFlag())
{
AD5940_ClrMCUIntFlag();
uint32_t fifo_count = AD5940_FIFOGetCnt();
if(fifo_count == 1){
int32_t rd;
AD5940_FIFORd((uint32_t*)&rd, 1);
rd &= 0xffff;
float volt = AD5940_ADCCode2Volt(rd, ADCPGA_1P5, 1.82)+1.11;
volt -= 1.82;
if(volt < 0) volt = -volt;
if(volt > 0.0005){
printf("FAILED:CODE:rd:%d\n", rd);
return 1;
}
printf("PASS\n");
return 0;
}
else{
printf("FAILED:%d\n", fifo_count);
return 1;
}
}
}
}
void AD5940_Main(void)
{
uint32_t failed = 0;
uint8_t sinc3=0, sinc2=0;
uint8_t adc_rate=0;
for(;adc_rate<=1;adc_rate++){
sinc3=0;
for(;sinc3<=ADCSINC3OSR_2;sinc3++){
sinc2=0;
for(;sinc2<=ADCSINC2OSR_1333;sinc2++){
failed |= ad5940_notch_test(adc_rate, sinc3, sinc2);
}
}
}
printf("Test Done with status: %s\n",failed?"FAILED":"SUCCEED");
while(1);
}
/**
* @}
* @}
* */

View File

@ -1,110 +0,0 @@
/*!
*****************************************************************************
@file: AD5940_ADCPolling.c
@author: $Author: nxu2 $
@brief: ADC Polling mode example
@version: $Revision: 766 $
@date: $Date: 2017-08-21 14:09:35 +0100 (Mon, 21 Aug 2017) $
-----------------------------------------------------------------------------
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.
*****************************************************************************/
/** @addtogroup AD5940_Standard_Examples
* @{
@defgroup ADC_Polling_Example
@{
*/
#include "ad5940.h"
#include <stdio.h>
#define ADCPGA_GAIN_SEL ADCPGA_1P5
static void AD5940_PGA_Calibration(void){
AD5940Err err;
ADCPGACal_Type pgacal;
pgacal.AdcClkFreq = 16e6;
pgacal.ADCSinc2Osr = ADCSINC2OSR_178;
pgacal.ADCSinc3Osr = ADCSINC3OSR_4;
pgacal.SysClkFreq = 16e6;
pgacal.TimeOut10us = 1000;
pgacal.VRef1p11 = 1.11f;
pgacal.VRef1p82 = 1.82f;
pgacal.PGACalType = PGACALTYPE_OFFSETGAIN;
pgacal.ADCPga = ADCPGA_GAIN_SEL;
err = AD5940_ADCPGACal(&pgacal);
if(err != AD5940ERR_OK){
printf("AD5940 PGA calibration failed.");
}
}
void AD5940_Main(void)
{
ADCBaseCfg_Type adc_base;
ADCFilterCfg_Type adc_filter;
/* Use hardware reset */
AD5940_HWReset();
/* Firstly call this function after reset to initialize AFE registers. */
AD5940_Initialize();
AD5940_PGA_Calibration();
/* Configure AFE power mode and bandwidth */
AD5940_AFEPwrBW(AFEPWR_LP, AFEBW_250KHZ);
/* Initialize ADC basic function */
AD5940_AFECtrlS(AFECTRL_DACREFPWR|AFECTRL_HSDACPWR, bTRUE); //We are going to measure DAC 1.82V reference.
adc_base.ADCMuxP = ADCMUXP_VREF1P8DAC;
adc_base.ADCMuxN = ADCMUXN_VSET1P1;
adc_base.ADCPga = ADCPGA_GAIN_SEL;
AD5940_ADCBaseCfgS(&adc_base);
/* Initialize ADC filters ADCRawData-->SINC3-->SINC2+NOTCH */
adc_filter.ADCSinc3Osr = ADCSINC3OSR_4;
adc_filter.ADCSinc2Osr = ADCSINC2OSR_1333;
adc_filter.ADCAvgNum = ADCAVGNUM_2; /* Don't care about it. Average function is only used for DFT */
adc_filter.ADCRate = ADCRATE_800KHZ; /* If ADC clock is 32MHz, then set it to ADCRATE_1P6MHZ. Default is 16MHz, use ADCRATE_800KHZ. */
adc_filter.BpNotch = bTRUE; /* SINC2+Notch is one block, when bypass notch filter, we can get fresh data from SINC2 filter. */
adc_filter.BpSinc3 = bFALSE; /* We use SINC3 filter. */
adc_filter.Sinc2NotchEnable = bTRUE; /* Enable the SINC2+Notch block. You can also use function AD5940_AFECtrlS */
AD5940_ADCFilterCfgS(&adc_filter);
//AD5940_ADCMuxCfgS(ADCMUXP_AIN2, ADCMUXN_VSET1P1); /* Optionally, you can change ADC MUX with this function */
/* Enable all interrupt at Interrupt Controller 1. So we can check the interrupt flag */
AD5940_INTCCfg(AFEINTC_1, AFEINTSRC_ALLINT, bTRUE);
//AD5940_AFECtrlS(AFECTRL_ADCPWR|AFECTRL_SINC2NOTCH, bTRUE);
//AD5940_AFECtrlS(AFECTRL_ADCCNV, bTRUE);
AD5940_ADCPowerCtrlS(bTRUE);
AD5940_ADCConvtCtrlS(bTRUE);
while(1)
{
uint32_t rd;
if(AD5940_INTCTestFlag(AFEINTC_1,AFEINTSRC_SINC2RDY))
{
static uint32_t count;
AD5940_INTCClrFlag(AFEINTSRC_SINC2RDY);
rd = AD5940_ReadAfeResult(AFERESULT_SINC2);
count ++;
/* ADC Sample rate is 800kSPS. SINC3 OSR is 4, SINC2 OSR is 1333. So the final output data rate is 800kSPS/4/1333 = 150.0375Hz */
if(count == 150) /* Print data @1Hz */
{
count = 0;
float diff_volt = AD5940_ADCCode2Volt(rd, ADCPGA_GAIN_SEL, 1.82);
printf("ADC Code:%d, diff-volt: %.4f, volt:%.4f\n",rd, diff_volt, diff_volt+1.11);
}
}
}
}
/**
* @}
* @}
* */

View File

@ -1,151 +0,0 @@
/*!
*****************************************************************************
@file: AD5940Main.c
@author: Neo Xu
@brief: Electrochemical impedance spectroscopy based on example AD5940_Impedance
This project is optomized for 3-lead electrochemical sensors that typically have
an impedance <200ohm. For optimum performance RCAL should be close to
impedance of the sensor.
-----------------------------------------------------------------------------
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 "Impedance.h"
#define APPBUFF_SIZE 512
uint32_t AppBuff[APPBUFF_SIZE];
int32_t ImpedanceShowResult(uint32_t *pData, uint32_t DataCount)
{
float freq;
fImpPol_Type *pImp = (fImpPol_Type*)pData;
AppIMPCtrl(IMPCTRL_GETFREQ, &freq);
printf("Freq:%.2f ", freq);
/*Process data*/
for(int i=0;i<DataCount;i++)
{
printf("RzMag: %f Ohm , RzPhase: %f \n",pImp[i].Magnitude,pImp[i].Phase*180/MATH_PI);
}
return 0;
}
static int32_t AD5940PlatformCfg(void)
{
CLKCfg_Type clk_cfg;
FIFOCfg_Type fifo_cfg;
AGPIOCfg_Type gpio_cfg;
/* Use hardware reset */
AD5940_HWReset();
AD5940_Initialize();
/* Platform configuration */
/* Step1. Configure clock */
clk_cfg.ADCClkDiv = ADCCLKDIV_1;
clk_cfg.ADCCLkSrc = ADCCLKSRC_HFOSC;
clk_cfg.SysClkDiv = SYSCLKDIV_1;
clk_cfg.SysClkSrc = SYSCLKSRC_HFOSC;
clk_cfg.HfOSC32MHzMode = bFALSE;
clk_cfg.HFOSCEn = bTRUE;
clk_cfg.HFXTALEn = bFALSE;
clk_cfg.LFOSCEn = bTRUE;
AD5940_CLKCfg(&clk_cfg);
/* Step2. Configure FIFO and Sequencer*/
fifo_cfg.FIFOEn = bFALSE;
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 = 6;
AD5940_FIFOCfg(&fifo_cfg);
fifo_cfg.FIFOEn = bTRUE;
AD5940_FIFOCfg(&fifo_cfg);
/* Step3. Interrupt controller */
AD5940_INTCCfg(AFEINTC_1, AFEINTSRC_ALLINT, bTRUE); /* Enable all interrupt in INTC1, so we can check INTC flags */
AD5940_INTCClrFlag(AFEINTSRC_ALLINT);
AD5940_INTCCfg(AFEINTC_0, AFEINTSRC_DATAFIFOTHRESH, bTRUE);
AD5940_INTCClrFlag(AFEINTSRC_ALLINT);
/* Step4: Reconfigure GPIO */
gpio_cfg.FuncSet = GP0_INT|GP1_SLEEP|GP2_SYNC;
gpio_cfg.InputEnSet = 0;
gpio_cfg.OutputEnSet = AGPIO_Pin0|AGPIO_Pin1|AGPIO_Pin2;
gpio_cfg.OutVal = 0;
gpio_cfg.PullEnSet = 0;
AD5940_AGPIOCfg(&gpio_cfg);
AD5940_SleepKeyCtrlS(SLPKEY_UNLOCK); /* Allow AFE to enter sleep mode. */
return 0;
}
void AD5940ImpedanceStructInit(void)
{
AppIMPCfg_Type *pImpedanceCfg;
AppIMPGetCfg(&pImpedanceCfg);
/* Step1: configure initialization sequence Info */
pImpedanceCfg->SeqStartAddr = 0;
pImpedanceCfg->MaxSeqLen = 512; /* @todo add checker in function */
pImpedanceCfg->RcalVal = 200.0;
pImpedanceCfg->FifoThresh = 6;
pImpedanceCfg->SinFreq = 1000.0;
/* Configure Excitation Waveform
*
* Output waveform = DacVoltPP * ExcitBufGain * HsDacGain
*
* = 300 * 0.25 * 0.2 = 15mV pk-pk
*
*/
pImpedanceCfg->DacVoltPP = 300; /* Maximum value is 600mV*/
pImpedanceCfg->ExcitBufGain = EXCITBUFGAIN_0P25;
pImpedanceCfg->HsDacGain = HSDACGAIN_0P2;
/* Set switch matrix to onboard(EVAL-AD5940ELECZ) gas sensor. */
pImpedanceCfg->DswitchSel = SWD_CE0;
pImpedanceCfg->PswitchSel = SWP_RE0;
pImpedanceCfg->NswitchSel = SWN_SE0LOAD;
pImpedanceCfg->TswitchSel = SWT_SE0LOAD;
/* The dummy sensor is as low as 5kOhm. We need to make sure RTIA is small enough that HSTIA won't be saturated. */
pImpedanceCfg->HstiaRtiaSel = HSTIARTIA_200;
pImpedanceCfg->BiasVolt = 0.0;
/* Configure the sweep function. */
pImpedanceCfg->SweepCfg.SweepEn = bFALSE;
pImpedanceCfg->SweepCfg.SweepStart = 100.0f; /* Start from 1kHz */
pImpedanceCfg->SweepCfg.SweepStop = 100e3f; /* Stop at 100kHz */
pImpedanceCfg->SweepCfg.SweepPoints = 101; /* Points is 101 */
pImpedanceCfg->SweepCfg.SweepLog = bTRUE;
/* Configure Power Mode. Use HP mode if frequency is higher than 80kHz. */
pImpedanceCfg->PwrMod = AFEPWR_LP;
/* Configure filters if necessary */
pImpedanceCfg->ADCSinc3Osr = ADCSINC3OSR_4; /* Sample rate is 800kSPS/2 = 400kSPS */
pImpedanceCfg->DftNum = DFTNUM_16384;
pImpedanceCfg->DftSrc = DFTSRC_SINC3;
}
void AD5940_Main(void)
{
uint32_t temp;
AD5940PlatformCfg();
AD5940ImpedanceStructInit();
AppIMPInit(AppBuff, APPBUFF_SIZE); /* Initialize IMP application. Provide a buffer, which is used to store sequencer commands */
AppIMPCtrl(IMPCTRL_START, 0); /* Control IMP measurement to start. Second parameter has no meaning with this command. */
while(1)
{
if(AD5940_GetMCUIntFlag())
{
AD5940_ClrMCUIntFlag();
temp = APPBUFF_SIZE;
AppIMPISR(AppBuff, &temp);
ImpedanceShowResult(AppBuff, temp);
}
}
}

View File

@ -1,95 +0,0 @@
/*!
*****************************************************************************
@file: AD5940_HSDACCal.c
@author: $Author: nxu2 $
@brief: HSDAC Offset Calibration Demo calibration demo.
@version: $Revision: 766 $
@date: $Date: 2017-08-21 14:09:35 +0100 (Mon, 21 Aug 2017) $
-----------------------------------------------------------------------------
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 "ad5940.h"
#include <stdio.h>
#include "string.h"
/* The HSDAC has a number of different gain settings shown in table below.
The HSDAC needs to be calibrated seperately for each gain setting. HSDAC has two powe
modes. There are seperate offset registers for both, DACOFFSET and DACOFFSETHP. The
HSDAC needs to be calibrated for each mode.
HSDACCON[12] | HSDACCON[0] | Output Range |
0 | 0 | +-607mV |
1 | 0 | +-75mV |
1 | 1 | +-15.14mV |
0 | 1 | +-121.2mV |
*/
void AD5940_Main(void){
HSDACCal_Type hsdac_cal;
ADCPGACal_Type adcpga_cal;
CLKCfg_Type clk_cfg;
/* Use hardware reset */
AD5940_HWReset();
AD5940_Initialize();
AD5940_AFEPwrBW(AFEPWR_LP, AFEBW_250KHZ);
clk_cfg.ADCClkDiv = ADCCLKDIV_1;
clk_cfg.ADCCLkSrc = ADCCLKSRC_HFOSC;
clk_cfg.SysClkDiv = SYSCLKDIV_1;
clk_cfg.SysClkSrc = SYSCLKSRC_HFOSC;
clk_cfg.HfOSC32MHzMode = bTRUE;
clk_cfg.HFOSCEn = bTRUE;
clk_cfg.HFXTALEn = bFALSE;
clk_cfg.LFOSCEn = bTRUE;
AD5940_CLKCfg(&clk_cfg);
printf("ADC Offset Cal\n");
adcpga_cal.AdcClkFreq=16000000;
adcpga_cal.ADCPga = ADCPGA_1;
adcpga_cal.ADCSinc2Osr = ADCSINC2OSR_1333;
adcpga_cal.ADCSinc3Osr = ADCSINC3OSR_4;
adcpga_cal.PGACalType = PGACALTYPE_OFFSET;
adcpga_cal.TimeOut10us = 1000;
adcpga_cal.VRef1p11 = 1.11;
adcpga_cal.VRef1p82 = 1.82;
AD5940_ADCPGACal(&adcpga_cal);
printf("\n 607mV Range Cal\n");
hsdac_cal.ExcitBufGain = EXCITBUFGAIN_2; /**< Select from EXCITBUFGAIN_2, EXCITBUFGAIN_0P25 */
hsdac_cal.HsDacGain = HSDACGAIN_1; /**< Select from HSDACGAIN_1, HSDACGAIN_0P2 */
hsdac_cal.AfePwrMode = AFEPWR_LP;
hsdac_cal.ADCSinc2Osr = ADCSINC2OSR_1333;
hsdac_cal.ADCSinc3Osr = ADCSINC3OSR_4;
AD5940_HSDACCal(&hsdac_cal);
printf("\nADC GN 4 Offset Cal\n");
adcpga_cal.ADCPga = ADCPGA_4;
AD5940_ADCPGACal(&adcpga_cal);
printf("\n 125mV Range Cal\n");
hsdac_cal.ExcitBufGain = EXCITBUFGAIN_2; /**< Select from EXCITBUFGAIN_2, EXCITBUFGAIN_0P25 */
hsdac_cal.HsDacGain = HSDACGAIN_0P2; /**< Select from HSDACGAIN_1, HSDACGAIN_0P2 */
AD5940_HSDACCal(&hsdac_cal);
printf("\n 75mV Range Cal\n");
hsdac_cal.ExcitBufGain = EXCITBUFGAIN_0P25; /**< Select from EXCITBUFGAIN_2, EXCITBUFGAIN_0P25 */
hsdac_cal.HsDacGain = HSDACGAIN_1; /**< Select from HSDACGAIN_1, HSDACGAIN_0P2 */
AD5940_HSDACCal(&hsdac_cal);
printf("\n 15mV Range Cal\n");
hsdac_cal.ExcitBufGain = EXCITBUFGAIN_0P25; /**< Select from EXCITBUFGAIN_2, EXCITBUFGAIN_0P25 */
hsdac_cal.HsDacGain = HSDACGAIN_0P2; /**< Select from HSDACGAIN_1, HSDACGAIN_0P2 */
AD5940_HSDACCal(&hsdac_cal);
printf("HSDAC Cal Complete!\n");
}

View File

@ -1,142 +0,0 @@
/*!
*****************************************************************************
@file: AD5940Main.c
@author: Neo Xu
@brief: Standard 4-wire or 2-wire impedance measurement example.
-----------------------------------------------------------------------------
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 "Impedance.h"
/**
User could configure following parameters
**/
#define APPBUFF_SIZE 512
uint32_t AppBuff[APPBUFF_SIZE];
int32_t ImpedanceShowResult(uint32_t *pData, uint32_t DataCount)
{
float freq;
fImpPol_Type *pImp = (fImpPol_Type*)pData;
AppIMPCtrl(IMPCTRL_GETFREQ, &freq);
printf("Freq:%.2f ", freq);
/*Process data*/
for(int i=0;i<DataCount;i++)
{
printf("RzMag: %f Ohm , RzPhase: %f \n",pImp[i].Magnitude,pImp[i].Phase*180/MATH_PI);
}
return 0;
}
static int32_t AD5940PlatformCfg(void)
{
CLKCfg_Type clk_cfg;
FIFOCfg_Type fifo_cfg;
AGPIOCfg_Type gpio_cfg;
/* Use hardware reset */
AD5940_HWReset();
AD5940_Initialize();
/* Platform configuration */
/* Step1. Configure clock */
clk_cfg.ADCClkDiv = ADCCLKDIV_1;
clk_cfg.ADCCLkSrc = ADCCLKSRC_HFOSC;
clk_cfg.SysClkDiv = SYSCLKDIV_1;
clk_cfg.SysClkSrc = SYSCLKSRC_HFOSC;
clk_cfg.HfOSC32MHzMode = bFALSE;
clk_cfg.HFOSCEn = bTRUE;
clk_cfg.HFXTALEn = bFALSE;
clk_cfg.LFOSCEn = bTRUE;
AD5940_CLKCfg(&clk_cfg);
/* Step2. Configure FIFO and Sequencer*/
fifo_cfg.FIFOEn = bFALSE;
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 = 4;//AppIMPCfg.FifoThresh; /* DFT result. One pair for RCAL, another for Rz. One DFT result have real part and imaginary part */
AD5940_FIFOCfg(&fifo_cfg);
fifo_cfg.FIFOEn = bTRUE;
AD5940_FIFOCfg(&fifo_cfg);
/* Step3. Interrupt controller */
AD5940_INTCCfg(AFEINTC_1, AFEINTSRC_ALLINT, bTRUE); /* Enable all interrupt in INTC1, so we can check INTC flags */
AD5940_INTCClrFlag(AFEINTSRC_ALLINT);
AD5940_INTCCfg(AFEINTC_0, AFEINTSRC_DATAFIFOTHRESH, bTRUE);
AD5940_INTCClrFlag(AFEINTSRC_ALLINT);
/* Step4: Reconfigure GPIO */
gpio_cfg.FuncSet = GP0_INT|GP1_SLEEP|GP2_SYNC;
gpio_cfg.InputEnSet = 0;
gpio_cfg.OutputEnSet = AGPIO_Pin0|AGPIO_Pin1|AGPIO_Pin2;
gpio_cfg.OutVal = 0;
gpio_cfg.PullEnSet = 0;
AD5940_AGPIOCfg(&gpio_cfg);
AD5940_SleepKeyCtrlS(SLPKEY_UNLOCK); /* Allow AFE to enter sleep mode. */
return 0;
}
void AD5940ImpedanceStructInit(void)
{
AppIMPCfg_Type *pImpedanceCfg;
AppIMPGetCfg(&pImpedanceCfg);
/* Step1: configure initialization sequence Info */
pImpedanceCfg->SeqStartAddr = 0;
pImpedanceCfg->MaxSeqLen = 512; /* @todo add checker in function */
pImpedanceCfg->RcalVal = 10000.0;
pImpedanceCfg->SinFreq = 60000.0;
pImpedanceCfg->FifoThresh = 4;
/* Set switch matrix to onboard(EVAL-AD5940ELECZ) dummy sensor. */
/* Note the RCAL0 resistor is 10kOhm. */
pImpedanceCfg->DswitchSel = SWD_CE0;
pImpedanceCfg->PswitchSel = SWP_RE0;
pImpedanceCfg->NswitchSel = SWN_SE0;
pImpedanceCfg->TswitchSel = SWT_SE0LOAD;
/* The dummy sensor is as low as 5kOhm. We need to make sure RTIA is small enough that HSTIA won't be saturated. */
pImpedanceCfg->HstiaRtiaSel = HSTIARTIA_5K;
/* Configure the sweep function. */
pImpedanceCfg->SweepCfg.SweepEn = bTRUE;
pImpedanceCfg->SweepCfg.SweepStart = 1.0f; /* Start from 1kHz */
pImpedanceCfg->SweepCfg.SweepStop = 200e3f; /* Stop at 100kHz */
pImpedanceCfg->SweepCfg.SweepPoints = 101; /* Points is 101 */
pImpedanceCfg->SweepCfg.SweepLog = bTRUE;
/* Configure Power Mode. Use HP mode if frequency is higher than 80kHz. */
pImpedanceCfg->PwrMod = AFEPWR_LP;
/* Configure filters if necessary */
pImpedanceCfg->ADCSinc3Osr = ADCSINC3OSR_2; /* Sample rate is 800kSPS/2 = 400kSPS */
pImpedanceCfg->DftNum = DFTNUM_16384;
pImpedanceCfg->DftSrc = DFTSRC_SINC3;
}
void AD5940_Main(void)
{
uint32_t temp;
AD5940PlatformCfg();
AD5940ImpedanceStructInit();
AppIMPInit(AppBuff, APPBUFF_SIZE); /* Initialize IMP application. Provide a buffer, which is used to store sequencer commands */
AppIMPCtrl(IMPCTRL_START, 0); /* Control IMP measurement to start. Second parameter has no meaning with this command. */
while(1)
{
if(AD5940_GetMCUIntFlag())
{
AD5940_ClrMCUIntFlag();
temp = APPBUFF_SIZE;
AppIMPISR(AppBuff, &temp);
ImpedanceShowResult(AppBuff, temp);
}
}
}

View File

@ -1,320 +0,0 @@
/*!
*****************************************************************************
@file: AD5940_Sequencer.c
@author: Neo Xu
@brief: Basic usage of sequencer.
-----------------------------------------------------------------------------
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.
*****************************************************************************/
/**
* Sequencer is used to control the AFE automatically. It can execute commands that
* is pre-loaded to SRAM. There are 6kB SRAM available while you can choose to use
* 2kB or 4kB of it and use reset of SRAM for data FIFO.
* There are 3 commands available. We mainly use only two commands:
* - Write register
* - Wait
* We control the AFE by registers, so with sequencer, we can do almost everything.
*
* Once sequencer is enabled, it starts to wait valid trigger signal. Sequencer can
* manage 4sequences at same time. You can choose which sequence you want to trigger.
* To make the AFE can manage measurement automatically, there are three method to
* trigger sequence.
* - MMR. You can trigger any sequence by register write. Or call function @ref AD5940_SEQMmrTrig
* - GPIO. You can trigger any sequence by GPIO. To use this, you must firstly set
* GPIO function to GPx_TRIG. Where x is the GPIO number. GPIO0 is used to trigger
* Sequence0 and GPIO3 is used to trigger Sequence3. Check the macro definition to
* Check the details (or below table).
* |GPIO|WhichSequence|
* |GP0|SEQUENCE0|
* |GP1|SEQUENCE1|
* |GP2|SEQUENCE2|
* |GP3|SEQUENCE3|
* |GP4|SEQUENCE0|
* |GP5|SEQUENCE1|
* |GP6|SEQUENCE2|
* |GP7|SEQUENCE3|
* - WakeupTimer. Wakeuptimer can automatically wakeup AFE from hibernate state and trigger selected
* sequence in register SEQORDER. This register defines the order of sequence that
* Wakeuptimer will trigger. There are 8 slots in this register. You can fill in any
* of the four sequences. Also, you can choose not to use all these 8 slots, just simply
* specify the end slot. We call the 8 slots are A/B/C/D/E/F/G/H. For example you can
* choose the end slot as C. So wakeup timer will trigger the sequence in below order:
* A->B->C->A->B->C->A->B->C->... until you stop Wakeuptimer.
* If you fill in slot A with sequence0, B with Sequence3, C with sequence1, the sequence
* will be executed in the order defined above(A-B-C-A-B-C...)
* SEQ0->SEQ3->SEQ1->SEQ0->SEQ3->SEQ1->...
* For each sequence, there is a sleep timer and a wakeup timer. The timer will automatically
* load corresponding value.
* The structure @ref WUPTCfg_Type can be used to initialize all above settings.
*
* In this example, we use both three kinds of trigger source.
* We firstly use Wakeup Timer to trigger sequence 0/1/2. The sequence is used to write registers and
* generate a custom-interrupt. We detect the interrupt to identify which sequence is running.
* Finally, we use GPIO to trigger sequence3.
*
* When there is conflict between trigger signals, for example, GPIO triggered one sequence that is running,
* current strategy is ignore this trigger.
* Use @reg SEQCfg_Type to configure sequencer.
*
* @note: connect GP2 and GP1 together. This demo show how to use GPIO to trigger sequencer. GP2 is the trigger input.
* We use GP1 to generate the trigger signal, while in real case, it should be the MCU's GPIO.
*/
#include "ad5940.h"
#include <stdio.h>
#include "string.h"
int32_t SeqISR(void);
BoolFlag bSeqEnd = bFALSE;
static const uint32_t Seq0Commands[]=
{
SEQ_WR(REG_AFE_SWCON, 0x0000),
SEQ_INT0(), /* generate custom-interrupt 0. We can generate any custom interrupt(SEQ_INT0/1/2/3()) by sequencer. */
};
static const uint32_t Seq1Commands[]=
{
SEQ_WR(REG_AFE_SWCON, 0x1111),
SEQ_INT1(), /* generate custom-interrupt 0 */
SEQ_STOP(), /* Disable sequencer */
};
static const uint32_t Seq2Commands[]=
{
SEQ_WR(REG_AFE_SWCON, 0x2222),
SEQ_INT2(), /* generate custom-interrupt 1 */
};
static const uint32_t Seq3Commands[]=
{
SEQ_WR(REG_AFE_SWCON, 0x3333),
SEQ_INT3(), /* generate custom-interrupt 1 */
};
static int32_t AD5940PlatformCfg(void)
{
CLKCfg_Type clk_cfg;
FIFOCfg_Type fifo_cfg;
AGPIOCfg_Type gpio_cfg;
/* Use hardware reset */
AD5940_HWReset();
AD5940_Initialize(); /* Call this right after AFE reset */
/* Platform configuration */
/* Step1. Configure clock */
clk_cfg.ADCClkDiv = ADCCLKDIV_1;
clk_cfg.ADCCLkSrc = ADCCLKSRC_HFOSC;
clk_cfg.SysClkDiv = SYSCLKDIV_1;
clk_cfg.SysClkSrc = SYSCLKSRC_HFOSC;
clk_cfg.HfOSC32MHzMode = bFALSE;
clk_cfg.HFOSCEn = bTRUE;
clk_cfg.HFXTALEn = bFALSE;
clk_cfg.LFOSCEn = bTRUE;
AD5940_CLKCfg(&clk_cfg);
/* Step2. Configure FIFO and Sequencer*/
fifo_cfg.FIFOEn = bFALSE;
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 = 4;//AppIMPCfg.FifoThresh; /* DFT result. One pair for RCAL, another for Rz. One DFT result have real part and imaginary part */
AD5940_FIFOCfg(&fifo_cfg);
fifo_cfg.FIFOEn = bTRUE;
AD5940_FIFOCfg(&fifo_cfg);
/* Step3. Interrupt controller */
AD5940_INTCCfg(AFEINTC_1, AFEINTSRC_ALLINT, bTRUE); /* Enable all interrupt in INTC1, so we can check INTC flags */
AD5940_INTCClrFlag(AFEINTSRC_ALLINT);
AD5940_INTCCfg(AFEINTC_0, AFEINTSRC_ENDSEQ|AFEINTSRC_CUSTOMINT0|AFEINTSRC_CUSTOMINT1|AFEINTSRC_CUSTOMINT2|AFEINTSRC_CUSTOMINT3, bTRUE);
AD5940_INTCClrFlag(AFEINTSRC_ALLINT);
/* Step4: Reconfigure GPIO */
/* GP0: the interrupt output.
GP1: normal GPIO
GP2: used as trigger to sequence2. If valid trigger signal detected, sequencer will try to run sequence2.
GP3: not used.
GP4: controlled by sequencer.
Others: not used. The default function is mode0.
*/
gpio_cfg.FuncSet = GP0_INT|GP1_GPIO|GP2_TRIG|GP4_SYNC;
gpio_cfg.InputEnSet = AGPIO_Pin2;
gpio_cfg.OutputEnSet = AGPIO_Pin0|AGPIO_Pin1|AGPIO_Pin2|AGPIO_Pin4;
gpio_cfg.OutVal = 0;
gpio_cfg.PullEnSet = 0;
AD5940_AGPIOCfg(&gpio_cfg);
return 0;
}
#define SEQ0ADDR 0
#define SEQ1ADDR 16
#define SEQ2ADDR 32
#define SEQ3ADDR 48
void AD5940_Main(void)
{
SEQCfg_Type seq_cfg;
FIFOCfg_Type fifo_cfg;
WUPTCfg_Type wupt_cfg;
SEQInfo_Type seqinfo0, seqinfo1, seqinfo2, seqinfo3;
SeqGpioTrig_Cfg seqgpiotrig_cfg;
AD5940PlatformCfg();
/* 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 = bTRUE;
seq_cfg.SeqCntCRCClr = bTRUE;
seq_cfg.SeqEnable = bTRUE;
seq_cfg.SeqWrTimer = 0;
AD5940_SEQCfg(&seq_cfg);
/* 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_SINC3;
fifo_cfg.FIFOThresh = 4;
AD5940_FIFOCfg(&fifo_cfg);
AD5940_INTCClrFlag(AFEINTSRC_ALLINT);
seqinfo0.pSeqCmd = Seq0Commands;
seqinfo0.SeqId = SEQID_0;
seqinfo0.SeqLen = SEQ_LEN(Seq0Commands);
seqinfo0.SeqRamAddr = SEQ0ADDR;
seqinfo0.WriteSRAM = bTRUE;
AD5940_SEQInfoCfg(&seqinfo0); /* Configure sequence0 info and write commands to SRAM */
seqinfo1.pSeqCmd = Seq1Commands;
seqinfo1.SeqId = SEQID_1;
seqinfo1.SeqLen = SEQ_LEN(Seq1Commands);
seqinfo1.SeqRamAddr = SEQ1ADDR;
seqinfo1.WriteSRAM = bTRUE;
AD5940_SEQInfoCfg(&seqinfo1);
seqinfo2.pSeqCmd = Seq2Commands;
seqinfo2.SeqId = SEQID_2;
seqinfo2.SeqLen = SEQ_LEN(Seq2Commands);
seqinfo2.SeqRamAddr = SEQ2ADDR;
seqinfo2.WriteSRAM = bTRUE;
AD5940_SEQInfoCfg(&seqinfo2);
seqinfo3.pSeqCmd = Seq3Commands;
seqinfo3.SeqId = SEQID_3;
seqinfo3.SeqLen = SEQ_LEN(Seq3Commands);
seqinfo3.SeqRamAddr = SEQ3ADDR;
seqinfo3.WriteSRAM = bTRUE;
AD5940_SEQInfoCfg(&seqinfo3);
/* Configure wakeup timer */
wupt_cfg.WuptEn = bFALSE; /* Don't start it right now. */
wupt_cfg.WuptEndSeq = WUPTENDSEQ_C; /* A->B->C->A->B-C */
wupt_cfg.WuptOrder[0] = SEQID_0; /* Put SEQ0 to slotA */
wupt_cfg.WuptOrder[1] = SEQID_3; /* Put SEQ3 to slotB */
wupt_cfg.WuptOrder[2] = SEQID_1; /* Put SEQ1 to slotC */
/* There is no need to init slot DEFGH, that's WuptOrder[3] to WuptOrder[7], becaue we don't use it. EndofSeq is C.*/
wupt_cfg.SeqxSleepTime[SEQID_0] = 10;
wupt_cfg.SeqxWakeupTime[SEQID_0] = (uint32_t)(32000.0f*500/1000.0f) - 10 - 2; /* 500ms after, wakeup and trigger seq0 */
wupt_cfg.SeqxSleepTime[SEQID_3] = 10;
wupt_cfg.SeqxWakeupTime[SEQID_3] = (uint32_t)(32000.0f*1000/1000.0f)- 10 -2; /* 1000ms after, trigger seq2 */
wupt_cfg.SeqxSleepTime[SEQID_1] = 10;
wupt_cfg.SeqxWakeupTime[SEQID_1] = (uint32_t)(32000.0f*2000/1000.0f)- 10 -2; /* 2000ms after, trigger seq2 */
AD5940_WUPTCfg(&wupt_cfg);
printf("Test0: trigger sequencer by wakeup timer.\n");
AD5940_WUPTCtrl(bTRUE); /* Enable wakeup timer. */
while(1)
{
if(AD5940_GetMCUIntFlag())
{
AD5940_ClrMCUIntFlag();
SeqISR();
if(bSeqEnd)
break;
}
}
AD5940_WUPTCtrl(bFALSE); /* Wakeup timer is still running and triggering. Trigger is not accepted because sequencer
is disabled in last sequence(SEQ1) command. */
AD5940_SEQCtrlS(bTRUE); /* Enable sequencer again, because we disabled it in seq3 last command. */
/* Test MMR trigger */
printf("\nTest1: trigger sequence2 manually by register write.\n");
AD5940_SEQMmrTrig(SEQID_2); /* Trigger sequence2 manually. */
/* Wait until CUSTMINT2 is set. We generate this interrupt in SEQ2 */
while(AD5940_INTCTestFlag(AFEINTC_1, AFEINTSRC_CUSTOMINT2) == bFALSE); /* Test INTC1, we enabled all interrupts in INTC1. */
AD5940_INTCClrFlag(AFEINTSRC_CUSTOMINT2);
printf("sequence2 has been executed\n");
printf("SWCON:0x%08x\n", AD5940_ReadReg(REG_AFE_SWCON));
AD5940_INTCClrFlag(AFEINTSRC_ALLINT);
/* Toggle GPIO to trigger sequencer2 */
printf("\nTest2: trigger sequence2 manually by GPIO\n");
printf("Please connect GP2 and GP1 together. We will set GP2 function to TRIG.\n"
"GP1 is set to GPIO function and is in output state. We use GP1 to toggle GP2.\n");
AD5940_Delay10us(100*1000*2);
printf("Toggle GPIO now\n");
/* Allow GP2 falling edge to trigger sequence2 */
seqgpiotrig_cfg.bEnable = bTRUE;
seqgpiotrig_cfg.PinSel = AGPIO_Pin2;
seqgpiotrig_cfg.SeqPinTrigMode = SEQPINTRIGMODE_FALLING;
AD5940_SEQGpioTrigCfg(&seqgpiotrig_cfg);
/* GP2 is connected to GP1 by user.
We generate falling edge on GP1(gpio, output) to control GP2(trigger, input).
*/
AD5940_AGPIOSet(AGPIO_Pin1);
AD5940_AGPIOClr(AGPIO_Pin1);
while(AD5940_INTCTestFlag(AFEINTC_1, AFEINTSRC_CUSTOMINT2) == bFALSE); /* Test INTC1, we enabled all interrupts in INTC1. */
printf("Trigger received and sequence2 has been executed\n\n");
printf("Sequencer test done!\n");
while(1);
}
int32_t SeqISR(void)
{
uint32_t IntFlag, temp;
IntFlag = AD5940_INTCGetFlag(AFEINTC_0);
if(IntFlag & AFEINTSRC_CUSTOMINT0)
{
AD5940_INTCClrFlag(AFEINTSRC_CUSTOMINT0);
printf("Custom INT0!\n");
temp = AD5940_ReadReg(REG_AFE_SWCON);
printf("SWCON:0x%08x\n", temp);
}
if(IntFlag & AFEINTSRC_CUSTOMINT1)
{
AD5940_INTCClrFlag(AFEINTSRC_CUSTOMINT1);
printf("Custom INT1!\n");
temp = AD5940_ReadReg(REG_AFE_SWCON);
printf("SWCON:0x%08x\n", temp);
}
if(IntFlag & AFEINTSRC_CUSTOMINT2)
{
AD5940_INTCClrFlag(AFEINTSRC_CUSTOMINT2);
printf("Custom INT2!\n");
temp = AD5940_ReadReg(REG_AFE_SWCON);
printf("SWCON:0x%08x\n", temp);
}
if(IntFlag & AFEINTSRC_CUSTOMINT3)
{
AD5940_INTCClrFlag(AFEINTSRC_CUSTOMINT3);
printf("Custom INT3!\n");
temp = AD5940_ReadReg(REG_AFE_SWCON);
printf("SWCON:0x%08x\n", temp);
}
if(IntFlag & AFEINTSRC_ENDSEQ) /* This interrupt is generated when Sequencer is disabled. */
{
AD5940_INTCClrFlag(AFEINTSRC_ENDSEQ);
printf("End of Sequence\n");
bSeqEnd = bTRUE;
}
return AD5940ERR_OK;
}

View File

@ -1,190 +0,0 @@
/**
* @file NUCLEOF411Port.c
* @brief ST NUCLEOF411 board port file.
* @version V0.2.0
* @author ADI
* @date March 2019
* @par Revision History:
*
* 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 "ad5940.h"
#include "stdio.h"
#include "stm32f4xx_hal.h"
/* Definition for STM32 SPI clock resources */
#define AD5940SPI SPI1
#define AD5940_CLK_ENABLE() __HAL_RCC_SPI1_CLK_ENABLE()
#define AD5940_SCK_GPIO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()
#define AD5940_MISO_GPIO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()
#define AD5940_MOSI_GPIO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()
#define AD5940_CS_GPIO_CLK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE()
#define AD5940_RST_GPIO_CLK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE()
#define AD5940_GP0INT_GPIO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()
#define AD5940SPI_FORCE_RESET() __HAL_RCC_SPI1_FORCE_RESET()
#define AD5940SPI_RELEASE_RESET() __HAL_RCC_SPI1_RELEASE_RESET()
/* Definition for AD5940 Pins */
#define AD5940_SCK_PIN GPIO_PIN_5
#define AD5940_SCK_GPIO_PORT GPIOA
#define AD5940_SCK_AF GPIO_AF5_SPI1
#define AD5940_MISO_PIN GPIO_PIN_6
#define AD5940_MISO_GPIO_PORT GPIOA
#define AD5940_MISO_AF GPIO_AF5_SPI1
#define AD5940_MOSI_PIN GPIO_PIN_7
#define AD5940_MOSI_GPIO_PORT GPIOA
#define AD5940_MOSI_AF GPIO_AF5_SPI1
#define AD5940_CS_PIN GPIO_PIN_6
#define AD5940_CS_GPIO_PORT GPIOB
#define AD5940_RST_PIN GPIO_PIN_0 //A3
#define AD5940_RST_GPIO_PORT GPIOB
#define AD5940_GP0INT_PIN GPIO_PIN_10 //A3
#define AD5940_GP0INT_GPIO_PORT GPIOA
#define AD5940_GP0INT_IRQn EXTI15_10_IRQn
SPI_HandleTypeDef SpiHandle;
#define SYSTICK_MAXCOUNT ((1L<<24)-1) /* we use Systick to complete function Delay10uS(). This value only applies to NUCLEOF411 board. */
#define SYSTICK_CLKFREQ 100000000L /* Systick clock frequency in Hz. This only appies to NUCLEOF411 board */
volatile static uint8_t ucInterrupted = 0; /* Flag to indicate interrupt occurred */
/**
@brief Using SPI to transmit N bytes and return the received bytes. This function targets to
provide a more efficent way to transmit/receive data.
@param pSendBuffer :{0 - 0xFFFFFFFF}
- Pointer to the data to be sent.
@param pRecvBuff :{0 - 0xFFFFFFFF}
- Pointer to the buffer used to store received data.
@param length :{0 - 0xFFFFFFFF}
- Data length in SendBuffer.
@return None.
**/
void AD5940_ReadWriteNBytes(unsigned char *pSendBuffer,unsigned char *pRecvBuff,unsigned long length)
{
HAL_SPI_TransmitReceive(&SpiHandle, pSendBuffer, pRecvBuff, length, (uint32_t)-1);
}
void AD5940_CsClr(void)
{
HAL_GPIO_WritePin(AD5940_CS_GPIO_PORT, AD5940_CS_PIN, GPIO_PIN_RESET);
}
void AD5940_CsSet(void)
{
HAL_GPIO_WritePin(AD5940_CS_GPIO_PORT, AD5940_CS_PIN, GPIO_PIN_SET);
}
void AD5940_RstSet(void)
{
HAL_GPIO_WritePin(AD5940_RST_GPIO_PORT, AD5940_RST_PIN, GPIO_PIN_SET);
}
void AD5940_RstClr(void)
{
HAL_GPIO_WritePin(AD5940_RST_GPIO_PORT, AD5940_RST_PIN, GPIO_PIN_RESET);
}
void AD5940_Delay10us(uint32_t time)
{
time/=100;
if(time == 0) time =1;
HAL_Delay(time);
}
uint32_t AD5940_GetMCUIntFlag(void)
{
return ucInterrupted;
}
uint32_t AD5940_ClrMCUIntFlag(void)
{
ucInterrupted = 0;
return 1;
}
uint32_t AD5940_MCUResourceInit(void *pCfg)
{
GPIO_InitTypeDef GPIO_InitStruct;
/* Step1, initialize SPI peripheral and its GPIOs for CS/RST */
AD5940_SCK_GPIO_CLK_ENABLE();
AD5940_MISO_GPIO_CLK_ENABLE();
AD5940_MOSI_GPIO_CLK_ENABLE();
AD5940_CS_GPIO_CLK_ENABLE();
AD5940_RST_GPIO_CLK_ENABLE();
/* Enable SPI clock */
AD5940_CLK_ENABLE();
GPIO_InitStruct.Pin = AD5940_SCK_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = AD5940_SCK_AF;
HAL_GPIO_Init(AD5940_SCK_GPIO_PORT, &GPIO_InitStruct);
/* SPI MISO GPIO pin configuration */
GPIO_InitStruct.Pin = AD5940_MISO_PIN;
GPIO_InitStruct.Alternate = AD5940_MISO_AF;
HAL_GPIO_Init(AD5940_MISO_GPIO_PORT, &GPIO_InitStruct);
/* SPI MOSI GPIO pin configuration */
GPIO_InitStruct.Pin = AD5940_MOSI_PIN;
GPIO_InitStruct.Alternate = AD5940_MOSI_AF;
HAL_GPIO_Init(AD5940_MOSI_GPIO_PORT, &GPIO_InitStruct);
/* SPI CS GPIO pin configuration */
GPIO_InitStruct.Pin = AD5940_CS_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
HAL_GPIO_Init(AD5940_CS_GPIO_PORT, &GPIO_InitStruct);
/* SPI RST GPIO pin configuration */
GPIO_InitStruct.Pin = AD5940_RST_PIN;
HAL_GPIO_Init(AD5940_RST_GPIO_PORT, &GPIO_InitStruct);
AD5940_CsSet();
AD5940_RstSet();
/* Set the SPI parameters */
SpiHandle.Instance = AD5940SPI;
SpiHandle.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8; //SPI clock should be < AD5940_SystemClock
SpiHandle.Init.Direction = SPI_DIRECTION_2LINES;
SpiHandle.Init.CLKPhase = SPI_PHASE_1EDGE;
SpiHandle.Init.CLKPolarity = SPI_POLARITY_LOW;
SpiHandle.Init.DataSize = SPI_DATASIZE_8BIT;
SpiHandle.Init.FirstBit = SPI_FIRSTBIT_MSB;
SpiHandle.Init.TIMode = SPI_TIMODE_DISABLE;
SpiHandle.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
SpiHandle.Init.CRCPolynomial = 7;
SpiHandle.Init.NSS = SPI_NSS_SOFT;
SpiHandle.Init.Mode = SPI_MODE_MASTER;
HAL_SPI_Init(&SpiHandle);
/* Step 2: Configure external interrupot line */
AD5940_GP0INT_GPIO_CLK_ENABLE();
GPIO_InitStruct.Pin = AD5940_GP0INT_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = 0;
HAL_GPIO_Init(AD5940_GP0INT_GPIO_PORT, &GPIO_InitStruct);
/* Enable and set EXTI Line0 Interrupt to the lowest priority */
HAL_NVIC_EnableIRQ(AD5940_GP0INT_IRQn);
// HAL_NVIC_SetPriority(AD5940_GP0INT_IRQn, 0, 0);
return 0;
}
/* MCU related external line interrupt service routine */
void EXTI15_10_IRQHandler()
{
ucInterrupted = 1;
__HAL_GPIO_EXTI_CLEAR_IT(AD5940_GP0INT_PIN);
}

View File

@ -1,143 +0,0 @@
/*
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 "stdio.h"
#include "ADuCM3029.h"
#include "AD5940.h"
/* Functions that used to initialize MCU platform */
uint32_t MCUPlatformInit(void *pCfg);
int main(void)
{
void AD5940_Main(void);
MCUPlatformInit(0);
AD5940_MCUResourceInit(0);
printf("Hello AD5940-Build Time:%s\n",__TIME__);
AD5940_Main();
}
/* Below functions are used to initialize MCU Platform */
uint32_t MCUPlatformInit(void *pCfg)
{
int UrtCfg(int iBaud);
/*Stop watch dog timer(ADuCM3029)*/
pADI_WDT0->CTL = 0xC9;
/* Clock Configure */
pADI_CLKG0_OSC->KEY = 0xCB14; // Select HFOSC as system clock.
pADI_CLKG0_OSC->CTL = // Int 32khz LFOSC selected in LFMUX
BITM_CLKG_OSC_CTL_HFOSCEN|BITM_CLKG_OSC_CTL_HFXTALEN;
while((pADI_CLKG0_OSC->CTL&BITM_CLKG_OSC_CTL_HFXTALOK) == 0);
pADI_CLKG0_OSC->KEY = 0xCB14;
pADI_CLKG0_CLK->CTL0 = 0x201; /* Select XTAL as system clock */
pADI_CLKG0_CLK->CTL1 = 0; // ACLK,PCLK,HCLK divided by 1
pADI_CLKG0_CLK->CTL5 = 0x00; // Enable clock to all peripherals - no clock gating
UrtCfg(230400);/*Baud rate: 230400*/
return 1;
}
/**
@brief int UrtCfg(int iBaud, int iBits, int iFormat)
==========Configure the UART.
@param iBaud :{B1200,B2200,B2400,B4800,B9600,B19200,B38400,B57600,B115200,B230400,B430800} \n
Set iBaud to the baudrate required:
Values usually: 1200, 2200 (for HART), 2400, 4800, 9600,
19200, 38400, 57600, 115200, 230400, 430800, or type in baud-rate directly
@note
- Powers up UART if not powered up.
- Standard baudrates are accurate to better than 0.1% plus clock error.\n
- Non standard baudrates are accurate to better than 1% plus clock error.
@warning - If an external clock is used for the system the ullRtClk must be modified with \n
the speed of the clock used.
**/
int UrtCfg(int iBaud)
{
int iBits = 3;//8bits,
int iFormat = 0;//, int iBits, int iFormat
int i1;
int iDiv;
int iRtC;
int iOSR;
int iPllMulValue;
unsigned long long ullRtClk = 16000000; // The root clock speed
/*Setup P0[11:10] as UART pins*/
pADI_GPIO0->CFG = (1<<22)|(1<<20)|(pADI_GPIO0->CFG&(~((3<<22)|(3<<20))));
iDiv = (pADI_CLKG0_CLK->CTL1& BITM_CLKG_CLK_CTL1_PCLKDIVCNT); // Read UART clock as set by CLKCON1[10:8]
iDiv = iDiv>>8;
if (iDiv == 0)
iDiv = 1;
iRtC = (pADI_CLKG0_CLK->CTL0& BITM_CLKG_CLK_CTL0_CLKMUX); // Check what is the root clock
switch (iRtC)
{
case 0: // HFOSC selected
ullRtClk = 26000000;
break;
case 1: // HFXTAL selected
if ((pADI_CLKG0_CLK->CTL0 & 0x200)==0x200) // 26Mhz XTAL used
ullRtClk = 26000000;
else
ullRtClk = 16000000; // Assume 16MHz XTAL
break;
case 2: // SPLL output
iPllMulValue = (pADI_CLKG0_CLK->CTL3 & // Check muliplication factor in PLL settings
BITM_CLKG_CLK_CTL3_SPLLNSEL); // bits[4:0]. Assume div value of 0xD in bits [14:11]
ullRtClk = (iPllMulValue *1000000); // Assume straight multiplication by pADI_CLKG0_CLK->CTL3[4:0]
break;
case 3:
ullRtClk = 26000000; //External clock is assumed to be 26MhZ, if different
break; //clock speed is used, this should be changed
default:
break;
}
// iOSR = (pADI_UART0->COMLCR2 & 0x3);
// iOSR = 2^(2+iOSR);
pADI_UART0->COMLCR2 = 0x3;
iOSR = 32;
//i1 = (ullRtClk/(iOSR*iDiv))/iBaud; // UART baud rate clock source is PCLK divided by OSR
i1 = (ullRtClk/(iOSR*iDiv))/iBaud-1; //for bigger M and N value
pADI_UART0->COMDIV = i1;
pADI_UART0->COMFBR = 0x8800|(((((2048/(iOSR*iDiv))*ullRtClk)/i1)/iBaud)-2048);
pADI_UART0->COMIEN = 0;
pADI_UART0->COMLCR = (iFormat&0x3c)|(iBits&3);
pADI_UART0->COMFCR = (BITM_UART_COMFCR_RFTRIG & 0/*RX_FIFO_1BYTE*/ ) |BITM_UART_COMFCR_FIFOEN;
pADI_UART0->COMFCR |= BITM_UART_COMFCR_RFCLR|BITM_UART_COMFCR_TFCLR; // Clear the UART FIFOs
pADI_UART0->COMFCR &= ~(BITM_UART_COMFCR_RFCLR|BITM_UART_COMFCR_TFCLR); // Disable clearing mechanism
NVIC_EnableIRQ(UART_EVT_IRQn); // Enable UART interrupt source in NVIC
pADI_UART0->COMIEN = BITM_UART_COMIEN_ERBFI|BITM_UART_COMIEN_ELSI; /* Rx Interrupt */
return pADI_UART0->COMLSR;
}
#include "stdio.h"
#ifdef __ICCARM__
int putchar(int c)
#else
int fputc(int c, FILE *f)
#endif
{
pADI_UART0->COMTX = c;
while((pADI_UART0->COMLSR&0x20) == 0);// tx fifo empty
return c;
}

View File

@ -31,6 +31,9 @@ endif()
# --- FFTW3 CONFIGURATION --- # --- FFTW3 CONFIGURATION ---
# ========================================== # ==========================================
# --- FFTW3 Configuration (Double Precision) ---
if(WIN32) if(WIN32)
# Windows: Expects FFTW3 to be installed/found via Config # Windows: Expects FFTW3 to be installed/found via Config
find_package(FFTW3 CONFIG REQUIRED) find_package(FFTW3 CONFIG REQUIRED)
@ -51,6 +54,7 @@ elseif(APPLE AND CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64" AND NOT BUILD_IOS)
IMPORTED_LOCATION "${FFTW3_LIB}" IMPORTED_LOCATION "${FFTW3_LIB}"
INTERFACE_INCLUDE_DIRECTORIES "${FFTW3_INCLUDE_DIR}" INTERFACE_INCLUDE_DIRECTORIES "${FFTW3_INCLUDE_DIR}"
) )
else() else()
message(STATUS "Building FFTW3 from source (Double Precision)...") message(STATUS "Building FFTW3 from source (Double Precision)...")
@ -65,15 +69,17 @@ else()
set(BUILD_SHARED_LIBS OFF CACHE BOOL "Build Static Libs" FORCE) set(BUILD_SHARED_LIBS OFF CACHE BOOL "Build Static Libs" FORCE)
set(BUILD_TESTS OFF CACHE BOOL "Disable Tests" FORCE) set(BUILD_TESTS OFF CACHE BOOL "Disable Tests" FORCE)
# Enable NEON for Android ARM64 / iOS # Enhanced NEON detection for Windows on Arm as well
if(ANDROID_ABI STREQUAL "arm64-v8a") if(ANDROID_ABI STREQUAL "arm64-v8a")
message(STATUS "Enabling NEON for Android ARM64") message(STATUS "Enabling NEON for Android ARM64")
set(ENABLE_NEON ON CACHE BOOL "Enable NEON" FORCE) set(ENABLE_NEON ON CACHE BOOL "Enable NEON" FORCE)
elseif(BUILD_IOS) elseif(BUILD_IOS)
set(ENABLE_NEON ON CACHE BOOL "Enable NEON" FORCE) set(ENABLE_NEON ON CACHE BOOL "Enable NEON" FORCE)
elseif(MSVC AND CMAKE_SYSTEM_PROCESSOR MATCHES "(ARM64|arm64|aarch64)")
set(ENABLE_NEON ON CACHE BOOL "Enable NEON" FORCE)
endif() endif()
# Patch for older CMake versions inside the tarball if needed # Only apply sed patch on UNIX-like systems
if(UNIX) if(UNIX)
set(PATCH_CMD sed -i.bak "s/cmake_minimum_required.*/cmake_minimum_required(VERSION 3.16)/" <SOURCE_DIR>/CMakeLists.txt) set(PATCH_CMD sed -i.bak "s/cmake_minimum_required.*/cmake_minimum_required(VERSION 3.16)/" <SOURCE_DIR>/CMakeLists.txt)
else() else()
@ -208,8 +214,10 @@ if(BUILD_ANDROID)
target_link_libraries(EISConfigurator PRIVATE Qt6::Widgets Qt6::SerialPort Qt6::AndroidExtras) target_link_libraries(EISConfigurator PRIVATE Qt6::Widgets Qt6::SerialPort Qt6::AndroidExtras)
else() else()
add_executable(EISConfigurator ${PROJECT_SOURCES}) target_link_libraries(EISConfigurator PRIVATE Qt6::Widgets Qt6::SerialPort Qt6::PrintSupport)
target_link_libraries(EISConfigurator PRIVATE Qt6::Widgets Qt6::SerialPort) if(APPLE)
target_link_libraries(EISConfigurator PRIVATE ${FFTW_TARGET})
endif()
endif() endif()
@ -253,5 +261,5 @@ elseif(WIN32)
endif() endif()
# CRITICAL: Triggers androiddeployqt to build the APK
qt_finalize_executable(EISConfigurator) qt_finalize_executable(EISConfigurator)

View File

@ -0,0 +1,27 @@
{
"images" : [
{ "size" : "20x20", "idiom" : "iphone", "filename" : "Icon-20@2x.png", "scale" : "2x" },
{ "size" : "20x20", "idiom" : "iphone", "filename" : "Icon-20@3x.png", "scale" : "3x" },
{ "size" : "29x29", "idiom" : "iphone", "filename" : "Icon-29.png", "scale" : "1x" },
{ "size" : "29x29", "idiom" : "iphone", "filename" : "Icon-29@2x.png", "scale" : "2x" },
{ "size" : "29x29", "idiom" : "iphone", "filename" : "Icon-29@3x.png", "scale" : "3x" },
{ "size" : "40x40", "idiom" : "iphone", "filename" : "Icon-40@2x.png", "scale" : "2x" },
{ "size" : "40x40", "idiom" : "iphone", "filename" : "Icon-40@3x.png", "scale" : "3x" },
{ "size" : "60x60", "idiom" : "iphone", "filename" : "Icon-60@2x.png", "scale" : "2x" },
{ "size" : "60x60", "idiom" : "iphone", "filename" : "Icon-60@3x.png", "scale" : "3x" },
{ "size" : "20x20", "idiom" : "ipad", "filename" : "Icon-20.png", "scale" : "1x" },
{ "size" : "20x20", "idiom" : "ipad", "filename" : "Icon-20@2x.png", "scale" : "2x" },
{ "size" : "29x29", "idiom" : "ipad", "filename" : "Icon-29.png", "scale" : "1x" },
{ "size" : "29x29", "idiom" : "ipad", "filename" : "Icon-29@2x.png", "scale" : "2x" },
{ "size" : "40x40", "idiom" : "ipad", "filename" : "Icon-40.png", "scale" : "1x" },
{ "size" : "40x40", "idiom" : "ipad", "filename" : "Icon-40@2x.png", "scale" : "2x" },
{ "size" : "76x76", "idiom" : "ipad", "filename" : "Icon-76.png", "scale" : "1x" },
{ "size" : "76x76", "idiom" : "ipad", "filename" : "Icon-76@2x.png", "scale" : "2x" },
{ "size" : "83.5x83.5", "idiom" : "ipad", "filename" : "Icon-83.5@2x.png", "scale" : "2x" },
{ "size" : "1024x1024", "idiom" : "ios-marketing", "filename" : "Icon-1024.png", "scale" : "1x" }
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@ -0,0 +1,6 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@ -0,0 +1,52 @@
@echo off
setlocal
:: Arguments passed from CMake:
:: %1 = Path to magick.exe
:: %2 = Source Image
:: %3 = Destination Icon
set "MAGICK_EXE=%~1"
set "SOURCE_IMG=%~2"
set "DEST_ICO=%~3"
:: -- FOR MISSING DELEGATES / REGISTRY ERRORS ---
for %%I in ("%MAGICK_EXE%") do set "MAGICK_DIR=%%~dpI"
if "%MAGICK_DIR:~-1%"=="\" set "MAGICK_DIR=%MAGICK_DIR:~0,-1%"
set "MAGICK_HOME=%MAGICK_DIR%"
set "MAGICK_CONFIGURE_PATH=%MAGICK_DIR%"
set "MAGICK_CODER_MODULE_PATH=%MAGICK_DIR%\modules\coders"
:: ---------------------------------------------------
:: 1. Validate Source
if not exist "%SOURCE_IMG%" (
echo [ERROR] Icon source not found at: %SOURCE_IMG%
exit /b 1
)
:: 2. Ensure Destination Directory Exists
if not exist "%~dp3" mkdir "%~dp3"
:: 3. Generate the .ico (Nearest Neighbor / Pixel Art Mode)
echo [ICONS] Generating Pixel-Perfect Windows Icon: %DEST_ICO%
:: We use -sample (Nearest Neighbor) explicitly for each standard icon size.
:: We clone the original (index 0) for every resize to ensure maximum accuracy from the source.
"%MAGICK_EXE%" "%SOURCE_IMG%" ^
-background none -alpha on ^
( -clone 0 -sample 256x256 ) ^
( -clone 0 -sample 128x128 ) ^
( -clone 0 -sample 64x64 ) ^
( -clone 0 -sample 48x48 ) ^
( -clone 0 -sample 32x32 ) ^
( -clone 0 -sample 16x16 ) ^
-delete 0 ^
"%DEST_ICO%"
if %errorlevel% neq 0 (
echo [ERROR] ImageMagick failed to generate icon.
exit /b %errorlevel%
)
echo [SUCCESS] Icon generated.
exit /b 0

View File

@ -1,21 +1,18 @@
# host/scripts/generate_icons.sh
#!/bin/bash #!/bin/bash
# Resolve the directory where the script is located # Argument 1: Path to magick executable
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
# Project Root is two levels up (host/scripts -> host -> root)
PROJECT_ROOT="$SCRIPT_DIR/../.."
MAGICK_BIN="$1" MAGICK_BIN="$1"
if [ -z "$MAGICK_BIN" ]; then MAGICK_BIN="magick"; fi
SOURCE="$PROJECT_ROOT/assets/icon_source.png" # Fallback if not provided
OUT_DIR="$PROJECT_ROOT/assets/icons" if [ -z "$MAGICK_BIN" ]; then
ANDROID_RES_DIR="$PROJECT_ROOT/host/android/res" MAGICK_BIN="magick"
fi
# Assumes running from Project Root
SOURCE="assets/icon_source.png"
if [ ! -f "$SOURCE" ]; then if [ ! -f "$SOURCE" ]; then
echo "Error: Source image '$SOURCE' not found." echo "Error: Source image '$SOURCE' not found in $(pwd)"
exit 1 exit 1
fi fi
@ -26,56 +23,66 @@ if [ $? -ne 0 ]; then
exit 1 exit 1
fi fi
mkdir -p "$OUT_DIR" # --- macOS ---
# Keep macOS icons in assets/icons as they are linked explicitly
# macOS MACOS_OUT_DIR="assets/icons"
ICONSET="$OUT_DIR/icon.iconset" mkdir -p "$MACOS_OUT_DIR"
ICONSET="$MACOS_OUT_DIR/icon.iconset"
mkdir -p "$ICONSET" mkdir -p "$ICONSET"
"$MAGICK_BIN" "$SOURCE" -scale 16x16 "$ICONSET/icon_16x16.png" echo "[ICONS] Generating macOS iconset (Pixel Perfect)..."
"$MAGICK_BIN" "$SOURCE" -scale 32x32 "$ICONSET/icon_16x16@2x.png" "$MAGICK_BIN" "$SOURCE" -sample 16x16 "$ICONSET/icon_16x16.png"
"$MAGICK_BIN" "$SOURCE" -scale 32x32 "$ICONSET/icon_32x32.png" "$MAGICK_BIN" "$SOURCE" -sample 32x32 "$ICONSET/icon_16x16@2x.png"
"$MAGICK_BIN" "$SOURCE" -scale 64x64 "$ICONSET/icon_32x32@2x.png" "$MAGICK_BIN" "$SOURCE" -sample 32x32 "$ICONSET/icon_32x32.png"
"$MAGICK_BIN" "$SOURCE" -scale 128x128 "$ICONSET/icon_128x128.png" "$MAGICK_BIN" "$SOURCE" -sample 64x64 "$ICONSET/icon_32x32@2x.png"
"$MAGICK_BIN" "$SOURCE" -scale 256x256 "$ICONSET/icon_128x128@2x.png" "$MAGICK_BIN" "$SOURCE" -sample 128x128 "$ICONSET/icon_128x128.png"
"$MAGICK_BIN" "$SOURCE" -scale 256x256 "$ICONSET/icon_256x256.png" "$MAGICK_BIN" "$SOURCE" -sample 256x256 "$ICONSET/icon_128x128@2x.png"
"$MAGICK_BIN" "$SOURCE" -scale 512x512 "$ICONSET/icon_256x256@2x.png" "$MAGICK_BIN" "$SOURCE" -sample 256x256 "$ICONSET/icon_256x256.png"
"$MAGICK_BIN" "$SOURCE" -scale 512x512 "$ICONSET/icon_512x512.png" "$MAGICK_BIN" "$SOURCE" -sample 512x512 "$ICONSET/icon_256x256@2x.png"
"$MAGICK_BIN" "$SOURCE" -scale 1024x1024 "$ICONSET/icon_512x512@2x.png" "$MAGICK_BIN" "$SOURCE" -sample 512x512 "$ICONSET/icon_512x512.png"
"$MAGICK_BIN" "$SOURCE" -sample 1024x1024 "$ICONSET/icon_512x512@2x.png"
iconutil -c icns "$ICONSET" -o "$OUT_DIR/app_icon.icns" iconutil -c icns "$ICONSET" -o "$MACOS_OUT_DIR/app_icon.icns"
rm -rf "$ICONSET" rm -rf "$ICONSET"
# Windows # --- Windows ---
echo "[ICONS] Generating Windows .ico (Pixel Perfect)..."
# Updated to match the high-quality logic from the Windows Batch file
# (Removed -alpha off and -colors 256 which would ruin transparency)
"$MAGICK_BIN" "$SOURCE" \ "$MAGICK_BIN" "$SOURCE" \
\( -clone 0 -scale 256x256 \) \ -background none -alpha on \
\( -clone 0 -scale 128x128 \) \ \( -clone 0 -sample 256x256 \) \
\( -clone 0 -scale 64x64 \) \ \( -clone 0 -sample 128x128 \) \
\( -clone 0 -scale 48x48 \) \ \( -clone 0 -sample 64x64 \) \
\( -clone 0 -scale 32x32 \) \ \( -clone 0 -sample 48x48 \) \
\( -clone 0 -scale 16x16 \) \ \( -clone 0 -sample 32x32 \) \
-delete 0 -alpha off -colors 256 "$OUT_DIR/app_icon.ico" \( -clone 0 -sample 16x16 \) \
-delete 0 "$MACOS_OUT_DIR/app_icon.ico"
# Android # --- Android ---
echo "Generating Android Icons into $ANDROID_RES_DIR..." # Output directly to android/res so QT_ANDROID_PACKAGE_SOURCE_DIR picks it up
echo "[ICONS] Generating Android mipmaps (Pixel Perfect)..."
ANDROID_DIR="android/res"
mkdir -p "$ANDROID_RES_DIR/mipmap-mdpi" mkdir -p "$ANDROID_DIR/mipmap-mdpi"
"$MAGICK_BIN" "$SOURCE" -scale 48x48 "$ANDROID_RES_DIR/mipmap-mdpi/ic_launcher.png" "$MAGICK_BIN" "$SOURCE" -sample 48x48 "$ANDROID_DIR/mipmap-mdpi/ic_launcher.png"
mkdir -p "$ANDROID_RES_DIR/mipmap-hdpi" mkdir -p "$ANDROID_DIR/mipmap-hdpi"
"$MAGICK_BIN" "$SOURCE" -scale 72x72 "$ANDROID_RES_DIR/mipmap-hdpi/ic_launcher.png" "$MAGICK_BIN" "$SOURCE" -sample 72x72 "$ANDROID_DIR/mipmap-hdpi/ic_launcher.png"
mkdir -p "$ANDROID_RES_DIR/mipmap-xhdpi" mkdir -p "$ANDROID_DIR/mipmap-xhdpi"
"$MAGICK_BIN" "$SOURCE" -scale 96x96 "$ANDROID_RES_DIR/mipmap-xhdpi/ic_launcher.png" "$MAGICK_BIN" "$SOURCE" -sample 96x96 "$ANDROID_DIR/mipmap-xhdpi/ic_launcher.png"
mkdir -p "$ANDROID_RES_DIR/mipmap-xxhdpi" mkdir -p "$ANDROID_DIR/mipmap-xxhdpi"
"$MAGICK_BIN" "$SOURCE" -scale 144x144 "$ANDROID_RES_DIR/mipmap-xxhdpi/ic_launcher.png" "$MAGICK_BIN" "$SOURCE" -sample 144x144 "$ANDROID_DIR/mipmap-xxhdpi/ic_launcher.png"
mkdir -p "$ANDROID_RES_DIR/mipmap-xxxhdpi" mkdir -p "$ANDROID_DIR/mipmap-xxxhdpi"
"$MAGICK_BIN" "$SOURCE" -scale 192x192 "$ANDROID_RES_DIR/mipmap-xxxhdpi/ic_launcher.png" "$MAGICK_BIN" "$SOURCE" -sample 192x192 "$ANDROID_DIR/mipmap-xxxhdpi/ic_launcher.png"
# iOS # --- iOS ---
XCASSETS_DIR="$OUT_DIR/ios/Assets.xcassets" # Output directly to ios/Assets.xcassets
echo "[ICONS] Generating iOS AppIcon (Pixel Perfect)..."
XCASSETS_DIR="ios/Assets.xcassets"
IOS_DIR="$XCASSETS_DIR/AppIcon.appiconset" IOS_DIR="$XCASSETS_DIR/AppIcon.appiconset"
mkdir -p "$IOS_DIR" mkdir -p "$IOS_DIR"
@ -88,21 +95,21 @@ cat > "$XCASSETS_DIR/Contents.json" <<EOF
} }
EOF EOF
"$MAGICK_BIN" "$SOURCE" -scale 20x20 "$IOS_DIR/Icon-20.png" "$MAGICK_BIN" "$SOURCE" -sample 20x20 "$IOS_DIR/Icon-20.png"
"$MAGICK_BIN" "$SOURCE" -scale 40x40 "$IOS_DIR/Icon-20@2x.png" "$MAGICK_BIN" "$SOURCE" -sample 40x40 "$IOS_DIR/Icon-20@2x.png"
"$MAGICK_BIN" "$SOURCE" -scale 60x60 "$IOS_DIR/Icon-20@3x.png" "$MAGICK_BIN" "$SOURCE" -sample 60x60 "$IOS_DIR/Icon-20@3x.png"
"$MAGICK_BIN" "$SOURCE" -scale 29x29 "$IOS_DIR/Icon-29.png" "$MAGICK_BIN" "$SOURCE" -sample 29x29 "$IOS_DIR/Icon-29.png"
"$MAGICK_BIN" "$SOURCE" -scale 58x58 "$IOS_DIR/Icon-29@2x.png" "$MAGICK_BIN" "$SOURCE" -sample 58x58 "$IOS_DIR/Icon-29@2x.png"
"$MAGICK_BIN" "$SOURCE" -scale 87x87 "$IOS_DIR/Icon-29@3x.png" "$MAGICK_BIN" "$SOURCE" -sample 87x87 "$IOS_DIR/Icon-29@3x.png"
"$MAGICK_BIN" "$SOURCE" -scale 40x40 "$IOS_DIR/Icon-40.png" "$MAGICK_BIN" "$SOURCE" -sample 40x40 "$IOS_DIR/Icon-40.png"
"$MAGICK_BIN" "$SOURCE" -scale 80x80 "$IOS_DIR/Icon-40@2x.png" "$MAGICK_BIN" "$SOURCE" -sample 80x80 "$IOS_DIR/Icon-40@2x.png"
"$MAGICK_BIN" "$SOURCE" -scale 120x120 "$IOS_DIR/Icon-40@3x.png" "$MAGICK_BIN" "$SOURCE" -sample 120x120 "$IOS_DIR/Icon-40@3x.png"
"$MAGICK_BIN" "$SOURCE" -scale 120x120 "$IOS_DIR/Icon-60@2x.png" "$MAGICK_BIN" "$SOURCE" -sample 120x120 "$IOS_DIR/Icon-60@2x.png"
"$MAGICK_BIN" "$SOURCE" -scale 180x180 "$IOS_DIR/Icon-60@3x.png" "$MAGICK_BIN" "$SOURCE" -sample 180x180 "$IOS_DIR/Icon-60@3x.png"
"$MAGICK_BIN" "$SOURCE" -scale 76x76 "$IOS_DIR/Icon-76.png" "$MAGICK_BIN" "$SOURCE" -sample 76x76 "$IOS_DIR/Icon-76.png"
"$MAGICK_BIN" "$SOURCE" -scale 152x152 "$IOS_DIR/Icon-76@2x.png" "$MAGICK_BIN" "$SOURCE" -sample 152x152 "$IOS_DIR/Icon-76@2x.png"
"$MAGICK_BIN" "$SOURCE" -scale 167x167 "$IOS_DIR/Icon-83.5@2x.png" "$MAGICK_BIN" "$SOURCE" -sample 167x167 "$IOS_DIR/Icon-83.5@2x.png"
"$MAGICK_BIN" "$SOURCE" -scale 1024x1024 "$IOS_DIR/Icon-1024.png" "$MAGICK_BIN" "$SOURCE" -sample 1024x1024 "$IOS_DIR/Icon-1024.png"
cat > "$IOS_DIR/Contents.json" <<EOF cat > "$IOS_DIR/Contents.json" <<EOF
{ {
@ -133,3 +140,5 @@ cat > "$IOS_DIR/Contents.json" <<EOF
} }
} }
EOF EOF
echo "[SUCCESS] All platform icons generated."

0
temp_legacy_core.c Normal file
View File

795
temp_legacy_impedance.c Normal file
View File

@ -0,0 +1,795 @@
// 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
/* Forward declaration */
AD5940Err AppIMPCheckFreq(float freq);
AppIMPCfg_Type AppIMPCfg =
{
.bParaChanged = bFALSE,
.SeqStartAddr = 0,
.MaxSeqLen = 0,
.SeqStartAddrCal = 0,
.MaxSeqLenCal = 0,
.ImpODR = 20.0, /* Output Data Rate: 20.0 Hz */
.NumOfData = 101, /* Default to 101 points (matches default sweep) */
.RealDataCount = -1,
.SysClkFreq = 16000000.0,
.WuptClkFreq = 32000.0, /* Low Frequency Oscillator (LFO) typically 32kHz */
.AdcClkFreq = 16000000.0,
.RcalVal = 100.0, /* Calibration Resistor Value (Ohms) */
.RtiaVal = 200.0, /* TIA Gain Resistor Value (Ohms) */
.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, /* Excitation Amplitude (mV peak-to-peak) */
.BiasVolt = -0.0f, /* DC Bias Voltage */
.SinFreq = 1000.0, /* Fixed Frequency (Hz) */
.DftNum = DFTNUM_16384, /* DFT Point Count */
.DftSrc = DFTSRC_SINC3,
.HanWinEn = bTRUE, /* Hanning Window for spectral leakage reduction */
.AdcPgaGain = ADCPGA_1P5,
.ADCSinc3Osr = ADCSINC3OSR_2,
.ADCSinc2Osr = ADCSINC2OSR_22,
.ADCAvgNum = ADCAVGNUM_16,
/* Default Sweep: 1kHz to 100kHz, 50 Points Per Decade (Log) */
/* Decades = log10(100k) - log10(1k) = 2. Points = 2 * 50 + 1 = 101 */
.SweepCfg.SweepEn = bTRUE,
.SweepCfg.SweepStart = 1000.0,
.SweepCfg.SweepStop = 100000.0,
.SweepCfg.SweepPoints = 101,
.SweepCfg.SweepLog = bTRUE,
.SweepCfg.SweepIndex = 0,
.FifoThresh = 6, /* Threshold: 3 measurements * 2 (Real/Imag) = 6 words */
.IMPInited = bFALSE,
.StopRequired = bFALSE,
};
/* ----------------------------------------------------------------------- */
/* Helper Functions */
/* ----------------------------------------------------------------------- */
/**
* @brief Configures the Impedance Sweep parameters.
* @param start Start Frequency in Hz
* @param stop Stop Frequency in Hz
* @param ppd Points Per Decade (Resolution)
*/
void AppIMPConfigureSweep(float start, float stop, float ppd) {
if (start <= 0 || stop <= 0 || ppd <= 0) return;
AppIMPCfg.SweepCfg.SweepEn = bTRUE;
AppIMPCfg.SweepCfg.SweepStart = start;
AppIMPCfg.SweepCfg.SweepStop = stop;
AppIMPCfg.SweepCfg.SweepLog = bTRUE;
// Calculate total points based on decades and PPD
// Formula: Points = (Decades * PPD) + 1
float decades = log10f(stop) - log10f(start);
if (decades < 0) decades = -decades; // Handle sweep down if needed
uint32_t points = (uint32_t)(decades * ppd) + 1;
AppIMPCfg.SweepCfg.SweepPoints = points;
// Set NumOfData to stop the sequencer automatically after the sweep
AppIMPCfg.NumOfData = points;
// Reset Sweep State
AppIMPCfg.FifoDataCount = 0;
AppIMPCfg.SweepCfg.SweepIndex = 0;
AppIMPCfg.SweepCurrFreq = start;
AppIMPCfg.SweepNextFreq = start;
}
void AppIMPCleanup(void) {
// Ensure chip is awake before sending commands
if(AD5940_WakeUp(10) > 10) return;
// Stop Sequencer and Wakeup Timer
AD5940_WUPTCtrl(bFALSE);
AD5940_SEQCtrlS(bFALSE);
// Stop active conversions and Waveform Generator, keep Reference/LDOs on
AD5940_AFECtrlS(AFECTRL_ADCCNV|AFECTRL_DFT|AFECTRL_WG, bFALSE);
// Reset FIFO configuration
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);
// Clear all interrupt flags
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;
// Measure LFOSC frequency to calibrate Wakeup Timer
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:
{
// Configure interrupts and trigger the first sequence manually
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;
// Reset Sweep State for subsequent sweeps
if(AppIMPCfg.SweepCfg.SweepEn)
{
AppIMPCfg.SweepCfg.SweepIndex = 0;
AppIMPCfg.SweepCurrFreq = AppIMPCfg.SweepCfg.SweepStart;
AppIMPCfg.FreqofData = AppIMPCfg.SweepCfg.SweepStart;
// Calculate next frequency immediately so the ISR has the correct 'next' value
AD5940_SweepNext(&AppIMPCfg.SweepCfg, &AppIMPCfg.SweepNextFreq);
// Reset Hardware WG Frequency to Start Frequency (it was left at Stop Freq)
AD5940_WGFreqCtrlS(AppIMPCfg.SweepCurrFreq, AppIMPCfg.SysClkFreq);
// Reset SRAM Wait Times for the Start Frequency
AppIMPCheckFreq(AppIMPCfg.SweepCurrFreq);
}
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;
}
/* Generate Initialization Sequence */
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);
// Configure Reference System (High Power and Low Power Buffers)
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);
// Configure High Speed Loop (DAC and TIA)
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;
// Configure Switch Matrix
HsLoopCfg.SWMatCfg.Dswitch = AppIMPCfg.DswitchSel;
HsLoopCfg.SWMatCfg.Pswitch = AppIMPCfg.PswitchSel;
HsLoopCfg.SWMatCfg.Nswitch = AppIMPCfg.NswitchSel;
HsLoopCfg.SWMatCfg.Tswitch = SWT_TRTIA|AppIMPCfg.TswitchSel;
// Configure Waveform Generator (Sine Wave)
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);
// Configure DSP and ADC
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);
// Enable Power for AFE blocks
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;
}
/* Generate Measurement Sequence */
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;
// Calculate settling time (WaitClks) based on DFT/Filter settings
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));
/* ----------------------------------------------------------------------- */
/* Step 1: Measure Current across RCAL (Calibration) */
/* ----------------------------------------------------------------------- */
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);
// Enable AFE Power and Waveform Generator
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);
// Store address to update wait times later during sweep
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);
/* ----------------------------------------------------------------------- */
/* Step 2: Measure 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));
AD5940_AFECtrlS(AFECTRL_ADCCNV|AFECTRL_DFT, bFALSE);
AD5940_SEQGenInsert(SEQ_WAIT(16*10));
AD5940_AFECtrlS(AFECTRL_WG, bFALSE);
/* ----------------------------------------------------------------------- */
/* Step 3: Measure 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, 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);
// Power down AFE blocks
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);
// Recalculate settling times (WaitClks) for the new frequency
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;
// Stop timers 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);
// Wait for initialization sequence to complete
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);
// Calculate Impedance: Z = (V / I) * Rtia
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);
// Discard extra data points if they exceed the requested count
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;
}

375
temp_legacy_main.c Normal file
View File

@ -0,0 +1,375 @@
// File: main.c
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include "pico/stdlib.h"
#include "hardware/spi.h"
#include "hardware/gpio.h"
#include "hardware/watchdog.h"
#include "ad5940.h"
#include "Impedance.h"
// ---------------------------------------------------------------------------
// Hardware Definitions
// ---------------------------------------------------------------------------
#define PIN_MISO 0
#define PIN_CS 1
#define PIN_SCK 2
#define PIN_MOSI 3
#define PIN_RST 9
#define PIN_INT 29
#define APPBUFF_SIZE 512
uint32_t AppBuff[APPBUFF_SIZE];
// ---------------------------------------------------------------------------
// Platform Interface Implementation
// ---------------------------------------------------------------------------
void AD5940_CsClr(void) { gpio_put(PIN_CS, 0); }
void AD5940_CsSet(void) { gpio_put(PIN_CS, 1); }
void AD5940_RstClr(void) { gpio_put(PIN_RST, 0); }
void AD5940_RstSet(void) { gpio_put(PIN_RST, 1); }
void AD5940_Delay10us(uint32_t time) { sleep_us(time * 10); }
void AD5940_ReadWriteNBytes(unsigned char *pSendBuffer, unsigned char *pRecvBuff, unsigned long length) {
spi_write_read_blocking(spi0, pSendBuffer, pRecvBuff, length);
}
uint32_t AD5940_GetMCUIntFlag(void) {
return (gpio_get(PIN_INT) == 0);
}
uint32_t AD5940_ClrMCUIntFlag(void) {
return 1;
}
uint32_t AD5940_MCUResourceInit(void *pCfg) {
return 0;
}
void AD5940_MCUGpioWrite(uint32_t data) { (void)data; }
uint32_t AD5940_MCUGpioRead(uint32_t pin) { (void)pin; return 0; }
void AD5940_MCUGpioCtrl(uint32_t pin, BoolFlag enable) { (void)pin; (void)enable; }
// ---------------------------------------------------------------------------
// Application Logic
// ---------------------------------------------------------------------------
void setup_pins(void) {
spi_init(spi0, 4000000);
gpio_set_function(PIN_MISO, GPIO_FUNC_SPI);
gpio_set_function(PIN_SCK, GPIO_FUNC_SPI);
gpio_set_function(PIN_MOSI, GPIO_FUNC_SPI);
gpio_init(PIN_CS);
gpio_set_dir(PIN_CS, GPIO_OUT);
gpio_put(PIN_CS, 1);
gpio_init(PIN_RST);
gpio_set_dir(PIN_RST, GPIO_OUT);
gpio_put(PIN_RST, 1);
gpio_init(PIN_INT);
gpio_set_dir(PIN_INT, GPIO_IN);
gpio_pull_up(PIN_INT);
}
void AD5940ImpedanceStructInit(void)
{
AppIMPCfg_Type *pImpedanceCfg;
AppIMPGetCfg(&pImpedanceCfg);
pImpedanceCfg->SeqStartAddr = 0;
pImpedanceCfg->MaxSeqLen = 512;
pImpedanceCfg->RcalVal = 100.0;
pImpedanceCfg->RtiaVal = 200.0;
pImpedanceCfg->SinFreq = 1000.0;
pImpedanceCfg->FifoThresh = 6;
pImpedanceCfg->DacVoltPP = 600.0;
pImpedanceCfg->ExcitBufGain = EXCITBUFGAIN_0P25;
pImpedanceCfg->HsDacGain = HSDACGAIN_0P2;
pImpedanceCfg->DswitchSel = SWD_CE0;
pImpedanceCfg->PswitchSel = SWP_CE0;
pImpedanceCfg->NswitchSel = SWN_SE0;
pImpedanceCfg->TswitchSel = SWT_SE0LOAD;
pImpedanceCfg->HstiaRtiaSel = HSTIARTIA_200;
pImpedanceCfg->BiasVolt = 0.0;
pImpedanceCfg->SweepCfg.SweepEn = bFALSE;
pImpedanceCfg->SweepCfg.SweepStart = 100.0f;
pImpedanceCfg->SweepCfg.SweepStop = 100000.0f;
pImpedanceCfg->SweepCfg.SweepPoints = 50;
pImpedanceCfg->SweepCfg.SweepLog = bTRUE;
pImpedanceCfg->PwrMod = AFEPWR_LP;
pImpedanceCfg->ADCSinc3Osr = ADCSINC3OSR_4;
pImpedanceCfg->DftNum = DFTNUM_16384;
pImpedanceCfg->DftSrc = DFTSRC_SINC3;
}
static int32_t AD5940PlatformCfg(void)
{
CLKCfg_Type clk_cfg;
FIFOCfg_Type fifo_cfg;
AGPIOCfg_Type gpio_cfg;
AD5940_HWReset();
AD5940_Initialize();
// Use HFOSC (16MHz) for stability across all frequencies
clk_cfg.ADCClkDiv = ADCCLKDIV_1;
clk_cfg.ADCCLkSrc = ADCCLKSRC_HFOSC;
clk_cfg.SysClkDiv = SYSCLKDIV_1;
clk_cfg.SysClkSrc = SYSCLKSRC_HFOSC;
clk_cfg.HfOSC32MHzMode = bFALSE;
clk_cfg.HFOSCEn = bTRUE;
clk_cfg.HFXTALEn = bFALSE;
clk_cfg.LFOSCEn = bTRUE;
AD5940_CLKCfg(&clk_cfg);
printf("Clock Configured (HFOSC 16MHz).\n");
fifo_cfg.FIFOEn = bFALSE;
fifo_cfg.FIFOMode = FIFOMODE_FIFO;
fifo_cfg.FIFOSize = FIFOSIZE_4KB;
fifo_cfg.FIFOSrc = FIFOSRC_DFT;
fifo_cfg.FIFOThresh = 6;
AD5940_FIFOCfg(&fifo_cfg);
fifo_cfg.FIFOEn = bTRUE;
AD5940_FIFOCfg(&fifo_cfg);
AD5940_INTCCfg(AFEINTC_1, AFEINTSRC_ALLINT, bTRUE);
AD5940_INTCClrFlag(AFEINTSRC_ALLINT);
AD5940_INTCCfg(AFEINTC_0, AFEINTSRC_DATAFIFOTHRESH, bTRUE);
AD5940_INTCClrFlag(AFEINTSRC_ALLINT);
gpio_cfg.FuncSet = GP0_INT;
gpio_cfg.InputEnSet = 0;
gpio_cfg.OutputEnSet = AGPIO_Pin0;
gpio_cfg.OutVal = 0;
gpio_cfg.PullEnSet = 0;
AD5940_AGPIOCfg(&gpio_cfg);
AD5940_SleepKeyCtrlS(SLPKEY_UNLOCK);
return 0;
}
void ImpedanceShowResult(uint32_t *pData, uint32_t DataCount)
{
float freq;
fImpPol_Type *pImp = (fImpPol_Type*)pData;
AppIMPCtrl(IMPCTRL_GETFREQ, &freq);
for(int i=0;i<DataCount;i++)
{
float mag = pImp[i].Magnitude;
float phase = pImp[i].Phase;
float real = mag * cosf(phase);
float imag = mag * sinf(phase);
printf("DATA,%.2f,%.4f,%.4f,%.4f,%.4f\n",
freq,
mag,
phase * 180.0f / MATH_PI,
real,
imag
);
}
}
// ---------------------------------------------------------------------------
// High-Level Routines
// ---------------------------------------------------------------------------
void Routine_CalibrateLFO(void) {
printf(">> Calibrating LFOSC...\n");
AppIMPCleanup();
AppIMPCalibrateLFO();
printf(">> LFOSC Calibrated.\n");
}
void Routine_Measure(float freq) {
AppIMPCfg_Type *pCfg;
AppIMPGetCfg(&pCfg);
AppIMPCleanup();
AppIMPCalibrateLFO();
pCfg->SweepCfg.SweepEn = bFALSE;
pCfg->SinFreq = freq;
pCfg->NumOfData = -1;
pCfg->RealDataCount = -1; // Disable filtering
pCfg->bParaChanged = bTRUE;
if(AppIMPInit(AppBuff, APPBUFF_SIZE) == AD5940ERR_OK) {
AppIMPCtrl(IMPCTRL_START, 0);
} else {
printf("ERROR: Init Failed\n");
}
}
void Routine_Sweep(float start, float end, int steps) {
AppIMPCfg_Type *pCfg;
AppIMPGetCfg(&pCfg);
AppIMPCleanup();
AppIMPCalibrateLFO();
pCfg->SweepCfg.SweepEn = bTRUE;
pCfg->SweepCfg.SweepStart = start;
pCfg->SweepCfg.SweepStop = end;
// DUMMY POINT STRATEGY:
// Request steps + 1 from the engine, but tell the ISR to only report 'steps'.
// The artifact will happen on the +1 point, which is discarded.
pCfg->SweepCfg.SweepPoints = steps + 1;
pCfg->NumOfData = steps + 1;
pCfg->RealDataCount = steps; // Stop reporting after this count
pCfg->SweepCfg.SweepLog = bTRUE;
pCfg->bParaChanged = bTRUE;
if(AppIMPInit(AppBuff, APPBUFF_SIZE) == AD5940ERR_OK) {
AppIMPCtrl(IMPCTRL_START, 0);
} else {
printf("ERROR: Init Failed\n");
}
}
void Routine_CalibrateSystem(void) {
AppIMPCfg_Type *pCfg;
AppIMPGetCfg(&pCfg);
AppIMPCleanup();
// 1. ADC Calibration
ADCPGACal_Type adcpga_cal;
adcpga_cal.AdcClkFreq = 16000000.0;
adcpga_cal.SysClkFreq = 16000000.0;
adcpga_cal.ADCSinc3Osr = ADCSINC3OSR_4;
adcpga_cal.ADCSinc2Osr = ADCSINC2OSR_22;
adcpga_cal.ADCPga = ADCPGA_1P5;
adcpga_cal.PGACalType = PGACALTYPE_OFFSET;
adcpga_cal.TimeOut10us = 1000;
adcpga_cal.VRef1p11 = 1.11;
adcpga_cal.VRef1p82 = 1.82;
printf(">> Calibrating ADC Offset...\n");
AD5940_ADCPGACal(&adcpga_cal);
// 2. HSDAC Configuration
HSDACCfg_Type hsdac_cfg;
hsdac_cfg.ExcitBufGain = EXCITBUFGAIN_0P25;
hsdac_cfg.HsDacGain = HSDACGAIN_0P2;
hsdac_cfg.HsDacUpdateRate = 7;
AD5940_HSDacCfgS(&hsdac_cfg);
// 3. RTIA Calibration
HSRTIACal_Type hsrtia_cal;
fImpPol_Type Res;
memset(&hsrtia_cal, 0, sizeof(hsrtia_cal));
hsrtia_cal.fFreq = 1000.0f;
hsrtia_cal.AdcClkFreq = 16000000.0;
hsrtia_cal.SysClkFreq = 16000000.0;
hsrtia_cal.ADCSinc3Osr = ADCSINC3OSR_4;
hsrtia_cal.ADCSinc2Osr = ADCSINC2OSR_22;
hsrtia_cal.bPolarResult = bTRUE;
hsrtia_cal.fRcal = 100.0;
hsrtia_cal.HsTiaCfg.DiodeClose = bFALSE;
hsrtia_cal.HsTiaCfg.HstiaBias = HSTIABIAS_1P1;
hsrtia_cal.HsTiaCfg.HstiaCtia = 31;
hsrtia_cal.HsTiaCfg.HstiaRtiaSel = HSTIARTIA_200;
hsrtia_cal.HsTiaCfg.HstiaDeRtia = HSTIADERTIA_OPEN;
hsrtia_cal.HsTiaCfg.HstiaDeRload = HSTIADERLOAD_OPEN;
hsrtia_cal.DftCfg.DftNum = DFTNUM_16384;
hsrtia_cal.DftCfg.DftSrc = DFTSRC_SINC3;
printf(">> Calibrating HSTIARTIA_200...\n");
if (AD5940_HSRtiaCal(&hsrtia_cal, &Res) == AD5940ERR_OK) {
printf("Calibrated Rtia: Mag = %f Ohm, Phase = %f\n", Res.Magnitude, Res.Phase);
pCfg->RtiaVal = Res.Magnitude;
} else {
printf("Calibration Failed\n");
}
}
// ---------------------------------------------------------------------------
// Main Loop
// ---------------------------------------------------------------------------
char input_buffer[64];
int input_pos = 0;
void process_command() {
char cmd = input_buffer[0];
sleep_ms(10);
if (cmd == 'v') {
uint32_t id = AD5940_ReadReg(REG_AFECON_CHIPID);
printf("CHIP_ID:0x%04X\n", id);
}
else if (cmd == 'c') {
Routine_CalibrateSystem();
}
else if (cmd == 'm') {
float freq = 1000.0f;
if (strlen(input_buffer) > 2) freq = atof(input_buffer + 2);
Routine_Measure(freq);
}
else if (cmd == 's') {
float start = 100.0f, end = 100000.0f;
int steps = 50;
if (strlen(input_buffer) > 2) sscanf(input_buffer + 2, "%f %f %d", &start, &end, &steps);
Routine_Sweep(start, end, steps);
}
else if (cmd == 'x') {
AppIMPCleanup();
printf("STOPPED\n");
}
else if (cmd == 'z') {
watchdog_reboot(0, 0, 0);
}
}
int main() {
stdio_init_all();
sleep_ms(2000);
setup_pins();
AD5940PlatformCfg();
AD5940ImpedanceStructInit();
printf("SYSTEM_READY\n");
while (true) {
int c = getchar_timeout_us(0);
if (c != PICO_ERROR_TIMEOUT) {
if (c == '\n' || c == '\r') {
input_buffer[input_pos] = 0;
if (input_pos > 0) process_command();
input_pos = 0;
} else if (input_pos < 63) {
input_buffer[input_pos++] = (char)c;
}
}
if (gpio_get(PIN_INT) == 0) {
uint32_t temp = APPBUFF_SIZE;
int32_t status = AppIMPISR(AppBuff, &temp);
if (status == AD5940ERR_FIFO) {
printf("ERROR: FIFO Overflow/Underflow. Stopping.\n");
AppIMPCleanup();
} else if(temp > 0) {
ImpedanceShowResult(AppBuff, temp);
}
}
}
return 0;
}