EIS/main.c

685 lines
21 KiB
C

// File: main.c
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include "pico/stdlib.h"
#include "hardware/spi.h"
#include "hardware/gpio.h"
#include "hardware/watchdog.h"
#include "ad5940.h"
#include "Impedance.h"
#include "Amperometric.h"
#include "RampTest.h"
#include "Reset.h"
#define AD5940ERR_STOP 10
// Fix for missing definition in some SDK versions
#ifndef LPTIARF_BYPASS
#define LPTIARF_BYPASS 0x2000
#endif
// ---------------------------------------------------------------------------
// Hardware Definitions
// ---------------------------------------------------------------------------
#define PIN_MISO 0
#define PIN_CS 1
#define PIN_SCK 2
#define PIN_MOSI 3
#define PIN_RST 9
#define PIN_INT 29
#define APPBUFF_SIZE 512
uint32_t AppBuff[APPBUFF_SIZE];
// Application State
typedef enum {
MODE_IDLE,
MODE_IMPEDANCE,
MODE_AMPEROMETRIC,
MODE_RAMP
} AppMode;
AppMode CurrentMode = MODE_IDLE;
float LFOSCFreq = 32000.0;
// ---------------------------------------------------------------------------
// Range / RTIA Management
// ---------------------------------------------------------------------------
// Current Configuration
uint32_t ConfigLptiaVal = 1000; // Default LP: 1k
uint32_t ConfigHstiaVal = 1000; // Default HP: 1k
uint32_t CurrentLpTiaRf = LPTIARF_20K;
// Calibrated Values
float CalibratedLptiaVal = 1000.0f;
float CalibratedHstiaVal = 1000.0f;
// Map integer value to HSTIA Enum (Impedance) - Limited Selection
uint32_t GetHSTIARtia(uint32_t val) {
switch(val) {
case 200: return HSTIARTIA_200;
case 1000: return HSTIARTIA_1K;
case 5000: return HSTIARTIA_5K;
case 10000: return HSTIARTIA_10K;
case 20000: return HSTIARTIA_20K;
case 40000: return HSTIARTIA_40K;
case 80000: return HSTIARTIA_80K;
case 160000: return HSTIARTIA_160K;
default: return HSTIARTIA_1K;
}
}
// Map integer value to LPTIA Enum (Amperometric/Ramp) - Massive Selection
uint32_t GetLPTIARtia(uint32_t val) {
switch(val) {
case 200: return LPTIARTIA_200R;
case 1000: return LPTIARTIA_1K;
case 2000: return LPTIARTIA_2K;
case 3000: return LPTIARTIA_3K;
case 4000: return LPTIARTIA_4K;
case 6000: return LPTIARTIA_6K;
case 8000: return LPTIARTIA_8K;
case 10000: return LPTIARTIA_10K;
case 12000: return LPTIARTIA_12K;
case 16000: return LPTIARTIA_16K;
case 20000: return LPTIARTIA_20K;
case 24000: return LPTIARTIA_24K;
case 30000: return LPTIARTIA_30K;
case 32000: return LPTIARTIA_32K;
case 40000: return LPTIARTIA_40K;
case 48000: return LPTIARTIA_48K;
case 64000: return LPTIARTIA_64K;
case 85000: return LPTIARTIA_85K;
case 96000: return LPTIARTIA_96K;
case 100000: return LPTIARTIA_100K;
case 120000: return LPTIARTIA_120K;
case 128000: return LPTIARTIA_128K;
case 160000: return LPTIARTIA_160K;
case 196000: return LPTIARTIA_196K;
case 256000: return LPTIARTIA_256K;
case 512000: return LPTIARTIA_512K;
default: return LPTIARTIA_1K;
}
}
// 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
// ---------------------------------------------------------------------------
void AD5940_CsClr(void) { gpio_put(PIN_CS, 0); }
void AD5940_CsSet(void) { gpio_put(PIN_CS, 1); }
void AD5940_RstClr(void) { gpio_put(PIN_RST, 0); }
void AD5940_RstSet(void) { gpio_put(PIN_RST, 1); }
void AD5940_Delay10us(uint32_t time) { sleep_us(time * 10); }
void AD5940_ReadWriteNBytes(unsigned char *pSendBuffer, unsigned char *pRecvBuff, unsigned long length) {
spi_write_read_blocking(spi0, pSendBuffer, pRecvBuff, length);
}
uint32_t AD5940_GetMCUIntFlag(void) {
return (gpio_get(PIN_INT) == 0);
}
uint32_t AD5940_ClrMCUIntFlag(void) {
return 1;
}
uint32_t AD5940_MCUResourceInit(void *pCfg) {
return 0;
}
void AD5940_MCUGpioWrite(uint32_t data) { (void)data; }
uint32_t AD5940_MCUGpioRead(uint32_t pin) { (void)pin; return 0; }
void AD5940_MCUGpioCtrl(uint32_t pin, BoolFlag enable) { (void)pin; (void)enable; }
// ---------------------------------------------------------------------------
// Application Logic
// ---------------------------------------------------------------------------
void setup_pins(void) {
// Run SPI at 16 MHz
spi_init(spi0, 16000000);
gpio_set_function(PIN_MISO, GPIO_FUNC_SPI);
gpio_set_function(PIN_SCK, GPIO_FUNC_SPI);
gpio_set_function(PIN_MOSI, GPIO_FUNC_SPI);
gpio_init(PIN_CS);
gpio_set_dir(PIN_CS, GPIO_OUT);
gpio_put(PIN_CS, 1);
gpio_init(PIN_RST);
gpio_set_dir(PIN_RST, GPIO_OUT);
gpio_put(PIN_RST, 1);
gpio_init(PIN_INT);
gpio_set_dir(PIN_INT, GPIO_IN);
gpio_pull_up(PIN_INT);
}
void AD5940ImpedanceStructInit(void)
{
AppIMPCfg_Type *pImpedanceCfg;
AppIMPGetCfg(&pImpedanceCfg);
pImpedanceCfg->SeqStartAddr = 0;
pImpedanceCfg->MaxSeqLen = 512;
pImpedanceCfg->RcalVal = 100.0;
pImpedanceCfg->RtiaVal = CalibratedHstiaVal;
pImpedanceCfg->SinFreq = 1000.0;
pImpedanceCfg->FifoThresh = 6;
pImpedanceCfg->DacVoltPP = 600.0;
pImpedanceCfg->ExcitBufGain = EXCITBUFGAIN_0P25;
pImpedanceCfg->HsDacGain = HSDACGAIN_0P2;
pImpedanceCfg->HsDacUpdateRate = 0;
pImpedanceCfg->DswitchSel = SWD_CE0;
pImpedanceCfg->PswitchSel = SWP_CE0;
pImpedanceCfg->NswitchSel = SWN_SE0;
pImpedanceCfg->TswitchSel = SWT_SE0LOAD;
pImpedanceCfg->HstiaRtiaSel = GetHSTIARtia(ConfigHstiaVal);
pImpedanceCfg->BiasVolt = 0.0;
pImpedanceCfg->SweepCfg.SweepEn = bFALSE;
pImpedanceCfg->SweepCfg.SweepStart = 100.0f;
pImpedanceCfg->SweepCfg.SweepStop = 100000.0f;
pImpedanceCfg->SweepCfg.SweepPoints = 50;
pImpedanceCfg->SweepCfg.SweepLog = bTRUE;
pImpedanceCfg->PwrMod = AFEPWR_LP;
pImpedanceCfg->ADCSinc3Osr = ADCSINC3OSR_4;
pImpedanceCfg->DftNum = DFTNUM_16384;
pImpedanceCfg->DftSrc = DFTSRC_SINC3;
}
void AD5940AMPStructInit(void)
{
AppAMPCfg_Type *pAMPCfg;
AppAMPGetCfg(&pAMPCfg);
pAMPCfg->WuptClkFreq = LFOSCFreq;
pAMPCfg->SeqStartAddr = 0;
pAMPCfg->MaxSeqLen = 512;
pAMPCfg->RcalVal = 100.0;
pAMPCfg->NumOfData = -1;
pAMPCfg->AmpODR = 1.0;
pAMPCfg->FifoThresh = 4;
pAMPCfg->SensorBias = 0;
pAMPCfg->LptiaRtiaSel = GetLPTIARtia(ConfigLptiaVal);
pAMPCfg->LpTiaRl = GetLPTIARload(ConfigLptiaVal);
pAMPCfg->LpTiaRf = CurrentLpTiaRf;
pAMPCfg->Vzero = 1100;
pAMPCfg->ADCRefVolt = 1.82;
pAMPCfg->RtiaCalValue.Magnitude = CalibratedLptiaVal;
}
void AD5940RampStructInit(void)
{
AppRAMPCfg_Type *pRampCfg;
AppRAMPGetCfg(&pRampCfg);
pRampCfg->SeqStartAddr = 0;
pRampCfg->MaxSeqLen = 1024;
pRampCfg->RcalVal = 100.0;
pRampCfg->ADCRefVolt = 1820.0f;
pRampCfg->FifoThresh = 4;
pRampCfg->SysClkFreq = 16000000.0f;
pRampCfg->LFOSCClkFreq = LFOSCFreq;
pRampCfg->RampStartVolt = -500.0f;
pRampCfg->RampPeakVolt = +500.0f;
pRampCfg->VzeroStart = 1100.0f;
pRampCfg->VzeroPeak = 1100.0f;
pRampCfg->StepNumber = 100;
pRampCfg->RampDuration = 10000;
pRampCfg->SampleDelay = 1.0f;
pRampCfg->LPTIARtiaSel = GetLPTIARtia(ConfigLptiaVal);
pRampCfg->LPTIARloadSel = GetLPTIARload(ConfigLptiaVal);
pRampCfg->LpTiaRf = CurrentLpTiaRf;
pRampCfg->AdcPgaGain = ADCPGA_1P5;
pRampCfg->RtiaValue.Magnitude = CalibratedLptiaVal;
}
/**
* @brief Configures the AD5940 Platform (Clocks, FIFO, GPIO).
* This must be called after every Reset.
*/
static int32_t AD5940PlatformCfg(void)
{
CLKCfg_Type clk_cfg;
FIFOCfg_Type fifo_cfg;
AGPIOCfg_Type gpio_cfg;
// Note: HWReset and Initialize are now handled by the caller (System Init or SoftReset)
clk_cfg.ADCClkDiv = ADCCLKDIV_1;
clk_cfg.ADCCLkSrc = ADCCLKSRC_HFOSC;
clk_cfg.SysClkDiv = SYSCLKDIV_1;
clk_cfg.SysClkSrc = SYSCLKSRC_HFOSC;
clk_cfg.HfOSC32MHzMode = bFALSE;
clk_cfg.HFOSCEn = bTRUE;
clk_cfg.HFXTALEn = bFALSE;
clk_cfg.LFOSCEn = bTRUE;
AD5940_CLKCfg(&clk_cfg);
fifo_cfg.FIFOEn = bFALSE;
fifo_cfg.FIFOMode = FIFOMODE_FIFO;
fifo_cfg.FIFOSize = FIFOSIZE_4KB;
fifo_cfg.FIFOSrc = FIFOSRC_DFT;
fifo_cfg.FIFOThresh = 6;
AD5940_FIFOCfg(&fifo_cfg);
fifo_cfg.FIFOEn = bTRUE;
AD5940_FIFOCfg(&fifo_cfg);
AD5940_INTCCfg(AFEINTC_1, AFEINTSRC_ALLINT, bTRUE);
AD5940_INTCClrFlag(AFEINTSRC_ALLINT);
AD5940_INTCCfg(AFEINTC_0, AFEINTSRC_DATAFIFOTHRESH|AFEINTSRC_CUSTOMINT0, bTRUE);
AD5940_INTCClrFlag(AFEINTSRC_ALLINT);
gpio_cfg.FuncSet = GP0_INT;
gpio_cfg.InputEnSet = 0;
gpio_cfg.OutputEnSet = AGPIO_Pin0;
gpio_cfg.OutVal = 0;
gpio_cfg.PullEnSet = 0;
AD5940_AGPIOCfg(&gpio_cfg);
AD5940_SleepKeyCtrlS(SLPKEY_UNLOCK);
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)
{
float freq;
fImpPol_Type *pImp = (fImpPol_Type*)pData;
AppIMPCtrl(IMPCTRL_GETFREQ, &freq);
for(int i=0;i<DataCount;i++)
{
float mag = pImp[i].Magnitude;
float phase = pImp[i].Phase;
float real = mag * cosf(phase);
float imag = mag * sinf(phase);
printf("DATA,%.2f,%.4f,%.4f,%.4f,%.4f\n", freq, mag, phase * 180.0f / MATH_PI, real, imag);
}
}
void AmperometricShowResult(float *pData, uint32_t DataCount)
{
static int index = 0;
for(int i=0;i<DataCount;i++)
{
printf("AMP,%d,%.4f\n", index++, pData[i]);
}
}
void RampShowResult(float *pData, uint32_t DataCount)
{
static int index = 0;
for(int i=0;i<DataCount;i++)
{
printf("RAMP,%d,%.4f\n", index++, pData[i]);
}
}
// ---------------------------------------------------------------------------
// High-Level Routines
// ---------------------------------------------------------------------------
void Routine_CalibrateLFO(void) {
printf(">> Calibrating LFOSC...\n");
LFOSCMeasure_Type cal_cfg;
cal_cfg.CalDuration = 1000.0;
cal_cfg.CalSeqAddr = 0;
cal_cfg.SystemClkFreq = 16000000.0;
if(AD5940_LFOSCMeasure(&cal_cfg, &LFOSCFreq) == AD5940ERR_OK) {
printf(">> LFOSC Calibrated: %.2f Hz\n", LFOSCFreq);
} else {
printf(">> LFOSC Calibration Failed.\n");
}
SystemReset(); // Clean up after calibration
}
void Routine_Measure(float freq) {
CurrentMode = MODE_IMPEDANCE;
AppIMPCfg_Type *pCfg;
AppIMPGetCfg(&pCfg);
AD5940ImpedanceStructInit();
pCfg->WuptClkFreq = LFOSCFreq;
pCfg->SweepCfg.SweepEn = bFALSE;
pCfg->SinFreq = freq;
pCfg->NumOfData = -1;
pCfg->RealDataCount = -1;
pCfg->bParaChanged = bTRUE;
if(AppIMPInit(AppBuff, APPBUFF_SIZE) == AD5940ERR_OK) {
AppIMPCtrl(IMPCTRL_START, 0);
} else {
printf("ERROR: Init Failed\n");
}
}
void Routine_Sweep(float start, float end, int steps) {
CurrentMode = MODE_IMPEDANCE;
AppIMPCfg_Type *pCfg;
AppIMPGetCfg(&pCfg);
AD5940ImpedanceStructInit();
pCfg->WuptClkFreq = LFOSCFreq;
pCfg->SweepCfg.SweepEn = bTRUE;
pCfg->SweepCfg.SweepStart = start;
pCfg->SweepCfg.SweepStop = end;
pCfg->SweepCfg.SweepPoints = steps + 1;
pCfg->NumOfData = steps + 1;
pCfg->RealDataCount = steps;
pCfg->SweepCfg.SweepLog = bTRUE;
pCfg->bParaChanged = bTRUE;
if(AppIMPInit(AppBuff, APPBUFF_SIZE) == AD5940ERR_OK) {
AppIMPCtrl(IMPCTRL_START, 0);
} else {
printf("ERROR: Init Failed\n");
}
}
void Routine_Amperometric(float bias_mv) {
CurrentMode = MODE_AMPEROMETRIC;
printf(">> Starting Amperometry (Bias: %.1f mV, LP Range: %d)...\n", bias_mv, ConfigLptiaVal);
AppAMPCfg_Type *pCfg;
AppAMPGetCfg(&pCfg);
AD5940AMPStructInit();
pCfg->SensorBias = bias_mv;
pCfg->ReDoRtiaCal = bFALSE;
if(AppAMPInit(AppBuff, APPBUFF_SIZE) == AD5940ERR_OK) {
AppAMPCtrl(AMPCTRL_START, 0);
} else {
printf("ERROR: AMP Init Failed\n");
}
}
void Routine_LSV(float start_mv, float end_mv, int steps, int duration_ms) {
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);
AppRAMPCfg_Type *pCfg;
AppRAMPGetCfg(&pCfg);
AD5940RampStructInit();
pCfg->RampStartVolt = start_mv;
pCfg->RampPeakVolt = end_mv;
pCfg->StepNumber = steps;
pCfg->RampDuration = duration_ms;
pCfg->bRampOneDir = bTRUE;
pCfg->bParaChanged = bTRUE;
if(AppRAMPInit(AppBuff, APPBUFF_SIZE) == AD5940ERR_OK) {
AppRAMPCtrl(APPCTRL_START, 0);
} else {
printf("ERROR: RAMP Init Failed\n");
}
}
void Routine_CalibrateSystem(void) {
CurrentMode = MODE_IMPEDANCE;
AppIMPCfg_Type *pCfg;
AppIMPGetCfg(&pCfg);
ADCPGACal_Type adcpga_cal;
adcpga_cal.AdcClkFreq = 16000000.0;
adcpga_cal.SysClkFreq = 16000000.0;
adcpga_cal.ADCSinc3Osr = ADCSINC3OSR_4;
adcpga_cal.ADCSinc2Osr = ADCSINC2OSR_22;
adcpga_cal.ADCPga = ADCPGA_1P5;
adcpga_cal.PGACalType = PGACALTYPE_OFFSET;
adcpga_cal.TimeOut10us = 1000;
adcpga_cal.VRef1p11 = 1.11;
adcpga_cal.VRef1p82 = 1.82;
printf(">> Calibrating ADC Offset...\n");
AD5940_ADCPGACal(&adcpga_cal);
// --- 1. Calibrate LPTIA (Low Power Loop) ---
LPRTIACal_Type lprtia_cal;
fImpPol_Type LpRes;
memset(&lprtia_cal, 0, sizeof(lprtia_cal));
lprtia_cal.AdcClkFreq = 16000000.0;
lprtia_cal.SysClkFreq = 16000000.0;
lprtia_cal.ADCSinc3Osr = ADCSINC3OSR_4;
lprtia_cal.ADCSinc2Osr = ADCSINC2OSR_22;
lprtia_cal.bPolarResult = bTRUE;
lprtia_cal.fRcal = 100.0;
lprtia_cal.LpTiaRtia = GetLPTIARtia(ConfigLptiaVal);
lprtia_cal.LpAmpPwrMod = LPAMPPWR_NORM;
lprtia_cal.bWithCtia = bFALSE;
lprtia_cal.fFreq = 100.0f;
lprtia_cal.DftCfg.DftNum = DFTNUM_2048;
lprtia_cal.DftCfg.DftSrc = DFTSRC_SINC3;
lprtia_cal.DftCfg.HanWinEn = bTRUE;
printf(">> Calibrating LPTIA %d Ohm...\n", ConfigLptiaVal);
if (AD5940_LPRtiaCal(&lprtia_cal, &LpRes) == AD5940ERR_OK) {
printf("Calibrated LPTIA: Mag = %f Ohm, Phase = %f\n", LpRes.Magnitude, LpRes.Phase);
CalibratedLptiaVal = LpRes.Magnitude;
} else {
printf("LPTIA Calibration Failed\n");
}
// --- 2. Calibrate HSTIA (High Speed Loop) ---
HSDACCfg_Type hsdac_cfg;
hsdac_cfg.ExcitBufGain = EXCITBUFGAIN_0P25;
hsdac_cfg.HsDacGain = HSDACGAIN_0P2;
hsdac_cfg.HsDacUpdateRate = 7;
AD5940_HSDacCfgS(&hsdac_cfg);
HSRTIACal_Type hsrtia_cal;
fImpPol_Type HsRes;
memset(&hsrtia_cal, 0, sizeof(hsrtia_cal));
hsrtia_cal.fFreq = 1000.0f;
hsrtia_cal.AdcClkFreq = 16000000.0;
hsrtia_cal.SysClkFreq = 16000000.0;
hsrtia_cal.ADCSinc3Osr = ADCSINC3OSR_4;
hsrtia_cal.ADCSinc2Osr = ADCSINC2OSR_22;
hsrtia_cal.bPolarResult = bTRUE;
hsrtia_cal.fRcal = 100.0;
hsrtia_cal.HsTiaCfg.DiodeClose = bFALSE;
hsrtia_cal.HsTiaCfg.HstiaBias = HSTIABIAS_1P1;
hsrtia_cal.HsTiaCfg.HstiaCtia = 31;
hsrtia_cal.HsTiaCfg.HstiaRtiaSel = GetHSTIARtia(ConfigHstiaVal);
hsrtia_cal.HsTiaCfg.HstiaDeRtia = HSTIADERTIA_OPEN;
hsrtia_cal.HsTiaCfg.HstiaDeRload = HSTIADERLOAD_OPEN;
hsrtia_cal.DftCfg.DftNum = DFTNUM_16384;
hsrtia_cal.DftCfg.DftSrc = DFTSRC_SINC3;
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);
CalibratedHstiaVal = HsRes.Magnitude;
} else {
printf("HSTIA Calibration Failed\n");
}
SystemReset(); // Clean up after calibration
}
// ---------------------------------------------------------------------------
// Main Loop
// ---------------------------------------------------------------------------
char input_buffer[64];
int input_pos = 0;
void process_command() {
char cmd = input_buffer[0];
sleep_ms(10);
if (cmd == 'v') {
uint32_t id = AD5940_ReadReg(REG_AFECON_CHIPID);
printf("CHIP_ID:0x%04X\n", id);
}
else if (cmd == 'r') {
// r <lp_val> <hp_val>
if (strlen(input_buffer) > 2) {
int lp = 0, hp = 0;
int count = sscanf(input_buffer + 2, "%d %d", &lp, &hp);
if (count >= 1) ConfigLptiaVal = lp;
if (count >= 2) ConfigHstiaVal = hp;
printf("RANGE_SET LP:%d HP:%d\n", ConfigLptiaVal, ConfigHstiaVal);
}
}
else if (cmd == 'f') {
if (strlen(input_buffer) > 2) {
int idx = atoi(input_buffer + 2);
switch(idx) {
case 0: CurrentLpTiaRf = LPTIARF_BYPASS; break;
case 1: CurrentLpTiaRf = LPTIARF_20K; break;
case 2: CurrentLpTiaRf = LPTIARF_100K; break;
case 3: CurrentLpTiaRf = LPTIARF_200K; break;
case 4: CurrentLpTiaRf = LPTIARF_400K; break;
case 5: CurrentLpTiaRf = LPTIARF_600K; break;
case 6: CurrentLpTiaRf = LPTIARF_1M; break;
default: CurrentLpTiaRf = LPTIARF_20K; break;
}
printf("LPF_SET:%d\n", idx);
}
}
else if (cmd == 'c') {
Routine_CalibrateLFO();
Routine_CalibrateSystem();
}
else if (cmd == 'm') {
float freq = 1000.0f;
if (strlen(input_buffer) > 2) freq = atof(input_buffer + 2);
Routine_Measure(freq);
}
else if (cmd == 's') {
float start = 100.0f, end = 100000.0f;
int steps = 50;
if (strlen(input_buffer) > 2) sscanf(input_buffer + 2, "%f %f %d", &start, &end, &steps);
Routine_Sweep(start, end, steps);
}
else if (cmd == 'a') {
float bias = 0.0f;
if (strlen(input_buffer) > 2) bias = atof(input_buffer + 2);
Routine_Amperometric(bias);
}
else if (cmd == 'l') {
// l <start> <end> <steps> <duration>
float start = -500.0f, end = 500.0f;
int steps = 100, duration = 10000;
if (strlen(input_buffer) > 2) sscanf(input_buffer + 2, "%f %f %d %d", &start, &end, &steps, &duration);
Routine_LSV(start, end, steps, duration);
}
else if (cmd == 'x') {
if (CurrentMode == MODE_IMPEDANCE) AppIMPCleanup();
else if (CurrentMode == MODE_AMPEROMETRIC) AppAMPCtrl(AMPCTRL_SHUTDOWN, 0);
else if (CurrentMode == MODE_RAMP) AppRAMPCtrl(APPCTRL_SHUTDOWN, 0);
CurrentMode = MODE_IDLE;
printf("STOPPED\n");
SystemReset(); // Reset here
}
else if (cmd == 'z') {
watchdog_reboot(0, 0, 0);
}
}
int main() {
stdio_init_all();
sleep_ms(2000);
setup_pins();
// Initial Hardware Reset and Configuration
AD5940_HWReset();
AD5940_Initialize();
AD5940PlatformCfg();
Routine_CalibrateLFO();
printf("SYSTEM_READY\n");
while (true) {
int c = getchar_timeout_us(0);
if (c != PICO_ERROR_TIMEOUT) {
if (c == '\n' || c == '\r') {
input_buffer[input_pos] = 0;
if (input_pos > 0) process_command();
input_pos = 0;
} else if (input_pos < 63) {
input_buffer[input_pos++] = (char)c;
}
}
if (gpio_get(PIN_INT) == 0) {
uint32_t temp = APPBUFF_SIZE;
int32_t status = 0;
if (CurrentMode == MODE_IMPEDANCE) {
status = AppIMPISR(AppBuff, &temp);
if (status == AD5940ERR_FIFO) {
printf("ERROR: FIFO Overflow/Underflow. Stopping.\n");
AppIMPCleanup();
CurrentMode = MODE_IDLE;
SystemReset(); // Reset on error
} else if(temp > 0) {
ImpedanceShowResult(AppBuff, temp);
}
}
else if (CurrentMode == MODE_AMPEROMETRIC) {
status = AppAMPISR(AppBuff, &temp);
if (status == AD5940ERR_FIFO) {
printf("ERROR: FIFO Overflow/Underflow. Stopping.\n");
AppAMPCtrl(AMPCTRL_SHUTDOWN, 0);
CurrentMode = MODE_IDLE;
SystemReset(); // Reset on error
} else if(temp > 0) {
AmperometricShowResult((float*)AppBuff, temp);
}
}
else if (CurrentMode == MODE_RAMP) {
status = AppRAMPISR(AppBuff, &temp);
if (status == AD5940ERR_FIFO) {
printf("ERROR: FIFO Overflow/Underflow. Stopping.\n");
AppRAMPCtrl(APPCTRL_SHUTDOWN, 0);
CurrentMode = MODE_IDLE;
SystemReset(); // Reset on error
} else if(temp > 0) {
RampShowResult((float*)AppBuff, temp);
}
}
if (status == AD5940ERR_STOP) {
printf("STOPPED\n");
if (CurrentMode == MODE_IMPEDANCE) AppIMPCleanup();
else if (CurrentMode == MODE_AMPEROMETRIC) AppAMPCtrl(AMPCTRL_SHUTDOWN, 0);
else if (CurrentMode == MODE_RAMP) AppRAMPCtrl(APPCTRL_SHUTDOWN, 0);
CurrentMode = MODE_IDLE;
SystemReset(); // Reset here
}
}
}
return 0;
}