gettin gooder

This commit is contained in:
pszsh 2026-01-26 14:48:45 -08:00
parent 98bd3534ea
commit b0b0feb7b2
6 changed files with 293 additions and 171 deletions

View File

@ -1,4 +1,4 @@
// Impedance.c
// File: Impedance.c
#include "ad5940.h"
#include <stdio.h>
#include "string.h"
@ -295,7 +295,8 @@ static AD5940Err AppIMPSeqMeasureGen(void)
AFECTRL_WG|AFECTRL_DACREFPWR|AFECTRL_HSDACPWR|\
AFECTRL_SINC2NOTCH, bTRUE);
AD5940_AFECtrlS(AFECTRL_WG|AFECTRL_ADCPWR, bTRUE);
AD5940_SEQGenInsert(SEQ_WAIT(16*10)); // Settling
// Increased settling time to 2000us (16*2000) to ensure stability
AD5940_SEQGenInsert(SEQ_WAIT(16*2000));
AD5940_AFECtrlS(AFECTRL_ADCCNV|AFECTRL_DFT, bTRUE);
AD5940_SEQGenFetchSeq(NULL, &AppIMPCfg.SeqWaitAddr[0]);
@ -317,7 +318,8 @@ static AD5940Err AppIMPSeqMeasureGen(void)
AD5940_ADCMuxCfgS(ADCMUXP_HSTIA_P, ADCMUXN_HSTIA_N);
AD5940_AFECtrlS(AFECTRL_ADCPWR|AFECTRL_WG, bTRUE);
AD5940_SEQGenInsert(SEQ_WAIT(16*10));
// Increased settling time to 2000us
AD5940_SEQGenInsert(SEQ_WAIT(16*2000));
AD5940_AFECtrlS(AFECTRL_ADCCNV|AFECTRL_DFT, bTRUE);
AD5940_SEQGenFetchSeq(NULL, &AppIMPCfg.SeqWaitAddr[1]);
@ -335,7 +337,8 @@ static AD5940Err AppIMPSeqMeasureGen(void)
AD5940_ADCMuxCfgS(ADCMUXP_AIN2, ADCMUXN_AIN3);
AD5940_AFECtrlS(AFECTRL_ADCPWR|AFECTRL_WG, bTRUE);
AD5940_SEQGenInsert(SEQ_WAIT(16*10));
// Increased settling time to 2000us
AD5940_SEQGenInsert(SEQ_WAIT(16*2000));
AD5940_AFECtrlS(AFECTRL_ADCCNV|AFECTRL_DFT, bTRUE);
AD5940_SEQGenFetchSeq(NULL, &AppIMPCfg.SeqWaitAddr[2]);
@ -370,7 +373,6 @@ AD5940Err AppIMPCheckFreq(float freq)
{
ADCFilterCfg_Type filter_cfg;
DFTCfg_Type dft_cfg;
// HSDACCfg_Type hsdac_cfg; // Removed to prevent override
uint32_t WaitClks;
ClksCalInfo_Type clks_cal;
FreqParams_Type freq_params;
@ -379,65 +381,25 @@ AD5940Err AppIMPCheckFreq(float freq)
freq_params = AD5940_GetFreqParameters(freq);
// CRITICAL FIX: Removed HSDAC and HSRTIA overrides.
// The configuration set in AppIMPSeqCfgGen (based on user config) should persist.
// Overriding HSTIARTIA_5K here while RtiaVal remains 200 causes massive math errors.
if(freq < 0.51)
// Only switch modes if necessary to avoid glitching the sequencer
if(freq < 80000)
{
// hsdac_cfg.ExcitBufGain = EXCITBUFGAIN_2;
// hsdac_cfg.HsDacGain = HSDACGAIN_1;
// hsdac_cfg.HsDacUpdateRate = 0x1B;
// AD5940_HSDacCfgS(&hsdac_cfg);
// AD5940_HSRTIACfgS(HSTIARTIA_40K);
if (AppIMPCfg.SysClkFreq != 16000000.0) {
filter_cfg.ADCRate = ADCRATE_800KHZ;
AppIMPCfg.AdcClkFreq = 16e6;
AppIMPCfg.SysClkFreq = 16000000.0;
AD5940_HPModeEn(bFALSE);
}
else if(freq < 5 )
{
// hsdac_cfg.ExcitBufGain = EXCITBUFGAIN_2;
// hsdac_cfg.HsDacGain = HSDACGAIN_1;
// hsdac_cfg.HsDacUpdateRate = 0x1B;
// AD5940_HSDacCfgS(&hsdac_cfg);
// AD5940_HSRTIACfgS(HSTIARTIA_40K);
filter_cfg.ADCRate = ADCRATE_800KHZ;
AppIMPCfg.AdcClkFreq = 16e6;
AD5940_HPModeEn(bFALSE);
}
else if(freq < 450)
else
{
// hsdac_cfg.ExcitBufGain = AppIMPCfg.ExcitBufGain;
// hsdac_cfg.HsDacGain = AppIMPCfg.HsDacGain;
// hsdac_cfg.HsDacUpdateRate = 0x1B;
// AD5940_HSDacCfgS(&hsdac_cfg);
// AD5940_HSRTIACfgS(HSTIARTIA_5K);
filter_cfg.ADCRate = ADCRATE_800KHZ;
AppIMPCfg.AdcClkFreq = 16e6;
AD5940_HPModeEn(bFALSE);
}
else if(freq<80000)
{
// hsdac_cfg.ExcitBufGain = AppIMPCfg.ExcitBufGain;
// hsdac_cfg.HsDacGain = AppIMPCfg.HsDacGain;
// hsdac_cfg.HsDacUpdateRate = 0x1B;
// AD5940_HSDacCfgS(&hsdac_cfg);
// AD5940_HSRTIACfgS(HSTIARTIA_5K);
filter_cfg.ADCRate = ADCRATE_800KHZ;
AppIMPCfg.AdcClkFreq = 16e6;
AD5940_HPModeEn(bFALSE);
}
if(freq >= 80000)
{
// hsdac_cfg.ExcitBufGain = AppIMPCfg.ExcitBufGain;
// hsdac_cfg.HsDacGain = AppIMPCfg.HsDacGain;
// hsdac_cfg.HsDacUpdateRate = 0x07;
// AD5940_HSDacCfgS(&hsdac_cfg);
// AD5940_HSRTIACfgS(HSTIARTIA_5K);
if (AppIMPCfg.SysClkFreq != 32000000.0) {
filter_cfg.ADCRate = ADCRATE_1P6MHZ;
AppIMPCfg.AdcClkFreq = 32e6;
AppIMPCfg.SysClkFreq = 32000000.0;
AD5940_HPModeEn(bTRUE);
}
}
filter_cfg.ADCAvgNum = ADCAVGNUM_16;
filter_cfg.ADCSinc2Osr = freq_params.ADCSinc2Osr;
@ -463,8 +425,15 @@ AD5940Err AppIMPCheckFreq(float freq)
// Update Wait Times for all 3 measurements
for (int i = 0; i < 3; i++) {
SRAMAddr = AppIMPCfg.MeasureSeqInfo.SeqRamAddr + AppIMPCfg.SeqWaitAddr[i];
SeqCmdBuff[0] = SEQ_WAIT(WaitClks/2);
SeqCmdBuff[1] = SEQ_WAIT(WaitClks/2);
// CRITICAL FIX: Double the wait time for High Power Mode (>=80kHz)
uint32_t finalWait = WaitClks/2;
if (freq >= 80000) {
finalWait *= 2;
}
SeqCmdBuff[0] = SEQ_WAIT(finalWait);
SeqCmdBuff[1] = SEQ_WAIT(finalWait);
AD5940_SEQCmdWrite(SRAMAddr, SeqCmdBuff, 2);
}
@ -551,6 +520,7 @@ int32_t AppIMPRegModify(int32_t * const pData, uint32_t *pDataCount)
if(AppIMPCfg.FifoDataCount >= AppIMPCfg.NumOfData)
{
AD5940_WUPTCtrl(bFALSE);
AD5940_SEQCtrlS(bFALSE); // Added safety
return AD5940ERR_OK;
}
}
@ -662,7 +632,12 @@ int32_t AppIMPISR(void *pBuff, uint32_t *pCount)
}
AD5940_FIFORd((uint32_t *)pBuff, FifoCnt);
AD5940_INTCClrFlag(AFEINTSRC_DATAFIFOTHRESH);
AppIMPRegModify(pBuff, &FifoCnt);
// Check if sweep is done
if (AppIMPRegModify(pBuff, &FifoCnt) != AD5940ERR_OK) {
// If sweep is done, we might want to signal main loop
}
AD5940_SleepKeyCtrlS(SLPKEY_UNLOCK);
AppIMPDataProcess((int32_t*)pBuff, &FifoCnt);
*pCount = FifoCnt;

View File

@ -1,3 +1,4 @@
// File: host/src/GraphWidget.cpp
#include "GraphWidget.h"
#include <limits>
#include <cmath>
@ -13,27 +14,40 @@ GraphWidget::GraphWidget(QWidget *parent) : QWidget(parent) {
// Setup Graphs
graph1 = plot->addGraph();
graph2 = plot->addGraph(plot->xAxis, plot->yAxis2);
graph3 = plot->addGraph(plot->xAxis, plot->yAxis2); // Hilbert Trace
// Style Graph 1 (Primary - Left Axis)
// Style Graph 1 (Real - Blue)
QPen pen1(Qt::blue);
pen1.setWidth(2);
graph1->setPen(pen1);
graph1->setLineStyle(QCPGraph::lsLine);
graph1->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssCircle, 3));
graph1->setName("Primary");
graph1->setName("Real");
// Style Graph 2 (Secondary - Right Axis)
// Style Graph 2 (Imaginary - Red)
QPen pen2(Qt::red);
pen2.setWidth(2);
graph2->setPen(pen2);
graph2->setLineStyle(QCPGraph::lsLine);
graph2->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssTriangle, 3));
graph2->setName("Secondary");
graph2->setName("Imaginary");
// Style Graph 3 (Hilbert - Green Dashed)
QPen pen3(Qt::green);
pen3.setWidth(2);
pen3.setStyle(Qt::DashLine);
graph3->setPen(pen3);
graph3->setLineStyle(QCPGraph::lsLine);
graph3->setName("Hilbert (Analytic)");
// Enable Right Axis
plot->yAxis2->setVisible(true);
plot->yAxis2->setTickLabels(true);
// Link Axes for Zooming
connect(plot->yAxis, SIGNAL(rangeChanged(QCPRange)), plot->yAxis2, SLOT(setRange(QCPRange)));
connect(plot->yAxis2, SIGNAL(rangeChanged(QCPRange)), plot->yAxis, SLOT(setRange(QCPRange)));
// Interactions
plot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);
@ -45,37 +59,7 @@ GraphWidget::GraphWidget(QWidget *parent) : QWidget(parent) {
plot->legend->setBrush(QBrush(QColor(255, 255, 255, 230)));
// Default Mode
configureBodePlot();
}
void GraphWidget::configureBodePlot() {
clear();
// X Axis: Frequency (Log)
plot->xAxis->setLabel("Frequency (Hz)");
plot->xAxis->setScaleType(QCPAxis::stLogarithmic);
QSharedPointer<QCPAxisTickerLog> logTicker(new QCPAxisTickerLog);
plot->xAxis->setTicker(logTicker);
plot->xAxis->setNumberFormat("eb");
// Y Axis 1: Impedance (Log)
plot->yAxis->setLabel("Impedance (Ohms)");
plot->yAxis->setScaleType(QCPAxis::stLogarithmic);
plot->yAxis->setTicker(logTicker);
plot->yAxis->setNumberFormat("eb");
// Y Axis 2: Phase (Linear)
plot->yAxis2->setLabel("Phase (Degrees)");
plot->yAxis2->setScaleType(QCPAxis::stLinear);
QSharedPointer<QCPAxisTicker> linTicker(new QCPAxisTicker);
plot->yAxis2->setTicker(linTicker);
plot->yAxis2->setNumberFormat("f");
plot->yAxis2->setRange(-180, 180);
graph1->setName("Impedance");
graph2->setName("Phase");
plot->replot();
configureRawPlot();
}
void GraphWidget::configureRawPlot() {
@ -86,6 +70,7 @@ void GraphWidget::configureRawPlot() {
plot->xAxis->setScaleType(QCPAxis::stLogarithmic);
QSharedPointer<QCPAxisTickerLog> logTicker(new QCPAxisTickerLog);
plot->xAxis->setTicker(logTicker);
plot->xAxis->setNumberFormat("eb");
// Y Axis 1: Real (Linear)
plot->yAxis->setLabel("Real (Ohms)");
@ -99,50 +84,82 @@ void GraphWidget::configureRawPlot() {
plot->yAxis2->setScaleType(QCPAxis::stLinear);
plot->yAxis2->setTicker(linTicker);
plot->yAxis2->setNumberFormat("f");
plot->yAxis2->setVisible(true);
graph1->setName("Real");
graph2->setName("Imaginary");
graph2->setVisible(true);
graph3->setVisible(true);
plot->replot();
}
void GraphWidget::addData(double freq, double val1, double val2) {
// 1. Validate X-Axis (Frequency)
// If Log scale, Frequency must be > 0.
if (plot->xAxis->scaleType() == QCPAxis::stLogarithmic && freq <= 0) {
return;
void GraphWidget::configureNyquistPlot() {
clear();
// X Axis: Real (Z')
plot->xAxis->setLabel("Real (Z')");
plot->xAxis->setScaleType(QCPAxis::stLinear);
QSharedPointer<QCPAxisTicker> linTicker(new QCPAxisTicker);
plot->xAxis->setTicker(linTicker);
plot->xAxis->setNumberFormat("f");
// Y Axis 1: -Imaginary (-Z'')
plot->yAxis->setLabel("-Imaginary (-Z'')");
plot->yAxis->setScaleType(QCPAxis::stLinear);
plot->yAxis->setTicker(linTicker);
plot->yAxis->setNumberFormat("f");
// Disable Secondary Axis for Nyquist
plot->yAxis2->setVisible(false);
graph2->setVisible(false);
graph3->setVisible(false);
graph1->setName("Nyquist");
graph1->setLineStyle(QCPGraph::lsLine);
graph1->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssCircle, 4));
plot->replot();
}
// 2. Validate Y-Axis 1 (Impedance/Real)
// If Log scale (Impedance), value must be > 0.
if (plot->yAxis->scaleType() == QCPAxis::stLogarithmic) {
// If we have a zero/negative impedance in log mode, skip it.
// Clamping to 1e-12 causes massive axis scaling issues (squished plots).
if (val1 <= 1e-7) {
val1 = std::numeric_limits<double>::quiet_NaN();
}
void GraphWidget::addData(double x, double val1, double val2) {
// Mode Detection based on Axis Labels (Simple state check)
bool isNyquist = (plot->xAxis->label() == "Real (Z')");
if (isNyquist) {
// For Nyquist: x = Real, val1 = Imaginary
// We plot Real vs -Imaginary
graph1->addData(x, -val1);
} else {
// Raw Plot: x = Freq, val1 = Real, val2 = Imag
if (plot->xAxis->scaleType() == QCPAxis::stLogarithmic && x <= 0) return;
graph1->addData(x, val1);
graph2->addData(x, val2);
}
// 3. Add Data
// QCustomPlot handles NaN by creating a line gap, which is visually correct for missing/bad data.
if (!std::isnan(val1)) {
graph1->addData(freq, val1);
}
// Graph 2 (Phase/Imag) is usually Linear.
graph2->addData(freq, val2);
// 4. Auto-scale
// We remove 'true' (onlyEnlarge). We want the axes to shrink
// if we zoom in or if the data range stabilizes.
// Auto-scale
graph1->rescaleAxes(false);
if (!isNyquist) {
graph2->rescaleAxes(false);
graph3->rescaleAxes(false);
}
plot->replot();
}
void GraphWidget::addHilbertData(const QVector<double>& freq, const QVector<double>& hilbertImag) {
// Only valid for Raw Plot
if (plot->xAxis->label() != "Frequency (Hz)") return;
graph3->setData(freq, hilbertImag);
graph3->rescaleAxes(false);
plot->replot();
}
void GraphWidget::clear() {
graph1->data()->clear();
graph2->data()->clear();
graph3->data()->clear();
plot->replot();
}

View File

@ -1,3 +1,4 @@
// File: host/src/GraphWidget.h
#pragma once
#include <QWidget>
@ -12,15 +13,17 @@ public:
// Data Handling
void addData(double freq, double val1, double val2);
void addHilbertData(const QVector<double>& freq, const QVector<double>& hilbertImag);
void clear();
// View Configurations
void configureBodePlot();
void configureRawPlot();
void configureNyquistPlot();
private:
QVBoxLayout *layout;
QCustomPlot *plot;
QCPGraph *graph1;
QCPGraph *graph2;
QCPGraph *graph1; // Real
QCPGraph *graph2; // Imaginary
QCPGraph *graph3; // Hilbert (Analytic Imaginary)
};

View File

@ -1,4 +1,4 @@
// host/src/MainWindow.cpp
// File: host/src/MainWindow.cpp
#include "MainWindow.h"
#include <QVBoxLayout>
#include <QDebug>
@ -10,6 +10,44 @@
#include <QLabel>
#include <QTimer>
#include <cmath>
#include <complex>
#include <vector>
// Simple FFT Implementation (Cooley-Tukey)
// Note: Size must be power of 2
void fft(std::vector<std::complex<double>>& a) {
int n = a.size();
if (n <= 1) return;
std::vector<std::complex<double>> a0(n / 2), a1(n / 2);
for (int i = 0; i < n / 2; i++) {
a0[i] = a[2 * i];
a1[i] = a[2 * i + 1];
}
fft(a0);
fft(a1);
double ang = 2 * M_PI / n;
std::complex<double> w(1), wn(cos(ang), sin(ang));
for (int i = 0; i < n / 2; i++) {
a[i] = a0[i] + w * a1[i];
a[i + n / 2] = a0[i] - w * a1[i];
w *= wn;
}
}
void ifft(std::vector<std::complex<double>>& a) {
int n = a.size();
// Conjugate
for (int i = 0; i < n; i++) a[i] = std::conj(a[i]);
// Forward FFT
fft(a);
// Conjugate again and scale
for (int i = 0; i < n; i++) {
a[i] = std::conj(a[i]);
a[i] /= n;
}
}
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) {
serial = new QSerialPort(this);
@ -37,13 +75,16 @@ void MainWindow::setupUi() {
// Tab Widget for Graphs
tabWidget = new QTabWidget(this);
finalGraph = new GraphWidget(this);
finalGraph->configureBodePlot();
rawGraph = new GraphWidget(this);
rawGraph->configureRawPlot();
tabWidget->addTab(finalGraph, "Bode Plot");
nyquistGraph = new GraphWidget(this);
nyquistGraph->configureNyquistPlot();
// Raw Data is now Default (Index 0)
tabWidget->addTab(rawGraph, "Raw Data");
tabWidget->addTab(nyquistGraph, "Nyquist Plot");
// Log Widget
logWidget = new QTextEdit(this);
@ -211,8 +252,12 @@ void MainWindow::runCalibration() {
void MainWindow::startSweep() {
if (!serial->isOpen()) return;
finalGraph->clear();
rawGraph->clear();
nyquistGraph->clear();
// Clear accumulated data
sweepFreqs.clear();
sweepReals.clear();
// Use Firmware Sweep Command: s <start> <end> <steps>
// Example: 100Hz to 200kHz, 50 steps
@ -260,15 +305,69 @@ void MainWindow::parseData(const QString &data) {
QStringList parts = data.split(',');
if (parts.size() < 6) return;
bool okF, okM, okP, okR, okI;
bool okF, okR, okI;
double freq = parts[1].toDouble(&okF);
double mag = parts[2].toDouble(&okM);
double phase= parts[3].toDouble(&okP);
double real = parts[4].toDouble(&okR);
double imag = parts[5].toDouble(&okI);
if (okF && okM && okP) finalGraph->addData(freq, mag, phase);
if (okF && okR && okI) rawGraph->addData(freq, real, imag);
if (okF && okR && okI) {
// Add to Raw Graph (Freq vs Real/Imag)
rawGraph->addData(freq, real, imag);
// Add to Nyquist Graph (Real vs Imag)
nyquistGraph->addData(real, imag, 0);
// Accumulate for Hilbert
sweepFreqs.append(freq);
sweepReals.append(real);
// Check if sweep is done (e.g., 50 points)
// For now, update Hilbert every 10 points or at end
if (sweepReals.size() >= 50) {
computeHilbert();
}
}
}
void MainWindow::computeHilbert() {
int n = sweepReals.size();
if (n == 0) return;
// 1. Zero-pad to next power of 2
int n_fft = 1;
while (n_fft < n) n_fft *= 2;
std::vector<std::complex<double>> signal(n_fft);
for (int i = 0; i < n; i++) {
signal[i] = std::complex<double>(sweepReals[i], 0.0);
}
// 2. FFT
fft(signal);
// 3. Create Analytic Signal in Frequency Domain
// H[0] = H[0]
// H[i] = 2*H[i] for 0 < i < N/2
// H[N/2] = H[N/2]
// H[i] = 0 for N/2 < i < N
for (int i = 1; i < n_fft / 2; i++) {
signal[i] *= 2.0;
}
for (int i = n_fft / 2 + 1; i < n_fft; i++) {
signal[i] = 0.0;
}
// 4. IFFT
ifft(signal);
// 5. Extract Imaginary Part (Hilbert Transform)
QVector<double> hilbertImag;
for (int i = 0; i < n; i++) {
hilbertImag.append(signal[i].imag());
}
// 6. Plot
rawGraph->addHilbertData(sweepFreqs, hilbertImag);
}
bool MainWindow::event(QEvent *event) {

View File

@ -1,4 +1,4 @@
// host/src/MainWindow.h
// File: host/src/MainWindow.h
#pragma once
#include <QMainWindow>
@ -42,12 +42,13 @@ private:
void setupUi();
void parseData(const QString &data);
void handleSwipe(QSwipeGesture *gesture);
void computeHilbert();
QSerialPort *serial;
// Views
GraphWidget *finalGraph; // Bode Plot
GraphWidget *rawGraph; // Raw Data
GraphWidget *rawGraph; // Raw Data (Freq vs Real/Imag)
GraphWidget *nyquistGraph; // Nyquist (Real vs -Imag)
QTextEdit *logWidget; // Serial Log
// Layout
@ -62,4 +63,8 @@ private:
QDoubleSpinBox *spinFreq;
bool isMeasuring = false;
// Data Accumulation for Hilbert
QVector<double> sweepFreqs;
QVector<double> sweepReals;
};

71
main.c
View File

@ -1,4 +1,4 @@
// main.c
// File: main.c
#include <stdio.h>
#include <math.h>
#include <string.h>
@ -182,28 +182,20 @@ void ImpedanceShowResult(uint32_t *pData, uint32_t DataCount)
char input_buffer[64];
int input_pos = 0;
void process_command() {
char cmd = input_buffer[0];
AppIMPCfg_Type *pCfg;
AppIMPGetCfg(&pCfg);
// Helper for robust state cleanup
void AD5940_Main_Cleanup(void) {
// Ensure chip is awake before sending commands
AD5940_WakeUp(10);
// CRITICAL: Stop any running measurement before reconfiguration
AppIMPCtrl(IMPCTRL_STOPNOW, 0);
sleep_ms(10); // Give AFE time to halt
// 1. Stop Sequencer and Wakeup Timer
AD5940_WUPTCtrl(bFALSE);
AD5940_SEQCtrlS(bFALSE);
if (cmd == 'v') {
uint32_t id = AD5940_ReadReg(REG_AFECON_CHIPID);
printf("CHIP_ID:0x%04X\n", id);
}
else if (cmd == 'c') {
// 1. CRITICAL FIX: Force System to 16MHz Low Power Mode
// This prevents the 32MHz post-sweep state from corrupting calibration timing
AD5940_HPModeEn(bFALSE);
// 2. Stop any active conversions/WG, but KEEP Reference/LDOs ON
// This prevents settling issues on restart
AD5940_AFECtrlS(AFECTRL_ADCCNV|AFECTRL_DFT|AFECTRL_WG, bFALSE);
// 2. Reset Analog Blocks to ensure clean state
AD5940_AFECtrlS(AFECTRL_ALL, bFALSE);
// 3. Disable and Reset the FIFO to stop "DATA" interrupts
// 3. Reset FIFO
FIFOCfg_Type fifo_cfg;
fifo_cfg.FIFOEn = bFALSE;
AD5940_FIFOCfg(&fifo_cfg);
@ -215,8 +207,25 @@ void process_command() {
fifo_cfg.FIFOThresh = 6;
AD5940_FIFOCfg(&fifo_cfg);
// 4. Clear any pending interrupts
// 4. Clear Interrupts
AD5940_INTCClrFlag(AFEINTSRC_ALLINT);
}
void process_command() {
char cmd = input_buffer[0];
AppIMPCfg_Type *pCfg;
AppIMPGetCfg(&pCfg);
// CRITICAL: Perform robust cleanup before any new operation
AD5940_Main_Cleanup();
sleep_ms(10); // Give AFE time to settle
if (cmd == 'v') {
uint32_t id = AD5940_ReadReg(REG_AFECON_CHIPID);
printf("CHIP_ID:0x%04X\n", id);
}
else if (cmd == 'c') {
// Cleanup already done by AD5940_Main_Cleanup() above
// 5. Perform ADC Calibration (Offset)
ADCPGACal_Type adcpga_cal;
@ -282,7 +291,11 @@ void process_command() {
pCfg->SweepCfg.SweepEn = bFALSE;
pCfg->SinFreq = freq;
pCfg->NumOfData = -1; // Continuous
pCfg->bParaChanged = bTRUE; // Force sequence regeneration
// CRITICAL FIX: Force parameter change flag to TRUE.
// This ensures AppIMPInit calls AppIMPSeqCfgGen, which re-enables
// the analog blocks (DAC, TIA, etc.) that AD5940_Main_Cleanup turned off.
pCfg->bParaChanged = bTRUE;
if(AppIMPInit(AppBuff, APPBUFF_SIZE) == AD5940ERR_OK) {
AppIMPCtrl(IMPCTRL_START, 0);
@ -302,7 +315,9 @@ void process_command() {
pCfg->SweepCfg.SweepPoints = steps;
pCfg->SweepCfg.SweepLog = bTRUE;
pCfg->NumOfData = steps; // Stop after sweep
pCfg->bParaChanged = bTRUE; // Force sequence regeneration
// CRITICAL FIX: Force parameter change flag to TRUE.
pCfg->bParaChanged = bTRUE;
if(AppIMPInit(AppBuff, APPBUFF_SIZE) == AD5940ERR_OK) {
AppIMPCtrl(IMPCTRL_START, 0);
@ -312,7 +327,7 @@ void process_command() {
}
else if (cmd == 'x') {
// Stop Measurement
AppIMPCtrl(IMPCTRL_STOPNOW, 0);
// Cleanup already done by AD5940_Main_Cleanup() at start of function
printf("STOPPED\n");
}
else if (cmd == 'z') {
@ -348,6 +363,14 @@ int main() {
AppIMPISR(AppBuff, &temp);
if(temp > 0) {
ImpedanceShowResult(AppBuff, temp);
// Check if sweep is done (simple check based on config)
AppIMPCfg_Type *pCfg;
AppIMPGetCfg(&pCfg);
if (pCfg->SweepCfg.SweepEn && pCfg->FifoDataCount >= pCfg->NumOfData) {
printf("DONE\n");
AD5940_Main_Cleanup(); // Ensure clean stop
}
}
}
}