AutoSpa/examples/rp2040_port/Measurement_Routines.c

573 lines
18 KiB
C

// File: Measurement_Routines.c
#include "App_Common.h"
#include "Impedance.h"
// Forward declaration if not in header
// int32_t ImpedanceShowResult(uint32_t *pData, uint32_t DataCount);
void Routine_CalibrateLFO(void) {
printf(">> Calibrating LFOSC...\n");
if (CurrentMode == MODE_IMPEDANCE)
AppIMPCleanup();
else if (CurrentMode == MODE_AMPEROMETRIC)
AppAMPCtrl(AMPCTRL_SHUTDOWN, 0);
else if (CurrentMode == MODE_RAMP)
AppRAMPCtrl(APPCTRL_SHUTDOWN, 0);
LFOSCMeasure_Type cal_cfg;
cal_cfg.CalDuration = 1000.0;
cal_cfg.CalSeqAddr = 0;
cal_cfg.SystemClkFreq = 16000000.0;
if (AD5940_LFOSCMeasure(&cal_cfg, &LFOSCFreq) == AD5940ERR_OK) {
printf(">> LFOSC Calibrated: %.2f Hz\n", LFOSCFreq);
} else {
printf(">> LFOSC Calibration Failed.\n");
}
}
// Helper to show results (adapted from test/AD5940Main.c)
void ImpedanceShowResult(uint32_t *pData, uint32_t DataCount) {
float freq;
fImpPol_Type *pImp = (fImpPol_Type *)pData;
AppIMPCtrl(IMPCTRL_GETFREQ, &freq);
/*Process data*/
for (int i = 0; i < DataCount; i++) {
printf("DATA,%.2f,0,0,%.6f,%.6f\n", freq, pImp[i].Magnitude, pImp[i].Phase);
}
}
void Routine_Measure(float freq, float bias_mv) {
if (CurrentMode == MODE_AMPEROMETRIC)
AppAMPCtrl(AMPCTRL_SHUTDOWN, 0);
else if (CurrentMode == MODE_RAMP)
AppRAMPCtrl(APPCTRL_SHUTDOWN, 0);
CurrentMode = MODE_IMPEDANCE;
// Cleanup any previous run
AppIMPCleanup();
// Initialize Structure
AD5940ImpedanceStructInit();
AppIMPCfg_Type *pCfg;
AppIMPGetCfg(&pCfg);
pCfg->WuptClkFreq = LFOSCFreq;
pCfg->SweepCfg.SweepEn = bFALSE;
pCfg->SinFreq = freq;
pCfg->NumOfData = -1; // Changes based on new logic? Test uses -1 for single
// point? No, test creates sequence.
// Apply Global Settings
pCfg->ShortRe0Se0 = GlobalShortRe0Se0;
pCfg->HstiaRtiaSel = GetHSTIARtia(ConfigHstiaVal);
// Apply Calibration Values
pCfg->RtiaVal = CalibratedHstiaVal;
pCfg->AdcPhaseOffset = CalibratedHstiaPhase;
pCfg->BiasVolt = bias_mv;
pCfg->bParaChanged = bTRUE;
// Initialize App
if (AppIMPInit(AppBuff, APPBUFF_SIZE) != AD5940ERR_OK) {
printf("ERROR: Init Failed\n");
return;
}
// Calibrate RTIA (New implementation requires this)
AppIMPRtiaCal();
// Start Measurement
AppIMPCtrl(IMPCTRL_START, 0);
// Poll for result (Blocking, similar to sweep) - or rely on Interrupt?
// The test code uses polling for sweep. For single measure, we can use the
// ISR method currently in main.c, BUT we need to make sure AppIMPInit didn't
// break anything. Actually, let's keep it consistent with the Sweep logic for
// now to ensure it works.
while (1) {
if (AD5940_GetMCUIntFlag()) {
AD5940_ClrMCUIntFlag();
uint32_t temp = APPBUFF_SIZE;
AppIMPISR(AppBuff, &temp);
ImpedanceShowResult(AppBuff, temp);
break;
}
// Timeout check?
}
}
// Sweep Implementation matching test/AD5940Main.c
void Routine_Sweep(float start, float end, int steps, float bias_mv) {
if (CurrentMode == MODE_AMPEROMETRIC)
AppAMPCtrl(AMPCTRL_SHUTDOWN, 0);
else if (CurrentMode == MODE_RAMP)
AppRAMPCtrl(APPCTRL_SHUTDOWN, 0);
CurrentMode = MODE_IMPEDANCE;
AppIMPCfg_Type *pCfg;
AppIMPGetCfg(&pCfg);
// Initial Setup
AD5940ImpedanceStructInit();
pCfg->WuptClkFreq = LFOSCFreq;
pCfg->ShortRe0Se0 = GlobalShortRe0Se0;
pCfg->HstiaRtiaSel = GetHSTIARtia(ConfigHstiaVal);
pCfg->BiasVolt = bias_mv;
// Apply Calibration Values
pCfg->RtiaVal = CalibratedHstiaVal;
pCfg->AdcPhaseOffset = CalibratedHstiaPhase;
// Calculate Sweep Points
float log_step = pow(end / start, 1.0 / (steps - 1));
float curr_freq = start;
printf("Starting Software Sweep: %.2f Hz to %.2f Hz, %d points\n", start, end,
steps);
for (int i = 0; i < steps; i++) {
// Check for Abort from UART (User wants to stop)
int c = getchar_timeout_us(0);
if (c == 'x') {
printf("Sweep Aborted by User.\n");
AppIMPCleanup();
break;
}
uint32_t temp;
/* Update Frequency */
pCfg->SinFreq = curr_freq;
pCfg->bParaChanged = bTRUE; // Force sequence regeneration
/* Re-Initialize App to apply new frequency (this regenerates sequences) */
printf("DEBUG: Before Init for %.2f\n", curr_freq);
if (AppIMPInit(AppBuff, APPBUFF_SIZE) != AD5940ERR_OK) {
printf("ERROR: Init failed at %.2f\n", curr_freq);
break;
}
printf("DEBUG: After Init\n");
/* Calibrate RTIA at this frequency (Already done in AppIMPInit) */
// AppIMPRtiaCal();
/* Measure Impedance */
printf("DEBUG: Starting Measurement\n");
AppIMPCtrl(IMPCTRL_START, 0);
/* Wait for result */
int timeout = 100000; // 1s timeout approx
while (timeout > 0) {
if (AD5940_GetMCUIntFlag()) {
// printf("DEBUG: Interrupt Triggered\n");
AD5940_ClrMCUIntFlag();
temp = APPBUFF_SIZE;
AppIMPISR(AppBuff, &temp);
if (temp > 0) {
// printf("DEBUG: ISR processed %d items\n", temp);
ImpedanceShowResult(AppBuff, temp);
break; // Done with this point only if we got data
} else {
// Spurious interrupt or not enough data yet
// printf("DEBUG: Spurious INT, 0 items. Continue waiting.\n");
}
}
AD5940_Delay10us(1);
timeout--;
}
if (timeout <= 0) {
printf("timeout at freq: %.2f\n", curr_freq);
}
/* Next Frequency */
curr_freq *= log_step;
}
AppIMPCleanup(); // Stop hardware
printf("Sweep Completed.\n");
}
void Routine_Amperometric(float bias_mv) {
if (CurrentMode == MODE_IMPEDANCE)
AppIMPCleanup();
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);
AppAMPCfg_Type *pCfg;
AppAMPGetCfg(&pCfg);
AD5940AMPStructInit(); // Reload config with current LP settings
pCfg->SensorBias = bias_mv;
pCfg->ReDoRtiaCal = bFALSE; // Use pre-calibrated value
if (AppAMPInit(AppBuff, APPBUFF_SIZE) == AD5940ERR_OK) {
AppAMPCtrl(AMPCTRL_START, 0);
} else {
printf("ERROR: AMP Init Failed\n");
}
}
void Routine_LSV(float start_mv, float end_mv, int steps, int duration_ms) {
if (CurrentMode == MODE_IMPEDANCE)
AppIMPCleanup();
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);
AppRAMPCfg_Type *pCfg;
AppRAMPGetCfg(&pCfg);
AD5940RampStructInit(); // Reload config with current LP settings
pCfg->RampStartVolt = start_mv;
pCfg->RampPeakVolt = end_mv;
pCfg->StepNumber = steps;
pCfg->RampDuration = duration_ms;
pCfg->bRampOneDir = bTRUE;
pCfg->bParaChanged = bTRUE;
if (AppRAMPInit(AppBuff, APPBUFF_SIZE) == AD5940ERR_OK) {
AppRAMPCtrl(APPCTRL_START, 0);
} else {
printf("ERROR: RAMP Init Failed\n");
}
}
extern void __AD5940_ReferenceON(void);
// Custom LPTIA Calibration using Internal HSTIA as Reference
// Routing: Excitation -> RE0/CE0, Short SE0
// This allows using HSTIA internal RTIA (e.g. 1k, 5k, etc) as the reference
// Rcal instead of the fixed external 100 Ohm Rcal which causes saturation.
AD5940Err AD5940_LPRtiaCal_UserCustom(LPRTIACal_Type *pCalCfg, void *pResult) {
HSLoopCfg_Type hs_loop;
LPLoopCfg_Type lp_loop;
DSPCfg_Type dsp_cfg;
ADCBaseCfg_Type *pADCBaseCfg;
SWMatrixCfg_Type *pSWCfg;
uint32_t INTCCfg;
BoolFlag bADCClk32MHzMode = bFALSE;
float ExcitVolt;
uint32_t RtiaVal;
uint32_t const LpRtiaTable[] = {
0, 110, 1000, 2000, 3000, 4000, 6000, 8000, 10000,
12000, 16000, 20000, 24000, 30000, 32000, 40000, 48000, 64000,
85000, 96000, 100000, 120000, 128000, 160000, 196000, 256000, 512000};
float const ADCPGAGainTable[] = {1, 1.5, 2, 4, 9};
uint32_t WgAmpWord;
uint32_t ADCPgaGainRtia, ADCPgaGainRcal;
float GainRatio;
iImpCar_Type DftRcal, DftRtia;
if (pCalCfg == NULL)
return AD5940ERR_NULLP;
if (pResult == NULL)
return AD5940ERR_NULLP;
if (pCalCfg->AdcClkFreq > (32000000 * 0.8))
bADCClk32MHzMode = bTRUE;
// Initialize Pointers
pSWCfg = &hs_loop.SWMatCfg;
pADCBaseCfg = &dsp_cfg.ADCBaseCfg;
RtiaVal = LpRtiaTable[pCalCfg->LpTiaRtia];
// Calculate Excitation Voltage
// Note: We are using HSTIA as Reference (Rcal).
// Let's assume we use 1k Internal HSTIA RTIA as Rcal for this calculation to
// aim for 800mVpp
float RcalEffective = 1000.0f; // Approximate
ExcitVolt = 2000 * 0.8 * RcalEffective / RtiaVal;
WgAmpWord = ((uint32_t)(ExcitVolt / 2200 * 2047 * 2) + 1) >> 1;
if (WgAmpWord > 0x7FF)
WgAmpWord = 0x7FF;
// Store original AFECON
// uint32_t reg_afecon = AD5940_ReadReg(REG_AFE_AFECON); // Unused in this
// snippet but good practice to restore if needed
// INTC Config
INTCCfg = AD5940_INTCGetCfg(AFEINTC_1);
AD5940_INTCCfg(AFEINTC_1, AFEINTSRC_DFTRDY | AFEINTSRC_SINC2RDY, bTRUE);
AD5940_INTCClrFlag(AFEINTSRC_ALLINT);
AD5940_AFECtrlS(AFECTRL_ALL, bFALSE);
/* Helper to turn on reference - adapted from AD5940_ReferenceON */
AFERefCfg_Type aferef_cfg;
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);
// __AD5940_ReferenceON();
// DSP Config
AD5940_StructInit(&dsp_cfg, sizeof(dsp_cfg));
dsp_cfg.ADCFilterCfg.ADCAvgNum = ADCAVGNUM_16;
dsp_cfg.ADCFilterCfg.ADCRate =
bADCClk32MHzMode ? ADCRATE_1P6MHZ : ADCRATE_800KHZ;
dsp_cfg.ADCFilterCfg.ADCSinc2Osr = pCalCfg->ADCSinc2Osr;
dsp_cfg.ADCFilterCfg.ADCSinc3Osr = pCalCfg->ADCSinc3Osr;
dsp_cfg.ADCFilterCfg.BpNotch = bTRUE;
dsp_cfg.ADCFilterCfg.BpSinc3 = bFALSE;
dsp_cfg.ADCFilterCfg.Sinc2NotchEnable = bTRUE;
memcpy(&dsp_cfg.DftCfg, &pCalCfg->DftCfg, sizeof(pCalCfg->DftCfg));
AD5940_DSPCfgS(&dsp_cfg);
// LP Loop Config
AD5940_StructInit(&lp_loop, sizeof(lp_loop));
lp_loop.LpDacCfg.LpdacSel = LPDAC0;
lp_loop.LpDacCfg.DacData12Bit = 0x800;
lp_loop.LpDacCfg.DacData6Bit = 32;
lp_loop.LpDacCfg.DataRst = bFALSE;
lp_loop.LpDacCfg.LpDacSW =
LPDACSW_VBIAS2LPPA | LPDACSW_VZERO2HSTIA; // Vzero to HSTIA
lp_loop.LpDacCfg.LpDacRef = LPDACREF_2P5;
lp_loop.LpDacCfg.LpDacSrc = LPDACSRC_WG;
lp_loop.LpDacCfg.LpDacVbiasMux = LPDACVBIAS_6BIT;
lp_loop.LpDacCfg.LpDacVzeroMux = LPDACVZERO_12BIT;
lp_loop.LpDacCfg.PowerEn = bTRUE;
lp_loop.LpAmpCfg.LpAmpSel = pCalCfg->LpAmpSel;
lp_loop.LpAmpCfg.LpAmpPwrMod = pCalCfg->LpAmpPwrMod;
lp_loop.LpAmpCfg.LpPaPwrEn = bTRUE;
lp_loop.LpAmpCfg.LpTiaPwrEn = bTRUE;
lp_loop.LpAmpCfg.LpTiaRload = LPTIARLOAD_100R;
lp_loop.LpAmpCfg.LpTiaRtia = pCalCfg->LpTiaRtia;
lp_loop.LpAmpCfg.LpTiaRf = LPTIARF_OPEN;
// Use User Routing for LPTIA Switches if needed, but standard should work for
// TIA part
lp_loop.LpAmpCfg.LpTiaSW =
LPTIASW(6) | LPTIASW(8) | (pCalCfg->bWithCtia == bTRUE ? LPTIASW(5) : 0);
AD5940_LPLoopCfgS(&lp_loop);
// HS Loop Config
AD5940_StructInit(&hs_loop, sizeof(hs_loop));
hs_loop.HsTiaCfg.DiodeClose = bFALSE;
hs_loop.HsTiaCfg.HstiaBias = HSTIABIAS_VZERO0; // Bias from LPDAC Vzero
hs_loop.HsTiaCfg.HstiaCtia = 31;
hs_loop.HsTiaCfg.HstiaDeRload = HSTIADERLOAD_OPEN;
hs_loop.HsTiaCfg.HstiaDeRtia = HSTIADERTIA_OPEN;
hs_loop.HsTiaCfg.HstiaDe1Rload = HSTIADERLOAD_OPEN;
hs_loop.HsTiaCfg.HstiaDe1Rtia = HSTIADERTIA_OPEN;
// Use 1k Internal RTIA as Reference (or match approximate LPTIA range if
// possible, but 1k is a safe start)
hs_loop.HsTiaCfg.HstiaRtiaSel = HSTIARTIA_1K;
hs_loop.HsDacCfg.ExcitBufGain = 0;
hs_loop.HsDacCfg.HsDacGain = 0;
hs_loop.HsDacCfg.HsDacUpdateRate = 255;
// USER ROUTING: RE0, CE0, SE0(Short)
// Dswitch: Connect SE0
// Pswitch: Connect RE0
// Nswitch: Connect SE0LOAD? Or use SE0 as N?
// User said "utilizing reo and setting it to re0 and ce0 then shorting se0"
// -> SE0 is shorted to RE0? Let's try standard Ladder Routing logic:
// Excitation via CE0/RE0 (P/N switches?) or High Power loop?
// Actually, for LPTIA Cal, we use LPDAC/WG.
// We need to route the current through LPTIA and the Reference.
// Standard Cal uses RCAL0/RCAL1.
// We want to use HSTIA.
// Connect HSTIA to SE0?
// Implementation based on interpretation:
// SWP = RE0 (Excitation P side)
// SWN = SE0 (Excitation N side?) No, SE0 is usually sense.
// SWT = TRTIA (Connects HSTIA to T-Matrix)
hs_loop.SWMatCfg.Dswitch = SWD_SE0;
hs_loop.SWMatCfg.Pswitch = SWP_RE0 | SWP_CE0; // "setting it to re0 and ce0"
hs_loop.SWMatCfg.Nswitch =
SWN_SE0; // "shorting se0" - maybe use SE0 as return?
hs_loop.SWMatCfg.Tswitch =
SWT_TRTIA | SWT_SE0LOAD; // Connect HSTIA and SE0LOAD?
AD5940_HSLoopCfgS(&hs_loop);
// Waveform Generator
hs_loop.WgCfg.WgType = WGTYPE_SIN;
hs_loop.WgCfg.GainCalEn = bTRUE;
hs_loop.WgCfg.OffsetCalEn = bTRUE;
hs_loop.WgCfg.SinCfg.SinFreqWord =
AD5940_WGFreqWordCal(pCalCfg->fFreq, pCalCfg->SysClkFreq);
hs_loop.WgCfg.SinCfg.SinAmplitudeWord = WgAmpWord;
hs_loop.WgCfg.SinCfg.SinOffsetWord = 0;
hs_loop.WgCfg.SinCfg.SinPhaseWord = 0;
AD5940_HSLoopCfgS(&hs_loop);
AD5940_AFECtrlS(AFECTRL_HSTIAPWR | AFECTRL_INAMPPWR | AFECTRL_EXTBUFPWR |
AFECTRL_SINC2NOTCH,
bTRUE);
// 1. Measure Reference (HSTIA Internal RTIA)
// We need to measure voltage across HSTIA.
// Mux P = HSTIA_P, Mux N = HSTIA_N
AD5940_ADCMuxCfgS(ADCMUXP_HSTIA_P, ADCMUXN_HSTIA_N);
AD5940_AFECtrlS(AFECTRL_WG | AFECTRL_ADCPWR, bTRUE);
AD5940_Delay10us(25);
AD5940_AFECtrlS(AFECTRL_ADCCNV | AFECTRL_DFT, bTRUE);
while (AD5940_INTCTestFlag(AFEINTC_1, AFEINTSRC_DFTRDY) == bFALSE)
;
AD5940_AFECtrlS(AFECTRL_ADCCNV | AFECTRL_DFT | AFECTRL_WG | AFECTRL_ADCPWR,
bFALSE);
AD5940_INTCClrFlag(AFEINTSRC_DFTRDY);
DftRcal.Real = AD5940_ReadAfeResult(AFERESULT_DFTREAL);
DftRcal.Image = AD5940_ReadAfeResult(AFERESULT_DFTIMAGE);
// 2. Measure LPTIA
// Mux P = LPTIA_P, Mux N = LPTIA_N
AD5940_ADCMuxCfgS(ADCMUXP_LPTIA0_P, ADCMUXN_LPTIA0_N);
AD5940_AFECtrlS(AFECTRL_WG | AFECTRL_ADCPWR, bTRUE);
AD5940_Delay10us(25);
AD5940_AFECtrlS(AFECTRL_ADCCNV | AFECTRL_DFT, bTRUE);
while (AD5940_INTCTestFlag(AFEINTC_1, AFEINTSRC_DFTRDY) == bFALSE)
;
AD5940_AFECtrlS(AFECTRL_ADCCNV | AFECTRL_DFT | AFECTRL_WG | AFECTRL_ADCPWR,
bFALSE);
AD5940_INTCClrFlag(AFEINTSRC_DFTRDY);
DftRtia.Real = AD5940_ReadAfeResult(AFERESULT_DFTREAL);
DftRtia.Image = AD5940_ReadAfeResult(AFERESULT_DFTIMAGE);
// Calculation: Rtia = (V_Rtia / V_Rcal) * Rcal_Value
// Here Rcal_Value is 1000 Ohm (HSTIA 1k)
fImpCar_Type temp;
temp = AD5940_ComplexDivInt(&DftRtia, &DftRcal);
temp.Real *= 1000.0f;
temp.Image *= 1000.0f;
if (pCalCfg->bPolarResult == bFALSE) {
*(fImpCar_Type *)pResult = temp;
} else {
((fImpPol_Type *)pResult)->Magnitude = AD5940_ComplexMag(&temp);
((fImpPol_Type *)pResult)->Phase = AD5940_ComplexPhase(&temp);
}
// Restore INTC
if (INTCCfg & AFEINTSRC_DFTRDY)
;
else
AD5940_INTCCfg(AFEINTC_1, AFEINTSRC_DFTRDY, bFALSE);
return AD5940ERR_OK;
}
void Routine_CalibrateSystem(void) {
if (CurrentMode == MODE_AMPEROMETRIC)
AppAMPCtrl(AMPCTRL_SHUTDOWN, 0);
else if (CurrentMode == MODE_RAMP)
AppRAMPCtrl(APPCTRL_SHUTDOWN, 0);
CurrentMode = MODE_IMPEDANCE;
AppIMPCfg_Type *pCfg;
AppIMPGetCfg(&pCfg);
AppIMPCleanup();
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);
/* LPTIA Calibration Removed for HSTIA-Only Mode */
// --- 1. Calibrate LPTIA (Low Power Loop) ---
/*
LPRTIACal_Type lprtia_cal;
fImpPol_Type LpRes;
memset(&lprtia_cal, 0, sizeof(lprtia_cal));
lprtia_cal.AdcClkFreq = 16000000.0;
lprtia_cal.SysClkFreq = 16000000.0;
lprtia_cal.ADCSinc3Osr = ADCSINC3OSR_4;
lprtia_cal.ADCSinc2Osr = ADCSINC2OSR_22;
lprtia_cal.bPolarResult = bTRUE;
lprtia_cal.fRcal = pCfg->RcalVal;
lprtia_cal.LpTiaRtia = GetLPTIARtia(ConfigLptiaVal);
lprtia_cal.LpAmpPwrMod = LPAMPPWR_NORM;
lprtia_cal.bWithCtia = bFALSE;
lprtia_cal.fFreq = 100.0f;
lprtia_cal.DftCfg.DftNum = DFTNUM_2048;
lprtia_cal.DftCfg.DftSrc = DFTSRC_SINC3;
lprtia_cal.DftCfg.HanWinEn = bTRUE;
printf(">> Calibrating LPTIA %d Ohm using Custom Routing (HSTIA Ref)...\n",
ConfigLptiaVal);
// CALL CUSTOM CALIBRATION FUNCTION
if (AD5940_LPRtiaCal_UserCustom(&lprtia_cal, &LpRes) == AD5940ERR_OK) {
printf("RCAL,LPTIA,%f,%f\n", LpRes.Magnitude, LpRes.Phase);
CalibratedLptiaVal = LpRes.Magnitude;
} else {
printf("RCAL,LPTIA,FAIL\n");
}
*/
// --- 2. Calibrate HSTIA (High Speed Loop) ---
HSDACCfg_Type hsdac_cfg;
hsdac_cfg.ExcitBufGain = EXCITBUFGAIN_0P25;
hsdac_cfg.HsDacGain = HSDACGAIN_0P2;
hsdac_cfg.HsDacUpdateRate = 7;
AD5940_HSDacCfgS(&hsdac_cfg);
HSRTIACal_Type hsrtia_cal;
fImpPol_Type HsRes;
memset(&hsrtia_cal, 0, sizeof(hsrtia_cal));
hsrtia_cal.fFreq = 1000.0f;
hsrtia_cal.AdcClkFreq = 16000000.0;
hsrtia_cal.SysClkFreq = 16000000.0; // Orig was 16M
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 = GetHSTIARtia(ConfigHstiaVal);
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 HSTIA %d Ohm...\n", ConfigHstiaVal);
if (AD5940_HSRtiaCal(&hsrtia_cal, &HsRes) == AD5940ERR_OK) {
printf("RCAL,HSTIA,%f,%f\n", HsRes.Magnitude, HsRes.Phase);
CalibratedHstiaVal = HsRes.Magnitude;
CalibratedHstiaPhase = HsRes.Phase; // Store Phase for correction
} else {
printf("RCAL,HSTIA,FAIL\n");
}
// Cleanup to prevent spurious interrupts in main loop
AppIMPCleanup();
CurrentMode = MODE_IDLE;
}