#[cfg(any(feature = "samd11", feature = "samd21"))]
use crate::pac::port::{
CTRL, DIR, DIRCLR, DIRSET, DIRTGL, IN, OUT, OUTCLR, OUTSET, OUTTGL, PINCFG0_ as PINCFG,
PMUX0_ as PMUX, WRCONFIG,
};
#[cfg(feature = "min-samd51g")]
use crate::pac::port::group::{
CTRL, DIR, DIRCLR, DIRSET, DIRTGL, IN, OUT, OUTCLR, OUTSET, OUTTGL, PINCFG, PMUX, WRCONFIG,
};
use crate::pac::PORT;
use super::dynpin::*;
#[derive(Default)]
struct ModeFields {
dir: bool,
inen: bool,
pullen: bool,
out: bool,
pmuxen: bool,
pmux: u8,
}
impl From<DynPinMode> for ModeFields {
#[inline]
fn from(mode: DynPinMode) -> Self {
let mut fields = Self::default();
use DynPinMode::*;
match mode {
Disabled(config) => {
use DynDisabled::*;
match config {
Floating => {
fields.pullen = false;
fields.out = false;
}
PullDown => {
fields.pullen = true;
fields.out = false;
}
PullUp => {
fields.pullen = true;
fields.out = true;
}
}
}
Input(config) => {
fields.inen = true;
use DynInput::*;
match config {
Floating => {
fields.pullen = false;
fields.out = false;
}
PullDown => {
fields.pullen = true;
fields.out = false;
}
PullUp => {
fields.pullen = true;
fields.out = true;
}
}
}
Interrupt(config) => {
fields.pmuxen = true;
fields.pmux = 0;
use DynInterrupt::*;
match config {
Floating => {
fields.pullen = false;
fields.out = false;
}
PullDown => {
fields.pullen = true;
fields.out = false;
}
PullUp => {
fields.pullen = true;
fields.out = true;
}
}
}
Output(config) => {
fields.dir = true;
use DynOutput::*;
match config {
PushPull => {
fields.inen = false;
}
Readable => {
fields.inen = true;
}
}
}
Alternate(config) => {
fields.pmuxen = true;
use DynAlternate::*;
match config {
B => {
fields.pmux = 1;
}
C => {
fields.pmux = 2;
}
D => {
fields.pmux = 3;
}
E => {
fields.pmux = 4;
}
F => {
fields.pmux = 5;
}
G => {
fields.pmux = 6;
}
#[cfg(any(feature = "samd21", feature = "min-samd51g"))]
H => {
fields.pmux = 7;
}
#[cfg(feature = "min-samd51g")]
I => {
fields.pmux = 8;
}
#[cfg(feature = "min-samd51g")]
J => {
fields.pmux = 9;
}
#[cfg(feature = "min-samd51g")]
K => {
fields.pmux = 10;
}
#[cfg(feature = "min-samd51g")]
L => {
fields.pmux = 11;
}
#[cfg(feature = "min-samd51g")]
M => {
fields.pmux = 12;
}
#[cfg(feature = "min-samd51g")]
N => {
fields.pmux = 13;
}
}
}
};
fields
}
}
#[repr(C)]
#[allow(clippy::upper_case_acronyms)]
pub(super) struct GROUP {
dir: DIR,
dirclr: DIRCLR,
dirset: DIRSET,
dirtgl: DIRTGL,
out: OUT,
outclr: OUTCLR,
outset: OUTSET,
outtgl: OUTTGL,
in_: IN,
ctrl: CTRL,
wrconfig: WRCONFIG,
_padding1: [u8; 4],
pmux: [PMUX; 16],
pincfg: [PINCFG; 32],
_padding2: [u8; 32],
}
pub(super) unsafe trait RegisterInterface {
fn id(&self) -> DynPinId;
const GROUPS: *const GROUP = PORT::ptr() as *const _;
#[inline]
fn group(&self) -> &GROUP {
let offset = match self.id().group {
DynGroup::A => 0,
#[cfg(any(feature = "samd21", feature = "min-samd51g"))]
DynGroup::B => 1,
#[cfg(feature = "min-samd51n")]
DynGroup::C => 2,
#[cfg(feature = "min-samd51p")]
DynGroup::D => 3,
};
unsafe { &*Self::GROUPS.add(offset) }
}
#[inline]
fn mask_32(&self) -> u32 {
1 << self.id().num
}
#[inline]
fn mask_16(&self) -> u16 {
1 << (self.id().num & 0xF)
}
#[inline]
fn hwsel(&self) -> bool {
self.id().num & 0x10 != 0
}
#[inline]
fn pincfg(&self) -> &PINCFG {
&self.group().pincfg[self.id().num as usize]
}
#[inline]
fn change_mode(&mut self, mode: DynPinMode) {
let ModeFields {
dir,
inen,
pullen,
out,
pmuxen,
pmux,
} = mode.into();
self.group().wrconfig.write(|w| unsafe {
w.hwsel().bit(self.hwsel());
w.wrpincfg().set_bit();
w.wrpmux().set_bit();
w.pmux().bits(pmux);
w.pullen().bit(pullen);
w.inen().bit(inen);
w.pmuxen().bit(pmuxen);
w.pinmask().bits(self.mask_16())
});
self.set_dir(dir);
if pullen {
self.write_pin(out)
};
}
#[inline]
fn set_dir(&mut self, bit: bool) {
let mask = self.mask_32();
unsafe {
if bit {
self.group().dirset.write(|w| w.bits(mask));
} else {
self.group().dirclr.write(|w| w.bits(mask));
}
}
}
#[inline]
#[allow(dead_code)]
fn read_pin(&self) -> bool {
let mask = self.mask_32();
self.group().in_.read().bits() & mask != 0
}
#[inline]
fn write_pin(&mut self, bit: bool) {
let mask = self.mask_32();
unsafe {
if bit {
self.group().outset.write(|w| w.bits(mask));
} else {
self.group().outclr.write(|w| w.bits(mask));
}
}
}
#[inline]
fn toggle_pin(&mut self) {
let mask = self.mask_32();
unsafe { self.group().outtgl.write(|w| w.bits(mask)) };
}
#[inline]
#[allow(dead_code)]
fn read_out_pin(&self) -> bool {
let mask = self.mask_32();
self.group().out.read().bits() & mask != 0
}
#[inline]
fn read_drive_strength(&self) -> bool {
self.pincfg().read().drvstr().bit()
}
#[inline]
fn write_drive_strength(&mut self, bit: bool) {
self.pincfg().modify(|_, w| w.drvstr().bit(bit));
}
}