Skip to content

Commit 0ee24e4

Browse files
bors[bot]Brandon Matthews
and
Brandon Matthews
committed
Merge #101
101: ADC-related traits r=hannobraun a=thenewwazoo Opening the discussion! One implementation currently exists [here](https://github.com/thenewwazoo/stm32l0x1-context-hal/blob/master/src/adc.rs), and I'll be adding another for the LPC177x/8x HAL soonish. I feel like these traits encompass nearly all the useful "modes" that an ADC operates in; n.b. that IME "continuous" sampling of a single pin looks just like a "scan" with one pin enabled, so I didn't distinguish between the two. I'm not sure if I _should_, but it's a known t.b.d. (obviously the final PR would gate this behind `unproven`, or however is appropriate) Co-authored-by: Brandon Matthews <[email protected]>
2 parents 96f8f61 + ca3adee commit 0ee24e4

File tree

2 files changed

+99
-0
lines changed

2 files changed

+99
-0
lines changed

src/adc.rs

+98
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
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+
}

src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -689,6 +689,7 @@
689689
extern crate nb;
690690
extern crate void;
691691

692+
pub mod adc;
692693
pub mod blocking;
693694
pub mod digital;
694695
pub mod prelude;

0 commit comments

Comments
 (0)