diff --git a/embassy-rp/src/adc.rs b/embassy-rp/src/adc.rs index 38b323ec..2824d893 100644 --- a/embassy-rp/src/adc.rs +++ b/embassy-rp/src/adc.rs @@ -10,8 +10,8 @@ use crate::gpio::sealed::Pin as GpioPin; use crate::gpio::{self, AnyPin, Pull}; use crate::interrupt::typelevel::Binding; use crate::interrupt::InterruptExt; -use crate::peripherals::ADC; -use crate::{interrupt, pac, peripherals, Peripheral}; +use crate::peripherals::{ADC, ADC_TEMP_SENSOR}; +use crate::{interrupt, pac, peripherals, Peripheral, RegExt}; static WAKER: AtomicWaker = AtomicWaker::new(); @@ -24,12 +24,15 @@ impl Default for Config { } } -pub struct Pin<'p> { - pin: PeripheralRef<'p, AnyPin>, +enum Source<'p> { + Pin(PeripheralRef<'p, AnyPin>), + TempSensor(PeripheralRef<'p, ADC_TEMP_SENSOR>), } -impl<'p> Pin<'p> { - pub fn new(pin: impl Peripheral

+ 'p, pull: Pull) -> Self { +pub struct Channel<'p>(Source<'p>); + +impl<'p> Channel<'p> { + pub fn new_pin(pin: impl Peripheral

+ 'p, pull: Pull) -> Self { into_ref!(pin); pin.pad_ctrl().modify(|w| { // manual says: @@ -42,24 +45,40 @@ impl<'p> Pin<'p> { w.set_pue(pull == Pull::Up); w.set_pde(pull == Pull::Down); }); - Self { pin: pin.map_into() } + Self(Source::Pin(pin.map_into())) + } + + pub fn new_sensor(s: impl Peripheral

+ 'p) -> Self { + let r = pac::ADC; + r.cs().write_set(|w| w.set_ts_en(true)); + Self(Source::TempSensor(s.into_ref())) } fn channel(&self) -> u8 { - // this requires adc pins to be sequential and matching the adc channels, - // which is the case for rp2040 - self.pin._pin() - 26 + match &self.0 { + // this requires adc pins to be sequential and matching the adc channels, + // which is the case for rp2040 + Source::Pin(p) => p._pin() - 26, + Source::TempSensor(_) => 4, + } } } -impl<'d> Drop for Pin<'d> { +impl<'p> Drop for Source<'p> { fn drop(&mut self) { - self.pin.pad_ctrl().modify(|w| { - w.set_ie(true); - w.set_od(false); - w.set_pue(false); - w.set_pde(true); - }); + match self { + Source::Pin(p) => { + p.pad_ctrl().modify(|w| { + w.set_ie(true); + w.set_od(false); + w.set_pue(false); + w.set_pde(true); + }); + } + Source::TempSensor(_) => { + pac::ADC.cs().write_clear(|w| w.set_ts_en(true)); + } + } } } @@ -115,10 +134,10 @@ impl<'d, M: Mode> Adc<'d, M> { while !r.cs().read().ready() {} } - fn sample_blocking(channel: u8) -> Result { + pub fn blocking_read(&mut self, ch: &mut Channel) -> Result { let r = Self::regs(); r.cs().modify(|w| { - w.set_ainsel(channel); + w.set_ainsel(ch.channel()); w.set_start_once(true); w.set_err(true); }); @@ -128,19 +147,6 @@ impl<'d, M: Mode> Adc<'d, M> { false => Ok(r.result().read().result().into()), } } - - pub fn blocking_read(&mut self, pin: &mut Pin) -> Result { - Self::sample_blocking(pin.channel()) - } - - pub fn blocking_read_temperature(&mut self) -> Result { - let r = Self::regs(); - r.cs().modify(|w| w.set_ts_en(true)); - while !r.cs().read().ready() {} - let result = Self::sample_blocking(4); - r.cs().modify(|w| w.set_ts_en(false)); - result - } } impl<'d> Adc<'d, Async> { @@ -172,10 +178,10 @@ impl<'d> Adc<'d, Async> { .await; } - async fn sample_async(channel: u8) -> Result { + pub async fn read(&mut self, ch: &mut Channel<'_>) -> Result { let r = Self::regs(); r.cs().modify(|w| { - w.set_ainsel(channel); + w.set_ainsel(ch.channel()); w.set_start_once(true); w.set_err(true); }); @@ -185,21 +191,6 @@ impl<'d> Adc<'d, Async> { false => Ok(r.result().read().result().into()), } } - - pub async fn read(&mut self, pin: &mut Pin<'_>) -> Result { - Self::sample_async(pin.channel()).await - } - - pub async fn read_temperature(&mut self) -> Result { - let r = Self::regs(); - r.cs().modify(|w| w.set_ts_en(true)); - if !r.cs().read().ready() { - Self::wait_for_ready().await; - } - let result = Self::sample_async(4).await; - r.cs().modify(|w| w.set_ts_en(false)); - result - } } impl<'d> Adc<'d, Blocking> { @@ -230,14 +221,17 @@ pub trait AdcChannel: sealed::AdcChannel {} pub trait AdcPin: AdcChannel + gpio::Pin {} macro_rules! impl_pin { - ($pin:ident) => { + ($pin:ident, $channel:expr) => { impl sealed::AdcChannel for peripherals::$pin {} impl AdcChannel for peripherals::$pin {} impl AdcPin for peripherals::$pin {} }; } -impl_pin!(PIN_26); -impl_pin!(PIN_27); -impl_pin!(PIN_28); -impl_pin!(PIN_29); +impl_pin!(PIN_26, 0); +impl_pin!(PIN_27, 1); +impl_pin!(PIN_28, 2); +impl_pin!(PIN_29, 3); + +impl sealed::AdcChannel for peripherals::ADC_TEMP_SENSOR {} +impl AdcChannel for peripherals::ADC_TEMP_SENSOR {} diff --git a/embassy-rp/src/lib.rs b/embassy-rp/src/lib.rs index 45156458..49bd3533 100644 --- a/embassy-rp/src/lib.rs +++ b/embassy-rp/src/lib.rs @@ -183,6 +183,7 @@ embassy_hal_internal::peripherals! { FLASH, ADC, + ADC_TEMP_SENSOR, CORE1, diff --git a/examples/rp/src/bin/adc.rs b/examples/rp/src/bin/adc.rs index 81a8b834..c5869551 100644 --- a/examples/rp/src/bin/adc.rs +++ b/examples/rp/src/bin/adc.rs @@ -7,7 +7,7 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_rp::adc::{Adc, Config, InterruptHandler, Pin}; +use embassy_rp::adc::{Adc, Channel, Config, InterruptHandler}; use embassy_rp::bind_interrupts; use embassy_rp::gpio::Pull; use embassy_time::{Duration, Timer}; @@ -22,9 +22,10 @@ async fn main(_spawner: Spawner) { let p = embassy_rp::init(Default::default()); let mut adc = Adc::new(p.ADC, Irqs, Config::default()); - let mut p26 = Pin::new(p.PIN_26, Pull::None); - let mut p27 = Pin::new(p.PIN_27, Pull::None); - let mut p28 = Pin::new(p.PIN_28, Pull::None); + let mut p26 = Channel::new_pin(p.PIN_26, Pull::None); + let mut p27 = Channel::new_pin(p.PIN_27, Pull::None); + let mut p28 = Channel::new_pin(p.PIN_28, Pull::None); + let mut ts = Channel::new_sensor(p.ADC_TEMP_SENSOR); loop { let level = adc.read(&mut p26).await.unwrap(); @@ -33,7 +34,7 @@ async fn main(_spawner: Spawner) { info!("Pin 27 ADC: {}", level); let level = adc.read(&mut p28).await.unwrap(); info!("Pin 28 ADC: {}", level); - let temp = adc.read_temperature().await.unwrap(); + let temp = adc.read(&mut ts).await.unwrap(); info!("Temp: {} degrees", convert_to_celsius(temp)); Timer::after(Duration::from_secs(1)).await; } diff --git a/tests/rp/src/bin/adc.rs b/tests/rp/src/bin/adc.rs index e659844a..9006ce8c 100644 --- a/tests/rp/src/bin/adc.rs +++ b/tests/rp/src/bin/adc.rs @@ -6,7 +6,7 @@ mod common; use defmt::*; use embassy_executor::Spawner; -use embassy_rp::adc::{Adc, Config, InterruptHandler, Pin}; +use embassy_rp::adc::{Adc, Channel, Config, InterruptHandler}; use embassy_rp::bind_interrupts; use embassy_rp::gpio::Pull; use {defmt_rtt as _, panic_probe as _}; @@ -22,12 +22,12 @@ async fn main(_spawner: Spawner) { { { - let mut p = Pin::new(&mut p.PIN_26, Pull::Down); + let mut p = Channel::new_pin(&mut p.PIN_26, Pull::Down); defmt::assert!(adc.blocking_read(&mut p).unwrap() < 0b01_0000_0000); defmt::assert!(adc.read(&mut p).await.unwrap() < 0b01_0000_0000); } { - let mut p = Pin::new(&mut p.PIN_26, Pull::Up); + let mut p = Channel::new_pin(&mut p.PIN_26, Pull::Up); defmt::assert!(adc.blocking_read(&mut p).unwrap() > 0b11_0000_0000); defmt::assert!(adc.read(&mut p).await.unwrap() > 0b11_0000_0000); } @@ -35,21 +35,21 @@ async fn main(_spawner: Spawner) { // not bothering with async reads from now on { { - let mut p = Pin::new(&mut p.PIN_27, Pull::Down); + let mut p = Channel::new_pin(&mut p.PIN_27, Pull::Down); defmt::assert!(adc.blocking_read(&mut p).unwrap() < 0b01_0000_0000); } { - let mut p = Pin::new(&mut p.PIN_27, Pull::Up); + let mut p = Channel::new_pin(&mut p.PIN_27, Pull::Up); defmt::assert!(adc.blocking_read(&mut p).unwrap() > 0b11_0000_0000); } } { { - let mut p = Pin::new(&mut p.PIN_28, Pull::Down); + let mut p = Channel::new_pin(&mut p.PIN_28, Pull::Down); defmt::assert!(adc.blocking_read(&mut p).unwrap() < 0b01_0000_0000); } { - let mut p = Pin::new(&mut p.PIN_28, Pull::Up); + let mut p = Channel::new_pin(&mut p.PIN_28, Pull::Up); defmt::assert!(adc.blocking_read(&mut p).unwrap() > 0b11_0000_0000); } } @@ -57,22 +57,22 @@ async fn main(_spawner: Spawner) { // gp29 is connected to vsys through a 200k/100k divider, // adding pulls should change the value let low = { - let mut p = Pin::new(&mut p.PIN_29, Pull::Down); + let mut p = Channel::new_pin(&mut p.PIN_29, Pull::Down); adc.blocking_read(&mut p).unwrap() }; let none = { - let mut p = Pin::new(&mut p.PIN_29, Pull::None); + let mut p = Channel::new_pin(&mut p.PIN_29, Pull::None); adc.blocking_read(&mut p).unwrap() }; let up = { - let mut p = Pin::new(&mut p.PIN_29, Pull::Up); + let mut p = Channel::new_pin(&mut p.PIN_29, Pull::Up); adc.blocking_read(&mut p).unwrap() }; defmt::assert!(low < none); defmt::assert!(none < up); } - let temp = convert_to_celsius(adc.read_temperature().await.unwrap()); + let temp = convert_to_celsius(adc.read(&mut Channel::new_sensor(p.ADC_TEMP_SENSOR)).await.unwrap()); defmt::assert!(temp > 0.0); defmt::assert!(temp < 60.0);