embedded_hal/adc.rs
1//! Analog-digital conversion traits
2
3#[cfg(feature = "unproven")]
4use 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")]
39pub 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")]
89pub 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}