#[cfg(any(feature = "rp2040", feature = "rp235xa", feature = "rp235xb"))] pub mod rp { use embassy_rp::{ Peri, adc::{self, Adc, AdcPin, Async, InterruptHandler}, dma, interrupt::typelevel::{ADC_IRQ_FIFO, Binding}, peripherals::ADC, pwm::{self, ChannelBPin, Pwm, SetDutyCycle, Slice}, }; use embassy_sync::{blocking_mutex::raw::RawMutex, mutex::Mutex}; use crate::traits::{AdcSource, PwmSource}; struct AdcInner<'device, T: dma::Channel> { adc: Adc<'device, Async>, pin: adc::Channel<'device>, dma: Peri<'device, T>, } pub struct AdcDriver<'device, M: RawMutex, T: dma::Channel> { inner: Mutex>, } impl AdcInner<'_, T> { /// Samples at 100Khz, or 10us per sample. If a sampling fails due to conversion error, /// it tries again until the sampling succeeds. async fn read_many(&mut self, buf: &mut [u16]) { let mut retries: u32 = 5; while self .adc .read_many(&mut self.pin, buf, 480, self.dma.reborrow()) .await .is_err() { retries -= 1; if retries == 0 { panic!("ADC not configured or connected correctly."); } } } } impl<'device, M: RawMutex, T: dma::Channel> AdcDriver<'device, M, T> { pub fn new( inner: Peri<'device, ADC>, pin: Peri<'device, impl AdcPin + 'device>, dma: Peri<'device, T>, irqs: impl Binding, ) -> Self { Self { inner: Mutex::new(AdcInner { adc: Adc::new(inner, irqs, adc::Config::default()), pin: adc::Channel::new_pin(pin, embassy_rp::gpio::Pull::None), dma, }), } } } impl<'device, M: RawMutex, T: dma::Channel> AdcSource for AdcDriver<'device, M, T> { async fn sample_average(&self, samples: &mut [u16]) -> u16 { self.sample(samples).await; let len = samples.len() as u32; (samples.iter().copied().map(u32::from).sum::() / len) as u16 } async fn sample(&self, samples: &mut [u16]) { self.inner.lock().await.read_many(samples).await; } } pub struct PwmDriver<'device> { config: pwm::Config, pwm: Pwm<'device>, } impl<'device> PwmDriver<'device> { pub fn new(slice: Peri<'device, T>, b: Peri<'device, impl ChannelBPin>) -> Self where T: Slice, { let mut config = pwm::Config::default(); config.top = u8::MAX as u16; config.phase_correct = true; config.divider = 48u8.into(); config.enable = true; config.compare_b = 0; let pwm = Pwm::new_output_b(slice, b, config.clone()); Self { pwm, config } } } impl PwmSource for PwmDriver<'_> { fn max_duty(&self) -> u16 { self.pwm.max_duty_cycle() } fn set_duty(&mut self, duty: u16) { let duty = duty.clamp(0, self.pwm.max_duty_cycle()); self.pwm.set_duty_cycle(duty).ok(); } fn enable(&mut self) { self.config.enable = true; self.pwm.set_config(&self.config); } fn disable(&mut self) { self.config.enable = false; self.pwm.set_config(&self.config); } } impl Drop for PwmDriver<'_> { fn drop(&mut self) { self.disable(); } } }