use embassy_stm32::adc::{Adc, AdcConfig, AnyAdcChannel, Averaging, Resolution, SampleTime};
use embassy_stm32::peripherals::ADC1;
pub const COUNT: usize = 4;
#[derive(Clone, Copy, PartialEq, Eq, defmt::Format)]
pub enum Knob {
Tl,
Tr,
Bl,
Br,
}
impl Knob {
pub const ALL: [Knob; COUNT] = [Knob::Tl, Knob::Tr, Knob::Bl, Knob::Br];
pub const fn index(self) -> usize {
self as usize
}
pub const fn label(self) -> &'static str {
match self {
Knob::Tl => "TL",
Knob::Tr => "TR",
Knob::Bl => "BL",
Knob::Br => "BR",
}
}
}
#[derive(Clone, Copy)]
pub struct Reading {
pub a: u16,
pub b: u16,
}
impl Reading {
pub fn angle_deg(&self) -> i32 {
const MID: f32 = 32768.0; let rad = libm::atan2f(self.a as f32 - MID, self.b as f32 - MID);
(rad * 180.0 / core::f32::consts::PI) as i32
}
}
const SAMPLE_TIME: SampleTime = SampleTime::CYCLES810_5;
pub struct Knobs {
adc: Adc<'static, ADC1>,
wipers: [AnyAdcChannel<'static, ADC1>; COUNT * 2],
}
impl Knobs {
pub fn new(
adc1: embassy_stm32::Peri<'static, ADC1>,
wipers: [AnyAdcChannel<'static, ADC1>; COUNT * 2],
) -> Self {
let adc = Adc::new_with_config(
adc1,
AdcConfig {
resolution: Some(Resolution::BITS16),
averaging: Some(Averaging::Samples8),
},
);
Self { adc, wipers }
}
pub fn read(&mut self, k: Knob) -> Reading {
let i = k.index() * 2;
let a = self.adc.blocking_read(&mut self.wipers[i], SAMPLE_TIME);
let b = self.adc.blocking_read(&mut self.wipers[i + 1], SAMPLE_TIME);
Reading { a, b }
}
pub fn read_all(&mut self) -> [Reading; COUNT] {
core::array::from_fn(|i| {
let a = self.adc.blocking_read(&mut self.wipers[i * 2], SAMPLE_TIME);
let b = self.adc.blocking_read(&mut self.wipers[i * 2 + 1], SAMPLE_TIME);
Reading { a, b }
})
}
}