mirror of
https://github.com/hubaldv/bioz-firmware-rs.git
synced 2026-04-24 08:42:03 +00:00
Average DFT input at lower stimulation frequencies to lower noise.
This commit is contained in:
@@ -125,6 +125,7 @@ pub struct DspConfig {
|
||||
muxselp: Option<MUXSELP>,
|
||||
ctiacon: Option<CTIACON>,
|
||||
rtiacon: Option<RTIACON>,
|
||||
pub avrgnum: Option<AVRGNUM>,
|
||||
sinc3osr: Option<SINC3OSR>,
|
||||
sinc2osr: Option<SINC2OSR>,
|
||||
adcsamplerate: Option<ADCSAMPLERATE>,
|
||||
@@ -162,6 +163,11 @@ impl DspConfig {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn avrgnum(&mut self, avrgnum: Option<AVRGNUM>) -> &mut Self {
|
||||
self.avrgnum = avrgnum;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn sinc3osr(&mut self, sinc3osr: SINC3OSR) -> &mut Self {
|
||||
self.sinc3osr = Some(sinc3osr);
|
||||
self
|
||||
@@ -561,6 +567,11 @@ impl AD5940 {
|
||||
}
|
||||
}
|
||||
|
||||
// When averaging, the wait time needs to be multiplied by the number of averages to fill the DFT buffer with the correct number of samples
|
||||
if let Some(avrgnum) = config.avrgnum {
|
||||
wait_time *= 2u32.pow(avrgnum as u32 + 1); // For low frequencies, we need to average more samples to get a stable measurement
|
||||
}
|
||||
|
||||
// Calculate wait time based on DFTNUM
|
||||
if let Some(dftnum) = config.dftnum {
|
||||
let samples_per_dft = 1 << (dftnum as u32 + 2);
|
||||
@@ -728,6 +739,13 @@ impl AD5940 {
|
||||
// ADCFILTERCON
|
||||
let mut current = self.read_reg(Register::ADCFILTERCON).await?;
|
||||
|
||||
if let Some(avrnum) = config.avrgnum {
|
||||
current = AVRGEN::apply(current, AVRGEN::AverageEnabled as u32);
|
||||
current = AVRGNUM::apply(current, avrnum as u32);
|
||||
} else {
|
||||
current = AVRGEN::apply(current, AVRGEN::AverageDisabled as u32);
|
||||
}
|
||||
|
||||
if let Some(sinc3osr) = config.sinc3osr{
|
||||
current = SINC3OSR::apply(current, sinc3osr as u32);
|
||||
}
|
||||
|
||||
@@ -395,6 +395,23 @@ impl RegisterField for RTIACON {
|
||||
const MASK: u32 = 0b1111;
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum AVRGNUM {
|
||||
ADC2 = 0b00,
|
||||
ADC4 = 0b01,
|
||||
ADC8 = 0b10,
|
||||
ADC16 = 0b11,
|
||||
}
|
||||
|
||||
impl RegisterField for AVRGNUM {
|
||||
fn reset() -> Self {
|
||||
AVRGNUM::ADC2
|
||||
}
|
||||
const BIT_OFFSET: u32 = 14;
|
||||
const MASK: u32 = 0b11;
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum SINC3OSR {
|
||||
@@ -436,6 +453,21 @@ impl RegisterField for SINC2OSR {
|
||||
const MASK: u32 = 0b1111;
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum AVRGEN {
|
||||
AverageDisabled = 0b0,
|
||||
AverageEnabled = 0b1,
|
||||
}
|
||||
|
||||
impl RegisterField for AVRGEN {
|
||||
fn reset() -> Self {
|
||||
AVRGEN::AverageDisabled
|
||||
}
|
||||
const BIT_OFFSET: u32 = 7;
|
||||
const MASK: u32 = 0b1;
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum ADCSAMPLERATE {
|
||||
|
||||
@@ -480,6 +480,11 @@ impl ImpedanceSetup {
|
||||
// Create vector to store the periods per DFT for each frequency
|
||||
let mut periods_per_dft_vec = heapless::Vec::<f32, N>::new();
|
||||
|
||||
// Find out if we have low frequencies (<300Hz) and/or high frequencies (>=300Hz) in our measurement points for the averaging configuration
|
||||
let averaging_cutoff = 300;
|
||||
let mut set_avg_low_freq = number_of_points.values().iter().any(|&f| f < averaging_cutoff);
|
||||
let mut set_avg_high_freq = number_of_points.values().iter().any(|&f| f >= averaging_cutoff);
|
||||
|
||||
// Reset FIFO
|
||||
self.ad5940.clear_and_enable_fifo().await.unwrap();
|
||||
|
||||
@@ -510,6 +515,20 @@ impl ImpedanceSetup {
|
||||
if let Some(dsp_config) = &mut self.dsp_config {
|
||||
dsp_config
|
||||
.dftnum(selected_dft_num);
|
||||
|
||||
// Decide averaging based on frequency, apply once to avoid unnecessary writes to the registers in the loop
|
||||
if frequency < averaging_cutoff && set_avg_low_freq {
|
||||
dsp_config
|
||||
.avrgnum(Some(AVRGNUM::ADC4));
|
||||
set_avg_low_freq = false;
|
||||
self.ad5940.apply_dsp_config(dsp_config).await.unwrap();
|
||||
}
|
||||
if frequency >= averaging_cutoff && set_avg_high_freq {
|
||||
dsp_config
|
||||
.avrgnum(None);
|
||||
set_avg_high_freq = false;
|
||||
self.ad5940.apply_dsp_config(dsp_config).await.unwrap();
|
||||
}
|
||||
|
||||
// Update DFTNUM
|
||||
let mut current = self.ad5940.read_reg(Register::DFTCON).await.unwrap();
|
||||
@@ -600,6 +619,11 @@ impl ImpedanceSetup {
|
||||
},
|
||||
}
|
||||
|
||||
// Find out if we have low frequencies (<300Hz) and/or high frequencies (>=300Hz) in our measurement points for the averaging configuration
|
||||
let averaging_cutoff = 300;
|
||||
let mut set_avg_low_freq = number_of_points.values().iter().any(|&f| f < averaging_cutoff);
|
||||
let mut set_avg_high_freq = number_of_points.values().iter().any(|&f| f >= averaging_cutoff);
|
||||
|
||||
// Reset FIFO
|
||||
self.ad5940.clear_and_enable_fifo().await.unwrap();
|
||||
|
||||
@@ -630,7 +654,21 @@ impl ImpedanceSetup {
|
||||
if let Some(dsp_config) = &mut self.dsp_config {
|
||||
dsp_config
|
||||
.dftnum(selected_dft_num);
|
||||
|
||||
|
||||
// Decide averaging based on frequency, apply once to avoid unnecessary writes to the registers in the loop
|
||||
if frequency < averaging_cutoff && set_avg_low_freq {
|
||||
dsp_config
|
||||
.avrgnum(Some(AVRGNUM::ADC4));
|
||||
set_avg_low_freq = false;
|
||||
self.ad5940.apply_dsp_config(dsp_config).await.unwrap(); // Apply immediately to avoid unnecessary waits in the loop when averaging is enabled for low frequencies
|
||||
}
|
||||
if frequency >= averaging_cutoff && set_avg_high_freq {
|
||||
dsp_config
|
||||
.avrgnum(None);
|
||||
set_avg_high_freq = false;
|
||||
self.ad5940.apply_dsp_config(dsp_config).await.unwrap(); // Apply immediately to avoid unnecessary waits in the loop when averaging is disabled for high frequencies
|
||||
}
|
||||
|
||||
// Update DFTNUM
|
||||
let mut current = self.ad5940.read_reg(Register::DFTCON).await.unwrap();
|
||||
current = DFTNUM::apply(current, selected_dft_num as u32);
|
||||
|
||||
Reference in New Issue
Block a user