[][src]Trait trellis_m4::gpio::v2::AnyPin

pub trait AnyPin: Sealed {
    type Id: PinId;
    type Mode: PinMode;
    pub fn as_concrete(self) -> Pin<Self::Id, Self::Mode>;
pub fn as_concrete_ref(&self) -> &Pin<Self::Id, Self::Mode>;
pub fn as_concrete_mut(&mut self) -> &mut Pin<Self::Id, Self::Mode>; pub fn into_mode<N>(self) -> Pin<Self::Id, N>
    where
        N: PinMode
, { ... }
pub fn into_floating_disabled(self) -> Pin<Self::Id, Disabled<Floating>> { ... }
pub fn into_pull_down_disabled(self) -> Pin<Self::Id, Disabled<PullDown>> { ... }
pub fn into_pull_up_disabled(self) -> Pin<Self::Id, Disabled<PullUp>> { ... }
pub fn into_floating_input(self) -> Pin<Self::Id, Input<Floating>> { ... }
pub fn into_pull_down_input(self) -> Pin<Self::Id, Input<PullDown>> { ... }
pub fn into_pull_up_input(self) -> Pin<Self::Id, Input<PullUp>> { ... }
pub fn into_push_pull_output(self) -> Pin<Self::Id, Output<PushPull>> { ... }
pub fn into_readable_output(self) -> Pin<Self::Id, Output<Readable>> { ... }
pub fn into_alternate<C>(self) -> Pin<Self::Id, Alternate<C>>
    where
        C: AlternateConfig
, { ... }
pub fn get_drive_strength(&self) { ... }
pub fn set_drive_strength(&mut self, stronger: bool) { ... } }

Meta-type representing any Pin

All instances of Pin implement this trait. When used as a trait bound, it acts to encapsulate a Pin. Without this trait, a completely generic Pin requires two type parameters, i.e. Pin<I, M>. But when using this trait, only one type parameter is required, i.e. P: AnyPin. However, even though we have dropped a type parameter, no information is lost, because the PinId and PinMode type parameters are stored as associated types in the trait. The implementation of AnyPin looks something like this:

impl<I: PinId, M: PinMode> AnyPin for Pin<I, M> {
    type Id = I;
    type Mode = M;
    // ...
}

Thus, there is a one-to-one mapping between Pin<I, M> and AnyPin<Id = I, Mode = M>, so you can always recover the full, concrete type from an implementation of AnyPin. The type alias ConcretePin is provided for just this purpose.

AnyPin as a trait bound

When using AnyPin as a trait bound, you can constrain the associated types to restrict the acceptable Pins. For example, you could restrict a function to accept a particular pin in any mode.

fn example<P>(pin: P)
where
    P: AnyPin<Id = PA27>
{
}

Or you could accept any pin, as long as it's in the desired mode.

fn example<P>(pin: P)
where
    P: AnyPin<Mode = PullDownInput>
{
}

You can also apply more complex bounds.

fn example<P, C>(pin: P)
where
    P: AnyPin<Mode = Output<C>>,
    C: OutputConfig,
    P::Id: UserTrait,
{
}

Generic AnyPins

Working with a generic type constrained by AnyPin is slightly different than working with a concrete Pin. When compiling a generic function, the compiler cannot assume anything about the specific concrete type. It can only use what it knows about the AnyPin trait. Consequently, we repeat all of Pin's inherent methods on the trait, for convenience. To cast a generic type to a concrete type, use the as_concrete method. To cast back to the generic type, use the Pin method as_any.

The following example walks through a few different ways to interact with a generic type constrained by AnyPin.

Suppose you wanted to store a completely generic Pin within a struct. You can do so using only one type parameter and the AnyPin trait.

pub struct Example<P: AnyPin> {
    pin: P,
}

Next, suppose you want to create a method that will take the Pin out of the struct, perform some operations in several PinModes, and put it back into the struct before returning. The elided method below shows such an example. However, it can be a bit tricky to follow all of the type conversions here. For clarity, the expanded method shows the same behavior with each transformation given its proper type annotation. Notice that it is not enough to simply put back a type that implements AnyPin<Id = P::Id, Mode = P::Mode>. As far as the compiler is concerned, there could be many different types that satisfy that trait bound. Instead, you must put back a P exactly. The as_any function is the key here. It transforms some type that implements AnyPin<Id = P::Id, Mode = P::Mode> into P itself.

impl<P: AnyPin> Example<P> {
    pub fn elided(mut self) -> Self {
        let mut pin = self.pin.into_push_pull_output();
        pin.set_high().unwrap();
        let pin = pin.into_floating_input();
        let _bit = pin.is_low().unwrap();
        self.pin = pin.into_mode().as_any();
        self
    }
    pub fn expanded(mut self) -> Self {
        // This step is skipped above, because the `into_push_pull_output`
        // trait method automatically calls `as_concrete`.
        // By definition, ConcretePin<P> == Pin<P::Id, P::Mode>
        let pin: ConcretePin<P> = self.pin.as_concrete();
        let mut pin: Pin<P::Id, PushPullOutput> = pin.into_push_pull_output();
        pin.set_high().unwrap();
        let pin: Pin<P::Id, FloatingInput> = pin.into_floating_input();
        let _bit = pin.is_low().unwrap();
        let pin: ConcretePin<P> = pin.into_mode::<P::Mode>();
        self.pin: P = pin.as_any::<P>();
        self
    }
}

Associated Types

type Id: PinId[src]

PinId of the corresponding Pin

type Mode: PinMode[src]

PinMode of the corresponding Pin

Loading content...

Required methods

pub fn as_concrete(self) -> Pin<Self::Id, Self::Mode>[src]

Convert a type that implements AnyPin to a concrete Pin

Even though there is a one-to-one mapping between Pin<I, M> and AnyPin<Id = I, Mode = M>, the compiler doesn't know that. This method provides a way to convert from an AnyPin to a Pin

pub fn as_concrete_ref(&self) -> &Pin<Self::Id, Self::Mode>[src]

Implement as_concrete for references

pub fn as_concrete_mut(&mut self) -> &mut Pin<Self::Id, Self::Mode>[src]

Implement as_concrete for mutable references

Loading content...

Provided methods

pub fn into_mode<N>(self) -> Pin<Self::Id, N> where
    N: PinMode
[src]

Convert the pin to the requested PinMode

pub fn into_floating_disabled(self) -> Pin<Self::Id, Disabled<Floating>>[src]

Disable the pin and set it to float

pub fn into_pull_down_disabled(self) -> Pin<Self::Id, Disabled<PullDown>>[src]

Disable the pin and set it to pull down

pub fn into_pull_up_disabled(self) -> Pin<Self::Id, Disabled<PullUp>>[src]

Disable the pin and set it to pull up

pub fn into_floating_input(self) -> Pin<Self::Id, Input<Floating>>[src]

Configure the pin to operate as a floating input

pub fn into_pull_down_input(self) -> Pin<Self::Id, Input<PullDown>>[src]

Configure the pin to operate as a pulled down input

pub fn into_pull_up_input(self) -> Pin<Self::Id, Input<PullUp>>[src]

Configure the pin to operate as a pulled up input

pub fn into_push_pull_output(self) -> Pin<Self::Id, Output<PushPull>>[src]

Configure the pin to operate as a push-pull output

pub fn into_readable_output(self) -> Pin<Self::Id, Output<Readable>>[src]

Configure the pin to operate as a readable push pull output

pub fn into_alternate<C>(self) -> Pin<Self::Id, Alternate<C>> where
    C: AlternateConfig
[src]

Configure the pin to operate as the corresponding peripheral function.

The type C indicates the desired peripheral function.

pub fn get_drive_strength(&self)[src]

Read the current drive strength of the pin.

The drive strength is reset to normal on every change in pin mode.

pub fn set_drive_strength(&mut self, stronger: bool)[src]

Set the drive strength for the pin.

The drive strength is reset to normal on every change in pin mode.

Loading content...

Implementors

impl<I, M> AnyPin for Pin<I, M> where
    M: PinMode,
    I: PinId
[src]

type Id = I

type Mode = M

Loading content...