use crate::{digital::PinMode, hw::mcu::kinetis::peripheral::port};
pub trait PinOp {
type Arg;
type Result;
fn op<M, const N: usize, const P: usize>(
pin: port::Pin<'_, M, N, P>,
arg: Self::Arg,
) -> Self::Result;
#[inline(always)]
fn do_op<M, const N: usize, const P: usize>(
pin: Option<port::Pin<'_, M, N, P>>,
arg: Self::Arg,
) -> Option<Self::Result> {
if let Some(pin) = pin {
Some(Self::op(pin, arg))
} else {
None
}
}
}
pub struct WriteOp;
impl PinOp for WriteOp {
type Arg = bool;
type Result = ();
#[inline(always)]
fn op<M, const N: usize, const P: usize>(pin: port::Pin<'_, M, N, P>, value: bool) {
pin.into_gpio().write(value);
}
}
pub struct ReadOp;
impl PinOp for ReadOp {
type Arg = ();
type Result = bool;
#[inline(always)]
fn op<M, const N: usize, const P: usize>(pin: port::Pin<'_, M, N, P>, _: ()) -> bool {
pin.into_gpio().read()
}
}
pub struct ModeOp;
impl PinOp for ModeOp {
type Arg = PinMode;
type Result = ();
#[inline(always)]
fn op<M, const N: usize, const P: usize>(pin: port::Pin<'_, M, N, P>, mode: PinMode) {
let mut pin = pin.into_gpio();
match mode {
PinMode::Input => {
pin.set_pull(None);
pin.set_output(false);
}
PinMode::PulledInput(pull) => {
pin.set_pull(Some(pull));
pin.set_output(false);
}
PinMode::Output => {
pin.set_open_drain(false);
pin.set_output(true);
pin.set_pull(None);
}
PinMode::OpenDrainOutput => {
pin.set_open_drain(true);
pin.set_output(true);
pin.set_pull(None);
}
}
}
}