EIS/main.c

258 lines
6.8 KiB
C

// File: main.c
#include <stdio.h>
#include <math.h>
#include "pico/stdlib.h"
#include "hardware/spi.h"
#include "hardware/gpio.h"
#include "ad5940.h"
// Pin 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 RCAL_VALUE 100.0f
// ---------------------------------------------------------------------------
// Platform Interface Implementation (Required by AD5940 Lib)
// ---------------------------------------------------------------------------
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);
}
// ---------------------------------------------------------------------------
// Application Logic
// ---------------------------------------------------------------------------
void setup_pins(void) {
// SPI0 at 1MHz
spi_init(spi0, 1000000);
gpio_set_function(PIN_MISO, GPIO_FUNC_SPI);
gpio_set_function(PIN_SCK, GPIO_FUNC_SPI);
gpio_set_function(PIN_MOSI, GPIO_FUNC_SPI);
// CS
gpio_init(PIN_CS);
gpio_set_dir(PIN_CS, GPIO_OUT);
gpio_put(PIN_CS, 1);
// RST
gpio_init(PIN_RST);
gpio_set_dir(PIN_RST, GPIO_OUT);
gpio_put(PIN_RST, 1);
// INT
gpio_init(PIN_INT);
gpio_set_dir(PIN_INT, GPIO_IN);
gpio_pull_up(PIN_INT);
}
void configure_afe(void) {
HSDACCfg_Type hsdac_cfg;
HSTIACfg_Type hsrtia_cfg;
HSLoopCfg_Type hsloop_cfg;
// Reset AFE control
AD5940_AFECtrlS(AFECTRL_ALL, bFALSE);
// Configure High Speed DAC
hsdac_cfg.ExcitBufGain = EXCITBUFGAIN_2;
hsdac_cfg.HsDacGain = HSDACGAIN_1;
hsdac_cfg.HsDacUpdateRate = 0x1B;
AD5940_HSDacCfgS(&hsdac_cfg);
// Configure High Speed TIA
hsrtia_cfg.HstiaDeRtia = HSTIADERTIA_1K;
hsrtia_cfg.HstiaCtia = 31; // 31pF
hsrtia_cfg.HstiaRtiaSel = HSTIARTIA_1K;
hsrtia_cfg.HstiaBias = HSTIABIAS_1P1;
hsrtia_cfg.DiodeClose = bFALSE;
hsrtia_cfg.HstiaDeRload = HSTIADERLOAD_OPEN;
AD5940_HSTIACfgS(&hsrtia_cfg);
// Configure High Speed Loop
hsloop_cfg.HsDacCfg = hsdac_cfg;
hsloop_cfg.HsTiaCfg = hsrtia_cfg;
hsloop_cfg.SWMatCfg.Dswitch = SWD_OPEN;
hsloop_cfg.SWMatCfg.Pswitch = SWP_OPEN;
hsloop_cfg.SWMatCfg.Nswitch = SWN_OPEN;
hsloop_cfg.SWMatCfg.Tswitch = SWT_OPEN;
hsloop_cfg.WgCfg.WgType = WGTYPE_SIN;
hsloop_cfg.WgCfg.GainCalEn = bFALSE;
hsloop_cfg.WgCfg.OffsetCalEn = bFALSE;
hsloop_cfg.WgCfg.SinCfg.SinFreqWord = AD5940_WGFreqWordCal(1000.0, 16000000.0);
hsloop_cfg.WgCfg.SinCfg.SinAmplitudeWord = 2047;
hsloop_cfg.WgCfg.SinCfg.SinOffsetWord = 0;
hsloop_cfg.WgCfg.SinCfg.SinPhaseWord = 0;
AD5940_HSLoopCfgS(&hsloop_cfg);
// Enable Power
AD5940_AFECtrlS(AFECTRL_ADCPWR | AFECTRL_HSTIAPWR | AFECTRL_HSDACPWR | AFECTRL_HPREFPWR, bTRUE);
// Enable Interrupts
AD5940_WriteReg(REG_INTC_INTCSEL0, BITM_INTC_INTCSEL0_INTSEL14);
}
float perform_dft(void) {
iImpCar_Type dft_res;
fImpCar_Type f_res;
AD5940_AFECtrlS(AFECTRL_ADCCNV | AFECTRL_DFT, bTRUE);
// Wait for interrupt or timeout
uint32_t timeout = 50000;
while(gpio_get(PIN_INT) && timeout--) {
sleep_us(10);
}
dft_res.Real = (int32_t)AD5940_ReadReg(REG_AFE_DFTREAL);
dft_res.Image = (int32_t)AD5940_ReadReg(REG_AFE_DFTIMAG);
AD5940_AFECtrlS(AFECTRL_ADCCNV | AFECTRL_DFT, bFALSE);
AD5940_WriteReg(REG_INTC_INTCFLAG0, BITM_INTC_INTCFLAG0_FLAG14);
f_res.Real = (float)dft_res.Real;
f_res.Image = (float)dft_res.Image;
return AD5940_ComplexMag(&f_res);
}
void set_sw_matrix(uint32_t lp_sw, uint32_t hs_sw) {
AD5940_WriteReg(REG_AFE_LPTIASW0, lp_sw);
AD5940_WriteReg(REG_AFE_HSTIACON, hs_sw);
}
void measure_at_freq(float freq) {
FreqParams_Type freq_params = AD5940_GetFreqParameters(freq);
// 1. Update HSDAC Update Rate based on frequency
uint32_t hsdac_rate = 0x1B;
if(freq >= 80000.0f) {
hsdac_rate = 0x07;
}
uint32_t hsdaccon = AD5940_ReadReg(REG_AFE_HSDACCON);
hsdaccon &= ~BITM_AFE_HSDACCON_RATE;
hsdaccon |= (hsdac_rate << BITP_AFE_HSDACCON_RATE);
AD5940_WriteReg(REG_AFE_HSDACCON, hsdaccon);
// 2. Update Waveform Generator Frequency
uint32_t freq_word = AD5940_WGFreqWordCal(freq, 16000000.0f);
AD5940_WriteReg(REG_AFE_WGFCW, freq_word);
// 3. Update Filter Settings
ADCFilterCfg_Type filter_cfg;
// Initialize struct to 0 to avoid garbage
filter_cfg.ADCSinc3Osr = freq_params.ADCSinc3Osr;
filter_cfg.ADCSinc2Osr = freq_params.ADCSinc2Osr;
filter_cfg.ADCAvgNum = ADCAVGNUM_16;
filter_cfg.ADCRate = ADCRATE_800KHZ;
filter_cfg.BpNotch = bTRUE;
filter_cfg.BpSinc3 = bFALSE;
filter_cfg.Sinc2NotchEnable = bTRUE;
filter_cfg.DFTClkEnable = bTRUE;
filter_cfg.WGClkEnable = bTRUE;
filter_cfg.Sinc3ClkEnable = bTRUE;
filter_cfg.Sinc2NotchClkEnable = bTRUE;
AD5940_ADCFilterCfgS(&filter_cfg);
DFTCfg_Type dft_cfg;
dft_cfg.DftNum = freq_params.DftNum;
dft_cfg.DftSrc = freq_params.DftSrc;
dft_cfg.HanWinEn = bTRUE;
AD5940_DFTCfgS(&dft_cfg);
// 4. Perform Measurement
// RCAL
set_sw_matrix(0, SWP_RCAL0 | SWN_RCAL1);
sleep_ms(5);
float mag_cal = perform_dft();
// Z
set_sw_matrix(0, SWP_CE0 | SWP_RE0 | SWN_SE0 | SWT_DE0);
sleep_ms(5);
float mag_z = perform_dft();
if (mag_z > 0.01f && mag_cal > 0.01f) {
float impedance = (mag_cal / mag_z) * RCAL_VALUE;
printf("DATA,%.2f,%.2f,0,0,0\n", freq, impedance);
} else {
printf("DATA,%.2f,0,0,0,0\n", freq);
}
}
void run_sweep(float start_freq, float end_freq, int steps) {
float log_start = log10f(start_freq);
float log_end = log10f(end_freq);
float step_size = (steps > 1) ? (log_end - log_start) / (steps - 1) : 0;
printf("START_SWEEP\n");
for (int i = 0; i < steps; ++i) {
float freq = powf(10.0f, log_start + (i * step_size));
measure_at_freq(freq);
}
printf("END_SWEEP\n");
}
void system_init(void) {
setup_pins();
// Hardware Reset AD5940
AD5940_RstClr();
sleep_ms(10);
AD5940_RstSet();
sleep_ms(10);
AD5940_Initialize();
configure_afe();
}
int main() {
stdio_init_all();
sleep_ms(2000);
system_init();
printf("SYSTEM_READY\n");
while (true) {
int c = getchar_timeout_us(100);
if (c == 'm') {
run_sweep(100.0f, 100000.0f, 50);
}
if (c == 'z') {
system_init();
printf("RESET_DONE\n");
}
}
return 0;
}