1 | //! Analog-digital conversion traits |
2 | |
3 | #[cfg (feature = "unproven" )] |
4 | use nb; |
5 | |
6 | /// A marker trait to identify MCU pins that can be used as inputs to an ADC channel. |
7 | /// |
8 | /// This marker trait denotes an object, i.e. a GPIO pin, that is ready for use as an input to the |
9 | /// ADC. As ADCs channels can be supplied by multiple pins, this trait defines the relationship |
10 | /// between the physical interface and the ADC sampling buffer. |
11 | /// |
12 | /// ``` |
13 | /// # use std::marker::PhantomData; |
14 | /// # use embedded_hal::adc::Channel; |
15 | /// |
16 | /// struct Adc1; // Example ADC with single bank of 8 channels |
17 | /// struct Gpio1Pin1<MODE>(PhantomData<MODE>); |
18 | /// struct Analog(()); // marker type to denote a pin in "analog" mode |
19 | /// |
20 | /// // GPIO 1 pin 1 can supply an ADC channel when it is configured in Analog mode |
21 | /// impl Channel<Adc1> for Gpio1Pin1<Analog> { |
22 | /// type ID = u8; // ADC channels are identified numerically |
23 | /// |
24 | /// fn channel() -> u8 { 7_u8 } // GPIO pin 1 is connected to ADC channel 7 |
25 | /// } |
26 | /// |
27 | /// struct Adc2; // ADC with two banks of 16 channels |
28 | /// struct Gpio2PinA<MODE>(PhantomData<MODE>); |
29 | /// struct AltFun(()); // marker type to denote some alternate function mode for the pin |
30 | /// |
31 | /// // GPIO 2 pin A can supply an ADC channel when it's configured in some alternate function mode |
32 | /// impl Channel<Adc2> for Gpio2PinA<AltFun> { |
33 | /// type ID = (u8, u8); // ADC channels are identified by bank number and channel number |
34 | /// |
35 | /// fn channel() -> (u8, u8) { (0, 3) } // bank 0 channel 3 |
36 | /// } |
37 | /// ``` |
38 | #[cfg (feature = "unproven" )] |
39 | pub trait Channel<ADC> { |
40 | /// Channel ID type |
41 | /// |
42 | /// A type used to identify this ADC channel. For example, if the ADC has eight channels, this |
43 | /// might be a `u8`. If the ADC has multiple banks of channels, it could be a tuple, like |
44 | /// `(u8: bank_id, u8: channel_id)`. |
45 | type ID; |
46 | |
47 | /// Get the specific ID that identifies this channel, for example `0_u8` for the first ADC |
48 | /// channel, if Self::ID is u8. |
49 | fn channel() -> Self::ID; |
50 | |
51 | // `channel` is a function due to [this reported |
52 | // issue](https://github.com/rust-lang/rust/issues/54973). Something about blanket impls |
53 | // combined with `type ID; const CHANNEL: Self::ID;` causes problems. |
54 | //const CHANNEL: Self::ID; |
55 | } |
56 | |
57 | /// ADCs that sample on single channels per request, and do so at the time of the request. |
58 | /// |
59 | /// This trait is the interface to an ADC that is configured to read a specific channel at the time |
60 | /// of the request (in contrast to continuous asynchronous sampling). |
61 | /// |
62 | /// ``` |
63 | /// use embedded_hal::adc::{Channel, OneShot}; |
64 | /// |
65 | /// struct MyAdc; // 10-bit ADC, with 5 channels |
66 | /// # impl MyAdc { |
67 | /// # pub fn power_up(&mut self) {} |
68 | /// # pub fn power_down(&mut self) {} |
69 | /// # pub fn do_conversion(&mut self, chan: u8) -> u16 { 0xAA55_u16 } |
70 | /// # } |
71 | /// |
72 | /// impl<WORD, PIN> OneShot<MyAdc, WORD, PIN> for MyAdc |
73 | /// where |
74 | /// WORD: From<u16>, |
75 | /// PIN: Channel<MyAdc, ID=u8>, |
76 | /// { |
77 | /// type Error = (); |
78 | /// |
79 | /// fn read(&mut self, _pin: &mut PIN) -> nb::Result<WORD, Self::Error> { |
80 | /// let chan = 1 << PIN::channel(); |
81 | /// self.power_up(); |
82 | /// let result = self.do_conversion(chan); |
83 | /// self.power_down(); |
84 | /// Ok(result.into()) |
85 | /// } |
86 | /// } |
87 | /// ``` |
88 | #[cfg (feature = "unproven" )] |
89 | pub trait OneShot<ADC, Word, Pin: Channel<ADC>> { |
90 | /// Error type returned by ADC methods |
91 | type Error; |
92 | |
93 | /// Request that the ADC begin a conversion on the specified pin |
94 | /// |
95 | /// This method takes a `Pin` reference, as it is expected that the ADC will be able to sample |
96 | /// whatever channel underlies the pin. |
97 | fn read(&mut self, pin: &mut Pin) -> nb::Result<Word, Self::Error>; |
98 | } |
99 | |