diff --git a/.gitignore b/.gitignore index 88918f4..c352adf 100644 --- a/.gitignore +++ b/.gitignore @@ -6,7 +6,7 @@ build *.swp *.cmake requirements.txt -ad5940 +ad5940.* pico_sdk_import.cmake build* *.png diff --git a/Impedance.c b/Impedance.c index 9027280..6970e9a 100644 --- a/Impedance.c +++ b/Impedance.c @@ -9,6 +9,9 @@ #define DAC12BITVOLT_1LSB (2200.0f/4095) // mV #define DAC6BITVOLT_1LSB (DAC12BITVOLT_1LSB*64) // mV +/* Forward declaration */ +AD5940Err AppIMPCheckFreq(float freq); + AppIMPCfg_Type AppIMPCfg = { .bParaChanged = bFALSE, @@ -19,12 +22,12 @@ AppIMPCfg_Type AppIMPCfg = .MaxSeqLenCal = 0, .ImpODR = 20.0, /* Output Data Rate: 20.0 Hz */ - .NumOfData = -1, /* -1 for infinite/continuous measurement */ + .NumOfData = 101, /* Default to 101 points (matches default sweep) */ .RealDataCount = -1, .SysClkFreq = 16000000.0, .WuptClkFreq = 32000.0, /* Low Frequency Oscillator (LFO) typically 32kHz */ .AdcClkFreq = 16000000.0, - .RcalVal = 10000.0, /* Calibration Resistor Value (Ohms) */ + .RcalVal = 100.0, /* Calibration Resistor Value (Ohms) */ .RtiaVal = 200.0, /* TIA Gain Resistor Value (Ohms) */ .DswitchSel = SWD_CE0, @@ -54,11 +57,13 @@ AppIMPCfg_Type AppIMPCfg = .ADCAvgNum = ADCAVGNUM_16, + /* Default Sweep: 1kHz to 100kHz, 50 Points Per Decade (Log) */ + /* Decades = log10(100k) - log10(1k) = 2. Points = 2 * 50 + 1 = 101 */ .SweepCfg.SweepEn = bTRUE, - .SweepCfg.SweepStart = 1000, + .SweepCfg.SweepStart = 1000.0, .SweepCfg.SweepStop = 100000.0, .SweepCfg.SweepPoints = 101, - .SweepCfg.SweepLog = bFALSE, + .SweepCfg.SweepLog = bTRUE, .SweepCfg.SweepIndex = 0, .FifoThresh = 6, /* Threshold: 3 measurements * 2 (Real/Imag) = 6 words */ @@ -70,8 +75,37 @@ AppIMPCfg_Type AppIMPCfg = /* Helper Functions */ /* ----------------------------------------------------------------------- */ -// Forward declaration to allow usage in AppIMPCtrl -AD5940Err AppIMPCheckFreq(float freq); +/** + * @brief Configures the Impedance Sweep parameters. + * @param start Start Frequency in Hz + * @param stop Stop Frequency in Hz + * @param ppd Points Per Decade (Resolution) + */ +void AppIMPConfigureSweep(float start, float stop, float ppd) { + if (start <= 0 || stop <= 0 || ppd <= 0) return; + + AppIMPCfg.SweepCfg.SweepEn = bTRUE; + AppIMPCfg.SweepCfg.SweepStart = start; + AppIMPCfg.SweepCfg.SweepStop = stop; + AppIMPCfg.SweepCfg.SweepLog = bTRUE; + + // Calculate total points based on decades and PPD + // Formula: Points = (Decades * PPD) + 1 + float decades = log10f(stop) - log10f(start); + if (decades < 0) decades = -decades; // Handle sweep down if needed + + uint32_t points = (uint32_t)(decades * ppd) + 1; + AppIMPCfg.SweepCfg.SweepPoints = points; + + // Set NumOfData to stop the sequencer automatically after the sweep + AppIMPCfg.NumOfData = points; + + // Reset Sweep State + AppIMPCfg.FifoDataCount = 0; + AppIMPCfg.SweepCfg.SweepIndex = 0; + AppIMPCfg.SweepCurrFreq = start; + AppIMPCfg.SweepNextFreq = start; +} void AppIMPCleanup(void) { // Ensure chip is awake before sending commands diff --git a/host/src/MainWindow.cpp b/host/src/MainWindow.cpp index 83f89c8..137a999 100644 --- a/host/src/MainWindow.cpp +++ b/host/src/MainWindow.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -113,10 +114,41 @@ void MainWindow::setupUi() { checkIdBtn = new QPushButton("Check ID", this); calibrateBtn = new QPushButton("Calibrate", this); - sweepBtn = new QPushButton("Sweep", this); toolbar->addWidget(checkIdBtn); toolbar->addWidget(calibrateBtn); + toolbar->addSeparator(); + + // Sweep Configuration + QLabel *lblStart = new QLabel(" Start:", this); + spinSweepStart = new QDoubleSpinBox(this); + spinSweepStart->setRange(0.1, 200000.0); + spinSweepStart->setValue(1000.0); + spinSweepStart->setSuffix(" Hz"); + spinSweepStart->setToolTip("Sweep Start Frequency"); + + QLabel *lblStop = new QLabel(" Stop:", this); + spinSweepStop = new QDoubleSpinBox(this); + spinSweepStop->setRange(0.1, 200000.0); + spinSweepStop->setValue(200000.0); + spinSweepStop->setSuffix(" Hz"); + spinSweepStop->setToolTip("Sweep Stop Frequency"); + + QLabel *lblPPD = new QLabel(" PPD:", this); + spinSweepPPD = new QSpinBox(this); + spinSweepPPD->setRange(1, 1000); + spinSweepPPD->setValue(200); + spinSweepPPD->setSuffix(" pts/dec"); + spinSweepPPD->setToolTip("Points Per Decade"); + + sweepBtn = new QPushButton("Sweep", this); + + toolbar->addWidget(lblStart); + toolbar->addWidget(spinSweepStart); + toolbar->addWidget(lblStop); + toolbar->addWidget(spinSweepStop); + toolbar->addWidget(lblPPD); + toolbar->addWidget(spinSweepPPD); toolbar->addWidget(sweepBtn); toolbar->addSeparator(); @@ -132,10 +164,14 @@ void MainWindow::setupUi() { toolbar->addWidget(spinFreq); toolbar->addWidget(measureBtn); + // Initial State: Disabled checkIdBtn->setEnabled(false); calibrateBtn->setEnabled(false); sweepBtn->setEnabled(false); measureBtn->setEnabled(false); + spinSweepStart->setEnabled(false); + spinSweepStop->setEnabled(false); + spinSweepPPD->setEnabled(false); // Signal Connections connect(connectBtn, &QPushButton::clicked, this, &MainWindow::connectToPort); @@ -157,6 +193,9 @@ void MainWindow::setupUi() { sweepBtn->setFont(font); measureBtn->setFont(font); spinFreq->setFont(font); + spinSweepStart->setFont(font); + spinSweepStop->setFont(font); + spinSweepPPD->setFont(font); #endif } @@ -198,6 +237,9 @@ void MainWindow::connectToPort() { calibrateBtn->setEnabled(false); sweepBtn->setEnabled(false); measureBtn->setEnabled(false); + spinSweepStart->setEnabled(false); + spinSweepStop->setEnabled(false); + spinSweepPPD->setEnabled(false); isMeasuring = false; measureBtn->setText("Measure"); return; @@ -215,6 +257,9 @@ void MainWindow::connectToPort() { calibrateBtn->setEnabled(true); sweepBtn->setEnabled(true); measureBtn->setEnabled(true); + spinSweepStart->setEnabled(true); + spinSweepStop->setEnabled(true); + spinSweepPPD->setEnabled(true); } else { logWidget->append(">> Connection Error: " + serial->errorString()); } @@ -229,6 +274,9 @@ void MainWindow::onPortError(QSerialPort::SerialPortError error) { calibrateBtn->setEnabled(false); sweepBtn->setEnabled(false); measureBtn->setEnabled(false); + spinSweepStart->setEnabled(false); + spinSweepStop->setEnabled(false); + spinSweepPPD->setEnabled(false); isMeasuring = false; measureBtn->setText("Measure"); } @@ -258,10 +306,13 @@ void MainWindow::startSweep() { sweepFreqs.clear(); sweepReals.clear(); - // Use Firmware Sweep Command: s - // Example: 100Hz to 200kHz, 50 steps - logWidget->append(">> Starting Firmware Sweep (s 100 200000 50)..."); - serial->write("s 100 200000 50\n"); + double start = spinSweepStart->value(); + double stop = spinSweepStop->value(); + int ppd = spinSweepPPD->value(); + + // Send Firmware Sweep Command: s + logWidget->append(QString(">> Starting Sweep (s %1 %2 %3)...").arg(start).arg(stop).arg(ppd)); + serial->write(QString("s %1 %2 %3\n").arg(start).arg(stop).arg(ppd).toUtf8()); } void MainWindow::toggleMeasurement() { @@ -320,9 +371,8 @@ void MainWindow::parseData(const QString &data) { 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) { + // Update Hilbert periodically (every 10 points) to show progress + if (sweepReals.size() > 10 && sweepReals.size() % 10 == 0) { computeHilbert(); } } diff --git a/host/src/MainWindow.h b/host/src/MainWindow.h index d77b26b..39bbb97 100644 --- a/host/src/MainWindow.h +++ b/host/src/MainWindow.h @@ -62,6 +62,11 @@ private: QPushButton *measureBtn; QDoubleSpinBox *spinFreq; + // EIS + QDoubleSpinBox *spinSweepStart; + QDoubleSpinBox *spinSweepStop; + QSpinBox *spinSweepPPD; + bool isMeasuring = false; // Data Accumulation for Hilbert