mirror of
https://github.com/hubaldv/bioz-firmware-rs.git
synced 2025-12-06 05:01:18 +00:00
Implemented LP DAC for enabling common-mode during 4-lead measurement.
This commit is contained in:
107
src/ad5940.rs
107
src/ad5940.rs
@@ -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
|
||||||
|
|||||||
@@ -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,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user