Skip to content

Commit

Permalink
adc: Add "dynamic" Channel type
Browse files Browse the repository at this point in the history
Add a type that can represent any channel for e.g. storing a list of
channels in an array.

Ref: #33
  • Loading branch information
Rahix committed Mar 13, 2021
1 parent 631f2d4 commit f698d10
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 1 deletion.
2 changes: 1 addition & 1 deletion arduino-hal/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ pub use i2c::I2c;
#[cfg(feature = "board-selected")]
pub mod adc {
pub use crate::hal::adc::{
channel, AdcChannel, AdcOps, AdcSettings, ClockDivider, ReferenceVoltage,
channel, AdcChannel, AdcOps, AdcSettings, Channel, ClockDivider, ReferenceVoltage,
};

/// Check the [`avr_hal_generic::adc::Adc`] documentation.
Expand Down
56 changes: 56 additions & 0 deletions avr-hal-generic/src/adc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,51 @@ pub trait AdcChannel<H, ADC: AdcOps<H>> {
fn channel(&self) -> ADC::Channel;
}

/// Representation of any ADC Channel.
///
/// Typically, distinct types are used per channel, like for example `Pin<mode::Analog, PC0>`. In
/// some situations, however, a type is needed which can represent _any_ channel. This is required
/// to, for example, store multiple channels in an array.
///
/// `Channel` is such a type. It can be created by calling the [`into_channel()`][into-channel]
/// method of a distinct type:
///
/// ```
/// let a0 = pins.a0.into_analog_input(&mut adc);
/// let a1 = pins.a1.into_analog_input(&mut adc);
///
/// let channels: [atmega_hal::adc::Channel; 2] = [
/// a0.into_channel(),
/// a1.into_channel(),
/// ];
///
/// for ch in channels.iter() {
/// adc.read_blocking(ch);
/// }
/// ```
///
/// [into-channel]: crate::port::Pin::into_channel
pub struct Channel<H, ADC: AdcOps<H>> {
ch: ADC::Channel,
_h: PhantomData<H>,
}

impl<H, ADC: AdcOps<H>> Channel<H, ADC> {
pub fn new<CH: AdcChannel<H, ADC>>(ch: CH) -> Self {
Self {
ch: ch.channel(),
_h: PhantomData,
}
}
}

impl<H, ADC: AdcOps<H>> AdcChannel<H, ADC> for Channel<H, ADC> {
#[inline]
fn channel(&self) -> ADC::Channel {
self.ch
}
}

/// Analog-to-Digital Converter
/// ```
/// let dp = atmega_hal::Peripherals::take().unwrap();
Expand Down Expand Up @@ -279,6 +324,17 @@ macro_rules! impl_adc {
$channel
}
}

/// Convert this channel into a generic "[`Channel`][adc-channel]" type.
///
/// The generic channel type can be used to store multiple channels in an array.
///
/// [adc-channel]: crate::adc::Channel
impl $channel_ty {
pub fn into_channel(self) -> $crate::adc::Channel<$HAL, $ADC> {
crate::adc::Channel::new(self)
}
}
)*)?
};
}
13 changes: 13 additions & 0 deletions avr-hal-generic/src/port.rs
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,19 @@ impl<PIN: PinOps> Pin<mode::Analog, PIN> {
{
adc.read_blocking(self)
}

/// Convert this pin into a generic [`Channel`][adc-channel] type.
///
/// The generic channel type can be used to store multiple channels in an array.
///
/// [adc-channel]: crate::adc::Channel
pub fn into_channel<H, ADC>(self) -> crate::adc::Channel<H, ADC>
where
Pin<mode::Analog, PIN>: crate::adc::AdcChannel<H, ADC>,
ADC: crate::adc::AdcOps<H>,
{
crate::adc::Channel::new(self)
}
}

#[macro_export]
Expand Down
3 changes: 3 additions & 0 deletions mcu/atmega-hal/src/adc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ pub use avr_hal_generic::adc::{AdcChannel, AdcOps, AdcSettings, ClockDivider, Re
/// Check the [`avr_hal_generic::adc::Adc`] documentation.
pub type Adc<CLOCK> = avr_hal_generic::adc::Adc<crate::Atmega, crate::pac::ADC, CLOCK>;

/// Check the [`avr_hal_generic::adc::Channel`] documentation.
pub type Channel = avr_hal_generic::adc::Channel<crate::Atmega, crate::pac::ADC>;

/// Additional channels
///
/// Some channels are not directly connected to pins. This module provides types which can be used
Expand Down

0 comments on commit f698d10

Please sign in to comment.