diff options
| -rw-r--r-- | embassy-rp/src/adc.rs | 102 | ||||
| -rw-r--r-- | embassy-rp/src/lib.rs | 1 | ||||
| -rw-r--r-- | examples/rp/src/bin/adc.rs | 11 | ||||
| -rw-r--r-- | tests/rp/src/bin/adc.rs | 22 |
4 files changed, 66 insertions, 70 deletions
diff --git a/embassy-rp/src/adc.rs b/embassy-rp/src/adc.rs index 38b323ec9..2824d893c 100644 --- a/embassy-rp/src/adc.rs +++ b/embassy-rp/src/adc.rs | |||
| @@ -10,8 +10,8 @@ use crate::gpio::sealed::Pin as GpioPin; | |||
| 10 | use crate::gpio::{self, AnyPin, Pull}; | 10 | use crate::gpio::{self, AnyPin, Pull}; |
| 11 | use crate::interrupt::typelevel::Binding; | 11 | use crate::interrupt::typelevel::Binding; |
| 12 | use crate::interrupt::InterruptExt; | 12 | use crate::interrupt::InterruptExt; |
| 13 | use crate::peripherals::ADC; | 13 | use crate::peripherals::{ADC, ADC_TEMP_SENSOR}; |
| 14 | use crate::{interrupt, pac, peripherals, Peripheral}; | 14 | use crate::{interrupt, pac, peripherals, Peripheral, RegExt}; |
| 15 | 15 | ||
| 16 | static WAKER: AtomicWaker = AtomicWaker::new(); | 16 | static WAKER: AtomicWaker = AtomicWaker::new(); |
| 17 | 17 | ||
| @@ -24,12 +24,15 @@ impl Default for Config { | |||
| 24 | } | 24 | } |
| 25 | } | 25 | } |
| 26 | 26 | ||
| 27 | pub struct Pin<'p> { | 27 | enum Source<'p> { |
| 28 | pin: PeripheralRef<'p, AnyPin>, | 28 | Pin(PeripheralRef<'p, AnyPin>), |
| 29 | TempSensor(PeripheralRef<'p, ADC_TEMP_SENSOR>), | ||
| 29 | } | 30 | } |
| 30 | 31 | ||
| 31 | impl<'p> Pin<'p> { | 32 | pub struct Channel<'p>(Source<'p>); |
| 32 | pub fn new(pin: impl Peripheral<P = impl AdcPin + 'p> + 'p, pull: Pull) -> Self { | 33 | |
| 34 | impl<'p> Channel<'p> { | ||
| 35 | pub fn new_pin(pin: impl Peripheral<P = impl AdcPin + 'p> + 'p, pull: Pull) -> Self { | ||
| 33 | into_ref!(pin); | 36 | into_ref!(pin); |
| 34 | pin.pad_ctrl().modify(|w| { | 37 | pin.pad_ctrl().modify(|w| { |
| 35 | // manual says: | 38 | // manual says: |
| @@ -42,24 +45,40 @@ impl<'p> Pin<'p> { | |||
| 42 | w.set_pue(pull == Pull::Up); | 45 | w.set_pue(pull == Pull::Up); |
| 43 | w.set_pde(pull == Pull::Down); | 46 | w.set_pde(pull == Pull::Down); |
| 44 | }); | 47 | }); |
| 45 | Self { pin: pin.map_into() } | 48 | Self(Source::Pin(pin.map_into())) |
| 49 | } | ||
| 50 | |||
| 51 | pub fn new_sensor(s: impl Peripheral<P = ADC_TEMP_SENSOR> + 'p) -> Self { | ||
| 52 | let r = pac::ADC; | ||
| 53 | r.cs().write_set(|w| w.set_ts_en(true)); | ||
| 54 | Self(Source::TempSensor(s.into_ref())) | ||
| 46 | } | 55 | } |
| 47 | 56 | ||
| 48 | fn channel(&self) -> u8 { | 57 | fn channel(&self) -> u8 { |
| 49 | // this requires adc pins to be sequential and matching the adc channels, | 58 | match &self.0 { |
| 50 | // which is the case for rp2040 | 59 | // this requires adc pins to be sequential and matching the adc channels, |
| 51 | self.pin._pin() - 26 | 60 | // which is the case for rp2040 |
| 61 | Source::Pin(p) => p._pin() - 26, | ||
| 62 | Source::TempSensor(_) => 4, | ||
| 63 | } | ||
| 52 | } | 64 | } |
| 53 | } | 65 | } |
| 54 | 66 | ||
| 55 | impl<'d> Drop for Pin<'d> { | 67 | impl<'p> Drop for Source<'p> { |
| 56 | fn drop(&mut self) { | 68 | fn drop(&mut self) { |
| 57 | self.pin.pad_ctrl().modify(|w| { | 69 | match self { |
| 58 | w.set_ie(true); | 70 | Source::Pin(p) => { |
| 59 | w.set_od(false); | 71 | p.pad_ctrl().modify(|w| { |
| 60 | w.set_pue(false); | 72 | w.set_ie(true); |
| 61 | w.set_pde(true); | 73 | w.set_od(false); |
| 62 | }); | 74 | w.set_pue(false); |
| 75 | w.set_pde(true); | ||
| 76 | }); | ||
| 77 | } | ||
| 78 | Source::TempSensor(_) => { | ||
| 79 | pac::ADC.cs().write_clear(|w| w.set_ts_en(true)); | ||
| 80 | } | ||
| 81 | } | ||
| 63 | } | 82 | } |
| 64 | } | 83 | } |
| 65 | 84 | ||
| @@ -115,10 +134,10 @@ impl<'d, M: Mode> Adc<'d, M> { | |||
| 115 | while !r.cs().read().ready() {} | 134 | while !r.cs().read().ready() {} |
| 116 | } | 135 | } |
| 117 | 136 | ||
| 118 | fn sample_blocking(channel: u8) -> Result<u16, Error> { | 137 | pub fn blocking_read(&mut self, ch: &mut Channel) -> Result<u16, Error> { |
| 119 | let r = Self::regs(); | 138 | let r = Self::regs(); |
| 120 | r.cs().modify(|w| { | 139 | r.cs().modify(|w| { |
| 121 | w.set_ainsel(channel); | 140 | w.set_ainsel(ch.channel()); |
| 122 | w.set_start_once(true); | 141 | w.set_start_once(true); |
| 123 | w.set_err(true); | 142 | w.set_err(true); |
| 124 | }); | 143 | }); |
| @@ -128,19 +147,6 @@ impl<'d, M: Mode> Adc<'d, M> { | |||
| 128 | false => Ok(r.result().read().result().into()), | 147 | false => Ok(r.result().read().result().into()), |
| 129 | } | 148 | } |
| 130 | } | 149 | } |
| 131 | |||
| 132 | pub fn blocking_read(&mut self, pin: &mut Pin) -> Result<u16, Error> { | ||
| 133 | Self::sample_blocking(pin.channel()) | ||
| 134 | } | ||
| 135 | |||
| 136 | pub fn blocking_read_temperature(&mut self) -> Result<u16, Error> { | ||
| 137 | let r = Self::regs(); | ||
| 138 | r.cs().modify(|w| w.set_ts_en(true)); | ||
| 139 | while !r.cs().read().ready() {} | ||
| 140 | let result = Self::sample_blocking(4); | ||
| 141 | r.cs().modify(|w| w.set_ts_en(false)); | ||
| 142 | result | ||
| 143 | } | ||
| 144 | } | 150 | } |
| 145 | 151 | ||
| 146 | impl<'d> Adc<'d, Async> { | 152 | impl<'d> Adc<'d, Async> { |
| @@ -172,10 +178,10 @@ impl<'d> Adc<'d, Async> { | |||
| 172 | .await; | 178 | .await; |
| 173 | } | 179 | } |
| 174 | 180 | ||
| 175 | async fn sample_async(channel: u8) -> Result<u16, Error> { | 181 | pub async fn read(&mut self, ch: &mut Channel<'_>) -> Result<u16, Error> { |
| 176 | let r = Self::regs(); | 182 | let r = Self::regs(); |
| 177 | r.cs().modify(|w| { | 183 | r.cs().modify(|w| { |
| 178 | w.set_ainsel(channel); | 184 | w.set_ainsel(ch.channel()); |
| 179 | w.set_start_once(true); | 185 | w.set_start_once(true); |
| 180 | w.set_err(true); | 186 | w.set_err(true); |
| 181 | }); | 187 | }); |
| @@ -185,21 +191,6 @@ impl<'d> Adc<'d, Async> { | |||
| 185 | false => Ok(r.result().read().result().into()), | 191 | false => Ok(r.result().read().result().into()), |
| 186 | } | 192 | } |
| 187 | } | 193 | } |
| 188 | |||
| 189 | pub async fn read(&mut self, pin: &mut Pin<'_>) -> Result<u16, Error> { | ||
| 190 | Self::sample_async(pin.channel()).await | ||
| 191 | } | ||
| 192 | |||
| 193 | pub async fn read_temperature(&mut self) -> Result<u16, Error> { | ||
| 194 | let r = Self::regs(); | ||
| 195 | r.cs().modify(|w| w.set_ts_en(true)); | ||
| 196 | if !r.cs().read().ready() { | ||
| 197 | Self::wait_for_ready().await; | ||
| 198 | } | ||
| 199 | let result = Self::sample_async(4).await; | ||
| 200 | r.cs().modify(|w| w.set_ts_en(false)); | ||
| 201 | result | ||
| 202 | } | ||
| 203 | } | 194 | } |
| 204 | 195 | ||
| 205 | impl<'d> Adc<'d, Blocking> { | 196 | impl<'d> Adc<'d, Blocking> { |
| @@ -230,14 +221,17 @@ pub trait AdcChannel: sealed::AdcChannel {} | |||
| 230 | pub trait AdcPin: AdcChannel + gpio::Pin {} | 221 | pub trait AdcPin: AdcChannel + gpio::Pin {} |
| 231 | 222 | ||
| 232 | macro_rules! impl_pin { | 223 | macro_rules! impl_pin { |
| 233 | ($pin:ident) => { | 224 | ($pin:ident, $channel:expr) => { |
| 234 | impl sealed::AdcChannel for peripherals::$pin {} | 225 | impl sealed::AdcChannel for peripherals::$pin {} |
| 235 | impl AdcChannel for peripherals::$pin {} | 226 | impl AdcChannel for peripherals::$pin {} |
| 236 | impl AdcPin for peripherals::$pin {} | 227 | impl AdcPin for peripherals::$pin {} |
| 237 | }; | 228 | }; |
| 238 | } | 229 | } |
| 239 | 230 | ||
| 240 | impl_pin!(PIN_26); | 231 | impl_pin!(PIN_26, 0); |
| 241 | impl_pin!(PIN_27); | 232 | impl_pin!(PIN_27, 1); |
| 242 | impl_pin!(PIN_28); | 233 | impl_pin!(PIN_28, 2); |
| 243 | impl_pin!(PIN_29); | 234 | impl_pin!(PIN_29, 3); |
| 235 | |||
| 236 | impl sealed::AdcChannel for peripherals::ADC_TEMP_SENSOR {} | ||
| 237 | impl AdcChannel for peripherals::ADC_TEMP_SENSOR {} | ||
diff --git a/embassy-rp/src/lib.rs b/embassy-rp/src/lib.rs index 45156458d..49bd3533e 100644 --- a/embassy-rp/src/lib.rs +++ b/embassy-rp/src/lib.rs | |||
| @@ -183,6 +183,7 @@ embassy_hal_internal::peripherals! { | |||
| 183 | FLASH, | 183 | FLASH, |
| 184 | 184 | ||
| 185 | ADC, | 185 | ADC, |
| 186 | ADC_TEMP_SENSOR, | ||
| 186 | 187 | ||
| 187 | CORE1, | 188 | CORE1, |
| 188 | 189 | ||
diff --git a/examples/rp/src/bin/adc.rs b/examples/rp/src/bin/adc.rs index 81a8b8340..c58695512 100644 --- a/examples/rp/src/bin/adc.rs +++ b/examples/rp/src/bin/adc.rs | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | 7 | ||
| 8 | use defmt::*; | 8 | use defmt::*; |
| 9 | use embassy_executor::Spawner; | 9 | use embassy_executor::Spawner; |
| 10 | use embassy_rp::adc::{Adc, Config, InterruptHandler, Pin}; | 10 | use embassy_rp::adc::{Adc, Channel, Config, InterruptHandler}; |
| 11 | use embassy_rp::bind_interrupts; | 11 | use embassy_rp::bind_interrupts; |
| 12 | use embassy_rp::gpio::Pull; | 12 | use embassy_rp::gpio::Pull; |
| 13 | use embassy_time::{Duration, Timer}; | 13 | use embassy_time::{Duration, Timer}; |
| @@ -22,9 +22,10 @@ async fn main(_spawner: Spawner) { | |||
| 22 | let p = embassy_rp::init(Default::default()); | 22 | let p = embassy_rp::init(Default::default()); |
| 23 | let mut adc = Adc::new(p.ADC, Irqs, Config::default()); | 23 | let mut adc = Adc::new(p.ADC, Irqs, Config::default()); |
| 24 | 24 | ||
| 25 | let mut p26 = Pin::new(p.PIN_26, Pull::None); | 25 | let mut p26 = Channel::new_pin(p.PIN_26, Pull::None); |
| 26 | let mut p27 = Pin::new(p.PIN_27, Pull::None); | 26 | let mut p27 = Channel::new_pin(p.PIN_27, Pull::None); |
| 27 | let mut p28 = Pin::new(p.PIN_28, Pull::None); | 27 | let mut p28 = Channel::new_pin(p.PIN_28, Pull::None); |
| 28 | let mut ts = Channel::new_sensor(p.ADC_TEMP_SENSOR); | ||
| 28 | 29 | ||
| 29 | loop { | 30 | loop { |
| 30 | let level = adc.read(&mut p26).await.unwrap(); | 31 | let level = adc.read(&mut p26).await.unwrap(); |
| @@ -33,7 +34,7 @@ async fn main(_spawner: Spawner) { | |||
| 33 | info!("Pin 27 ADC: {}", level); | 34 | info!("Pin 27 ADC: {}", level); |
| 34 | let level = adc.read(&mut p28).await.unwrap(); | 35 | let level = adc.read(&mut p28).await.unwrap(); |
| 35 | info!("Pin 28 ADC: {}", level); | 36 | info!("Pin 28 ADC: {}", level); |
| 36 | let temp = adc.read_temperature().await.unwrap(); | 37 | let temp = adc.read(&mut ts).await.unwrap(); |
| 37 | info!("Temp: {} degrees", convert_to_celsius(temp)); | 38 | info!("Temp: {} degrees", convert_to_celsius(temp)); |
| 38 | Timer::after(Duration::from_secs(1)).await; | 39 | Timer::after(Duration::from_secs(1)).await; |
| 39 | } | 40 | } |
diff --git a/tests/rp/src/bin/adc.rs b/tests/rp/src/bin/adc.rs index e659844ae..9006ce8cc 100644 --- a/tests/rp/src/bin/adc.rs +++ b/tests/rp/src/bin/adc.rs | |||
| @@ -6,7 +6,7 @@ mod common; | |||
| 6 | 6 | ||
| 7 | use defmt::*; | 7 | use defmt::*; |
| 8 | use embassy_executor::Spawner; | 8 | use embassy_executor::Spawner; |
| 9 | use embassy_rp::adc::{Adc, Config, InterruptHandler, Pin}; | 9 | use embassy_rp::adc::{Adc, Channel, Config, InterruptHandler}; |
| 10 | use embassy_rp::bind_interrupts; | 10 | use embassy_rp::bind_interrupts; |
| 11 | use embassy_rp::gpio::Pull; | 11 | use embassy_rp::gpio::Pull; |
| 12 | use {defmt_rtt as _, panic_probe as _}; | 12 | use {defmt_rtt as _, panic_probe as _}; |
| @@ -22,12 +22,12 @@ async fn main(_spawner: Spawner) { | |||
| 22 | 22 | ||
| 23 | { | 23 | { |
| 24 | { | 24 | { |
| 25 | let mut p = Pin::new(&mut p.PIN_26, Pull::Down); | 25 | let mut p = Channel::new_pin(&mut p.PIN_26, Pull::Down); |
| 26 | defmt::assert!(adc.blocking_read(&mut p).unwrap() < 0b01_0000_0000); | 26 | defmt::assert!(adc.blocking_read(&mut p).unwrap() < 0b01_0000_0000); |
| 27 | defmt::assert!(adc.read(&mut p).await.unwrap() < 0b01_0000_0000); | 27 | defmt::assert!(adc.read(&mut p).await.unwrap() < 0b01_0000_0000); |
| 28 | } | 28 | } |
| 29 | { | 29 | { |
| 30 | let mut p = Pin::new(&mut p.PIN_26, Pull::Up); | 30 | let mut p = Channel::new_pin(&mut p.PIN_26, Pull::Up); |
| 31 | defmt::assert!(adc.blocking_read(&mut p).unwrap() > 0b11_0000_0000); | 31 | defmt::assert!(adc.blocking_read(&mut p).unwrap() > 0b11_0000_0000); |
| 32 | defmt::assert!(adc.read(&mut p).await.unwrap() > 0b11_0000_0000); | 32 | defmt::assert!(adc.read(&mut p).await.unwrap() > 0b11_0000_0000); |
| 33 | } | 33 | } |
| @@ -35,21 +35,21 @@ async fn main(_spawner: Spawner) { | |||
| 35 | // not bothering with async reads from now on | 35 | // not bothering with async reads from now on |
| 36 | { | 36 | { |
| 37 | { | 37 | { |
| 38 | let mut p = Pin::new(&mut p.PIN_27, Pull::Down); | 38 | let mut p = Channel::new_pin(&mut p.PIN_27, Pull::Down); |
| 39 | defmt::assert!(adc.blocking_read(&mut p).unwrap() < 0b01_0000_0000); | 39 | defmt::assert!(adc.blocking_read(&mut p).unwrap() < 0b01_0000_0000); |
| 40 | } | 40 | } |
| 41 | { | 41 | { |
| 42 | let mut p = Pin::new(&mut p.PIN_27, Pull::Up); | 42 | let mut p = Channel::new_pin(&mut p.PIN_27, Pull::Up); |
| 43 | defmt::assert!(adc.blocking_read(&mut p).unwrap() > 0b11_0000_0000); | 43 | defmt::assert!(adc.blocking_read(&mut p).unwrap() > 0b11_0000_0000); |
| 44 | } | 44 | } |
| 45 | } | 45 | } |
| 46 | { | 46 | { |
| 47 | { | 47 | { |
| 48 | let mut p = Pin::new(&mut p.PIN_28, Pull::Down); | 48 | let mut p = Channel::new_pin(&mut p.PIN_28, Pull::Down); |
| 49 | defmt::assert!(adc.blocking_read(&mut p).unwrap() < 0b01_0000_0000); | 49 | defmt::assert!(adc.blocking_read(&mut p).unwrap() < 0b01_0000_0000); |
| 50 | } | 50 | } |
| 51 | { | 51 | { |
| 52 | let mut p = Pin::new(&mut p.PIN_28, Pull::Up); | 52 | let mut p = Channel::new_pin(&mut p.PIN_28, Pull::Up); |
| 53 | defmt::assert!(adc.blocking_read(&mut p).unwrap() > 0b11_0000_0000); | 53 | defmt::assert!(adc.blocking_read(&mut p).unwrap() > 0b11_0000_0000); |
| 54 | } | 54 | } |
| 55 | } | 55 | } |
| @@ -57,22 +57,22 @@ async fn main(_spawner: Spawner) { | |||
| 57 | // gp29 is connected to vsys through a 200k/100k divider, | 57 | // gp29 is connected to vsys through a 200k/100k divider, |
| 58 | // adding pulls should change the value | 58 | // adding pulls should change the value |
| 59 | let low = { | 59 | let low = { |
| 60 | let mut p = Pin::new(&mut p.PIN_29, Pull::Down); | 60 | let mut p = Channel::new_pin(&mut p.PIN_29, Pull::Down); |
| 61 | adc.blocking_read(&mut p).unwrap() | 61 | adc.blocking_read(&mut p).unwrap() |
| 62 | }; | 62 | }; |
| 63 | let none = { | 63 | let none = { |
| 64 | let mut p = Pin::new(&mut p.PIN_29, Pull::None); | 64 | let mut p = Channel::new_pin(&mut p.PIN_29, Pull::None); |
| 65 | adc.blocking_read(&mut p).unwrap() | 65 | adc.blocking_read(&mut p).unwrap() |
| 66 | }; | 66 | }; |
| 67 | let up = { | 67 | let up = { |
| 68 | let mut p = Pin::new(&mut p.PIN_29, Pull::Up); | 68 | let mut p = Channel::new_pin(&mut p.PIN_29, Pull::Up); |
| 69 | adc.blocking_read(&mut p).unwrap() | 69 | adc.blocking_read(&mut p).unwrap() |
| 70 | }; | 70 | }; |
| 71 | defmt::assert!(low < none); | 71 | defmt::assert!(low < none); |
| 72 | defmt::assert!(none < up); | 72 | defmt::assert!(none < up); |
| 73 | } | 73 | } |
| 74 | 74 | ||
| 75 | let temp = convert_to_celsius(adc.read_temperature().await.unwrap()); | 75 | let temp = convert_to_celsius(adc.read(&mut Channel::new_sensor(p.ADC_TEMP_SENSOR)).await.unwrap()); |
| 76 | defmt::assert!(temp > 0.0); | 76 | defmt::assert!(temp > 0.0); |
| 77 | defmt::assert!(temp < 60.0); | 77 | defmt::assert!(temp < 60.0); |
| 78 | 78 | ||
