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>,
|
muxselp: Option<MUXSELP>,
|
||||||
ctiacon: Option<CTIACON>,
|
ctiacon: Option<CTIACON>,
|
||||||
rtiacon: Option<RTIACON>,
|
rtiacon: Option<RTIACON>,
|
||||||
|
pub avrgnum: Option<AVRGNUM>,
|
||||||
sinc3osr: Option<SINC3OSR>,
|
sinc3osr: Option<SINC3OSR>,
|
||||||
sinc2osr: Option<SINC2OSR>,
|
sinc2osr: Option<SINC2OSR>,
|
||||||
adcsamplerate: Option<ADCSAMPLERATE>,
|
adcsamplerate: Option<ADCSAMPLERATE>,
|
||||||
@@ -162,6 +163,11 @@ impl DspConfig {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn avrgnum(&mut self, avrgnum: Option<AVRGNUM>) -> &mut Self {
|
||||||
|
self.avrgnum = avrgnum;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn sinc3osr(&mut self, sinc3osr: SINC3OSR) -> &mut Self {
|
pub fn sinc3osr(&mut self, sinc3osr: SINC3OSR) -> &mut Self {
|
||||||
self.sinc3osr = Some(sinc3osr);
|
self.sinc3osr = Some(sinc3osr);
|
||||||
self
|
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
|
// Calculate wait time based on DFTNUM
|
||||||
if let Some(dftnum) = config.dftnum {
|
if let Some(dftnum) = config.dftnum {
|
||||||
let samples_per_dft = 1 << (dftnum as u32 + 2);
|
let samples_per_dft = 1 << (dftnum as u32 + 2);
|
||||||
@@ -728,6 +739,13 @@ impl AD5940 {
|
|||||||
// ADCFILTERCON
|
// ADCFILTERCON
|
||||||
let mut current = self.read_reg(Register::ADCFILTERCON).await?;
|
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{
|
if let Some(sinc3osr) = config.sinc3osr{
|
||||||
current = SINC3OSR::apply(current, sinc3osr as u32);
|
current = SINC3OSR::apply(current, sinc3osr as u32);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -395,6 +395,23 @@ impl RegisterField for RTIACON {
|
|||||||
const MASK: u32 = 0b1111;
|
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)]
|
#[allow(dead_code)]
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub enum SINC3OSR {
|
pub enum SINC3OSR {
|
||||||
@@ -436,6 +453,21 @@ impl RegisterField for SINC2OSR {
|
|||||||
const MASK: u32 = 0b1111;
|
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)]
|
#[allow(dead_code)]
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub enum ADCSAMPLERATE {
|
pub enum ADCSAMPLERATE {
|
||||||
|
|||||||
@@ -480,6 +480,11 @@ impl ImpedanceSetup {
|
|||||||
// 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();
|
||||||
|
|
||||||
|
// 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
|
// Reset FIFO
|
||||||
self.ad5940.clear_and_enable_fifo().await.unwrap();
|
self.ad5940.clear_and_enable_fifo().await.unwrap();
|
||||||
|
|
||||||
@@ -511,6 +516,20 @@ impl ImpedanceSetup {
|
|||||||
dsp_config
|
dsp_config
|
||||||
.dftnum(selected_dft_num);
|
.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
|
// Update DFTNUM
|
||||||
let mut current = self.ad5940.read_reg(Register::DFTCON).await.unwrap();
|
let mut current = self.ad5940.read_reg(Register::DFTCON).await.unwrap();
|
||||||
current = DFTNUM::apply(current, selected_dft_num as u32);
|
current = DFTNUM::apply(current, selected_dft_num as u32);
|
||||||
@@ -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
|
// Reset FIFO
|
||||||
self.ad5940.clear_and_enable_fifo().await.unwrap();
|
self.ad5940.clear_and_enable_fifo().await.unwrap();
|
||||||
|
|
||||||
@@ -631,6 +655,20 @@ impl ImpedanceSetup {
|
|||||||
dsp_config
|
dsp_config
|
||||||
.dftnum(selected_dft_num);
|
.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
|
// Update DFTNUM
|
||||||
let mut current = self.ad5940.read_reg(Register::DFTCON).await.unwrap();
|
let mut current = self.ad5940.read_reg(Register::DFTCON).await.unwrap();
|
||||||
current = DFTNUM::apply(current, selected_dft_num as u32);
|
current = DFTNUM::apply(current, selected_dft_num as u32);
|
||||||
|
|||||||
Reference in New Issue
Block a user