1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
//! # GPIO
//!
//! The GPIO module is used to configure GPIO pins through the
//! [PORT](crate::pac::PORT) interface.
//!
//! ## Versions
//!
//! There are currently two versions of the GPIO module. The inital GPIO API
//! used a macro-heavy implementation, and it contained a few mistakes. The
//! discussion in issue [#214](https://github.com/atsamd-rs/atsamd/issues/214)
//! spurred the creation of a new module with fewer macros and a corrected,
//! refactored API.
//!
//! The new module is provided in [`v2`]. The old module was removed, but a
//! compatibility shim is provided in [`v1`] to support existing code. Users
//! should expect to eventually migrate to [`v2`].
//!
//! ## Errors in [`v1`]
//!
//! [`v2`] fixes a number of errors in [`v1`]:
//!
//! - [`v1`] implements an open-drain output mode, but SAMD chips do not have
//! open-drain outputs. There is (almost) no mention of "open-drain" anywhere
//! in the datasheets. In fact, the SAMD21 datasheet notes a removal of the
//! term in Rev. E. Open-drain outputs have been has been removed in [`v2`].
//! - [`v1`] allows users to enable a pull-up resistor while in an output mode,
//! but this is not possible for SAMD chips. There is no corresponding entry
//! in the "Pin Configurations Summary" table in any of the three datasheets.
//! Moreover, when a pull resistor is enabled for inputs, its direction is set
//! using the `OUT` bit, which would not be possible in an output mode.
//! - [`v1`] does not implement any of the disabled pin modes, i.e. when both
//! `DIR` and `INEN` are `0`. As a consequence, the state of [`v1`] pins at
//! reset is incorrect. [`v1`] assumes they are in floating input mode, but
//! they are actually in floating disabled mode.
//!
//! ## New features
//!
//! The [`v2`] module has several new features:
//!
//! - Converting between pin modes no longer requires access to the [`Port`]
//! type.
//!
//! For example, the follow code in [`v1`],
//! ```
//! let pins = peripherals.PORT.split();
//! let pa8 = pins.pa8.into_push_pull_output(&mut pins.port);
//! ```
//! would look like this in [`v2`].
//! ```
//! let pins = v2::Pins::new(peripherals.PORT);
//! let pa08 = pins.pa08.into_push_pull_output();
//! ```
//! As a consequence, pin mode conversions can now be implemented using
//! [`From`]/[`Into`].
//! ```
//! let pins = Pins::new(peripherals.PORT);
//! let pa08: Pin<PA08, PushPullOutput> = pins.pa08.into();
//! ```
//!
//! - [`v2`] defines a new [`AnyPin`] trait that can be used to simplify
//! function arguments and reduce the number of type parameters required when
//! dealing with GPIO pins.
//! - [`v2`] offers a type-erased, [`DynPin`] type, for run-time tracking of
//! pins.
//! - [`v2`] provides a new [`bsp_pins`] macro to help BSP authors provide
//! meaningful names and type aliases for their GPIO pins.
//!
//! ## Compatibility
//!
//! The original [`v1`] module has been removed. It has been replaced with a
//! compatibility shim to support existing code. The shim implements all [`v1`]
//! pin types in terms of [`v2::Pin`]. In fact, it declares its own [`v1::Pin`]
//! type as a newtype wrapper around a [`v2::Pin`], and it defines the
//! individual `Pa0`, `Pa1`, etc. pin types as type aliases of the new
//! [`v1::Pin`] type.
//!
//! As a consequence, it is easy to define the conversion between a [`v1::Pin`]
//! and its corresponding [`v2::Pin`] using [`From`]/[`Into`].
//! ```
//! let pins = peripherals.PORT.split();
//! let pa8: v1::Pa8<_> = pins.pa8;
//! let pa08 = v2::Pin<_, _> = pa8.into();
//! ```
//! Moreover, all [`v1::Pin`] and [`v2::Pin`] types implement the [`AnyPin`]
//! trait, which is particularly useful for supporting both module versions
//! simultaneously. See the [`AnyPin`] documentation for more details.
//! ```
//! /// Take the v1 or v2 representation of pin PA08, in any mode, then convert
//! /// it to a push-pull output and set it high
//! fn example(pin: impl AnyPin<Id = PA08>) {
//! let mut pin = pin.into().into_push_pull_output();
//! pin.set_high().ok();
//! }
//! ```
//! [`AnyPin`]: v2::AnyPin
//! [`DynPin`]: v2::DynPin
//! [`bsp_pins`]: crate::bsp_pins
pub mod v1;
#[allow(deprecated)]
pub use v1::*;
pub mod v2;