use core::future::poll_fn; use core::marker::PhantomData; use core::sync::atomic::{compiler_fence, Ordering}; use core::task::Poll; use embassy_hal_common::into_ref; use embassy_sync::waitqueue::AtomicWaker; use embedded_hal_02::adc::{Channel, OneShot}; use crate::interrupt::{self, InterruptExt}; use crate::peripherals::ADC; use crate::{pac, peripherals, Peripheral}; static WAKER: AtomicWaker = AtomicWaker::new(); #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[non_exhaustive] pub enum Error { // No errors for now } #[non_exhaustive] pub struct Config {} impl Default for Config { fn default() -> Self { Self {} } } pub struct Adc<'d> { phantom: PhantomData<&'d ADC>, } impl<'d> Adc<'d> { #[inline] fn regs() -> pac::adc::Adc { pac::ADC } #[inline] fn reset() -> pac::resets::regs::Peripherals { let mut ret = pac::resets::regs::Peripherals::default(); ret.set_adc(true); ret } pub fn new( _inner: impl Peripheral
+ 'd, irq: impl Peripheral
+ 'd,
_config: Config,
) -> Self {
into_ref!(irq);
unsafe {
let reset = Self::reset();
crate::reset::reset(reset);
crate::reset::unreset_wait(reset);
let r = Self::regs();
// Enable ADC
r.cs().write(|w| w.set_en(true));
// Wait for ADC ready
while !r.cs().read().ready() {}
}
// Setup IRQ
irq.disable();
irq.set_handler(|_| unsafe {
let r = Self::regs();
r.inte().write(|w| w.set_fifo(false));
WAKER.wake();
});
irq.unpend();
irq.enable();
Self { phantom: PhantomData }
}
async fn wait_for_ready() {
let r = Self::regs();
unsafe {
r.inte().write(|w| w.set_fifo(true));
compiler_fence(Ordering::SeqCst);
poll_fn(|cx| {
WAKER.register(cx.waker());
if r.cs().read().ready() {
return Poll::Ready(());
}
Poll::Pending
})
.await;
}
}
pub async fn read