aboutsummaryrefslogtreecommitdiff
path: root/embassy-mspm0
diff options
context:
space:
mode:
authorcrispaudio <[email protected]>2025-09-14 01:34:49 +0200
committercrispaudio <[email protected]>2025-09-14 01:34:49 +0200
commit31b5a3f0a4fafd425aef34b9d6fb93ead851b4c6 (patch)
tree43987fc7e35cdd3d0a533ee2818bd464299a39e8 /embassy-mspm0
parentb2fa01cec7164980333a17355af215feb3cb33c2 (diff)
mspm0-adc: implement From for AnyAdcChannel
Diffstat (limited to 'embassy-mspm0')
-rw-r--r--embassy-mspm0/src/adc.rs64
1 files changed, 29 insertions, 35 deletions
diff --git a/embassy-mspm0/src/adc.rs b/embassy-mspm0/src/adc.rs
index 71569aef0..5b93e9a6e 100644
--- a/embassy-mspm0/src/adc.rs
+++ b/embassy-mspm0/src/adc.rs
@@ -217,7 +217,7 @@ impl<'d, T: Instance, M: Mode> Adc<'d, T, M> {
217 }); 217 });
218 } 218 }
219 219
220 fn setup_blocking_channel(&mut self, channel: &mut impl AdcChannel<T>) { 220 fn setup_blocking_channel(&mut self, channel: &Peri<'d, impl AdcChannel<T>>) {
221 channel.setup(); 221 channel.setup();
222 222
223 // CTL0.ENC must be 0 to write the MEMCTL register 223 // CTL0.ENC must be 0 to write the MEMCTL register
@@ -262,7 +262,7 @@ impl<'d, T: Instance, M: Mode> Adc<'d, T, M> {
262 } 262 }
263 263
264 /// Read one ADC channel in blocking mode using the config provided at initialization. 264 /// Read one ADC channel in blocking mode using the config provided at initialization.
265 pub fn blocking_read(&mut self, channel: &mut impl AdcChannel<T>) -> u16 { 265 pub fn blocking_read(&mut self, channel: &Peri<'d, impl AdcChannel<T>>) -> u16 {
266 self.setup_blocking_channel(channel); 266 self.setup_blocking_channel(channel);
267 self.enable_conversion(); 267 self.enable_conversion();
268 self.start_conversion(); 268 self.start_conversion();
@@ -292,7 +292,7 @@ impl<'d, T: Instance> Adc<'d, T, Async> {
292 .await; 292 .await;
293 } 293 }
294 294
295 fn setup_async_channel(&self, id: usize, channel: &impl AdcChannel<T>, vrsel: Vrsel) { 295 fn setup_async_channel(&self, id: usize, channel: &Peri<'d, impl AdcChannel<T>>, vrsel: Vrsel) {
296 let vrsel = vals::Vrsel::from_bits(vrsel as u8); 296 let vrsel = vals::Vrsel::from_bits(vrsel as u8);
297 // Conversion mem config 297 // Conversion mem config
298 self.info.regs.memctl(id).modify(|reg| { 298 self.info.regs.memctl(id).modify(|reg| {
@@ -316,7 +316,7 @@ impl<'d, T: Instance> Adc<'d, T, Async> {
316 } 316 }
317 317
318 /// Read one ADC channel asynchronously using the config provided at initialization. 318 /// Read one ADC channel asynchronously using the config provided at initialization.
319 pub async fn read_channel(&mut self, channel: &mut impl AdcChannel<T>) -> u16 { 319 pub async fn read_channel(&mut self, channel: &Peri<'d, impl AdcChannel<T>>) -> u16 {
320 channel.setup(); 320 channel.setup();
321 321
322 // CTL0.ENC must be 0 to write the MEMCTL register 322 // CTL0.ENC must be 0 to write the MEMCTL register
@@ -345,24 +345,18 @@ impl<'d, T: Instance> Adc<'d, T, Async> {
345 /// use embassy_mspm0::adc::{Adc, AdcChannel, Vrsel}; 345 /// use embassy_mspm0::adc::{Adc, AdcChannel, Vrsel};
346 /// 346 ///
347 /// let mut adc = Adc::new_async(p.ADC0, adc_config, Irqs); 347 /// let mut adc = Adc::new_async(p.ADC0, adc_config, Irqs);
348 /// let pin1 = p.PA14.degrade_adc(); 348 /// let sequence = [(&p.PA22.into(), Vrsel::VddaVssa), (&p.PA20.into(), Vrsel::VddaVssa)];
349 /// let pin2 = p.PA25.degrade_adc();
350 /// let sequence = [(&pin1, Vrsel::VddaVssa), (&pin2, Vrsel::VddaVssa)];
351 /// let mut readings = [0u16; 2]; 349 /// let mut readings = [0u16; 2];
352 /// 350 ///
353 /// adc.read_sequence( 351 /// adc.read_sequence(sequence.into_iter(), &mut readings).await;
354 /// sequence.into_iter(),
355 /// &mut readings,
356 /// )
357 /// .await;
358 /// defmt::info!("Measurements: {}", readings); 352 /// defmt::info!("Measurements: {}", readings);
359 /// ``` 353 /// ```
360 pub async fn read_sequence<'a>( 354 pub async fn read_sequence<'a>(
361 &mut self, 355 &mut self,
362 sequence: impl ExactSizeIterator<Item = (&'a AnyAdcChannel<T>, Vrsel)>, 356 sequence: impl ExactSizeIterator<Item = (&'a Peri<'d, AnyAdcChannel<T>>, Vrsel)>,
363 readings: &mut [u16], 357 readings: &mut [u16],
364 ) where 358 ) where
365 T: 'a, 359 'd: 'a,
366 { 360 {
367 assert!(sequence.len() != 0, "Asynchronous read sequence cannot be empty"); 361 assert!(sequence.len() != 0, "Asynchronous read sequence cannot be empty");
368 assert!( 362 assert!(
@@ -398,7 +392,7 @@ impl<'d, T: Instance> Adc<'d, T, Async> {
398 392
399/// Peripheral instance trait. 393/// Peripheral instance trait.
400#[allow(private_bounds)] 394#[allow(private_bounds)]
401pub trait Instance: SealedInstance + PeripheralType { 395pub trait Instance: PeripheralType + SealedInstance {
402 type Interrupt: crate::interrupt::typelevel::Interrupt; 396 type Interrupt: crate::interrupt::typelevel::Interrupt;
403} 397}
404 398
@@ -460,8 +454,8 @@ macro_rules! impl_adc_instance {
460/// This is useful in scenarios where you need the ADC channels to have the same type, such as 454/// This is useful in scenarios where you need the ADC channels to have the same type, such as
461/// storing them in an array. 455/// storing them in an array.
462pub struct AnyAdcChannel<T> { 456pub struct AnyAdcChannel<T> {
463 channel: u8, 457 pub(crate) channel: u8,
464 _phantom: PhantomData<T>, 458 pub(crate) _phantom: PhantomData<T>,
465} 459}
466 460
467impl_peripheral!(AnyAdcChannel<T: Instance>); 461impl_peripheral!(AnyAdcChannel<T: Instance>);
@@ -481,36 +475,36 @@ impl<T> AnyAdcChannel<T> {
481 475
482/// ADC channel. 476/// ADC channel.
483#[allow(private_bounds)] 477#[allow(private_bounds)]
484pub trait AdcChannel<T>: SealedAdcChannel<T> + Sized { 478pub trait AdcChannel<T>: PeripheralType + Into<AnyAdcChannel<T>> + SealedAdcChannel<T> + Sized {}
485 /// Allows an ADC channel to be converted into a type-erased [`AnyAdcChannel`].
486 #[allow(unused_mut)]
487 fn degrade_adc(mut self) -> AnyAdcChannel<T> {
488 self.setup();
489
490 AnyAdcChannel {
491 channel: self.channel(),
492 _phantom: PhantomData,
493 }
494 }
495}
496 479
497pub(crate) trait SealedAdcChannel<T> { 480pub(crate) trait SealedAdcChannel<T> {
498 fn setup(&mut self) {} 481 fn setup(&self) {}
499 482
500 fn channel(&self) -> u8; 483 fn channel(&self) -> u8;
501} 484}
502 485
503macro_rules! impl_adc_pin { 486macro_rules! impl_adc_pin {
504 ($inst:ident, $pin:ident, $ch:expr) => { 487 ($inst: ident, $pin: ident, $ch: expr) => {
505 impl crate::adc::AdcChannel<peripherals::$inst> for crate::Peri<'_, crate::peripherals::$pin> {} 488 impl crate::adc::AdcChannel<peripherals::$inst> for crate::peripherals::$pin {}
506 impl crate::adc::SealedAdcChannel<peripherals::$inst> for crate::Peri<'_, crate::peripherals::$pin> { 489 impl crate::adc::SealedAdcChannel<peripherals::$inst> for crate::peripherals::$pin {
507 fn setup(&mut self) { 490 fn setup(&self) {
508 <crate::peripherals::$pin as crate::gpio::SealedPin>::set_as_analog(self); 491 crate::gpio::SealedPin::set_as_analog(self);
509 } 492 }
510 493
511 fn channel(&self) -> u8 { 494 fn channel(&self) -> u8 {
512 $ch 495 $ch
513 } 496 }
514 } 497 }
498
499 impl From<crate::peripherals::$pin> for crate::adc::AnyAdcChannel<peripherals::$inst> {
500 fn from(val: crate::peripherals::$pin) -> Self {
501 crate::adc::SealedAdcChannel::<peripherals::$inst>::setup(&val);
502
503 Self {
504 channel: crate::adc::SealedAdcChannel::<peripherals::$inst>::channel(&val),
505 _phantom: core::marker::PhantomData,
506 }
507 }
508 }
515 }; 509 };
516} 510}