working on it, getting there.

This commit is contained in:
pszsh 2026-02-03 02:13:31 -08:00
parent ce6f8e6a46
commit 6fc616593b
8 changed files with 195 additions and 74 deletions

View File

@ -17,6 +17,7 @@ add_executable(EIS
Impedance.c Impedance.c
Amperometric.c Amperometric.c
RampTest.c RampTest.c
Reset.c
) )
target_compile_definitions(EIS PRIVATE CHIPSEL_594X) target_compile_definitions(EIS PRIVATE CHIPSEL_594X)

View File

@ -1,4 +1,4 @@
// Impedance.c // File: Impedance.c
#include "ad5940.h" #include "ad5940.h"
#include <stdio.h> #include <stdio.h>
#include "string.h" #include "string.h"
@ -43,7 +43,7 @@ AppIMPCfg_Type AppIMPCfg =
.ExtRtia = 0, .ExtRtia = 0,
.ExcitBufGain = EXCITBUFGAIN_0P25, .ExcitBufGain = EXCITBUFGAIN_0P25,
.HsDacGain = HSDACGAIN_0P2, .HsDacGain = HSDACGAIN_0P2,
.HsDacUpdateRate = 7, .HsDacUpdateRate = 0, /* UPDATED: 0 = Max Speed (16MHz) for cleaner high-freq signals */
.DacVoltPP = 600.0, /* Excitation Amplitude (mV peak-to-peak) */ .DacVoltPP = 600.0, /* Excitation Amplitude (mV peak-to-peak) */
.BiasVolt = -0.0f, /* DC Bias Voltage */ .BiasVolt = -0.0f, /* DC Bias Voltage */
@ -499,8 +499,23 @@ AD5940Err AppIMPCheckFreq(float freq)
filter_cfg.ADCSinc2Osr = freq_params.ADCSinc2Osr; filter_cfg.ADCSinc2Osr = freq_params.ADCSinc2Osr;
filter_cfg.ADCSinc3Osr = freq_params.ADCSinc3Osr; filter_cfg.ADCSinc3Osr = freq_params.ADCSinc3Osr;
filter_cfg.BpSinc3 = bFALSE; filter_cfg.BpSinc3 = bFALSE;
// --- CRITICAL FIX: Disable Notch Filter for High Frequencies ---
// The Notch filter (50/60Hz) has a long settling time (~60ms).
// If enabled at high frequencies (e.g., 100kHz), the sequencer waits only microseconds,
// capturing the filter's settling artifacts (noise/hook).
if(freq > 10.0f)
{
filter_cfg.BpNotch = bFALSE;
filter_cfg.Sinc2NotchEnable = bFALSE;
}
else
{
filter_cfg.BpNotch = bTRUE; filter_cfg.BpNotch = bTRUE;
filter_cfg.Sinc2NotchEnable = bTRUE; filter_cfg.Sinc2NotchEnable = bTRUE;
}
// ---------------------------------------------------------------
filter_cfg.ADCRate = ADCRATE_800KHZ; // Fixed ADC Rate for stability filter_cfg.ADCRate = ADCRATE_800KHZ; // Fixed ADC Rate for stability
dft_cfg.DftNum = freq_params.DftNum; dft_cfg.DftNum = freq_params.DftNum;
@ -520,8 +535,8 @@ AD5940Err AppIMPCheckFreq(float freq)
clks_cal.RatioSys2AdcClk = AppIMPCfg.SysClkFreq/AppIMPCfg.AdcClkFreq; clks_cal.RatioSys2AdcClk = AppIMPCfg.SysClkFreq/AppIMPCfg.AdcClkFreq;
AD5940_ClksCalculate(&clks_cal, &WaitClks); AD5940_ClksCalculate(&clks_cal, &WaitClks);
// Add safety margin // Add safety margin (Increased from 200 to 2000 to ensure full flush)
WaitClks += 200; WaitClks += 2000;
// Update Wait Times in SRAM for all 3 measurements // Update Wait Times in SRAM for all 3 measurements
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {

48
Reset.c Normal file
View File

@ -0,0 +1,48 @@
// File: Reset.c
#include "Reset.h"
#include "ad5940.h"
#include <stdio.h>
/**
* @brief Checks and prints the cause of the last reset.
* @note The RSTSTA register is sticky. It must be cleared manually.
*/
void AD5940_CheckResetStatus(void)
{
uint32_t rststa = AD5940_ReadReg(REG_ALLON_RSTSTA);
// printf(">> Reset Status (0x%04X): ", rststa);
if(rststa & 0x01) printf("POR ");
if(rststa & 0x02) printf("EXT ");
if(rststa & 0x04) printf("WDT ");
if(rststa & 0x08) printf("MMR ");
if(rststa == 0) printf("None");
// printf("\n");
// Clear the reset status (Write 1 to clear)
AD5940_WriteReg(REG_ALLON_RSTSTA, 0xF);
}
/**
* @brief Performs a Software Reset (MMR Reset).
* @return AD5940Err
*/
AD5940Err AD5940_SoftReset(void)
{
// Trigger Software Reset
AD5940_SoftRst();
// Wait for the chip to reboot (essential)
AD5940_Delay10us(100); // 1ms wait
// Re-initialize the AD5940 driver internal state (SPI, etc.)
// This function is required after any reset.
AD5940_Initialize();
// Check and clear the reset flag (Should show MMR)
AD5940_CheckResetStatus();
return AD5940ERR_OK;
}

10
Reset.h Normal file
View File

@ -0,0 +1,10 @@
// File: Reset.h
#ifndef _RESET_H_
#define _RESET_H_
#include "ad5940.h"
void AD5940_CheckResetStatus(void);
AD5940Err AD5940_SoftReset(void);
#endif

View File

@ -65,6 +65,12 @@ private:
void calculateLSVDiff(); void calculateLSVDiff();
void setButtonBlinking(QPushButton *btn, bool blinking); void setButtonBlinking(QPushButton *btn, bool blinking);
// Sequence Handling
enum SequenceState { SEQ_IDLE, SEQ_WAIT_BOOT, SEQ_WAIT_CALIB };
SequenceState currentSequence = SEQ_IDLE;
QString pendingCommand;
void initiateSequence(const QString &cmd);
QSerialPort *serial; QSerialPort *serial;
QSettings *settings; QSettings *settings;
QTimer *blinkTimer; QTimer *blinkTimer;

View File

@ -25,6 +25,16 @@ void MainWindow::onLPFChanged(int index) {
} }
} }
void MainWindow::initiateSequence(const QString &cmd) {
if (!serial->isOpen()) return;
pendingCommand = cmd;
currentSequence = SEQ_WAIT_BOOT;
logWidget->append(">> Sequence: Resetting device (z)...");
serial->write("z\n"); // Watchdog reboot to force clean state
}
void MainWindow::startSweep() { void MainWindow::startSweep() {
if (!serial->isOpen()) return; if (!serial->isOpen()) return;
@ -49,19 +59,14 @@ void MainWindow::startSweep() {
double stop = spinSweepStop->value(); double stop = spinSweepStop->value();
int ppd = spinSweepPPD->value(); int ppd = spinSweepPPD->value();
// Ensure firmware has correct ranges before starting QString cmd = QString("s %1 %2 %3").arg(start).arg(stop).arg(ppd);
int lpVal = comboRangeLP->currentData().toInt();
int hpVal = comboRangeHP->currentData().toInt();
serial->write(QString("r %1 %2\n").arg(lpVal).arg(hpVal).toUtf8());
logWidget->append(QString(">> Starting Sweep (HP Range: %1, s %2 %3 %4)...").arg(hpVal).arg(start).arg(stop).arg(ppd));
serial->write(QString("s %1 %2 %3\n").arg(start).arg(stop).arg(ppd).toUtf8());
isSweeping = true; isSweeping = true;
sweepBtn->setText("Stop Sweep"); sweepBtn->setText("Stop Sweep");
setButtonBlinking(sweepBtn, true); setButtonBlinking(sweepBtn, true);
tabWidget->setCurrentIndex(1); tabWidget->setCurrentIndex(1);
initiateSequence(cmd);
} }
void MainWindow::toggleMeasurement() { void MainWindow::toggleMeasurement() {
@ -77,16 +82,14 @@ void MainWindow::toggleMeasurement() {
isMeasuringImp = false; isMeasuringImp = false;
} else { } else {
double freq = spinFreq->value(); double freq = spinFreq->value();
int lpVal = comboRangeLP->currentData().toInt(); QString cmd = QString("m %1").arg(freq);
int hpVal = comboRangeHP->currentData().toInt();
serial->write(QString("r %1 %2\n").arg(lpVal).arg(hpVal).toUtf8());
serial->write(QString("m %1\n").arg(freq).toUtf8());
measureBtn->setText("Stop"); measureBtn->setText("Stop");
setButtonBlinking(measureBtn, true); setButtonBlinking(measureBtn, true);
isMeasuringImp = true; isMeasuringImp = true;
tabWidget->setCurrentIndex(0); tabWidget->setCurrentIndex(0);
initiateSequence(cmd);
} }
} }
@ -103,17 +106,15 @@ void MainWindow::toggleAmperometry() {
isMeasuringAmp = false; isMeasuringAmp = false;
} else { } else {
double bias = spinAmpBias->value(); double bias = spinAmpBias->value();
int lpVal = comboRangeLP->currentData().toInt(); QString cmd = QString("a %1").arg(bias);
int hpVal = comboRangeHP->currentData().toInt();
serial->write(QString("r %1 %2\n").arg(lpVal).arg(hpVal).toUtf8());
serial->write(QString("a %1\n").arg(bias).toUtf8());
ampBtn->setText("Stop Amp"); ampBtn->setText("Stop Amp");
setButtonBlinking(ampBtn, true); setButtonBlinking(ampBtn, true);
isMeasuringAmp = true; isMeasuringAmp = true;
ampGraph->clear(); ampGraph->clear();
tabWidget->setCurrentIndex(2); tabWidget->setCurrentIndex(2);
initiateSequence(cmd);
} }
} }
@ -135,13 +136,8 @@ void MainWindow::startLSVBlank() {
double stop = spinLsvStop->value(); double stop = spinLsvStop->value();
int steps = spinLsvSteps->value(); int steps = spinLsvSteps->value();
int duration = spinLsvDuration->value(); int duration = spinLsvDuration->value();
int lpVal = comboRangeLP->currentData().toInt();
int hpVal = comboRangeHP->currentData().toInt();
logWidget->append(QString(">> Starting LSV Blank (LP Range: %1, %.1f to %.1f mV)...").arg(lpVal).arg(start).arg(stop)); QString cmd = QString("l %1 %2 %3 %4").arg(start).arg(stop).arg(steps).arg(duration);
serial->write(QString("r %1 %2\n").arg(lpVal).arg(hpVal).toUtf8());
serial->write(QString("l %1 %2 %3 %4\n").arg(start).arg(stop).arg(steps).arg(duration).toUtf8());
lsvBlankBtn->setText("Stop Blank"); lsvBlankBtn->setText("Stop Blank");
setButtonBlinking(lsvBlankBtn, true); setButtonBlinking(lsvBlankBtn, true);
@ -153,6 +149,8 @@ void MainWindow::startLSVBlank() {
lsvBlankData.clear(); lsvBlankData.clear();
tabWidget->setCurrentIndex(3); tabWidget->setCurrentIndex(3);
initiateSequence(cmd);
} }
void MainWindow::startLSVSample() { void MainWindow::startLSVSample() {
@ -173,13 +171,8 @@ void MainWindow::startLSVSample() {
double stop = spinLsvStop->value(); double stop = spinLsvStop->value();
int steps = spinLsvSteps->value(); int steps = spinLsvSteps->value();
int duration = spinLsvDuration->value(); int duration = spinLsvDuration->value();
int lpVal = comboRangeLP->currentData().toInt();
int hpVal = comboRangeHP->currentData().toInt();
logWidget->append(QString(">> Starting LSV Sample (LP Range: %1, %.1f to %.1f mV)...").arg(lpVal).arg(start).arg(stop)); QString cmd = QString("l %1 %2 %3 %4").arg(start).arg(stop).arg(steps).arg(duration);
serial->write(QString("r %1 %2\n").arg(lpVal).arg(hpVal).toUtf8());
serial->write(QString("l %1 %2 %3 %4\n").arg(start).arg(stop).arg(steps).arg(duration).toUtf8());
lsvSampleBtn->setText("Stop Sample"); lsvSampleBtn->setText("Stop Sample");
setButtonBlinking(lsvSampleBtn, true); setButtonBlinking(lsvSampleBtn, true);
@ -191,6 +184,8 @@ void MainWindow::startLSVSample() {
lsvSampleData.clear(); lsvSampleData.clear();
tabWidget->setCurrentIndex(3); tabWidget->setCurrentIndex(3);
initiateSequence(cmd);
} }
void MainWindow::stopLSV() { void MainWindow::stopLSV() {

View File

@ -57,6 +57,7 @@ void MainWindow::connectToPort() {
isMeasuringAmp = false; isMeasuringAmp = false;
isSweeping = false; isSweeping = false;
lsvState = LSV_IDLE; lsvState = LSV_IDLE;
currentSequence = SEQ_IDLE;
setButtonBlinking(nullptr, false); setButtonBlinking(nullptr, false);
measureBtn->setText("Measure"); measureBtn->setText("Measure");
@ -132,6 +133,7 @@ void MainWindow::onPortError(QSerialPort::SerialPortError error) {
spinLsvSteps->setEnabled(false); spinLsvSteps->setEnabled(false);
spinLsvDuration->setEnabled(false); spinLsvDuration->setEnabled(false);
setButtonBlinking(nullptr, false); setButtonBlinking(nullptr, false);
currentSequence = SEQ_IDLE;
} }
} }
@ -145,6 +147,37 @@ void MainWindow::handleSerialData() {
logWidget->append(QString("[%1] %2").arg(timestamp, str)); logWidget->append(QString("[%1] %2").arg(timestamp, str));
logWidget->moveCursor(QTextCursor::End); logWidget->moveCursor(QTextCursor::End);
// --- Sequence State Machine ---
if (currentSequence == SEQ_WAIT_BOOT) {
if (str.contains("AD5940LIB Version:v0.2.1")) {
logWidget->append(">> Sequence: Boot detected. Configuring...");
// 1. Restore Settings (Range & Filter)
int lpVal = comboRangeLP->currentData().toInt();
int hpVal = comboRangeHP->currentData().toInt();
serial->write(QString("r %1 %2\n").arg(lpVal).arg(hpVal).toUtf8());
int lpfIdx = comboLPF->currentIndex();
int lpfVal = comboLPF->itemData(lpfIdx).toInt();
serial->write(QString("f %1\n").arg(lpfVal).toUtf8());
// 2. Start Calibration
logWidget->append(">> Sequence: Calibrating...");
serial->write("c\n");
currentSequence = SEQ_WAIT_CALIB;
}
}
else if (currentSequence == SEQ_WAIT_CALIB) {
if (str.contains("Calibrated HSTIA:")) {
logWidget->append(">> Sequence: Calibration Done. Sending Command.");
serial->write(pendingCommand.toUtf8());
serial->write("\n");
currentSequence = SEQ_IDLE;
}
}
// ------------------------------
if (str.startsWith("DATA,")) { if (str.startsWith("DATA,")) {
parseData(str); parseData(str);
} else if (str.startsWith("AMP,")) { } else if (str.startsWith("AMP,")) {

87
main.c
View File

@ -11,6 +11,7 @@
#include "Impedance.h" #include "Impedance.h"
#include "Amperometric.h" #include "Amperometric.h"
#include "RampTest.h" #include "RampTest.h"
#include "Reset.h"
#define AD5940ERR_STOP 10 #define AD5940ERR_STOP 10
@ -104,6 +105,12 @@ uint32_t GetLPTIARtia(uint32_t val) {
} }
} }
// Determine correct internal RLOAD based on RTIA selection
uint32_t GetLPTIARload(uint32_t val) {
if (val <= 200) return LPTIARLOAD_10R;
return LPTIARLOAD_100R;
}
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Platform Interface Implementation // Platform Interface Implementation
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -137,7 +144,8 @@ void AD5940_MCUGpioCtrl(uint32_t pin, BoolFlag enable) { (void)pin; (void)enable
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
void setup_pins(void) { void setup_pins(void) {
spi_init(spi0, 4000000); // Run SPI at 16 MHz
spi_init(spi0, 16000000);
gpio_set_function(PIN_MISO, GPIO_FUNC_SPI); gpio_set_function(PIN_MISO, GPIO_FUNC_SPI);
gpio_set_function(PIN_SCK, GPIO_FUNC_SPI); gpio_set_function(PIN_SCK, GPIO_FUNC_SPI);
gpio_set_function(PIN_MOSI, GPIO_FUNC_SPI); gpio_set_function(PIN_MOSI, GPIO_FUNC_SPI);
@ -163,17 +171,18 @@ void AD5940ImpedanceStructInit(void)
pImpedanceCfg->SeqStartAddr = 0; pImpedanceCfg->SeqStartAddr = 0;
pImpedanceCfg->MaxSeqLen = 512; pImpedanceCfg->MaxSeqLen = 512;
pImpedanceCfg->RcalVal = 100.0; pImpedanceCfg->RcalVal = 100.0;
pImpedanceCfg->RtiaVal = CalibratedHstiaVal; // Use Calibrated HP Value 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 = 0;
pImpedanceCfg->DswitchSel = SWD_CE0; pImpedanceCfg->DswitchSel = SWD_CE0;
pImpedanceCfg->PswitchSel = SWP_CE0; pImpedanceCfg->PswitchSel = SWP_CE0;
pImpedanceCfg->NswitchSel = SWN_SE0; pImpedanceCfg->NswitchSel = SWN_SE0;
pImpedanceCfg->TswitchSel = SWT_SE0LOAD; pImpedanceCfg->TswitchSel = SWT_SE0LOAD;
pImpedanceCfg->HstiaRtiaSel = GetHSTIARtia(ConfigHstiaVal); // Use HP Selection 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;
@ -198,12 +207,12 @@ void AD5940AMPStructInit(void)
pAMPCfg->AmpODR = 1.0; pAMPCfg->AmpODR = 1.0;
pAMPCfg->FifoThresh = 4; pAMPCfg->FifoThresh = 4;
pAMPCfg->SensorBias = 0; pAMPCfg->SensorBias = 0;
pAMPCfg->LptiaRtiaSel = GetLPTIARtia(ConfigLptiaVal); // Use LP Selection pAMPCfg->LptiaRtiaSel = GetLPTIARtia(ConfigLptiaVal);
pAMPCfg->LpTiaRl = LPTIARLOAD_10R; pAMPCfg->LpTiaRl = GetLPTIARload(ConfigLptiaVal);
pAMPCfg->LpTiaRf = CurrentLpTiaRf; pAMPCfg->LpTiaRf = CurrentLpTiaRf;
pAMPCfg->Vzero = 1100; pAMPCfg->Vzero = 1100;
pAMPCfg->ADCRefVolt = 1.82; pAMPCfg->ADCRefVolt = 1.82;
pAMPCfg->RtiaCalValue.Magnitude = CalibratedLptiaVal; // Use Calibrated LP Value pAMPCfg->RtiaCalValue.Magnitude = CalibratedLptiaVal;
} }
void AD5940RampStructInit(void) void AD5940RampStructInit(void)
@ -227,21 +236,24 @@ void AD5940RampStructInit(void)
pRampCfg->RampDuration = 10000; pRampCfg->RampDuration = 10000;
pRampCfg->SampleDelay = 1.0f; pRampCfg->SampleDelay = 1.0f;
pRampCfg->LPTIARtiaSel = GetLPTIARtia(ConfigLptiaVal); // Use LP Selection pRampCfg->LPTIARtiaSel = GetLPTIARtia(ConfigLptiaVal);
pRampCfg->LPTIARloadSel = LPTIARLOAD_10R; pRampCfg->LPTIARloadSel = GetLPTIARload(ConfigLptiaVal);
pRampCfg->LpTiaRf = CurrentLpTiaRf; pRampCfg->LpTiaRf = CurrentLpTiaRf;
pRampCfg->AdcPgaGain = ADCPGA_1P5; pRampCfg->AdcPgaGain = ADCPGA_1P5;
pRampCfg->RtiaValue.Magnitude = CalibratedLptiaVal; // Use Calibrated LP Value pRampCfg->RtiaValue.Magnitude = CalibratedLptiaVal;
} }
/**
* @brief Configures the AD5940 Platform (Clocks, FIFO, GPIO).
* This must be called after every Reset.
*/
static int32_t AD5940PlatformCfg(void) static int32_t AD5940PlatformCfg(void)
{ {
CLKCfg_Type clk_cfg; CLKCfg_Type clk_cfg;
FIFOCfg_Type fifo_cfg; FIFOCfg_Type fifo_cfg;
AGPIOCfg_Type gpio_cfg; AGPIOCfg_Type gpio_cfg;
AD5940_HWReset(); // Note: HWReset and Initialize are now handled by the caller (System Init or SoftReset)
AD5940_Initialize();
clk_cfg.ADCClkDiv = ADCCLKDIV_1; clk_cfg.ADCClkDiv = ADCCLKDIV_1;
clk_cfg.ADCCLkSrc = ADCCLKSRC_HFOSC; clk_cfg.ADCCLkSrc = ADCCLKSRC_HFOSC;
@ -252,7 +264,6 @@ static int32_t AD5940PlatformCfg(void)
clk_cfg.HFXTALEn = bFALSE; clk_cfg.HFXTALEn = bFALSE;
clk_cfg.LFOSCEn = bTRUE; clk_cfg.LFOSCEn = bTRUE;
AD5940_CLKCfg(&clk_cfg); AD5940_CLKCfg(&clk_cfg);
printf("Clock Configured (HFOSC 16MHz).\n");
fifo_cfg.FIFOEn = bFALSE; fifo_cfg.FIFOEn = bFALSE;
fifo_cfg.FIFOMode = FIFOMODE_FIFO; fifo_cfg.FIFOMode = FIFOMODE_FIFO;
@ -279,6 +290,15 @@ static int32_t AD5940PlatformCfg(void)
return 0; return 0;
} }
/**
* @brief Performs a full system reset and re-configuration.
* Call this after a measurement sequence finishes to park the device in a clean state.
*/
void SystemReset(void) {
AD5940_SoftReset();
AD5940PlatformCfg();
}
void ImpedanceShowResult(uint32_t *pData, uint32_t DataCount) void ImpedanceShowResult(uint32_t *pData, uint32_t DataCount)
{ {
float freq; float freq;
@ -320,9 +340,6 @@ void RampShowResult(float *pData, uint32_t DataCount)
void Routine_CalibrateLFO(void) { void Routine_CalibrateLFO(void) {
printf(">> Calibrating LFOSC...\n"); 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; LFOSCMeasure_Type cal_cfg;
cal_cfg.CalDuration = 1000.0; cal_cfg.CalDuration = 1000.0;
@ -334,18 +351,17 @@ void Routine_CalibrateLFO(void) {
} else { } else {
printf(">> LFOSC Calibration Failed.\n"); printf(">> LFOSC Calibration Failed.\n");
} }
SystemReset(); // Clean up after calibration
} }
void Routine_Measure(float freq) { void Routine_Measure(float freq) {
if (CurrentMode == MODE_AMPEROMETRIC) AppAMPCtrl(AMPCTRL_SHUTDOWN, 0);
else if (CurrentMode == MODE_RAMP) AppRAMPCtrl(APPCTRL_SHUTDOWN, 0);
CurrentMode = MODE_IMPEDANCE; CurrentMode = MODE_IMPEDANCE;
AppIMPCfg_Type *pCfg; AppIMPCfg_Type *pCfg;
AppIMPGetCfg(&pCfg); AppIMPGetCfg(&pCfg);
AppIMPCleanup();
AD5940ImpedanceStructInit(); // Reload config with current HP settings AD5940ImpedanceStructInit();
pCfg->WuptClkFreq = LFOSCFreq; pCfg->WuptClkFreq = LFOSCFreq;
pCfg->SweepCfg.SweepEn = bFALSE; pCfg->SweepCfg.SweepEn = bFALSE;
@ -362,15 +378,12 @@ void Routine_Measure(float freq) {
} }
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);
else if (CurrentMode == MODE_RAMP) AppRAMPCtrl(APPCTRL_SHUTDOWN, 0);
CurrentMode = MODE_IMPEDANCE; CurrentMode = MODE_IMPEDANCE;
AppIMPCfg_Type *pCfg; AppIMPCfg_Type *pCfg;
AppIMPGetCfg(&pCfg); AppIMPGetCfg(&pCfg);
AppIMPCleanup();
AD5940ImpedanceStructInit(); // Reload config with current HP settings AD5940ImpedanceStructInit();
pCfg->WuptClkFreq = LFOSCFreq; pCfg->WuptClkFreq = LFOSCFreq;
pCfg->SweepCfg.SweepEn = bTRUE; pCfg->SweepCfg.SweepEn = bTRUE;
@ -390,17 +403,15 @@ void Routine_Sweep(float start, float end, int steps) {
} }
void Routine_Amperometric(float bias_mv) { void Routine_Amperometric(float bias_mv) {
if (CurrentMode == MODE_IMPEDANCE) AppIMPCleanup();
else if (CurrentMode == MODE_RAMP) AppRAMPCtrl(APPCTRL_SHUTDOWN, 0);
CurrentMode = MODE_AMPEROMETRIC; 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();
pCfg->SensorBias = bias_mv; pCfg->SensorBias = bias_mv;
pCfg->ReDoRtiaCal = bFALSE; // Use pre-calibrated value pCfg->ReDoRtiaCal = bFALSE;
if(AppAMPInit(AppBuff, APPBUFF_SIZE) == AD5940ERR_OK) { if(AppAMPInit(AppBuff, APPBUFF_SIZE) == AD5940ERR_OK) {
AppAMPCtrl(AMPCTRL_START, 0); AppAMPCtrl(AMPCTRL_START, 0);
@ -410,15 +421,13 @@ void Routine_Amperometric(float bias_mv) {
} }
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();
else if (CurrentMode == MODE_AMPEROMETRIC) AppAMPCtrl(AMPCTRL_SHUTDOWN, 0);
CurrentMode = MODE_RAMP; 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();
pCfg->RampStartVolt = start_mv; pCfg->RampStartVolt = start_mv;
pCfg->RampPeakVolt = end_mv; pCfg->RampPeakVolt = end_mv;
@ -435,13 +444,10 @@ void Routine_LSV(float start_mv, float end_mv, int steps, int duration_ms) {
} }
void Routine_CalibrateSystem(void) { void Routine_CalibrateSystem(void) {
if (CurrentMode == MODE_AMPEROMETRIC) AppAMPCtrl(AMPCTRL_SHUTDOWN, 0);
else if (CurrentMode == MODE_RAMP) AppRAMPCtrl(APPCTRL_SHUTDOWN, 0);
CurrentMode = MODE_IMPEDANCE; CurrentMode = MODE_IMPEDANCE;
AppIMPCfg_Type *pCfg; AppIMPCfg_Type *pCfg;
AppIMPGetCfg(&pCfg); AppIMPGetCfg(&pCfg);
AppIMPCleanup();
ADCPGACal_Type adcpga_cal; ADCPGACal_Type adcpga_cal;
adcpga_cal.AdcClkFreq = 16000000.0; adcpga_cal.AdcClkFreq = 16000000.0;
@ -469,7 +475,6 @@ void Routine_CalibrateSystem(void) {
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
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;
@ -516,6 +521,8 @@ void Routine_CalibrateSystem(void) {
} else { } else {
printf("HSTIA Calibration Failed\n"); printf("HSTIA Calibration Failed\n");
} }
SystemReset(); // Clean up after calibration
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -592,6 +599,7 @@ void process_command() {
else if (CurrentMode == MODE_RAMP) AppRAMPCtrl(APPCTRL_SHUTDOWN, 0); else if (CurrentMode == MODE_RAMP) AppRAMPCtrl(APPCTRL_SHUTDOWN, 0);
CurrentMode = MODE_IDLE; CurrentMode = MODE_IDLE;
printf("STOPPED\n"); printf("STOPPED\n");
SystemReset(); // Reset here
} }
else if (cmd == 'z') { else if (cmd == 'z') {
watchdog_reboot(0, 0, 0); watchdog_reboot(0, 0, 0);
@ -603,10 +611,11 @@ int main() {
sleep_ms(2000); sleep_ms(2000);
setup_pins(); setup_pins();
// Initial Hardware Reset and Configuration
AD5940_HWReset();
AD5940_Initialize();
AD5940PlatformCfg(); AD5940PlatformCfg();
AD5940ImpedanceStructInit();
AD5940AMPStructInit();
AD5940RampStructInit();
Routine_CalibrateLFO(); Routine_CalibrateLFO();
@ -634,6 +643,7 @@ int main() {
printf("ERROR: FIFO Overflow/Underflow. Stopping.\n"); printf("ERROR: FIFO Overflow/Underflow. Stopping.\n");
AppIMPCleanup(); AppIMPCleanup();
CurrentMode = MODE_IDLE; CurrentMode = MODE_IDLE;
SystemReset(); // Reset on error
} else if(temp > 0) { } else if(temp > 0) {
ImpedanceShowResult(AppBuff, temp); ImpedanceShowResult(AppBuff, temp);
} }
@ -644,6 +654,7 @@ int main() {
printf("ERROR: FIFO Overflow/Underflow. Stopping.\n"); printf("ERROR: FIFO Overflow/Underflow. Stopping.\n");
AppAMPCtrl(AMPCTRL_SHUTDOWN, 0); AppAMPCtrl(AMPCTRL_SHUTDOWN, 0);
CurrentMode = MODE_IDLE; CurrentMode = MODE_IDLE;
SystemReset(); // Reset on error
} else if(temp > 0) { } else if(temp > 0) {
AmperometricShowResult((float*)AppBuff, temp); AmperometricShowResult((float*)AppBuff, temp);
} }
@ -654,6 +665,7 @@ int main() {
printf("ERROR: FIFO Overflow/Underflow. Stopping.\n"); printf("ERROR: FIFO Overflow/Underflow. Stopping.\n");
AppRAMPCtrl(APPCTRL_SHUTDOWN, 0); AppRAMPCtrl(APPCTRL_SHUTDOWN, 0);
CurrentMode = MODE_IDLE; CurrentMode = MODE_IDLE;
SystemReset(); // Reset on error
} else if(temp > 0) { } else if(temp > 0) {
RampShowResult((float*)AppBuff, temp); RampShowResult((float*)AppBuff, temp);
} }
@ -665,6 +677,7 @@ int main() {
else if (CurrentMode == MODE_AMPEROMETRIC) AppAMPCtrl(AMPCTRL_SHUTDOWN, 0); else if (CurrentMode == MODE_AMPEROMETRIC) AppAMPCtrl(AMPCTRL_SHUTDOWN, 0);
else if (CurrentMode == MODE_RAMP) AppRAMPCtrl(APPCTRL_SHUTDOWN, 0); else if (CurrentMode == MODE_RAMP) AppRAMPCtrl(APPCTRL_SHUTDOWN, 0);
CurrentMode = MODE_IDLE; CurrentMode = MODE_IDLE;
SystemReset(); // Reset here
} }
} }
} }