EIS/main.c

281 lines
7.9 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"
// ---------------------------------------------------------------------------
// 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];
// ---------------------------------------------------------------------------
// 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) {
// Increase SPI speed to 4MHz to prevent FIFO overflow during fast sweeps
spi_init(spi0, 4000000);
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 = 10000.0;
pImpedanceCfg->RtiaVal = 200.0;
pImpedanceCfg->SinFreq = 1000.0;
pImpedanceCfg->FifoThresh = 6;
pImpedanceCfg->DacVoltPP = 600.0;
pImpedanceCfg->ExcitBufGain = EXCITBUFGAIN_0P25;
pImpedanceCfg->HsDacGain = HSDACGAIN_0P2;
pImpedanceCfg->DswitchSel = SWD_CE0;
pImpedanceCfg->PswitchSel = SWP_CE0;
pImpedanceCfg->NswitchSel = SWN_SE0;
pImpedanceCfg->TswitchSel = SWT_TRTIA;
pImpedanceCfg->HstiaRtiaSel = HSTIARTIA_200;
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;
}
static int32_t AD5940PlatformCfg(void)
{
CLKCfg_Type clk_cfg;
FIFOCfg_Type fifo_cfg;
AGPIOCfg_Type gpio_cfg;
AD5940_HWReset();
AD5940_Initialize();
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, 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;
}
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++)
{
printf("DATA,%.2f,%.4f,%.4f,%.4f,%.4f\n",
freq,
pImp[i].Magnitude,
pImp[i].Phase*180/MATH_PI,
pImp[i].Magnitude,
pImp[i].Phase
);
}
}
// ---------------------------------------------------------------------------
// Main Loop
// ---------------------------------------------------------------------------
char input_buffer[64];
int input_pos = 0;
void process_command() {
char cmd = input_buffer[0];
AppIMPCfg_Type *pCfg;
AppIMPGetCfg(&pCfg);
// CRITICAL: Stop any running measurement before reconfiguration
AppIMPCtrl(IMPCTRL_STOPNOW, 0);
sleep_ms(10); // Give AFE time to halt
if (cmd == 'v') {
uint32_t id = AD5940_ReadReg(REG_AFECON_CHIPID);
printf("CHIP_ID:0x%04X\n", id);
}
else if (cmd == 'c') {
// Calibration: Run a single measurement at 1kHz
pCfg->SweepCfg.SweepEn = bFALSE;
pCfg->SinFreq = 1000.0f;
pCfg->NumOfData = 1; // Single Shot
if(AppIMPInit(AppBuff, APPBUFF_SIZE) == AD5940ERR_OK) {
AppIMPCtrl(IMPCTRL_START, 0);
} else {
printf("ERROR: Init Failed\n");
}
}
else if (cmd == 'm') {
// Measure: Continuous monitoring at fixed frequency
float freq = 1000.0f;
if (strlen(input_buffer) > 2) freq = atof(input_buffer + 2);
pCfg->SweepCfg.SweepEn = bFALSE;
pCfg->SinFreq = freq;
pCfg->NumOfData = -1; // Continuous
if(AppIMPInit(AppBuff, APPBUFF_SIZE) == AD5940ERR_OK) {
AppIMPCtrl(IMPCTRL_START, 0);
} else {
printf("ERROR: Init Failed\n");
}
}
else if (cmd == 's') {
// Sweep: Run exactly 'steps' measurements then stop
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);
pCfg->SweepCfg.SweepEn = bTRUE;
pCfg->SweepCfg.SweepStart = start;
pCfg->SweepCfg.SweepStop = end;
pCfg->SweepCfg.SweepPoints = steps;
pCfg->SweepCfg.SweepLog = bTRUE;
pCfg->NumOfData = steps; // Stop after sweep
if(AppIMPInit(AppBuff, APPBUFF_SIZE) == AD5940ERR_OK) {
AppIMPCtrl(IMPCTRL_START, 0);
} else {
printf("ERROR: Init Failed\n");
}
}
else if (cmd == 'z') {
// Full System Reset
watchdog_reboot(0, 0, 0);
}
}
int main() {
stdio_init_all();
sleep_ms(2000);
setup_pins();
AD5940PlatformCfg();
AD5940ImpedanceStructInit();
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;
AppIMPISR(AppBuff, &temp);
if(temp > 0) {
ImpedanceShowResult(AppBuff, temp);
}
}
}
return 0;
}