pub mod asynch;
mod access;
use access::*;
use core::{convert::Infallible, fmt::Debug, marker::PhantomData};
use critical_section::CriticalSection;
pub use embedded_hal::digital::PinState;
use psoc_macros::hsiom;
use crate::{
NonExhaustive,
regs::{self, RegisterValue},
security::{self, Security, SecurityAttribute, WithSecurity},
};
#[non_exhaustive]
pub struct Pin<const PORT: u8, const PIN: u8, Mode: PinMode, Sec: Security = security::Default> {
pub mode: Mode,
security: Sec,
}
#[derive(Debug)]
pub struct AnyPin<'a> {
port: u8,
pin: u8,
security: SecurityAttribute,
_p: PhantomData<&'a ()>,
}
pub trait PinMode: Default + Copy {
const DRIVE_MODE: DriveMode;
const INPUT_BUFFER: bool;
const IO_SELECTOR: IoSelector;
}
pub trait InputMode: PinMode {}
pub trait OutputMode: PinMode {}
pub mod mode {
use super::*;
macro_rules! mode {
($mode:ident, $default_buffered:expr, $doc:literal) => {
#[derive(Default, Copy, Clone, Debug)]
#[doc = $doc]
pub struct $mode<const INPUT_BUFFER: bool = $default_buffered>;
impl<const INPUT_BUFFER: bool> PinMode for $mode<INPUT_BUFFER> {
const DRIVE_MODE: DriveMode = DriveMode::$mode;
const INPUT_BUFFER: bool = INPUT_BUFFER;
const IO_SELECTOR: IoSelector = IoSelector::Gpio;
}
};
}
macro_rules! in_mode {
($mode:ident, $default_buffered:expr, $doc:literal) => {
mode!($mode, $default_buffered, $doc);
impl InputMode for $mode<true> {}
};
}
macro_rules! out_mode {
($mode:ident, $default_buffered:expr, $doc:literal) => {
mode!($mode, $default_buffered, $doc);
impl OutputMode for $mode<true> {}
impl OutputMode for $mode<false> {}
};
}
macro_rules! inout_mode {
($mode:ident, $default_buffered:expr, $doc:literal) => {
mode!($mode, $default_buffered, $doc);
impl InputMode for $mode<true> {}
impl OutputMode for $mode<true> {}
impl OutputMode for $mode<false> {}
};
}
in_mode!(HighZ, true, "A [high-impedance](DriveMode::HighZ) pin.");
inout_mode!(PullUp, true, "A [pull-up](DriveMode::PullUp) pin.");
inout_mode!(PullDown, true, "A [pull-down](DriveMode::PullUp) pin.");
inout_mode!(
OpenDrainDrivesLow,
true,
"An [open-drain high, strongly-driven low](DriveMode::OpenDrainDrivesLow) pin."
);
inout_mode!(
OpenDrainDrivesHigh,
true,
"An [open-drain low, strongly-driven high](DriveMode::OpenDrainDrivesHigh) pin."
);
out_mode!(Strong, false, "A [strongly-driven](DriveMode::Strong) pin.");
inout_mode!(
PullUpPullDown,
true,
"A [pull-up pull-down](DriveMode::PullUpPullDown) pin."
);
pub type Disabled = HighZ<false>;
pub mod debug {
use super::*;
cfg_select! {
mxs40ioss => {
hsiom!(SwclkTck, cpuss.swj_swclk_tclk, PullDown::<true>, "SWD/JTAG clock pin");
hsiom!(SwdioTms, cpuss.swj_swdio_tms, PullUp::<true>, "SWD/JTAG SWDIO/Tms pin");
hsiom!(Tdi, cpuss.swj_swdoe_tdi, PullUp::<true>, "JTAG Tdi pin");
hsiom!(SwoTdo, cpuss.swj_swo_tdo, Strong::<false>, "SWD/JTAG SWO/Tdo pin");
},
mxs40sioss => {
hsiom!(SwclkTck, debug600.clk_swj_swclk_tclk, PullDown::<true>, "SWD/JTAG clock pin");
hsiom!(SwdioTms, debug600.swj_swdio_tms, PullUp::<true>, "SWD/JTAG SWDIO/Tms pin");
hsiom!(Tdi, debug600.swj_swdoe_tdi, PullUp::<true>, "JTAG Tdi pin");
hsiom!(SwoTdo, debug600.swj_swo_tdo, Strong::<false>, "SWD/JTAG SWO/Tdo pin");
}
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(u32)]
pub enum DriveMode {
HighZ = 0,
Reserved = 1,
PullUp = 2,
PullDown = 3,
OpenDrainDrivesLow = 4,
OpenDrainDrivesHigh = 5,
Strong = 6,
PullUpPullDown = 7,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(u32)]
pub enum IoSelector {
Gpio = 0,
Act0 = 8,
Act1,
Act2,
Act3,
Ds0 = 12,
Ds1,
Ds2,
Ds3,
Act4 = 16,
Act5,
Act6,
Act7,
Act8,
Act9,
Act10,
Act11,
Act12,
Act13,
Act14,
Act15,
Ds4 = 28,
Ds5,
Ds6,
Ds7,
}
#[derive(Clone, Debug)]
pub struct PinConfig {
pub initial_output: PinState,
pub interrupt_edge: InterruptEdge,
pub interrupt_enabled: bool,
pub threshold: VtripMode,
pub slew_rate: SlewRate,
pub drive_strength: DriveStrength,
pub _ne: NonExhaustive,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(u32)]
pub enum InterruptEdge {
Disabled = 0,
Rising,
Falling,
RisingFalling,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(u32)]
pub enum VtripMode {
Cmos = 0,
Ttl = 1,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(u32)]
pub enum SlewRate {
Fast = 0,
Slow = 1,
}
#[cfg(mxs40ioss)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(u32)]
pub enum DriveStrength {
Full = 0,
Half = 1,
Quarter = 2,
Eighth = 3,
}
#[cfg(mxs40sioss)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(u32)]
pub enum DriveStrength {
_0 = 0,
_1,
_2,
_3,
}
#[cfg(mxs40sioss)]
#[allow(non_upper_case_globals)]
impl DriveStrength {
pub const Full: DriveStrength = DriveStrength::_0;
pub const Half: DriveStrength = DriveStrength::_2;
pub const Quarter: DriveStrength = DriveStrength::_3;
}
impl Default for PinConfig {
fn default() -> Self {
PinConfig::new()
}
}
impl PinConfig {
pub const fn new() -> Self {
Self {
initial_output: PinState::Low,
interrupt_edge: InterruptEdge::Disabled,
interrupt_enabled: false,
threshold: VtripMode::Cmos,
slew_rate: SlewRate::Fast,
drive_strength: DriveStrength::Full,
_ne: NonExhaustive,
}
}
#[must_use]
pub const fn initial_output(mut self, initial_output: PinState) -> Self {
self.initial_output = initial_output;
self
}
#[must_use]
pub const fn interrupt_edge(mut self, interrupt_edge: InterruptEdge) -> Self {
self.interrupt_edge = interrupt_edge;
self
}
#[must_use]
pub const fn interrupt_enabled(mut self, interrupt_enabled: bool) -> Self {
self.interrupt_enabled = interrupt_enabled;
self
}
#[must_use]
pub const fn threshold(mut self, threshold: VtripMode) -> Self {
self.threshold = threshold;
self
}
#[must_use]
pub const fn slew_rate(mut self, slew_rate: SlewRate) -> Self {
self.slew_rate = slew_rate;
self
}
#[must_use]
pub const fn drive_strength(mut self, drive_strength: DriveStrength) -> Self {
self.drive_strength = drive_strength;
self
}
}
impl<const PORT: u8, const PIN: u8, Mode: PinMode> Pin<PORT, PIN, Mode, security::Default> {
pub const unsafe fn steal(mode: Mode) -> Self {
const { assert!(PIN < 8) };
Pin {
mode,
security: security::DEFAULT,
}
}
}
impl<const PORT: u8, const PIN: u8, Mode: PinMode, Sec: Security> Pin<PORT, PIN, Mode, Sec> {
pub const fn with_security<New: Security>(self, security: New) -> Pin<PORT, PIN, Mode, New> {
Pin {
mode: self.mode,
security,
}
}
pub fn into_erased(self) -> AnyPin<'static> {
AnyPin {
port: PORT,
pin: PIN,
security: self.security.into(),
_p: PhantomData,
}
}
pub fn as_erased(&mut self) -> AnyPin<'_> {
unsafe { self.as_erased_ref() }
}
unsafe fn as_erased_ref(&self) -> AnyPin<'_> {
AnyPin {
port: PORT,
pin: PIN,
security: self.security.into(),
_p: PhantomData,
}
}
#[inline(always)]
pub fn port_regs(&self) -> regs::gpio::Prt {
unsafe { self.as_erased_ref().port_regs() }
}
pub fn port_no(&self) -> u8 {
PORT
}
pub fn pin_no(&self) -> u8 {
PIN
}
pub fn into_mode<M: PinMode>(self, mode: M) -> Pin<PORT, PIN, M, Sec> {
critical_section::with(|cs| self.into_mode_cs(mode, cs))
}
pub fn into_mode_cs<M: PinMode>(self, mode: M, cs: CriticalSection) -> Pin<PORT, PIN, M, Sec> {
let Pin {
mode: old,
security,
} = self;
self.into_erased().change_mode(old, mode, cs);
Pin { mode, security }
}
pub fn with_mode<M: PinMode, T>(
&mut self,
mode: M,
f: impl FnOnce(&mut Pin<PORT, PIN, M, Sec>) -> T,
) -> T {
let Pin {
mode: old,
security,
} = self;
let mut pin = Pin {
mode: *old,
security: *security,
}
.into_mode(mode);
let result = f(&mut pin);
pin.into_mode(*old);
result
}
pub fn drive_mode(&self) -> DriveMode {
unsafe { self.as_erased_ref().drive_mode() }
}
pub fn input_buffer_enabled(&self) -> bool {
unsafe { self.as_erased_ref().input_buffer_enabled() }
}
pub fn io_selector(&self) -> IoSelector {
unsafe { self.as_erased_ref().io_selector() }
}
pub fn threshold(&self) -> VtripMode {
unsafe { self.as_erased_ref().threshold() }
}
pub fn set_threshold(&mut self, threshold: VtripMode) {
self.as_erased().set_threshold(threshold);
}
pub fn set_threshold_cs(&mut self, threshold: VtripMode, cs: CriticalSection) {
self.as_erased().set_threshold_cs(threshold, cs);
}
pub fn slew_rate(&self) -> SlewRate {
unsafe { self.as_erased_ref().slew_rate() }
}
pub fn set_slew_rate(&mut self, slew_rate: SlewRate) {
self.as_erased().set_slew_rate(slew_rate);
}
pub fn set_slew_rate_cs(&mut self, slew_rate: SlewRate, cs: CriticalSection) {
self.as_erased().set_slew_rate_cs(slew_rate, cs);
}
pub fn drive_strength(&self) -> DriveStrength {
unsafe { self.as_erased_ref().drive_strength() }
}
pub fn set_drive_strength(&mut self, drive_strength: DriveStrength) {
self.as_erased().set_drive_strength(drive_strength);
}
pub fn set_drive_strength_cs(&mut self, drive_strength: DriveStrength, cs: CriticalSection) {
self.as_erased().set_drive_strength_cs(drive_strength, cs);
}
pub fn interrupt_enabled(&self) -> bool {
unsafe { self.as_erased_ref().interrupt_enabled() }
}
pub fn set_interrupt_enabled(&mut self, enabled: bool) {
self.as_erased().set_interrupt_enabled(enabled);
}
pub fn set_interrupt_enabled_cs(&mut self, enabled: bool, cs: CriticalSection) {
self.as_erased().set_interrupt_enabled_cs(enabled, cs);
}
pub fn interrupt_edge(&self) -> InterruptEdge {
unsafe { self.as_erased_ref().interrupt_edge() }
}
pub fn set_interrupt_edge(&mut self, interrupt_edge: InterruptEdge) {
self.as_erased().set_interrupt_edge(interrupt_edge);
}
pub fn set_interrupt_edge_cs(&mut self, interrupt_edge: InterruptEdge, cs: CriticalSection) {
self.as_erased().set_interrupt_edge_cs(interrupt_edge, cs);
}
#[cfg(trustzone)]
pub fn nonsecure_mask(&self) -> bool {
unsafe { self.as_erased_ref().nonsecure_mask() }
}
#[cfg(trustzone)]
pub fn set_nonsecure_mask(&mut self, nonsecure: bool) {
self.as_erased().set_nonsecure_mask(nonsecure);
}
#[cfg(trustzone)]
pub fn set_nonsecure_mask_cs(&mut self, nonsecure: bool, cs: CriticalSection) {
self.as_erased().set_nonsecure_mask_cs(nonsecure, cs);
}
pub fn interrupt_asserted(&self) -> bool {
unsafe { self.as_erased_ref().interrupt_asserted() }
}
pub fn clear_interrupt(&mut self) {
self.as_erased().clear_interrupt();
}
}
impl<const PIN: u8, const PORT: u8, Mode: OutputMode, Sec: Security> Pin<PIN, PORT, Mode, Sec> {
pub fn set_low(&mut self) {
self.as_erased().set_low();
}
pub fn set_high(&mut self) {
self.as_erased().set_high();
}
pub fn set_state(&mut self, state: PinState) {
self.as_erased().set_state(state);
}
pub fn is_set_high(&self) -> bool {
unsafe { self.as_erased_ref().is_set_high() }
}
pub fn is_set_low(&self) -> bool {
unsafe { self.as_erased_ref().is_set_low() }
}
pub fn toggle(&mut self) {
unsafe {
self.as_erased_ref().toggle();
}
}
}
impl<const PIN: u8, const PORT: u8, Mode: InputMode, Sec: Security> Pin<PIN, PORT, Mode, Sec> {
pub fn is_high(&self) -> bool {
unsafe { self.as_erased_ref().is_high() }
}
pub fn is_low(&self) -> bool {
unsafe { self.as_erased_ref().is_low() }
}
}
impl<const PIN: u8, const PORT: u8, Mode: PinMode, Sec: Security> embedded_hal::digital::ErrorType
for Pin<PIN, PORT, Mode, Sec>
{
type Error = Infallible;
}
impl<const PIN: u8, const PORT: u8, Mode: OutputMode, Sec: Security>
embedded_hal::digital::OutputPin for Pin<PIN, PORT, Mode, Sec>
{
fn set_low(&mut self) -> Result<(), Infallible> {
self.set_low();
Ok(())
}
fn set_high(&mut self) -> Result<(), Infallible> {
self.set_high();
Ok(())
}
}
impl<const PORT: u8, const PIN: u8, Mode: PinMode + Debug, Sec: Security> Debug
for Pin<PORT, PIN, Mode, Sec>
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("Pin")
.field("port", &PORT)
.field("pin", &PIN)
.field("mode", &self.mode)
.finish()
}
}
impl AnyPin<'_> {
pub const unsafe fn steal(port: u8, pin: u8) -> Self {
AnyPin {
port,
pin,
security: security::DEFAULT.as_security_attribute(),
_p: PhantomData,
}
}
pub fn port_no(&self) -> u8 {
self.port
}
pub fn pin_no(&self) -> u8 {
self.pin
}
#[inline(always)]
pub fn port_regs(&self) -> regs::gpio::Prt {
regs::GPIO.prt()[self.port as usize].with_security(self.security)
}
pub fn set_low(&mut self) {
unsafe {
self.port_regs().out_clr().write_raw(1 << self.pin);
}
}
pub fn set_high(&mut self) {
unsafe {
self.port_regs().out_set().write_raw(1 << self.pin);
}
}
pub fn set_state(&mut self, state: PinState) {
match state {
PinState::Low => self.set_low(),
PinState::High => self.set_high(),
}
}
pub fn is_set_high(&self) -> bool {
self.read().out() == PinState::High
}
pub fn is_set_low(&self) -> bool {
self.read().out() == PinState::Low
}
pub fn toggle(&mut self) {
unsafe {
self.port_regs().out_inv().write_raw(1 << self.pin);
}
}
pub fn is_high(&self) -> bool {
self.read().input() == PinState::High
}
pub fn is_low(&self) -> bool {
self.read().input() == PinState::Low
}
pub fn set_mode<Mode: PinMode>(&mut self, mode: Mode)
where
Self: 'static,
{
critical_section::with(|cs| self.set_mode_cs(mode, cs))
}
pub fn set_mode_cs<Mode: PinMode>(&mut self, _mode: Mode, cs: CriticalSection)
where
Self: 'static,
{
let mut pin = self.modify(cs);
pin.set_mode(Mode::DRIVE_MODE, Mode::INPUT_BUFFER);
pin.set_io_sel(Mode::IO_SELECTOR);
}
fn change_mode<Old: PinMode, New: PinMode>(
&mut self,
_old: Old,
_new: New,
cs: CriticalSection,
) {
let mut pin = self.modify(cs);
if (Old::DRIVE_MODE, Old::INPUT_BUFFER) != (New::DRIVE_MODE, New::INPUT_BUFFER) {
pin.set_mode(New::DRIVE_MODE, New::INPUT_BUFFER);
}
if Old::IO_SELECTOR != New::IO_SELECTOR {
pin.set_io_sel(New::IO_SELECTOR);
}
}
pub fn initialize<Mode: PinMode>(&mut self, mode: Mode, config: PinConfig)
where
Self: 'static,
{
critical_section::with(|cs| self.initialize_cs(mode, config, cs))
}
pub fn initialize_cs<Mode: PinMode>(
&mut self,
mode: Mode,
config: PinConfig,
cs: CriticalSection,
) where
Self: 'static,
{
let security = self.security;
self.modify(cs).initialize(mode, config, security);
}
pub fn drive_mode(&self) -> DriveMode {
self.read().mode().0
}
pub fn set_drive_mode(&mut self, drive_mode: DriveMode)
where
Self: 'static,
{
critical_section::with(|cs| self.set_drive_mode_cs(drive_mode, cs))
}
pub fn set_drive_mode_cs(&mut self, drive_mode: DriveMode, cs: CriticalSection)
where
Self: 'static,
{
self.modify(cs).set_drive_mode(drive_mode);
}
pub fn input_buffer_enabled(&self) -> bool {
self.read().mode().1
}
pub fn set_input_buffer(&mut self, enabled: bool)
where
Self: 'static,
{
critical_section::with(|cs| self.set_input_buffer_cs(enabled, cs))
}
pub fn set_input_buffer_cs(&mut self, enabled: bool, cs: CriticalSection)
where
Self: 'static,
{
self.modify(cs).set_input_buffer(enabled);
}
pub fn io_selector(&self) -> IoSelector {
self.read().io_sel()
}
pub fn set_io_selector(&mut self, io_sel: IoSelector)
where
Self: 'static,
{
critical_section::with(|cs| self.set_io_selector_cs(io_sel, cs))
}
pub fn set_io_selector_cs(&mut self, io_sel: IoSelector, cs: CriticalSection)
where
Self: 'static,
{
self.modify(cs).set_io_sel(io_sel);
}
pub fn threshold(&self) -> VtripMode {
self.read().threshold()
}
pub fn set_threshold(&mut self, threshold: VtripMode) {
critical_section::with(|cs| self.set_threshold_cs(threshold, cs));
}
pub fn set_threshold_cs(&mut self, threshold: VtripMode, cs: CriticalSection) {
self.modify(cs).set_threshold(threshold);
}
pub fn slew_rate(&self) -> SlewRate {
self.read().slew_rate()
}
pub fn set_slew_rate(&mut self, slew_rate: SlewRate) {
critical_section::with(|cs| self.set_slew_rate_cs(slew_rate, cs));
}
pub fn set_slew_rate_cs(&mut self, slew_rate: SlewRate, cs: CriticalSection) {
self.modify(cs).set_slew_rate(slew_rate);
}
pub fn drive_strength(&self) -> DriveStrength {
self.read().drive_strength()
}
pub fn set_drive_strength(&mut self, drive_strength: DriveStrength) {
critical_section::with(|cs| self.set_drive_strength_cs(drive_strength, cs));
}
pub fn set_drive_strength_cs(&mut self, drive_strength: DriveStrength, cs: CriticalSection) {
self.modify(cs).set_drive_strength(drive_strength);
}
pub fn interrupt_enabled(&self) -> bool {
self.read().interrupt_mask()
}
pub fn set_interrupt_enabled(&mut self, enabled: bool) {
critical_section::with(|cs| self.set_interrupt_enabled_cs(enabled, cs));
}
pub fn set_interrupt_enabled_cs(&mut self, enabled: bool, cs: CriticalSection) {
self.modify(cs).set_interrupt_mask(enabled);
}
pub fn interrupt_edge(&self) -> InterruptEdge {
self.read().interrupt_edge()
}
pub fn set_interrupt_edge(&mut self, interrupt_edge: InterruptEdge) {
critical_section::with(|cs| self.set_interrupt_edge_cs(interrupt_edge, cs));
}
pub fn set_interrupt_edge_cs(&mut self, interrupt_edge: InterruptEdge, cs: CriticalSection) {
self.modify(cs).set_interrupt_edge(interrupt_edge);
}
#[cfg(trustzone)]
pub fn nonsecure_mask(&self) -> bool {
self.read().nonsecure_mask()
}
#[cfg(trustzone)]
pub fn set_nonsecure_mask(&mut self, nonsecure: bool) {
critical_section::with(|cs| self.set_nonsecure_mask_cs(nonsecure, cs));
}
#[cfg(trustzone)]
pub fn set_nonsecure_mask_cs(&mut self, nonsecure: bool, cs: CriticalSection) {
self.modify(cs).set_nonsecure_mask(nonsecure);
}
pub fn interrupt_asserted(&self) -> bool {
unsafe {
regs::GPIO.prt()[self.port as usize].intr().read().get_raw() & (1 << self.pin) != 0
}
}
pub fn clear_interrupt(&mut self) {
unsafe {
self.port_regs().intr().write_raw(1 << self.pin);
}
}
fn read(&self) -> PinAccess<'_, PortRegAccess, Read> {
unsafe { PinAccess::steal_read(PortRegAccess(self.port, self.security), self.pin) }
}
fn modify(&mut self, _cs: CriticalSection<'_>) -> PinAccess<'_, PortRegAccess, Modify> {
unsafe { PinAccess::steal_modify(PortRegAccess(self.port, self.security), self.pin) }
}
}
impl<const PIN: u8, const PORT: u8, Mode: PinMode, Sec: Security> From<Pin<PIN, PORT, Mode, Sec>>
for AnyPin<'static>
{
fn from(pin: Pin<PIN, PORT, Mode, Sec>) -> Self {
pin.into_erased()
}
}
impl<'a, const PIN: u8, const PORT: u8, Mode: PinMode, Sec: Security>
From<&'a mut Pin<PIN, PORT, Mode, Sec>> for AnyPin<'a>
{
fn from(pin: &'a mut Pin<PIN, PORT, Mode, Sec>) -> Self {
pin.as_erased()
}
}
impl embedded_hal::digital::ErrorType for AnyPin<'_> {
type Error = Infallible;
}
impl embedded_hal::digital::OutputPin for AnyPin<'_> {
fn set_low(&mut self) -> Result<(), Infallible> {
unsafe {
self.port_regs().out_clr().write_raw(1 << self.pin);
}
Ok(())
}
fn set_high(&mut self) -> Result<(), Infallible> {
unsafe {
self.port_regs().out_set().write_raw(1 << self.pin);
}
Ok(())
}
}
impl embedded_hal::digital::StatefulOutputPin for AnyPin<'_> {
fn is_set_high(&mut self) -> Result<bool, Infallible> {
Ok(self.read().out() == PinState::High)
}
fn is_set_low(&mut self) -> Result<bool, Infallible> {
Ok(self.read().out() == PinState::Low)
}
fn toggle(&mut self) -> Result<(), Self::Error> {
unsafe {
self.port_regs().out_inv().write_raw(1 << self.pin);
}
Ok(())
}
}
impl embedded_hal::digital::InputPin for AnyPin<'_> {
fn is_high(&mut self) -> Result<bool, Self::Error> {
Ok(self.read().input() == PinState::High)
}
fn is_low(&mut self) -> Result<bool, Self::Error> {
Ok(self.read().input() == PinState::Low)
}
}
#[non_exhaustive]
#[derive(Debug)]
pub struct UnconfiguredPort<
const PORT: u8,
P0: UnconfiguredPinMode = (),
P1: UnconfiguredPinMode = (),
P2: UnconfiguredPinMode = (),
P3: UnconfiguredPinMode = (),
P4: UnconfiguredPinMode = (),
P5: UnconfiguredPinMode = (),
P6: UnconfiguredPinMode = (),
P7: UnconfiguredPinMode = (),
>(
pub (P0, PinConfig),
pub (P1, PinConfig),
pub (P2, PinConfig),
pub (P3, PinConfig),
pub (P4, PinConfig),
pub (P5, PinConfig),
pub (P6, PinConfig),
pub (P7, PinConfig),
);
pub trait UnconfiguredPinMode: Default {
type PinType<const PORT: u8, const PIN: u8>;
#[doc(hidden)]
unsafe fn initialize<const PORT: u8, const PIN: u8, A: PortAccess>(
self,
config: PinConfig,
pin: PinAccess<'_, A, Modify>,
) -> Self::PinType<PORT, PIN>;
}
impl<M: PinMode> UnconfiguredPinMode for M {
type PinType<const PORT: u8, const PIN: u8> = Pin<PORT, PIN, Self, security::Default>;
#[inline(always)]
unsafe fn initialize<const PORT: u8, const PIN: u8, A: PortAccess>(
self,
config: PinConfig,
mut pin: PinAccess<'_, A, Modify>,
) -> Self::PinType<PORT, PIN> {
pin.initialize(self, config, security::DEFAULT.into());
unsafe { Pin::steal(self) }
}
}
impl UnconfiguredPinMode for () {
type PinType<const PORT: u8, const PIN: u8> = ();
unsafe fn initialize<const PORT: u8, const PIN: u8, A: PortAccess>(
self,
_config: PinConfig,
_pin: PinAccess<'_, A, Modify>,
) -> Self::PinType<PORT, PIN> {
}
}
impl<
const PORT: u8,
P0: UnconfiguredPinMode,
P1: UnconfiguredPinMode,
P2: UnconfiguredPinMode,
P3: UnconfiguredPinMode,
P4: UnconfiguredPinMode,
P5: UnconfiguredPinMode,
P6: UnconfiguredPinMode,
P7: UnconfiguredPinMode,
> UnconfiguredPort<PORT, P0, P1, P2, P3, P4, P5, P6, P7>
{
pub unsafe fn steal() -> Self {
Self(
Default::default(),
Default::default(),
Default::default(),
Default::default(),
Default::default(),
Default::default(),
Default::default(),
Default::default(),
)
}
#[allow(clippy::type_complexity)]
#[inline(always)]
pub fn initialize(
self,
) -> (
P0::PinType<PORT, 0>,
P1::PinType<PORT, 1>,
P2::PinType<PORT, 2>,
P3::PinType<PORT, 3>,
P4::PinType<PORT, 4>,
P5::PinType<PORT, 5>,
P6::PinType<PORT, 6>,
P7::PinType<PORT, 7>,
) {
#[inline(always)]
fn initialize<const PORT: u8, const PIN: u8, P: UnconfiguredPinMode>(
config: (P, PinConfig),
port: impl PortAccess,
) -> P::PinType<PORT, PIN> {
unsafe {
config
.0
.initialize(config.1, PinAccess::steal_modify(port, PIN))
}
}
let mut port = InitPortAccess::new(PortRegAccess(PORT, security::DEFAULT.into()));
let result = (
initialize(self.0, &mut port),
initialize(self.1, &mut port),
initialize(self.2, &mut port),
initialize(self.3, &mut port),
initialize(self.4, &mut port),
initialize(self.5, &mut port),
initialize(self.6, &mut port),
initialize(self.7, &mut port),
);
port.finish();
result
}
#[must_use]
pub fn p0<Mode: PinMode>(
self,
mode: Mode,
config: PinConfig,
) -> UnconfiguredPort<PORT, Mode, P1, P2, P3, P4, P5, P6, P7> {
UnconfiguredPort(
(mode, config),
self.1,
self.2,
self.3,
self.4,
self.5,
self.6,
self.7,
)
}
#[must_use]
pub fn p1<Mode: PinMode>(
self,
mode: Mode,
config: PinConfig,
) -> UnconfiguredPort<PORT, P0, Mode, P2, P3, P4, P5, P6, P7> {
UnconfiguredPort(
self.0,
(mode, config),
self.2,
self.3,
self.4,
self.5,
self.6,
self.7,
)
}
#[must_use]
pub fn p2<Mode: PinMode>(
self,
mode: Mode,
config: PinConfig,
) -> UnconfiguredPort<PORT, P0, P1, Mode, P3, P4, P5, P6, P7> {
UnconfiguredPort(
self.0,
self.1,
(mode, config),
self.3,
self.4,
self.5,
self.6,
self.7,
)
}
#[must_use]
pub fn p3<Mode: PinMode>(
self,
mode: Mode,
config: PinConfig,
) -> UnconfiguredPort<PORT, P0, P1, P2, Mode, P4, P5, P6, P7> {
UnconfiguredPort(
self.0,
self.1,
self.2,
(mode, config),
self.4,
self.5,
self.6,
self.7,
)
}
#[must_use]
pub fn p4<Mode: PinMode>(
self,
mode: Mode,
config: PinConfig,
) -> UnconfiguredPort<PORT, P0, P1, P2, P3, Mode, P5, P6, P7> {
UnconfiguredPort(
self.0,
self.1,
self.2,
self.3,
(mode, config),
self.5,
self.6,
self.7,
)
}
#[must_use]
pub fn p5<Mode: PinMode>(
self,
mode: Mode,
config: PinConfig,
) -> UnconfiguredPort<PORT, P0, P1, P2, P3, P4, Mode, P6, P7> {
UnconfiguredPort(
self.0,
self.1,
self.2,
self.3,
self.4,
(mode, config),
self.6,
self.7,
)
}
#[must_use]
pub fn p6<Mode: PinMode>(
self,
mode: Mode,
config: PinConfig,
) -> UnconfiguredPort<PORT, P0, P1, P2, P3, P4, P5, Mode, P7> {
UnconfiguredPort(
self.0,
self.1,
self.2,
self.3,
self.4,
self.5,
(mode, config),
self.7,
)
}
#[must_use]
pub fn p7<Mode: PinMode>(
self,
mode: Mode,
config: PinConfig,
) -> UnconfiguredPort<PORT, P0, P1, P2, P3, P4, P5, P6, Mode> {
UnconfiguredPort(
self.0,
self.1,
self.2,
self.3,
self.4,
self.5,
self.6,
(mode, config),
)
}
}