embassy/embassy-nrf/src/temp.rs

79 lines
2.2 KiB
Rust
Raw Normal View History

//! Temperature sensor interface.
2021-10-19 15:31:28 +02:00
use core::task::Poll;
2022-06-12 22:15:44 +02:00
2021-10-19 15:31:28 +02:00
use embassy::waitqueue::AtomicWaker;
2022-06-12 22:15:44 +02:00
use embassy_hal_common::drop::OnDrop;
2022-07-03 23:16:10 +02:00
use embassy_hal_common::{unborrow, Unborrowed};
use fixed::types::I30F2;
2021-10-19 15:31:28 +02:00
use futures::future::poll_fn;
2022-06-12 22:15:44 +02:00
use crate::interrupt::InterruptExt;
use crate::peripherals::TEMP;
use crate::{interrupt, pac, Unborrow};
/// Integrated temperature sensor.
pub struct Temp<'d> {
2022-07-03 23:16:10 +02:00
_irq: Unborrowed<'d, interrupt::TEMP>,
}
2021-10-19 15:31:28 +02:00
static WAKER: AtomicWaker = AtomicWaker::new();
impl<'d> Temp<'d> {
2022-06-12 22:15:44 +02:00
pub fn new(_t: impl Unborrow<Target = TEMP> + 'd, irq: impl Unborrow<Target = interrupt::TEMP> + 'd) -> Self {
unborrow!(_t, irq);
// Enable interrupt that signals temperature values
irq.disable();
irq.set_handler(|_| {
let t = Self::regs();
2021-10-19 15:31:28 +02:00
t.intenclr.write(|w| w.datardy().clear());
WAKER.wake();
});
irq.enable();
2022-07-03 23:16:10 +02:00
Self { _irq: irq }
}
/// Perform an asynchronous temperature measurement. The returned future
/// can be awaited to obtain the measurement.
///
/// If the future is dropped, the measurement is cancelled.
///
/// # Example
///
/// ```no_run
/// let mut t = Temp::new(p.TEMP, interrupt::take!(TEMP));
/// let v: u16 = t.read().await.to_num::<u16>();
/// ```
2021-10-19 20:48:46 +02:00
pub async fn read(&mut self) -> I30F2 {
// In case the future is dropped, stop the task and reset events.
let on_drop = OnDrop::new(|| {
let t = Self::regs();
2021-10-19 15:31:28 +02:00
t.tasks_stop.write(|w| unsafe { w.bits(1) });
t.events_datardy.reset();
});
let t = Self::regs();
2021-10-19 15:31:28 +02:00
t.intenset.write(|w| w.datardy().set());
unsafe { t.tasks_start.write(|w| w.bits(1)) };
2021-10-19 20:48:46 +02:00
let value = poll_fn(|cx| {
WAKER.register(cx.waker());
if t.events_datardy.read().bits() == 0 {
return Poll::Pending;
} else {
t.events_datardy.reset();
let raw = t.temp.read().bits();
Poll::Ready(I30F2::from_bits(raw as i32))
}
})
.await;
on_drop.defuse();
value
}
fn regs() -> &'static pac::temp::RegisterBlock {
unsafe { &*pac::TEMP::ptr() }
}
}