Added external interrupt and test to determine impedance. Not working yet.

This commit is contained in:
2025-08-12 22:44:08 +02:00
parent 04b6083460
commit f1015ee00d
5 changed files with 162 additions and 23 deletions

View File

@@ -3,13 +3,14 @@
use defmt::info;
use embassy_executor::Spawner;
use embassy_stm32::exti::ExtiInput;
use embassy_time::{Timer, Duration};
use embassy_futures::{select::select, select::Either};
use embassy_stm32::gpio::{Level, Output, Speed};
use embassy_stm32::{i2c, spi, Config};
use embassy_stm32::time::Hertz;
use crate::ad5940_registers::{AFECON, AFEGENINTSTA};
use crate::ad5940_registers::{AFECON, SWCON};
use {defmt_rtt as _, panic_probe as _};
@@ -69,6 +70,10 @@ async fn main(spawner: Spawner) {
let cs = Output::new(p.PC9, Level::High, Speed::Low);
let rst = Output::new(p.PB3, Level::High, Speed::Low);
// Set up interrupt at GPIO for AD5940
let ad5940_gpio_0 = ExtiInput::new(p.PC8, p.EXTI8, embassy_stm32::gpio::Pull::Up);
spawner.must_spawn(ad5940_readout_task(ad5940_gpio_0));
let spi = spi::Spi::new_blocking(
p.SPI1,
p.PA5, // SCK
@@ -103,18 +108,37 @@ async fn main(spawner: Spawner) {
// // electrodes.set(Electrode::E12, AD5940Pin::RE0, State::ENABLED);
// Turn on the green LED
ad5940.write_reg_raw(0x0000_0004, 1 << 1).await.unwrap();
ad5940.write_reg_raw(0x0000_001C, 1 << 1).await.unwrap();
// ad5940.write_reg_raw(0x0000_0004, 1 << 1).await.unwrap();
// ad5940.write_reg_raw(0x0000_001C, 1 << 1).await.unwrap();
// // Sequencer test
ad5940.write_reg(ad5940::Register::GP0CON, 0b10 << 4 | 0b10 << 2 | 0b10).await.unwrap();
ad5940.write_reg(ad5940::Register::SYNCEXTDEVICE, 0b111).await.unwrap();
// Sequencer test
ad5940.sequencer_enable(true).await;
ad5940.afecon(AFECON::WAVEGENEN, true).await;
ad5940.wgfcw(1000).await;
ad5940.sequencer_wait(300_000).await;
ad5940.wgfcw(2000).await;
ad5940.sequencer_wait(160_000).await;
// ad5940.sequencer_trigger_interrupt(AFEGENINTSTA::CUSTOMINT0).await;
ad5940.afecon(AFECON::WAVEGENEN, false).await;
ad5940.wgfcw(100).await;
// Rcal
ad5940.swcon(SWCON::DMUXCON_DR0 | SWCON::PMUXCON_PR0 | SWCON::NMUXCON_NR1 | SWCON::TMUXCON_TR1 | SWCON::T9CON).await; // RCAL0 -->
ad5940.afecon(AFECON::WAVEGENEN | AFECON::ADCEN, true).await;
ad5940.sequencer_wait(16*10).await; // 10 us
ad5940.afecon(AFECON::ADCCONVEN | AFECON::DFTEN, true).await;
ad5940.sequencer_wait(16 * 1_500_000).await; // 1.5 second
ad5940.afecon(AFECON::WAVEGENEN | AFECON:: ADCEN | AFECON::ADCCONVEN | AFECON::DFTEN, false).await;
// Rz
ad5940.swcon(SWCON::DMUXCON_D5 | SWCON::PMUXCON_P11 | SWCON::NMUXCON_N2 | SWCON::TMUXCON_MSK | SWCON::TMUXCON_T2).await;
ad5940.afecon(AFECON::WAVEGENEN | AFECON::ADCEN, true).await;
ad5940.sequencer_wait(16*10).await; // 10 us
ad5940.afecon(AFECON::ADCCONVEN | AFECON::DFTEN, true).await;
ad5940.sequencer_wait(16 * 1_500_000).await; // 1.5 second
ad5940.afecon(AFECON::WAVEGENEN | AFECON:: ADCEN | AFECON::ADCCONVEN | AFECON::DFTEN, false).await;
// Toggle leds
ad5940.write_reg(ad5940::Register::SYNCEXTDEVICE, 0b010).await.unwrap();
ad5940.sequencer_wait(16 * 100_000).await; // 0.1 second
ad5940.write_reg(ad5940::Register::SYNCEXTDEVICE, 0b111).await.unwrap();
ad5940.sequencer_enable(false).await;
// // Configure the sequencer cmd data sram
@@ -148,13 +172,26 @@ async fn main(spawner: Spawner) {
ad5940.sequencer_trigger(0).await;
// info!("Mainloop still running!");
Timer::after_millis(250).await;
Timer::after_millis(3500).await;
// let test = ad5940.read_reg_raw(0x2200).await.unwrap();
// info!("FIFOCNTSTA: {}", (test>>16) & 0b111_1111_1111);
let mut data: [u32; 4] = [0; 4];
data[0] = ad5940.read_reg(ad5940::Register::DATAFIFORD).await.unwrap();
data[1] = ad5940.read_reg(ad5940::Register::DATAFIFORD).await.unwrap();
data[2] = ad5940.read_reg(ad5940::Register::DATAFIFORD).await.unwrap();
data[3] = ad5940.read_reg(ad5940::Register::DATAFIFORD).await.unwrap();
let result = calculate_impedance(data);
// Youll need to implement your own logging or send this over serial in embedded
info!("Impedance: Magnitude = {} Ω, Phase = {} rad", result.magnitude, result.phase);
// let test = ad5940.read_reg_raw(0x2200).await.unwrap();
// info!("FIFOCNTSTA: {}", (test>>16) & 0b111_1111_1111);
}
}
@@ -179,4 +216,72 @@ async fn green_led(mut led: Output<'static>) {
led.toggle();
}
}
}
#[embassy_executor::task]
async fn ad5940_readout_task(mut pin: ExtiInput<'static>) {
loop {
pin.wait_for_falling_edge().await;
info!("AD5940 interrupt triggered!");
}
}
extern crate libm;
#[derive(Debug, Clone, Copy)]
pub struct Complex {
real: i32,
imag: i32,
}
#[derive(Debug)]
pub struct ImpedanceResult {
pub magnitude: f32,
pub phase: f32,
}
// Example Rcal value (Ohms)
const RCAL_VAL: f32 = 1000.0;
/// Convert raw 18-bit 2's complement value to signed i32
fn sign_extend_18bit(val: u32) -> i32 {
let masked = val & 0x3FFFF;
if masked & (1 << 17) != 0 {
(masked | 0xFFFC0000) as i32
} else {
masked as i32
}
}
/// Calculate magnitude and phase of Rz using Rcal reference
pub fn calculate_impedance(data: [u32; 4]) -> ImpedanceResult {
let mut signed_data = [0i32; 4];
for (i, &val) in data.iter().enumerate() {
signed_data[i] = sign_extend_18bit(val);
}
let dft_rcal = Complex {
real: signed_data[0],
imag: signed_data[1],
};
let dft_rz = Complex {
real: signed_data[2],
imag: signed_data[3],
};
let rcal_mag = libm::sqrtf((dft_rcal.real as f32) * (dft_rcal.real as f32)
+ (dft_rcal.imag as f32) * (dft_rcal.imag as f32));
let rz_mag = libm::sqrtf((dft_rz.real as f32) * (dft_rz.real as f32)
+ (dft_rz.imag as f32) * (dft_rz.imag as f32));
let rcal_phase = libm::atan2f(-(dft_rcal.imag as f32), dft_rcal.real as f32);
let rz_phase = libm::atan2f(-(dft_rz.imag as f32), dft_rz.real as f32);
let magnitude = (rcal_mag / rz_mag) * RCAL_VAL;
let phase = rcal_phase - rz_phase;
ImpedanceResult { magnitude, phase }
}