diff --git a/Impedance.c b/Impedance.c index 63e8183..3e0577d 100644 --- a/Impedance.c +++ b/Impedance.c @@ -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; @@ -700,4 +602,77 @@ 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; } \ No newline at end of file diff --git a/Impedance.h b/Impedance.h index e341761..f0e5203 100644 --- a/Impedance.h +++ b/Impedance.h @@ -19,9 +19,6 @@ Analog Devices Software License Agreement. #include "string.h" #include -// 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; @@ -87,8 +85,7 @@ typedef struct { BoolFlag 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 */ + FifoDataCount; /* Count how many times impedance have been measured */ } 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 \ No newline at end of file diff --git a/Measurement_Routines.c b/Measurement_Routines.c index 03d904e..0c5cd05 100644 --- a/Measurement_Routines.c +++ b/Measurement_Routines.c @@ -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); - ImpedanceShowResult(AppBuff, temp); - break; // Done with this point + + 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--; @@ -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 diff --git a/host/src/MainWindow_Serial.cpp b/host/src/MainWindow_Serial.cpp index c4f9cc5..d2fd482 100644 --- a/host/src/MainWindow_Serial.cpp +++ b/host/src/MainWindow_Serial.cpp @@ -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); diff --git a/main.c b/main.c index 585f89f..615bc3c 100644 --- a/main.c +++ b/main.c @@ -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;