use embassy_time::Timer;
#[cfg(feature = "filter-ema")]
use crate::filter_ema::EmaFilter;
#[cfg(feature = "filter-median")]
use crate::filter_median::MedianFilter;
pub trait AdcReader {
async fn read(&mut self) -> u16;
}
pub struct Max4466<A: AdcReader> {
adc: A,
zero_point: u16,
#[cfg(feature = "filter-ema")]
ema: EmaFilter,
#[cfg(feature = "filter-median")]
median: MedianFilter,
}
impl<A: AdcReader> Max4466<A> {
pub fn new(adc: A) -> Self {
Self {
adc,
zero_point: 2048,
#[cfg(feature = "filter-ema")]
ema: EmaFilter::new(),
#[cfg(feature = "filter-median")]
median: MedianFilter::new(),
}
}
pub async fn calibrate(&mut self) {
let mut sum: u32 = 0;
for _ in 0..128 {
sum += self.adc.read().await as u32;
Timer::after_micros(500).await;
}
self.zero_point = (sum / 128) as u16;
}
pub async fn read_raw(&mut self) -> u16 {
self.adc.read().await
}
pub async fn read_filtered(&mut self) -> u16 {
let raw = self.adc.read().await;
#[allow(unused_mut, unused_variables)]
let mut value = raw;
#[cfg(feature = "filter-ema")]
{
value = self.ema.update(value);
}
#[cfg(feature = "filter-median")]
{
value = self.median.update(value);
}
value
}
pub async fn read_amplitude(&mut self, window_ms: u32) -> u16 {
let samples = window_ms * 5;
let mut min = u16::MAX;
let mut max = u16::MIN;
for _ in 0..samples {
let val = self.read_filtered().await;
if val > max {
max = val;
}
if val < min {
min = val;
}
Timer::after_micros(200).await;
}
let amplitude = if max > min { max - min } else { 0 };
let raw = self.adc.read().await;
crate::signals::MIC_SIGNAL.signal(crate::MicData { raw, amplitude });
amplitude
}
pub fn zero_point(&self) -> u16 {
self.zero_point
}
}