Implemented LP DAC for enabling common-mode during 4-lead measurement.

This commit is contained in:
2025-11-06 11:33:49 +01:00
parent 324189ba72
commit 3716d7367e
3 changed files with 251 additions and 0 deletions

View File

@@ -68,6 +68,55 @@ impl SwitchConfig {
} }
} }
#[allow(dead_code)]
#[derive(Default)]
pub struct LpConfig {
data_reset: Option<bool>,
power_enable: Option<bool>,
data_6bit: Option<u8>,
common_mode_switch: Option<bool>,
tia_switches_enabled: Option<u16>,
tia_enable: Option<bool>,
filter_resistor: Option<TIARF>,
}
impl LpConfig {
pub fn data_reset(&mut self, rsten: bool) -> &mut Self {
self.data_reset = Some(rsten);
self
}
pub fn power_enable(&mut self, pwden: bool) -> &mut Self {
self.power_enable = Some(pwden);
self
}
pub fn data_6bit(&mut self, data: u8) -> &mut Self {
self.data_6bit = Some(data & 0x3F);
self
}
pub fn common_mode_enable(&mut self, enable: bool) -> &mut Self {
self.common_mode_switch = Some(enable);
self
}
pub fn tia_switches_enabled(&mut self, enable: u16) -> &mut Self {
self.tia_switches_enabled = Some(enable);
self
}
pub fn tia_enable(&mut self, enable: bool) -> &mut Self {
self.tia_enable = Some(enable);
self
}
pub fn filter_resistor(&mut self, tiarf: TIARF) -> &mut Self {
self.filter_resistor = Some(tiarf);
self
}
}
#[allow(dead_code)] #[allow(dead_code)]
#[derive(Default)] #[derive(Default)]
pub struct DspConfig { pub struct DspConfig {
@@ -594,6 +643,59 @@ impl AD5940 {
Ok(()) Ok(())
} }
pub async fn apply_lp_config(&mut self, config: &LpConfig) -> Result<(), Error> {
// LPDACCON0
let mut current = self.read_reg(Register::LPDACCON0).await?;
if let Some(data_reset) = config.data_reset {
current = RSTEN::apply(current, data_reset as u32);
}
if let Some(power_enable) = config.power_enable {
current = PWDEN::apply(current, !power_enable as u32);
}
self.write_reg(Register::LPDACCON0, current).await?;
// LPDACDAT0
let mut current = self.read_reg(Register::LPDACDAT0).await?;
if let Some(data) = config.data_6bit {
current = DACIN6::apply(current, data as u32);
}
self.write_reg(Register::LPDACDAT0, current).await?;
// SWMUX
let mut current = self.read_reg(Register::SWMUX).await?;
if let Some(common_mode_switch) = config.common_mode_switch {
current = SWMUX::apply(current, common_mode_switch as u32);
}
self.write_reg(Register::SWMUX, current).await?;
// LPTIASW0
if let Some(tia_switches_enabled) = config.tia_switches_enabled {
self.write_reg(Register::LPTIASW0, tia_switches_enabled as u32).await?;
}
// LPTIACON0
let mut current = self.read_reg(Register::LPTIACON0).await?;
if let Some(tia_enable) = config.tia_enable {
current = TIAPDEN::apply(current, !tia_enable as u32);
}
if let Some(tiarf) = config.filter_resistor {
current = TIARF::apply(current, tiarf as u32);
}
self.write_reg(Register::LPTIACON0, current).await?;
Ok(())
}
pub async fn apply_dsp_config(&mut self, config: &DspConfig) -> Result<(), Error> { pub async fn apply_dsp_config(&mut self, config: &DspConfig) -> Result<(), Error> {
// ADCCON // ADCCON
let mut current = self.read_reg(Register::ADCCON).await?; let mut current = self.read_reg(Register::ADCCON).await?;
@@ -849,6 +951,10 @@ pub enum Register {
CMDFIFOWRITE = 0x0000_2070, // Command FIFO Write Register CMDFIFOWRITE = 0x0000_2070, // Command FIFO Write Register
TEMPSENSDAT = 0x0000_2084, // Temperature Sensor Result Register TEMPSENSDAT = 0x0000_2084, // Temperature Sensor Result Register
ADCDAT = 0x0000_2074, // ADC Raw Result Register ADCDAT = 0x0000_2074, // ADC Raw Result Register
LPTIASW0 = 0x0000_20E4, // Low power TIA switch configuration
LPTIACON0 = 0x0000_20EC, // Low power TIA control bits, Channel 0
LPDACDAT0 = 0x0000_2120, // Low power DAC data output Register
LPDACCON0 = 0x0000_2128, // Low power DAC configuration register
TEMPSENS = 0x0000_2174, // Temperature Sensor Configuration Register TEMPSENS = 0x0000_2174, // Temperature Sensor Configuration Register
ADCCON = 0x0000_21A8, // ADC Configuration Register ADCCON = 0x0000_21A8, // ADC Configuration Register
SEQ0INFO = 0x0000_21CC, // Sequence 0 Information Register SEQ0INFO = 0x0000_21CC, // Sequence 0 Information Register
@@ -859,6 +965,7 @@ pub enum Register {
AFEGENINTSTA = 0x0000_209C, // Analog Generation Interrupt Register AFEGENINTSTA = 0x0000_209C, // Analog Generation Interrupt Register
CMDFIFOWADDR = 0x0000_21D4, // Command FIFO Write Address Register CMDFIFOWADDR = 0x0000_21D4, // Command FIFO Write Address Register
PMBW = 0x0000_22F0, // Power Mode Configuration Register PMBW = 0x0000_22F0, // Power Mode Configuration Register
SWMUX = 0x0000_235C, // Common-mode switch mux select register
INTCFLAG0 = 0x0000_3010, // Interrupt Control Flag 0 Register INTCFLAG0 = 0x0000_3010, // Interrupt Control Flag 0 Register
INTCFLAG1 = 0x0000_3014, // Interrupt Control Flag 1 Register INTCFLAG1 = 0x0000_3014, // Interrupt Control Flag 1 Register
OSCCON = 0x0000_0A10, // Oscillator Control Register OSCCON = 0x0000_0A10, // Oscillator Control Register

View File

@@ -130,6 +130,107 @@ impl RegisterField for DMUXCON {
const MASK: u32 = 0b1111; const MASK: u32 = 0b1111;
} }
#[allow(dead_code)]
#[repr(u32)]
#[derive(Copy, Clone)]
pub enum RSTEN {
Disabled = 0b0,
Enabled = 0b1,
}
impl RegisterField for RSTEN {
fn reset() -> Self {
RSTEN::Disabled
}
const BIT_OFFSET: u32 = 0;
const MASK: u32 = 0b1;
}
#[allow(dead_code)]
#[repr(u32)]
#[derive(Copy, Clone)]
pub enum PWDEN {
DACPoweredOn = 0b0,
DACPoweredOff = 0b1,
}
impl RegisterField for PWDEN {
fn reset() -> Self {
PWDEN::DACPoweredOff
}
const BIT_OFFSET: u32 = 1;
const MASK: u32 = 0b1;
}
#[allow(dead_code)]
#[repr(u32)]
#[derive(Copy, Clone)]
pub enum DACIN6 {
Default = 0b0,
}
impl RegisterField for DACIN6 {
fn reset() -> Self {
DACIN6::Default
}
const BIT_OFFSET: u32 = 12;
const MASK: u32 = 0b11_1111;
}
#[allow(dead_code)]
#[repr(u32)]
#[derive(Copy, Clone)]
pub enum SWMUX {
CommonModeOff = 0b0,
COmmonModeOn = 0b1,
}
impl RegisterField for SWMUX {
fn reset() -> Self {
SWMUX::CommonModeOff
}
const BIT_OFFSET: u32 = 3;
const MASK: u32 = 0b1;
}
#[allow(dead_code)]
#[repr(u32)]
#[derive(Copy, Clone)]
pub enum TIAPDEN {
PowerUp = 0b0,
PowerDown = 0b1,
}
impl RegisterField for TIAPDEN {
fn reset() -> Self {
TIAPDEN::PowerDown
}
const BIT_OFFSET: u32 = 0;
const MASK: u32 = 0b1;
}
#[allow(dead_code)]
#[repr(u32)]
#[derive(Copy, Clone)]
pub enum TIARF {
Disconnected = 0b0,
R0 = 0b1,
R20k = 0b10,
R100k = 0b11,
R200k = 0b100,
R400k = 0b101,
R600k = 0b110,
R1M = 0b111,
}
impl RegisterField for TIARF {
fn reset() -> Self {
TIARF::Disconnected
}
const BIT_OFFSET: u32 = 13;
const MASK: u32 = 0b111;
}
#[allow(dead_code)] #[allow(dead_code)]
#[repr(u32)] #[repr(u32)]
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
@@ -158,7 +259,9 @@ pub enum MUXSELN
HsTiaNeg = 0b00001, HsTiaNeg = 0b00001,
LpTiaNeg = 0b00010, LpTiaNeg = 0b00010,
AIN1 = 0b00101, AIN1 = 0b00101,
AIN2 = 0b00110,
AIN3 = 0b00111, AIN3 = 0b00111,
VBIAS_CAP= 0b01000,
ExciNNode= 0b10100, ExciNNode= 0b10100,
} }

View File

@@ -83,6 +83,9 @@ impl ImpedanceSetup {
self.ad5940.apply_clk_config(&clk_config).await.unwrap(); self.ad5940.apply_clk_config(&clk_config).await.unwrap();
// Configure LP DAC and TIA
self.common_mode_output_enable(false).await.unwrap();
// Set DSP configuration // Set DSP configuration
let mut dsp_config = DspConfig::default(); let mut dsp_config = DspConfig::default();
dsp_config dsp_config
@@ -253,7 +256,36 @@ impl ImpedanceSetup {
Ok(results) Ok(results)
} }
pub async fn common_mode_output_enable(&mut self, enable: bool) -> Result<(), Error> {
// Configure LP DAC and TIA
let mut lp_config = LpConfig::default();
if enable {
lp_config
.data_reset(true)
.power_enable(true)
.data_6bit(31) // Mid-scale for 6-bit DAC
.common_mode_enable(true)
.tia_switches_enabled(1 << 5 | 1 << 7 | 1 << 9 | 1 << 13)
.tia_enable(true)
.filter_resistor(TIARF::R20k);
} else {
lp_config
.power_enable(false)
.common_mode_enable(false)
.tia_enable(false);
}
self.ad5940.apply_lp_config(&lp_config).await.unwrap();
Ok(())
}
pub async fn init_single_frequency_measurement_2_lead(&mut self, frequency: u32, dft_number: IcdDftNum) -> Result<f32, ImpedanceInitError> { pub async fn init_single_frequency_measurement_2_lead(&mut self, frequency: u32, dft_number: IcdDftNum) -> Result<f32, ImpedanceInitError> {
// Configure LP DAC and TIA
self.common_mode_output_enable(false).await.unwrap();
// Reset FIFO // Reset FIFO
self.ad5940.clear_and_enable_fifo().await.unwrap(); self.ad5940.clear_and_enable_fifo().await.unwrap();
@@ -333,6 +365,9 @@ impl ImpedanceSetup {
} }
pub async fn init_single_frequency_measurement_4_lead(&mut self, frequency: u32, dft_number: IcdDftNum) -> Result<f32, ImpedanceInitError> { pub async fn init_single_frequency_measurement_4_lead(&mut self, frequency: u32, dft_number: IcdDftNum) -> Result<f32, ImpedanceInitError> {
// Configure LP DAC and TIA
self.common_mode_output_enable(true).await.unwrap();
// Reset FIFO // Reset FIFO
self.ad5940.clear_and_enable_fifo().await.unwrap(); self.ad5940.clear_and_enable_fifo().await.unwrap();
@@ -430,6 +465,9 @@ impl ImpedanceSetup {
} }
pub async fn init_multi_frequency_measurement_2_lead<const N: usize>(&mut self, number_of_points: MeasurementPointSet) -> Result<heapless::Vec<f32, N>, ImpedanceInitError> { pub async fn init_multi_frequency_measurement_2_lead<const N: usize>(&mut self, number_of_points: MeasurementPointSet) -> Result<heapless::Vec<f32, N>, ImpedanceInitError> {
// Configure LP DAC and TIA
self.common_mode_output_enable(false).await.unwrap();
// Create vector to store the periods per DFT for each frequency // Create vector to store the periods per DFT for each frequency
let mut periods_per_dft_vec = heapless::Vec::<f32, N>::new(); let mut periods_per_dft_vec = heapless::Vec::<f32, N>::new();
@@ -535,6 +573,9 @@ impl ImpedanceSetup {
} }
pub async fn init_multi_frequency_measurement_4_lead<const N: usize>(&mut self, number_of_points: MeasurementPointSet) -> Result<heapless::Vec<f32, N>, ImpedanceInitError> { pub async fn init_multi_frequency_measurement_4_lead<const N: usize>(&mut self, number_of_points: MeasurementPointSet) -> Result<heapless::Vec<f32, N>, ImpedanceInitError> {
// Configure LP DAC and TIA
self.common_mode_output_enable(true).await.unwrap();
// Create vector to store the periods per DFT for each frequency // Create vector to store the periods per DFT for each frequency
let mut periods_per_dft_vec = heapless::Vec::<f32, N>::new(); let mut periods_per_dft_vec = heapless::Vec::<f32, N>::new();