44
55use core:: future:: poll_fn;
66use core:: marker:: PhantomData ;
7+ use core:: ops:: Deref ;
78use core:: task:: Poll ;
89
910use embassy_hal_internal:: interrupt:: InterruptExt ;
10- use embassy_hal_internal:: { impl_peripheral , Peri , PeripheralType } ;
11+ use embassy_hal_internal:: { Peri , PeripheralType } ;
1112use embassy_sync:: waitqueue:: AtomicWaker ;
1213
1314use crate :: clocks:: enable_and_reset;
1415use crate :: interrupt:: typelevel:: Binding ;
15- use crate :: iopctl:: { DriveMode , DriveStrength , Function , Inverter , IopctlPin , Pull , SlewRate } ;
16+ use crate :: iopctl:: {
17+ AnyPin , DriveMode , DriveStrength , Function , Inverter , IopctlFunctionPin , IopctlPin , Pull , SlewRate ,
18+ } ;
1619use crate :: pac:: adc0;
1720use crate :: peripherals:: ADC0 ;
1821use crate :: { interrupt, peripherals} ;
@@ -45,16 +48,16 @@ impl Default for Config {
4548/// ADC channel config
4649pub struct ChannelConfig < ' d > {
4750 /// Positive channel to sample
48- p_channel : Peri < ' d , AnyInput > ,
51+ p_channel : GuardedAnyInput < ' d > ,
4952 /// An optional negative channel to sample
50- n_channel : Option < Peri < ' d , AnyInput > > ,
53+ n_channel : Option < GuardedAnyInput < ' d > > ,
5154}
5255
5356impl < ' d > ChannelConfig < ' d > {
5457 /// Default configuration for single ended channel sampling.
55- pub fn single_ended ( input : Peri < ' d , impl Input > ) -> Self {
58+ pub fn single_ended ( p_input : Peri < ' d , impl Input > ) -> Self {
5659 Self {
57- p_channel : input . into ( ) ,
60+ p_channel : GuardedAnyInput :: from ( p_input ) ,
5861 n_channel : None ,
5962 }
6063 }
@@ -68,8 +71,8 @@ impl<'d> ChannelConfig<'d> {
6871 }
6972
7073 Ok ( Self {
71- p_channel : p_input . into ( ) ,
72- n_channel : Some ( n_input . into ( ) ) ,
74+ p_channel : GuardedAnyInput :: from ( p_input ) ,
75+ n_channel : Some ( GuardedAnyInput :: from ( n_input ) ) ,
7376 } )
7477 }
7578}
@@ -92,6 +95,7 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
9295/// ADC driver
9396pub struct Adc < ' p , const N : usize > {
9497 info : Info ,
98+ channels : [ ChannelConfig < ' p > ; N ] ,
9599 _lifetime : PhantomData < & ' p ( ) > ,
96100}
97101
@@ -163,13 +167,13 @@ impl<const N: usize> Adc<'_, N> {
163167 self . info . regs . ctrl ( ) . modify ( |_, w| w. rstfifo ( ) . rstfifo_1 ( ) ) ;
164168 }
165169
166- fn configure_channels ( & mut self , channel_config : & [ ChannelConfig ; N ] ) {
167- let mut cmd = channel_config . len ( ) ;
170+ fn configure_channels ( & mut self ) {
171+ let mut cmd = self . channels . len ( ) ;
168172
169173 // Configure conversion CMD configuration
170174 // Set up a cmd chain, one cmd per channel
171175 // one points to the next, last one points to 0
172- for ch in channel_config {
176+ for ch in & self . channels {
173177 // Mapping cmd [1-15] into reg array index [0-14]
174178 // Reg array index is one less than cmd
175179 let cmd_index = cmd - 1 ;
@@ -218,7 +222,7 @@ impl<const N: usize> Adc<'_, N> {
218222 . tdly ( )
219223 . bits ( 0 )
220224 . tcmd ( )
221- . bits ( channel_config . len ( ) as u8 )
225+ . bits ( self . channels . len ( ) as u8 )
222226 } ) ;
223227 }
224228}
@@ -229,16 +233,17 @@ impl<'p, const N: usize> Adc<'p, N> {
229233 _adc : Peri < ' p , T > ,
230234 _irq : impl Binding < T :: Interrupt , InterruptHandler < T > > + ' p ,
231235 config : Config ,
232- channel_config : [ ChannelConfig ; N ] ,
236+ channels : [ ChannelConfig < ' p > ; N ] ,
233237 ) -> Self {
234238 let mut inst = Self {
235239 info : T :: info ( ) ,
240+ channels,
236241 _lifetime : PhantomData ,
237242 } ;
238243
239244 Self :: init ( ) ;
240245 inst. configure_adc ( config) ;
241- inst. configure_channels ( & channel_config ) ;
246+ inst. configure_channels ( ) ;
242247
243248 // Enable interrupt
244249 interrupt:: ADC0 . unpend ( ) ;
@@ -367,27 +372,17 @@ pub(crate) trait SealedInput {
367372
368373/// A dual purpose (digital/analog) input that can be used as analog input to ADC peripheral.
369374#[ allow( private_bounds) ]
370- pub trait Input : SealedInput + Into < AnyInput > + PeripheralType + Sized + ' static {
371- /// Convert this ADC input pin to a type-erased `AnyInput`.
372- ///
373- /// This allows using several inputs in situations that might require
374- /// them to be the same type, like putting them in an array.
375- fn degrade_adc ( self ) -> AnyInput {
376- AnyInput {
377- channel : self . channel ( ) ,
378- }
379- }
380- }
375+ pub trait Input : SealedInput + Into < AnyInput > + PeripheralType + Sized + ' static { }
381376
382377/// A type-erased ADC input.
383378///
384379/// This allows using several inputs in situations that might require
385380/// them to be the same type, like putting them in an array.
386381pub struct AnyInput {
387382 channel : AdcChannel ,
383+ pin : AnyPin ,
388384}
389-
390- impl_peripheral ! ( AnyInput ) ;
385+ embassy_hal_internal:: impl_peripheral!( AnyInput ) ;
391386
392387impl SealedInput for AnyInput {
393388 fn channel ( & self ) -> AdcChannel {
@@ -397,6 +392,30 @@ impl SealedInput for AnyInput {
397392
398393impl Input for AnyInput { }
399394
395+ struct GuardedAnyInput < ' a > {
396+ inner : Peri < ' a , AnyInput > ,
397+ }
398+
399+ impl < ' a , T : Into < AnyInput > + PeripheralType > From < Peri < ' a , T > > for GuardedAnyInput < ' a > {
400+ fn from ( val : Peri < ' a , T > ) -> Self {
401+ GuardedAnyInput { inner : val. into ( ) }
402+ }
403+ }
404+
405+ impl < ' a > Deref for GuardedAnyInput < ' a > {
406+ type Target = Peri < ' a , AnyInput > ;
407+
408+ fn deref ( & self ) -> & Self :: Target {
409+ & self . inner
410+ }
411+ }
412+
413+ impl Drop for GuardedAnyInput < ' _ > {
414+ fn drop ( & mut self ) {
415+ self . inner . pin . reset ( ) ;
416+ }
417+ }
418+
400419/// Macro to implement required types for dual purpose pins
401420macro_rules! impl_pin {
402421 ( $pin: ident, $ch: ident, $side: ident) => {
@@ -425,7 +444,10 @@ macro_rules! impl_pin {
425444
426445 impl From <$pin> for crate :: adc:: AnyInput {
427446 fn from( val: $pin) -> Self {
428- crate :: adc:: Input :: degrade_adc( val)
447+ crate :: adc:: AnyInput {
448+ channel: val. channel( ) ,
449+ pin: val. into( ) ,
450+ }
429451 }
430452 }
431453 } ;
0 commit comments