well... full circle

This commit is contained in:
pszsh 2026-02-17 12:18:36 -07:00
parent ca8682b00a
commit 06eed95eb9
5 changed files with 135 additions and 129 deletions

View File

@ -26,34 +26,6 @@ static uint32_t const HpRtiaTable[] = {200, 1000, 5000, 10000, 20000,
40000, 80000, 160000, 0};
static float ResRtiaCal = 0.0f;
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 = 4; // Match the new threshold
AD5940_FIFOCfg(&fifo_cfg);
// Clear all interrupt flags
AD5940_INTCClrFlag(AFEINTSRC_ALLINT);
}
/*
Application configuration structure. Specified by user from template.
The variables are usable in this whole application.
@ -73,8 +45,9 @@ AppIMPCfg_Type AppIMPCfg = {
.SysClkFreq = 16000000.0,
.WuptClkFreq = 32000.0,
.AdcClkFreq = 16000000.0,
.RcalVal = 100.0,
.RcalVal = 10000.0,
.RtiaVal = 1000.0,
.ShortRe0Se0 = bFALSE,
.DswitchSel = SWD_CE0,
.PswitchSel = SWP_CE0,
@ -83,7 +56,7 @@ AppIMPCfg_Type AppIMPCfg = {
.PwrMod = AFEPWR_HP,
.HstiaRtiaSel = HSTIARTIA_1K,
.HstiaRtiaSel = HSTIARTIA_5K,
.ExcitBufGain = EXCITBUFGAIN_2,
.HsDacGain = HSDACGAIN_1,
.HsDacUpdateRate = 7,
@ -112,7 +85,6 @@ AppIMPCfg_Type AppIMPCfg = {
.FifoThresh = 4,
.IMPInited = bFALSE,
.StopRequired = bFALSE,
.ShortRe0Se0 = bFALSE,
};
/**
@ -371,7 +343,7 @@ static AD5940Err AppIMPSeqMeasureGen(void) {
AD5940_SEQGenCtrl(bTRUE);
AD5940_SEQGpioCtrlS(
AGPIO_Pin2); /* Set GPIO1, clear others that under control */
AD5940_SEQGenInsert(SEQ_WAIT(16 * 125)); /* @todo wait 125us (halved) */
AD5940_SEQGenInsert(SEQ_WAIT(16 * 250)); /* @todo wait 250us? */
sw_cfg.Dswitch = SWD_RCAL0;
sw_cfg.Pswitch = SWP_RCAL0;
sw_cfg.Nswitch = SWN_RCAL1;
@ -431,63 +403,6 @@ static AD5940Err AppIMPSeqMeasureGen(void) {
return AD5940ERR_OK;
}
AD5940Err AppIMPRtiaCal(void) {
HSRTIACal_Type hs_cal;
fImpPol_Type res;
AD5940Err error;
hs_cal.fFreq = AppIMPCfg.SinFreq;
hs_cal.fRcal = AppIMPCfg.RcalVal;
hs_cal.SysClkFreq = AppIMPCfg.SysClkFreq;
hs_cal.AdcClkFreq = AppIMPCfg.AdcClkFreq;
hs_cal.HsTiaCfg.DiodeClose = bFALSE;
if (AppIMPCfg.BiasVolt != 0.0f)
hs_cal.HsTiaCfg.HstiaBias = HSTIABIAS_VZERO0;
else
hs_cal.HsTiaCfg.HstiaBias = HSTIABIAS_1P1;
hs_cal.HsTiaCfg.HstiaCtia = 31;
hs_cal.HsTiaCfg.HstiaDeRload = HSTIADERLOAD_OPEN;
hs_cal.HsTiaCfg.HstiaDeRtia = HSTIADERTIA_OPEN;
hs_cal.HsTiaCfg.HstiaRtiaSel = AppIMPCfg.HstiaRtiaSel;
hs_cal.ADCSinc3Osr = AppIMPCfg.ADCSinc3Osr;
hs_cal.ADCSinc2Osr = AppIMPCfg.ADCSinc2Osr;
hs_cal.DftCfg.DftNum = AppIMPCfg.DftNum;
hs_cal.DftCfg.DftSrc = AppIMPCfg.DftSrc;
hs_cal.DftCfg.HanWinEn = AppIMPCfg.HanWinEn;
hs_cal.bPolarResult = bTRUE;
hs_cal.bPolarResult = bTRUE;
error = AD5940_HSRtiaCal(&hs_cal, &res);
if (error == AD5940ERR_OK) {
ResRtiaCal = res.Magnitude;
AppIMPCfg.RtiaVal =
ResRtiaCal; // Update global config with calibrated value
// Conditional Phase Normalization:
// If phase is close to PI (inverted), shift by PI to bring it to 0 (or
// 2PI). If phase is already close to 0, leave it alone.
if (res.Phase > 1.5f || res.Phase < -1.5f) {
res.Phase += MATH_PI;
}
// Wrap to -PI..PI range
while (res.Phase > MATH_PI)
res.Phase -= 2 * MATH_PI;
while (res.Phase < -MATH_PI)
res.Phase += 2 * MATH_PI;
printf("Measured RTIA: %f Ohm, Phase: %f\n", res.Magnitude, res.Phase);
} else
printf("RTIA Calibration Failed: %d\n", error);
return error;
}
/* This function provide application initialize. It can also enable Wupt that
* will automatically trigger sequence. Or it can configure */
int32_t AppIMPInit(uint32_t *pBuffer, uint32_t BufferSize) {
@ -523,9 +438,6 @@ int32_t AppIMPInit(uint32_t *pBuffer, uint32_t BufferSize) {
AD5940_FIFOCfg(&fifo_cfg);
AD5940_INTCClrFlag(AFEINTSRC_ALLINT);
/* Perform RTIA Calibration */
AppIMPRtiaCal();
/* Start sequence generator */
/* Initialize sequencer generator */
if ((AppIMPCfg.IMPInited == bFALSE) || (AppIMPCfg.bParaChanged == bTRUE)) {
@ -633,20 +545,10 @@ int32_t AppIMPDataProcess(int32_t *const pData, uint32_t *pDataCount) {
(float)pDftRz->Image * pDftRz->Image);
RzPhase = atan2(-pDftRz->Image, pDftRz->Real);
// DEBUG: Print raw values
// printf("DEBUG: RCAL: %d, %d | Rz: %d, %d | Mag: %.2f / %.2f\n",
// pDftRcal->Real, pDftRcal->Image, pDftRz->Real, pDftRz->Image,
// RcalMag, RzMag);
// Uncommenting for diagnosis:
printf("DEBUG: RcalMag=%.0f RzMag=%.0f Ratio=%.4f RcalVal=%.0f\n", RcalMag,
RzMag, RcalMag / RzMag, AppIMPCfg.RcalVal);
RzPhase = atan2(-pDftRz->Image, pDftRz->Real);
RzPhase = atan2(-pDftRz->Image, pDftRz->Real);
RzMag = RcalMag / RzMag * AppIMPCfg.RcalVal;
RzPhase = RcalPhase - RzPhase + MATH_PI;
RzPhase = RcalPhase - RzPhase;
// printf("V:%d,%d,I:%d,%d ",pDftRcal->Real,pDftRcal->Image, pDftRz->Real,
// pDftRz->Image);
pOut[i].Magnitude = RzMag;
pOut[i].Phase = RzPhase;
@ -678,7 +580,7 @@ int32_t AppIMPISR(void *pBuff, uint32_t *pCount) {
return AD5940ERR_WAKEUP; /* Wakeup Failed */
AD5940_SleepKeyCtrlS(SLPKEY_LOCK); /* Prohibit AFE to enter sleep mode. */
if (AD5940_INTCTestFlag(AFEINTC_1, AFEINTSRC_DATAFIFOTHRESH) == bTRUE) {
if (AD5940_INTCTestFlag(AFEINTC_0, AFEINTSRC_DATAFIFOTHRESH) == bTRUE) {
/* Now there should be 4 data in FIFO */
FifoCnt = (AD5940_FIFOGetCnt() / 4) * 4;
@ -701,3 +603,76 @@ int32_t AppIMPISR(void *pBuff, uint32_t *pCount) {
return 0;
}
// Added for compatibility with Measurement_Routines.c
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 = 4; // Match the new threshold
AD5940_FIFOCfg(&fifo_cfg);
// Clear all interrupt flags
AD5940_INTCClrFlag(AFEINTSRC_ALLINT);
}
// Added for compatibility with Measurement_Routines.c
AD5940Err AppIMPRtiaCal(void) {
HSRTIACal_Type hs_cal;
fImpPol_Type res;
AD5940Err error;
hs_cal.fFreq = AppIMPCfg.SinFreq;
hs_cal.fRcal = AppIMPCfg.RcalVal;
hs_cal.SysClkFreq = AppIMPCfg.SysClkFreq;
hs_cal.AdcClkFreq = AppIMPCfg.AdcClkFreq;
hs_cal.HsTiaCfg.DiodeClose = bFALSE;
if (AppIMPCfg.BiasVolt != 0.0f)
hs_cal.HsTiaCfg.HstiaBias = HSTIABIAS_VZERO0;
else
hs_cal.HsTiaCfg.HstiaBias = HSTIABIAS_1P1;
hs_cal.HsTiaCfg.HstiaCtia = 31;
hs_cal.HsTiaCfg.HstiaDeRload = HSTIADERLOAD_OPEN;
hs_cal.HsTiaCfg.HstiaDeRtia = HSTIADERTIA_OPEN;
hs_cal.HsTiaCfg.HstiaRtiaSel = AppIMPCfg.HstiaRtiaSel;
hs_cal.ADCSinc3Osr = AppIMPCfg.ADCSinc3Osr;
hs_cal.ADCSinc2Osr = AppIMPCfg.ADCSinc2Osr;
hs_cal.DftCfg.DftNum = AppIMPCfg.DftNum;
hs_cal.DftCfg.DftSrc = AppIMPCfg.DftSrc;
hs_cal.DftCfg.HanWinEn = AppIMPCfg.HanWinEn;
hs_cal.bPolarResult = bTRUE;
hs_cal.bPolarResult = bTRUE;
error = AD5940_HSRtiaCal(&hs_cal, &res);
if (error == AD5940ERR_OK) {
ResRtiaCal = res.Magnitude;
// AppIMPCfg.RtiaVal = ResRtiaCal; // Removed as it was custom addition
printf("Calibrated RTIA: %f Ohm, Phase: %f\n", res.Magnitude, res.Phase);
} else
printf("RTIA Calibration Failed: %d\n", error);
return error;
}

View File

@ -19,9 +19,6 @@ Analog Devices Software License Agreement.
#include "string.h"
#include <stdio.h>
// Define custom error code for FIFO overflow
#define AD5940ERR_FIFO 20
typedef struct {
/* Common configurations for all kinds of Application. */
BoolFlag bParaChanged; /* Indicate to generate sequence again. It's auto
@ -31,6 +28,7 @@ typedef struct {
uint32_t MaxSeqLen; /* Limit the maximum sequence. */
uint32_t SeqStartAddrCal; /* Measurement sequence start address in SRAM of
AD5940 */
uint32_t SeqWaitAddr[2];
uint32_t MaxSeqLenCal;
/* Application related parameters */
float ImpODR; /* */
@ -43,7 +41,8 @@ typedef struct {
float SysClkFreq; /* The real frequency of system clock */
float AdcClkFreq; /* The real frequency of ADC clock */
float RcalVal; /* Rcal value in Ohm */
float RtiaVal; /* Rtia value in Ohm (used for 4-wire calculation) */
float RtiaVal; /* Calibrated Rtia value in Ohm */
BoolFlag ShortRe0Se0; /* Short RE0 to SE0 */
/* Switch Configuration */
uint32_t DswitchSel;
uint32_t PswitchSel;
@ -54,7 +53,6 @@ typedef struct {
HstiaRtiaSel; /* Use internal RTIA, select from RTIA_INT_200, RTIA_INT_1K,
RTIA_INT_5K, RTIA_INT_10K, RTIA_INT_20K, RTIA_INT_40K,
RTIA_INT_80K, RTIA_INT_160K */
uint32_t ExtRtia; /* External RTIA switch control/value */
uint32_t ExcitBufGain; /* Select from EXCTBUFGAIN_2, EXCTBUFGAIN_0P25 */
uint32_t HsDacGain; /* Select from HSDACGAIN_1, HSDACGAIN_0P2 */
uint32_t HsDacUpdateRate;
@ -88,7 +86,6 @@ typedef struct {
StopRequired; /* After FIFO is ready, stop the measurement sequence */
uint32_t
FifoDataCount; /* Count how many times impedance have been measured */
BoolFlag ShortRe0Se0; /* Short RE0 to SE0 */
} AppIMPCfg_Type;
#define IMPCTRL_START 0
@ -105,7 +102,7 @@ int32_t AppIMPInit(uint32_t *pBuffer, uint32_t BufferSize);
int32_t AppIMPGetCfg(void *pCfg);
int32_t AppIMPISR(void *pBuff, uint32_t *pCount);
int32_t AppIMPCtrl(uint32_t Command, void *pPara);
AD5940Err AppIMPRtiaCal(void);
void AppIMPCleanup(void);
AD5940Err AppIMPRtiaCal(void);
#endif

View File

@ -140,23 +140,37 @@ void Routine_Sweep(float start, float end, int steps, float bias_mv) {
pCfg->bParaChanged = bTRUE; // Force sequence regeneration
/* Re-Initialize App to apply new frequency (this regenerates sequences) */
AppIMPInit(AppBuff, APPBUFF_SIZE);
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 */
AppIMPRtiaCal();
/* 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
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--;
@ -504,11 +518,10 @@ void Routine_CalibrateSystem(void) {
// CALL CUSTOM CALIBRATION FUNCTION
if (AD5940_LPRtiaCal_UserCustom(&lprtia_cal, &LpRes) == AD5940ERR_OK) {
printf("Calibrated LPTIA: Mag = %f Ohm, Phase = %f\n", LpRes.Magnitude,
LpRes.Phase);
printf("RCAL,LPTIA,%f,%f\n", LpRes.Magnitude, LpRes.Phase);
CalibratedLptiaVal = LpRes.Magnitude;
} else {
printf("LPTIA Calibration Failed\n");
printf("RCAL,LPTIA,FAIL\n");
}
// --- 2. Calibrate HSTIA (High Speed Loop) ---
@ -539,11 +552,10 @@ void Routine_CalibrateSystem(void) {
printf(">> Calibrating HSTIA %d Ohm...\n", ConfigHstiaVal);
if (AD5940_HSRtiaCal(&hsrtia_cal, &HsRes) == AD5940ERR_OK) {
printf("Calibrated HSTIA: Mag = %f Ohm, Phase = %f\n", HsRes.Magnitude,
HsRes.Phase);
printf("RCAL,HSTIA,%f,%f\n", HsRes.Magnitude, HsRes.Phase);
CalibratedHstiaVal = HsRes.Magnitude;
} else {
printf("HSTIA Calibration Failed\n");
printf("RCAL,HSTIA,FAIL\n");
}
// Cleanup to prevent spurious interrupts in main loop

View File

@ -148,7 +148,7 @@ void MainWindow::handleSerialData() {
currentSequence = SEQ_WAIT_CALIB;
}
} else if (currentSequence == SEQ_WAIT_CALIB) {
if (str.contains("Calibrated HSTIA:")) {
if (str.contains("RCAL,HSTIA")) {
logWidget->append(">> Sequence: Calibration Done. Sending Command.");
serial->write(pendingCommand.toUtf8());
serial->write("\n");
@ -159,6 +159,8 @@ void MainWindow::handleSerialData() {
if (str.startsWith("DATA,")) {
parseData(str);
} else if (str.startsWith("RCAL,")) {
parseData(str);
} else if (str.startsWith("AMP,")) {
parseData(str);
} else if (str.startsWith("RAMP,")) {
@ -222,6 +224,26 @@ void MainWindow::parseData(const QString &data) {
return;
}
if (parts[0] == "RCAL" && parts.size() >= 4) {
QString type = parts[1];
if (type == "FAIL") {
logWidget->append(QString(">> RCAL FAIL: %1").arg(data));
return;
}
bool okM, okP;
double mag = parts[2].toDouble(&okM);
double phase = parts[3].toDouble(&okP);
if (okM && okP) {
logWidget->append(QString(">> Calibration [%1]: Mag=%.2f Phase=%.2f")
.arg(type)
.arg(mag)
.arg(phase));
// TODO: Store this if needed for UI display
}
return;
}
if (parts[0] == "DATA" && parts.size() >= 6) {
bool okF, okM, okP;
double freq = parts[1].toDouble(&okF);

6
main.c
View File

@ -179,7 +179,7 @@ int main() {
if (CurrentMode == MODE_IMPEDANCE) {
status = AppIMPISR(AppBuff, &temp);
if (status == AD5940ERR_FIFO) {
if (status == AD5940ERR_BUFF) {
printf("ERROR: FIFO Overflow/Underflow. Stopping.\n");
AppIMPCleanup();
CurrentMode = MODE_IDLE;
@ -189,7 +189,7 @@ int main() {
}
} else if (CurrentMode == MODE_AMPEROMETRIC) {
status = AppAMPISR(AppBuff, &temp);
if (status == AD5940ERR_FIFO) {
if (status == AD5940ERR_BUFF) {
printf("ERROR: FIFO Overflow/Underflow. Stopping.\n");
AppAMPCtrl(AMPCTRL_SHUTDOWN, 0);
CurrentMode = MODE_IDLE;
@ -199,7 +199,7 @@ int main() {
}
} else if (CurrentMode == MODE_RAMP) {
status = AppRAMPISR(AppBuff, &temp);
if (status == AD5940ERR_FIFO) {
if (status == AD5940ERR_BUFF) {
printf("ERROR: FIFO Overflow/Underflow. Stopping.\n");
AppRAMPCtrl(APPCTRL_SHUTDOWN, 0);
CurrentMode = MODE_IDLE;