|
|
|
@ -1,22 +1,628 @@
|
|
|
|
|
//! General Purpose Input / Output
|
|
|
|
|
//! # Digital Input / Output
|
|
|
|
|
//!
|
|
|
|
|
//! ## Hardware Summary:
|
|
|
|
|
//!
|
|
|
|
|
//! + Devices may have up to 11 I/O ports, most of which have 8 I/O lines.
|
|
|
|
|
//! + Each I/O line can be configured to the input or output direction
|
|
|
|
|
//! + Each I/O line can be individually read or written
|
|
|
|
|
//! + Each I/O line can be individually configured for a pull-up/down resistor
|
|
|
|
|
//! + Individual ports can be accessed byte-wise
|
|
|
|
|
//! + Ports are also arranged in pairs; e.g. P1 and P2 together are PA
|
|
|
|
|
//! + Port pairs can be accessed half-word-wise (16-bits at a time)
|
|
|
|
|
//!
|
|
|
|
|
//! ## API:
|
|
|
|
|
//!
|
|
|
|
|
//! With the `DIOExt` trait, you can consume the PAC-provided `DIO` and get back
|
|
|
|
|
//! a `Parts` struct that breaks out individual pins. Each pin struct is
|
|
|
|
|
//! parameterized by two typestate variables, one that describes the current I/O
|
|
|
|
|
//! configuration (e.g. input w/pull up, output w/regular drive) and one that
|
|
|
|
|
//! describes the current mode (e.g. GPIO, Primary peripheral).
|
|
|
|
|
//!
|
|
|
|
|
//! Depending on the current typestate, methods are available to transition to
|
|
|
|
|
//! available states from the current one via methods that have names beginning
|
|
|
|
|
//! with `into_`. Invalid transitions are not available.
|
|
|
|
|
//!
|
|
|
|
|
//! The `embedded_hal` trait `OutputPin` is provided for pins in `Gpio` mode
|
|
|
|
|
//! with an output configuration. Additional methods for interacting with the
|
|
|
|
|
//! hardware in ways not covered by HAL traits are provided in typestates where
|
|
|
|
|
//! they are appropriate.
|
|
|
|
|
|
|
|
|
|
use pac::DIO;
|
|
|
|
|
use core::marker::PhantomData;
|
|
|
|
|
use hal::digital::OutputPin;
|
|
|
|
|
|
|
|
|
|
pub trait GpioExt {
|
|
|
|
|
type Parts;
|
|
|
|
|
/// Extension trait to manage Digital I/O resources
|
|
|
|
|
pub trait DIOExt {
|
|
|
|
|
|
|
|
|
|
/// Consume and split the device into its constituent parts
|
|
|
|
|
fn split(self) -> Self::Parts;
|
|
|
|
|
/// Consume and split the DIO device into individual pin proxies
|
|
|
|
|
fn split(self) -> Parts;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Input Pin Pull typestate
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
/// Types implementing this marker trait are typestate parameters to Input pins
|
|
|
|
|
/// that determine the pull up/down resistor configuration.
|
|
|
|
|
pub trait Pull {}
|
|
|
|
|
|
|
|
|
|
/// An input of this type is internally floating; it has no pull up/down resistor.
|
|
|
|
|
pub struct NoPull;
|
|
|
|
|
impl Pull for NoPull {}
|
|
|
|
|
|
|
|
|
|
/// An input of this type is configured with an internal pull-up resistor.
|
|
|
|
|
pub struct PullUp;
|
|
|
|
|
impl Pull for PullUp {}
|
|
|
|
|
|
|
|
|
|
/// An input of this type is configured with an internal pull-down resistor.
|
|
|
|
|
pub struct PullDown;
|
|
|
|
|
impl Pull for PullDown {}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Output Pin Drive Strength typestate
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
/// Types implementing this marker trait are typestate parameters to Output pins
|
|
|
|
|
/// that determine the drive strength of the pin
|
|
|
|
|
pub trait Drive {}
|
|
|
|
|
|
|
|
|
|
/// An output of this type is configured for standard drive strength.
|
|
|
|
|
pub struct Regular;
|
|
|
|
|
impl Drive for Regular {}
|
|
|
|
|
|
|
|
|
|
/// An output of this type is configured for strong drive strength.
|
|
|
|
|
pub struct Strong;
|
|
|
|
|
impl Drive for Strong {}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// I/O Pin Mode typestate
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
/// Types implementing this marker trait are typestate parameters to Input and
|
|
|
|
|
/// Output pins that determine which I/O function they are configured for
|
|
|
|
|
pub trait Mode {}
|
|
|
|
|
|
|
|
|
|
/// This type represents a pin configured as a general purpose I/O pin.
|
|
|
|
|
pub struct Gpio;
|
|
|
|
|
impl Mode for Gpio {}
|
|
|
|
|
|
|
|
|
|
/// This type represents a pin configured to serve its primary peripheral.
|
|
|
|
|
pub struct Primary;
|
|
|
|
|
impl Mode for Primary {}
|
|
|
|
|
|
|
|
|
|
/// This type represents a pin configured to serve its secondary peripheral.
|
|
|
|
|
pub struct Secondary;
|
|
|
|
|
impl Mode for Secondary {}
|
|
|
|
|
|
|
|
|
|
/// This type represents a pin configured to serve its tertiary peripheral.
|
|
|
|
|
pub struct Tertiary;
|
|
|
|
|
impl Mode for Tertiary {}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// I/O Pin Config typestate
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
/// Types implementing this marker trait are typestate parameters to DIO pins
|
|
|
|
|
/// that determine which operations are valid for their configuration
|
|
|
|
|
pub trait PinConfig {}
|
|
|
|
|
|
|
|
|
|
/// Represents a pin configured for input.
|
|
|
|
|
pub struct Input<MODE> {
|
|
|
|
|
_mode: PhantomData<MODE>,
|
|
|
|
|
pub struct Input<P: Pull> {
|
|
|
|
|
_pull: PhantomData<P>,
|
|
|
|
|
}
|
|
|
|
|
impl<P: Pull> PinConfig for Input<P> {}
|
|
|
|
|
|
|
|
|
|
/// Represents a pin configured for output.
|
|
|
|
|
pub struct Output<MODE> {
|
|
|
|
|
_mode: PhantomData<MODE>,
|
|
|
|
|
pub struct Output<D: Drive> {
|
|
|
|
|
_drive: PhantomData<D>,
|
|
|
|
|
}
|
|
|
|
|
impl<D: Drive> PinConfig for Output<D> {}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Temp manual stuff, to replace with a macro
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
macro_rules! gpio {
|
|
|
|
|
([$($PX_i:ident : ($px_i:ident, $i:expr, $px_in:ident, $px_out:ident, $px_dir:ident, $px_ren:ident, $px_ds:ident, $px_sel0:ident, $px_sel1:ident, $px_selc:ident),)+]) => {
|
|
|
|
|
/// Individual types for each I/O pin.
|
|
|
|
|
///
|
|
|
|
|
/// These types are parameterized over phantom types that represent the
|
|
|
|
|
/// state of the pins, but the pin types themselves are zero-sized.
|
|
|
|
|
/// Methods are provided to transition between states and to perform I/O
|
|
|
|
|
/// operations.
|
|
|
|
|
pub mod pins {
|
|
|
|
|
use hal::digital::OutputPin;
|
|
|
|
|
use core::marker::PhantomData;
|
|
|
|
|
use crate::bitband;
|
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
|
|
$(
|
|
|
|
|
/// The type of an individual pin, parameterized by its state
|
|
|
|
|
/// and mode.
|
|
|
|
|
pub struct $PX_i<C: PinConfig, M: Mode> {
|
|
|
|
|
_config: PhantomData<C>,
|
|
|
|
|
_mode: PhantomData<M>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<C: PinConfig, M: Mode> Default for $PX_i<C, M> {
|
|
|
|
|
fn default() -> $PX_i<C, M> {
|
|
|
|
|
$PX_i { _config: PhantomData, _mode: PhantomData }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Functions specific to Input pins
|
|
|
|
|
impl<M: Mode, P: Pull> $PX_i<Input<P>, M> {
|
|
|
|
|
/// Consume the input pin, returning the same pin configured
|
|
|
|
|
/// as an output pin in the same mode. It will have regular
|
|
|
|
|
/// drive strength.
|
|
|
|
|
pub fn into_output(self) -> $PX_i<Output<Regular>, M> {
|
|
|
|
|
self.regular_drive_strength();
|
|
|
|
|
self.output();
|
|
|
|
|
$PX_i { _config: PhantomData, _mode: PhantomData }
|
|
|
|
|
}
|
|
|
|
|
/// Consume the input pin, returning the same pin configured
|
|
|
|
|
/// as an output pin in the same mode. It will have strong
|
|
|
|
|
/// drive strength if the physical pin supports it.
|
|
|
|
|
pub fn into_strong_output(self) -> $PX_i<Output<Strong>, M> {
|
|
|
|
|
self.strong_drive_strength();
|
|
|
|
|
self.output();
|
|
|
|
|
$PX_i { _config: PhantomData, _mode: PhantomData }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<M: Mode> $PX_i<Input<NoPull>, M> {
|
|
|
|
|
/// Consume the floating input pin, returning the same pin
|
|
|
|
|
/// configured as an input with pull-up resistor.
|
|
|
|
|
pub fn into_pullup(self) -> $PX_i<Input<PullUp>, M> {
|
|
|
|
|
self.pull_up();
|
|
|
|
|
$PX_i { _config: PhantomData, _mode: PhantomData }
|
|
|
|
|
}
|
|
|
|
|
/// Consume the floating input pin, returning the same pin
|
|
|
|
|
/// configured as an input with pull-down resistor.
|
|
|
|
|
pub fn into_pulldown(self) -> $PX_i<Input<PullDown>, M> {
|
|
|
|
|
self.pull_down();
|
|
|
|
|
$PX_i { _config: PhantomData, _mode: PhantomData }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<M: Mode> $PX_i<Input<PullUp>, M> {
|
|
|
|
|
/// Consume the input pin with pull-up resistor, returning
|
|
|
|
|
/// the same pin configured as a floating input (no pull-up/
|
|
|
|
|
/// down resistor).
|
|
|
|
|
pub fn into_floating(self) -> $PX_i<Input<NoPull>, M> {
|
|
|
|
|
self.pull_up();
|
|
|
|
|
$PX_i { _config: PhantomData, _mode: PhantomData }
|
|
|
|
|
}
|
|
|
|
|
/// Consume the input pin with pull-up resistor, returning
|
|
|
|
|
/// the same pin configured as an input with pull-down
|
|
|
|
|
/// resistor.
|
|
|
|
|
pub fn into_pulldown(self) -> $PX_i<Input<PullDown>, M> {
|
|
|
|
|
self.pull_down();
|
|
|
|
|
$PX_i { _config: PhantomData, _mode: PhantomData }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<M: Mode> $PX_i<Input<PullDown>, M> {
|
|
|
|
|
/// Consume the input pin with pull-down resistor, returning
|
|
|
|
|
/// the same pin configured as an input with pull-up resistor.
|
|
|
|
|
pub fn into_pullup(self) -> $PX_i<Input<PullUp>, M> {
|
|
|
|
|
self.pull_up();
|
|
|
|
|
$PX_i {_config: PhantomData, _mode: PhantomData }
|
|
|
|
|
}
|
|
|
|
|
/// Consume the input pin with pull-down resistor, returning
|
|
|
|
|
/// the same pin configured as a floating input (no pull-up/
|
|
|
|
|
/// down resistor).
|
|
|
|
|
pub fn into_floating(self) -> $PX_i<Input<NoPull>, M> {
|
|
|
|
|
self.pull_down();
|
|
|
|
|
$PX_i { _config: PhantomData, _mode: PhantomData }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Functions specific to Input pins in Gpio mode
|
|
|
|
|
impl<P: Pull> $PX_i<Input<P>, Gpio> {
|
|
|
|
|
/// Read the state of the pin.
|
|
|
|
|
///
|
|
|
|
|
/// If the pin is in a logic-high state, this returns 1;
|
|
|
|
|
/// if the pin is in a logic-low state, this returns 0.
|
|
|
|
|
pub fn read_pin(&self) -> u16 {
|
|
|
|
|
let dio = unsafe { &*DIO::ptr() };
|
|
|
|
|
let din = &dio.$px_in as *const _ as *const u16;
|
|
|
|
|
unsafe {
|
|
|
|
|
bitband::read_bit(din, $i)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Functions specific to Output pins
|
|
|
|
|
impl<M: Mode, D: Drive> $PX_i<Output<D>, M> {
|
|
|
|
|
/// Consume the output pin, returning the same pin
|
|
|
|
|
/// configured as a floating input (no pull-up/down
|
|
|
|
|
/// resistor).
|
|
|
|
|
pub fn into_floating_input(self) -> $PX_i<Input<NoPull>, M> {
|
|
|
|
|
self.floating();
|
|
|
|
|
self.input();
|
|
|
|
|
$PX_i { _config: PhantomData, _mode: PhantomData }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Consume the output pin, returning the same pin
|
|
|
|
|
/// configured as an input with pull-up resistor.
|
|
|
|
|
pub fn into_input_with_pullup(self) -> $PX_i<Input<PullUp>, M> {
|
|
|
|
|
self.pull_up();
|
|
|
|
|
self.input();
|
|
|
|
|
$PX_i { _config: PhantomData, _mode: PhantomData }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Consume the output pin, returning the same pin
|
|
|
|
|
/// configured as an input with pull-down resistor.
|
|
|
|
|
pub fn into_input_with_pulldown(self) -> $PX_i<Input<PullDown>, M> {
|
|
|
|
|
self.pull_down();
|
|
|
|
|
self.input();
|
|
|
|
|
$PX_i { _config: PhantomData, _mode: PhantomData }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<M: Mode> $PX_i<Output<Regular>, M> {
|
|
|
|
|
/// Consume the output pin of regular drive strength,
|
|
|
|
|
/// returning the same pin configured to strong drive
|
|
|
|
|
/// strength.
|
|
|
|
|
pub fn into_strong(self) -> $PX_i<Output<Strong>, M> {
|
|
|
|
|
self.strong_drive_strength();
|
|
|
|
|
$PX_i { _config: PhantomData, _mode: PhantomData }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<M: Mode> $PX_i<Output<Strong>, M> {
|
|
|
|
|
/// Consume the output pin of strong drive strength,
|
|
|
|
|
/// returning the same pin configured to regular drive
|
|
|
|
|
/// strength.
|
|
|
|
|
pub fn into_regular(self) -> $PX_i<Output<Regular>, M> {
|
|
|
|
|
self.regular_drive_strength();
|
|
|
|
|
$PX_i { _config: PhantomData, _mode: PhantomData }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Functions specific to Output pins in Gpio mode
|
|
|
|
|
impl<D: Drive> OutputPin for $PX_i<Output<D>, Gpio> {
|
|
|
|
|
fn set_high(&mut self) {
|
|
|
|
|
let dio = unsafe { &*DIO::ptr() };
|
|
|
|
|
let dout = &dio.$px_out as *const _ as *const u16;
|
|
|
|
|
unsafe {
|
|
|
|
|
bitband::set_bit(dout, $i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn set_low(&mut self) {
|
|
|
|
|
let dio = unsafe { &*DIO::ptr() };
|
|
|
|
|
let dout = &dio.$px_out as *const _ as *const u16;
|
|
|
|
|
unsafe {
|
|
|
|
|
bitband::clear_bit(dout, $i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Mode changing functions
|
|
|
|
|
//
|
|
|
|
|
// SEL1 SEL0
|
|
|
|
|
// Gpio 0 0
|
|
|
|
|
// Primary 0 1
|
|
|
|
|
// Secondary 1 0
|
|
|
|
|
// Tertiary 1 1
|
|
|
|
|
//
|
|
|
|
|
// Setting SELC toggles both SEL1 and SEL0
|
|
|
|
|
//
|
|
|
|
|
impl<C: PinConfig> $PX_i<C, Gpio> {
|
|
|
|
|
/// Change the pin mode from Gpio mode to the Primary
|
|
|
|
|
/// peripheral mode.
|
|
|
|
|
pub fn into_primary(self) -> $PX_i<C, Primary> {
|
|
|
|
|
let dio = unsafe { &*DIO::ptr() };
|
|
|
|
|
let sel0 = &dio.$px_sel0 as *const _ as *const u16;
|
|
|
|
|
unsafe {
|
|
|
|
|
bitband::set_bit(sel0, $i);
|
|
|
|
|
}
|
|
|
|
|
$PX_i { _config: PhantomData, _mode: PhantomData }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Change the pin mode from Gpio mode into the Secondary
|
|
|
|
|
/// peripheral mode.
|
|
|
|
|
pub fn into_secondary(self) -> $PX_i<C, Secondary> {
|
|
|
|
|
let dio = unsafe { &*DIO::ptr() };
|
|
|
|
|
let sel1 = &dio.$px_sel1 as *const _ as *const u16;
|
|
|
|
|
unsafe {
|
|
|
|
|
bitband::set_bit(sel1, $i);
|
|
|
|
|
}
|
|
|
|
|
$PX_i { _config: PhantomData, _mode: PhantomData }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Change the pin mode from Gpio mode into the Tertiary
|
|
|
|
|
/// peripheral mode.
|
|
|
|
|
pub fn into_tertiary(self) -> $PX_i<C, Tertiary> {
|
|
|
|
|
let dio = unsafe { &*DIO::ptr() };
|
|
|
|
|
let selc = &dio.$px_selc as *const _ as *const u16;
|
|
|
|
|
unsafe {
|
|
|
|
|
bitband::set_bit(selc, $i);
|
|
|
|
|
}
|
|
|
|
|
$PX_i { _config: PhantomData, _mode: PhantomData }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<C: PinConfig> $PX_i<C, Primary> {
|
|
|
|
|
/// Change the pin mode from Primary peripheral mode into
|
|
|
|
|
/// the Gpio mode.
|
|
|
|
|
pub fn into_gpio(self) -> $PX_i<C, Gpio> {
|
|
|
|
|
let dio = unsafe { &*DIO::ptr() };
|
|
|
|
|
let sel0 = &dio.$px_sel0 as *const _ as *const u16;
|
|
|
|
|
unsafe {
|
|
|
|
|
bitband::clear_bit(sel0, $i);
|
|
|
|
|
}
|
|
|
|
|
$PX_i { _config: PhantomData, _mode: PhantomData }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Change the pin mode from Primary peripheral mode into
|
|
|
|
|
/// the Secondary peripheral mode.
|
|
|
|
|
pub fn into_secondary(self) -> $PX_i<C, Secondary> {
|
|
|
|
|
let dio = unsafe { &*DIO::ptr() };
|
|
|
|
|
let selc = &dio.$px_selc as *const _ as *const u16;
|
|
|
|
|
unsafe {
|
|
|
|
|
bitband::set_bit(selc, $i);
|
|
|
|
|
}
|
|
|
|
|
$PX_i { _config: PhantomData, _mode: PhantomData }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Change the pin mode from Primary peripheral mode into
|
|
|
|
|
/// the Tertiary peripheral mode.
|
|
|
|
|
pub fn into_tertiary(self) -> $PX_i<C, Tertiary> {
|
|
|
|
|
let dio = unsafe { &*DIO::ptr() };
|
|
|
|
|
let sel1 = &dio.$px_sel1 as *const _ as *const u16;
|
|
|
|
|
unsafe {
|
|
|
|
|
bitband::set_bit(sel1, $i);
|
|
|
|
|
}
|
|
|
|
|
$PX_i { _config: PhantomData, _mode: PhantomData }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<C: PinConfig> $PX_i<C, Secondary> {
|
|
|
|
|
/// Change the pin mode from Secondary peripheral mode into
|
|
|
|
|
/// into the Primary peripheral mode.
|
|
|
|
|
pub fn into_primary(self) -> $PX_i<C, Primary> {
|
|
|
|
|
let dio = unsafe { &*DIO::ptr() };
|
|
|
|
|
let selc = &dio.$px_selc as *const _ as *const u16;
|
|
|
|
|
unsafe {
|
|
|
|
|
bitband::set_bit(selc, $i);
|
|
|
|
|
}
|
|
|
|
|
$PX_i { _config: PhantomData, _mode: PhantomData }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Change the pin mode from Secondary peripheral mode into
|
|
|
|
|
/// the Gpio mode.
|
|
|
|
|
pub fn into_gpio(self) -> $PX_i<C, Secondary> {
|
|
|
|
|
let dio = unsafe { &*DIO::ptr() };
|
|
|
|
|
let sel1 = &dio.$px_sel1 as *const _ as *const u16;
|
|
|
|
|
unsafe {
|
|
|
|
|
bitband::clear_bit(sel1, $i);
|
|
|
|
|
}
|
|
|
|
|
$PX_i { _config: PhantomData, _mode: PhantomData }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Change the pin mode from Secondary peripheral mode into
|
|
|
|
|
/// the Tertiary peripheral mode.
|
|
|
|
|
pub fn into_tertiary(self) -> $PX_i<C, Tertiary> {
|
|
|
|
|
let dio = unsafe { &*DIO::ptr() };
|
|
|
|
|
let sel0 = &dio.$px_sel0 as *const _ as *const u16;
|
|
|
|
|
unsafe {
|
|
|
|
|
bitband::set_bit(sel0, $i);
|
|
|
|
|
}
|
|
|
|
|
$PX_i { _config: PhantomData, _mode: PhantomData }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<C: PinConfig> $PX_i<C, Tertiary> {
|
|
|
|
|
/// Change the pin mode from Tertiary peripheral mode into
|
|
|
|
|
/// the Primary peripheral mode.
|
|
|
|
|
pub fn into_primary(self) -> $PX_i<C, Primary> {
|
|
|
|
|
let dio = unsafe { &*DIO::ptr() };
|
|
|
|
|
let sel1 = &dio.$px_sel1 as *const _ as *const u16;
|
|
|
|
|
unsafe {
|
|
|
|
|
bitband::clear_bit(sel1, $i);
|
|
|
|
|
}
|
|
|
|
|
$PX_i { _config: PhantomData, _mode: PhantomData }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Change the pin mode from Tertiary peripheral mode into
|
|
|
|
|
/// the Secondary peripheral mode.
|
|
|
|
|
pub fn into_secondary(self) -> $PX_i<C, Secondary> {
|
|
|
|
|
let dio = unsafe { &*DIO::ptr() };
|
|
|
|
|
let sel0 = &dio.$px_sel0 as *const _ as *const u16;
|
|
|
|
|
unsafe {
|
|
|
|
|
bitband::clear_bit(sel0, $i);
|
|
|
|
|
}
|
|
|
|
|
$PX_i { _config: PhantomData, _mode: PhantomData }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Change the pin mode from Tertiary peripheral mode into
|
|
|
|
|
/// the Gpio mode.
|
|
|
|
|
pub fn into_gpio(self) -> $PX_i<C, Tertiary> {
|
|
|
|
|
let dio = unsafe { &*DIO::ptr() };
|
|
|
|
|
let selc = &dio.$px_selc as *const _ as *const u16;
|
|
|
|
|
unsafe {
|
|
|
|
|
bitband::set_bit(selc, $i);
|
|
|
|
|
}
|
|
|
|
|
$PX_i { _config: PhantomData, _mode: PhantomData }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Private and all-pin functions
|
|
|
|
|
impl<C: PinConfig, M: Mode> $PX_i<C, M> {
|
|
|
|
|
fn output(&self) {
|
|
|
|
|
let dio = unsafe { &*DIO::ptr() };
|
|
|
|
|
let dir = &dio.padir as *const _ as *const u16;
|
|
|
|
|
unsafe {
|
|
|
|
|
bitband::set_bit(dir, $i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
fn input(&self) {
|
|
|
|
|
let dio = unsafe { &*DIO::ptr() };
|
|
|
|
|
let dir = &dio.padir as *const _ as *const u16;
|
|
|
|
|
unsafe {
|
|
|
|
|
bitband::clear_bit(dir, $i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
fn strong_drive_strength(&self) {
|
|
|
|
|
let dio = unsafe { &*DIO::ptr() };
|
|
|
|
|
let ds = &dio.$px_ds as *const _ as *const u16;
|
|
|
|
|
unsafe {
|
|
|
|
|
bitband::set_bit(ds, $i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
fn regular_drive_strength(&self) {
|
|
|
|
|
let dio = unsafe { &*DIO::ptr() };
|
|
|
|
|
let ds = &dio.$px_ds as *const _ as *const u16;
|
|
|
|
|
unsafe {
|
|
|
|
|
bitband::clear_bit(ds, $i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
fn pull_up(&self) {
|
|
|
|
|
let dio = unsafe { &*DIO::ptr() };
|
|
|
|
|
let ren = &dio.$px_ren as *const _ as *const u16;
|
|
|
|
|
let out = &dio.$px_out as *const _ as *const u16;
|
|
|
|
|
unsafe {
|
|
|
|
|
bitband::set_bit(out, $i);
|
|
|
|
|
bitband::set_bit(ren, $i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
fn pull_down(&self) {
|
|
|
|
|
let dio = unsafe { &*DIO::ptr() };
|
|
|
|
|
let ren = &dio.$px_ren as *const _ as *const u16;
|
|
|
|
|
let out = &dio.$px_out as *const _ as *const u16;
|
|
|
|
|
unsafe {
|
|
|
|
|
bitband::clear_bit(out, $i);
|
|
|
|
|
bitband::set_bit(ren, $i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
fn floating(&self) {
|
|
|
|
|
let dio = unsafe { &*DIO::ptr() };
|
|
|
|
|
let ren = &dio.$px_ren as *const _ as *const u16;
|
|
|
|
|
let out = &dio.$px_out as *const _ as *const u16;
|
|
|
|
|
unsafe {
|
|
|
|
|
bitband::clear_bit(out, $i);
|
|
|
|
|
bitband::clear_bit(ren, $i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
)+
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// The DIO peripheral split into individual pins.
|
|
|
|
|
pub struct Parts {
|
|
|
|
|
$(
|
|
|
|
|
/// One of the DIO pins. It defaults to a floating input in Gpio mode.
|
|
|
|
|
pub $px_i: pins::$PX_i<Input<NoPull>, Gpio>,
|
|
|
|
|
)+
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl DIOExt for DIO {
|
|
|
|
|
fn split(self) -> Parts {
|
|
|
|
|
Parts {
|
|
|
|
|
$(
|
|
|
|
|
$px_i: Default::default(),
|
|
|
|
|
)+
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gpio!([
|
|
|
|
|
P1_0: (p1_0, 0, pain, paout, padir, paren, pads, pasel0, pasel1, paselc),
|
|
|
|
|
P1_1: (p1_1, 1, pain, paout, padir, paren, pads, pasel0, pasel1, paselc),
|
|
|
|
|
P1_2: (p1_2, 2, pain, paout, padir, paren, pads, pasel0, pasel1, paselc),
|
|
|
|
|
P1_3: (p1_3, 3, pain, paout, padir, paren, pads, pasel0, pasel1, paselc),
|
|
|
|
|
P1_4: (p1_4, 4, pain, paout, padir, paren, pads, pasel0, pasel1, paselc),
|
|
|
|
|
P1_5: (p1_5, 5, pain, paout, padir, paren, pads, pasel0, pasel1, paselc),
|
|
|
|
|
P1_6: (p1_6, 6, pain, paout, padir, paren, pads, pasel0, pasel1, paselc),
|
|
|
|
|
P1_7: (p1_7, 7, pain, paout, padir, paren, pads, pasel0, pasel1, paselc),
|
|
|
|
|
|
|
|
|
|
P2_0: (p2_0, 8, pain, paout, padir, paren, pads, pasel0, pasel1, paselc),
|
|
|
|
|
P2_1: (p2_1, 9, pain, paout, padir, paren, pads, pasel0, pasel1, paselc),
|
|
|
|
|
P2_2: (p2_2, 10, pain, paout, padir, paren, pads, pasel0, pasel1, paselc),
|
|
|
|
|
P2_3: (p2_3, 11, pain, paout, padir, paren, pads, pasel0, pasel1, paselc),
|
|
|
|
|
P2_4: (p2_4, 12, pain, paout, padir, paren, pads, pasel0, pasel1, paselc),
|
|
|
|
|
P2_5: (p2_5, 13, pain, paout, padir, paren, pads, pasel0, pasel1, paselc),
|
|
|
|
|
P2_6: (p2_6, 14, pain, paout, padir, paren, pads, pasel0, pasel1, paselc),
|
|
|
|
|
P2_7: (p2_7, 15, pain, paout, padir, paren, pads, pasel0, pasel1, paselc),
|
|
|
|
|
|
|
|
|
|
P3_0: (p3_0, 0, pbin, pbout, pbdir, pbren, pbds, pbsel0, pbsel1, pbselc),
|
|
|
|
|
P3_1: (p3_1, 1, pbin, pbout, pbdir, pbren, pbds, pbsel0, pbsel1, pbselc),
|
|
|
|
|
P3_2: (p3_2, 2, pbin, pbout, pbdir, pbren, pbds, pbsel0, pbsel1, pbselc),
|
|
|
|
|
P3_3: (p3_3, 3, pbin, pbout, pbdir, pbren, pbds, pbsel0, pbsel1, pbselc),
|
|
|
|
|
P3_4: (p3_4, 4, pbin, pbout, pbdir, pbren, pbds, pbsel0, pbsel1, pbselc),
|
|
|
|
|
P3_5: (p3_5, 5, pbin, pbout, pbdir, pbren, pbds, pbsel0, pbsel1, pbselc),
|
|
|
|
|
P3_6: (p3_6, 6, pbin, pbout, pbdir, pbren, pbds, pbsel0, pbsel1, pbselc),
|
|
|
|
|
P3_7: (p3_7, 7, pbin, pbout, pbdir, pbren, pbds, pbsel0, pbsel1, pbselc),
|
|
|
|
|
|
|
|
|
|
P4_0: (p4_0, 8, pbin, pbout, pbdir, pbren, pbds, pbsel0, pbsel1, pbselc),
|
|
|
|
|
P4_1: (p4_1, 9, pbin, pbout, pbdir, pbren, pbds, pbsel0, pbsel1, pbselc),
|
|
|
|
|
P4_2: (p4_2, 10, pbin, pbout, pbdir, pbren, pbds, pbsel0, pbsel1, pbselc),
|
|
|
|
|
P4_3: (p4_3, 11, pbin, pbout, pbdir, pbren, pbds, pbsel0, pbsel1, pbselc),
|
|
|
|
|
P4_4: (p4_4, 12, pbin, pbout, pbdir, pbren, pbds, pbsel0, pbsel1, pbselc),
|
|
|
|
|
P4_5: (p4_5, 13, pbin, pbout, pbdir, pbren, pbds, pbsel0, pbsel1, pbselc),
|
|
|
|
|
P4_6: (p4_6, 14, pbin, pbout, pbdir, pbren, pbds, pbsel0, pbsel1, pbselc),
|
|
|
|
|
P4_7: (p4_7, 15, pbin, pbout, pbdir, pbren, pbds, pbsel0, pbsel1, pbselc),
|
|
|
|
|
|
|
|
|
|
P5_0: (p5_0, 0, pcin, pcout, pcdir, pcren, pcds, pcsel0, pcsel1, pcselc),
|
|
|
|
|
P5_1: (p5_1, 1, pcin, pcout, pcdir, pcren, pcds, pcsel0, pcsel1, pcselc),
|
|
|
|
|
P5_2: (p5_2, 2, pcin, pcout, pcdir, pcren, pcds, pcsel0, pcsel1, pcselc),
|
|
|
|
|
P5_3: (p5_3, 3, pcin, pcout, pcdir, pcren, pcds, pcsel0, pcsel1, pcselc),
|
|
|
|
|
P5_4: (p5_4, 4, pcin, pcout, pcdir, pcren, pcds, pcsel0, pcsel1, pcselc),
|
|
|
|
|
P5_5: (p5_5, 5, pcin, pcout, pcdir, pcren, pcds, pcsel0, pcsel1, pcselc),
|
|
|
|
|
P5_6: (p5_6, 6, pcin, pcout, pcdir, pcren, pcds, pcsel0, pcsel1, pcselc),
|
|
|
|
|
P5_7: (p5_7, 7, pcin, pcout, pcdir, pcren, pcds, pcsel0, pcsel1, pcselc),
|
|
|
|
|
|
|
|
|
|
P6_0: (p6_0, 8, pcin, pcout, pcdir, pcren, pcds, pcsel0, pcsel1, pcselc),
|
|
|
|
|
P6_1: (p6_1, 9, pcin, pcout, pcdir, pcren, pcds, pcsel0, pcsel1, pcselc),
|
|
|
|
|
P6_2: (p6_2, 10, pcin, pcout, pcdir, pcren, pcds, pcsel0, pcsel1, pcselc),
|
|
|
|
|
P6_3: (p6_3, 11, pcin, pcout, pcdir, pcren, pcds, pcsel0, pcsel1, pcselc),
|
|
|
|
|
P6_4: (p6_4, 12, pcin, pcout, pcdir, pcren, pcds, pcsel0, pcsel1, pcselc),
|
|
|
|
|
P6_5: (p6_5, 13, pcin, pcout, pcdir, pcren, pcds, pcsel0, pcsel1, pcselc),
|
|
|
|
|
P6_6: (p6_6, 14, pcin, pcout, pcdir, pcren, pcds, pcsel0, pcsel1, pcselc),
|
|
|
|
|
P6_7: (p6_7, 15, pcin, pcout, pcdir, pcren, pcds, pcsel0, pcsel1, pcselc),
|
|
|
|
|
|
|
|
|
|
P7_0: (p7_0, 0, pdin, pdout, pddir, pdren, pdds, pdsel0, pdsel1, pdselc),
|
|
|
|
|
P7_1: (p7_1, 1, pdin, pdout, pddir, pdren, pdds, pdsel0, pdsel1, pdselc),
|
|
|
|
|
P7_2: (p7_2, 2, pdin, pdout, pddir, pdren, pdds, pdsel0, pdsel1, pdselc),
|
|
|
|
|
P7_3: (p7_3, 3, pdin, pdout, pddir, pdren, pdds, pdsel0, pdsel1, pdselc),
|
|
|
|
|
P7_4: (p7_4, 4, pdin, pdout, pddir, pdren, pdds, pdsel0, pdsel1, pdselc),
|
|
|
|
|
P7_5: (p7_5, 5, pdin, pdout, pddir, pdren, pdds, pdsel0, pdsel1, pdselc),
|
|
|
|
|
P7_6: (p7_6, 6, pdin, pdout, pddir, pdren, pdds, pdsel0, pdsel1, pdselc),
|
|
|
|
|
P7_7: (p7_7, 7, pdin, pdout, pddir, pdren, pdds, pdsel0, pdsel1, pdselc),
|
|
|
|
|
|
|
|
|
|
P8_0: (p8_0, 8, pdin, pdout, pddir, pdren, pdds, pdsel0, pdsel1, pdselc),
|
|
|
|
|
P8_1: (p8_1, 9, pdin, pdout, pddir, pdren, pdds, pdsel0, pdsel1, pdselc),
|
|
|
|
|
P8_2: (p8_2, 10, pdin, pdout, pddir, pdren, pdds, pdsel0, pdsel1, pdselc),
|
|
|
|
|
P8_3: (p8_3, 11, pdin, pdout, pddir, pdren, pdds, pdsel0, pdsel1, pdselc),
|
|
|
|
|
P8_4: (p8_4, 12, pdin, pdout, pddir, pdren, pdds, pdsel0, pdsel1, pdselc),
|
|
|
|
|
P8_5: (p8_5, 13, pdin, pdout, pddir, pdren, pdds, pdsel0, pdsel1, pdselc),
|
|
|
|
|
P8_6: (p8_6, 14, pdin, pdout, pddir, pdren, pdds, pdsel0, pdsel1, pdselc),
|
|
|
|
|
P8_7: (p8_7, 15, pdin, pdout, pddir, pdren, pdds, pdsel0, pdsel1, pdselc),
|
|
|
|
|
|
|
|
|
|
P9_0: (p9_0, 0, pein, peout, pedir, peren, peds, pesel0, pesel1, peselc),
|
|
|
|
|
P9_1: (p9_1, 1, pein, peout, pedir, peren, peds, pesel0, pesel1, peselc),
|
|
|
|
|
P9_2: (p9_2, 2, pein, peout, pedir, peren, peds, pesel0, pesel1, peselc),
|
|
|
|
|
P9_3: (p9_3, 3, pein, peout, pedir, peren, peds, pesel0, pesel1, peselc),
|
|
|
|
|
P9_4: (p9_4, 4, pein, peout, pedir, peren, peds, pesel0, pesel1, peselc),
|
|
|
|
|
P9_5: (p9_5, 5, pein, peout, pedir, peren, peds, pesel0, pesel1, peselc),
|
|
|
|
|
P9_6: (p9_6, 6, pein, peout, pedir, peren, peds, pesel0, pesel1, peselc),
|
|
|
|
|
P9_7: (p9_7, 7, pein, peout, pedir, peren, peds, pesel0, pesel1, peselc),
|
|
|
|
|
|
|
|
|
|
P10_0: (p10_0, 8, pein, peout, pedir, peren, peds, pesel0, pesel1, peselc),
|
|
|
|
|
P10_1: (p10_1, 9, pein, peout, pedir, peren, peds, pesel0, pesel1, peselc),
|
|
|
|
|
P10_2: (p10_2, 10, pein, peout, pedir, peren, peds, pesel0, pesel1, peselc),
|
|
|
|
|
P10_3: (p10_3, 11, pein, peout, pedir, peren, peds, pesel0, pesel1, peselc),
|
|
|
|
|
P10_4: (p10_4, 12, pein, peout, pedir, peren, peds, pesel0, pesel1, peselc),
|
|
|
|
|
P10_5: (p10_5, 13, pein, peout, pedir, peren, peds, pesel0, pesel1, peselc),
|
|
|
|
|
P10_6: (p10_6, 14, pein, peout, pedir, peren, peds, pesel0, pesel1, peselc),
|
|
|
|
|
P10_7: (p10_7, 15, pein, peout, pedir, peren, peds, pesel0, pesel1, peselc),
|
|
|
|
|
|
|
|
|
|
]);
|
|
|
|
|