use crate::gpio::{p0::*, Floating, Input};
#[cfg(not(feature = "5340-app"))]
use crate::pac::comp::{
extrefsel::EXTREFSEL_A, psel::PSEL_A, EVENTS_CROSS, EVENTS_DOWN, EVENTS_UP,
};
use crate::pac::COMP;
#[cfg(feature = "5340-app")]
use crate::pac::comp_ns::{
extrefsel::EXTREFSEL_A, psel::PSEL_A, EVENTS_CROSS, EVENTS_DOWN, EVENTS_UP,
};
pub struct Comp {
comp: COMP,
}
impl Comp {
pub fn new<P: CompInputPin>(comp: COMP, input_pin: &P) -> Self {
comp.psel.write(|w| w.psel().variant(input_pin.ain()));
comp.mode.write(|w| w.sp().normal());
comp.mode.write(|w| w.main().se());
comp.refsel.write(|w| w.refsel().int1v2());
Self { comp }
}
#[inline(always)]
pub fn power_mode(&self, mode: PowerMode) -> &Self {
match mode {
PowerMode::LowPower => self.comp.mode.write(|w| w.sp().low()),
PowerMode::Normal => self.comp.mode.write(|w| w.sp().normal()),
PowerMode::HighSpeed => self.comp.mode.write(|w| w.sp().high()),
}
self
}
#[inline(always)]
pub fn vref(&self, vref: VRef) -> &Self {
self.comp.refsel.write(|w| match vref {
VRef::Int1V2 => w.refsel().int1v2(),
VRef::Int1V8 => w.refsel().int1v8(),
VRef::Int2V4 => w.refsel().int2v4(),
VRef::Vdd => w.refsel().vdd(),
VRef::ARef(r) => {
self.comp.extrefsel.write(|w| w.extrefsel().variant(r));
w.refsel().aref()
}
});
self
}
#[inline(always)]
pub fn aref_pin<P: CompRefPin>(&self, ref_pin: &P) -> &Self {
self.comp
.extrefsel
.write(|w| w.extrefsel().variant(ref_pin.aref()));
self
}
#[inline(always)]
pub fn differential<P: CompRefPin>(&self, ref_pin: &P) -> &Self {
self.comp.mode.write(|w| w.main().diff());
self.aref_pin(ref_pin);
self
}
#[inline(always)]
pub fn hysteresis_threshold_up(&self, value: u8) -> &Self {
self.comp
.th
.write(|w| unsafe { w.thup().bits(value.min(63)) });
self
}
#[inline(always)]
pub fn hysteresis_threshold_down(&self, value: u8) -> &Self {
self.comp
.th
.write(|w| unsafe { w.thdown().bits(value.min(63)) });
self
}
#[inline(always)]
pub fn hysteresis(&self, enabled: bool) -> &Self {
self.comp.hyst.write(|w| match enabled {
true => w.hyst().hyst50m_v(),
false => w.hyst().no_hyst(),
});
self
}
#[inline(always)]
pub fn enable_interrupt(&self, event: Transition) -> &Self {
self.comp.intenset.modify(|_r, w| match event {
Transition::Cross => w.cross().set_bit(),
Transition::Down => w.down().set_bit(),
Transition::Up => w.up().set_bit(),
});
self
}
#[inline(always)]
pub fn disable_interrupt(&self, event: Transition) -> &Self {
self.comp.intenclr.modify(|_r, w| match event {
Transition::Cross => w.cross().set_bit(),
Transition::Down => w.down().set_bit(),
Transition::Up => w.up().set_bit(),
});
self
}
#[inline(always)]
pub fn enable(&self) {
self.comp.enable.write(|w| w.enable().enabled());
self.comp.tasks_start.write(|w| unsafe { w.bits(1) });
while self.comp.events_ready.read().bits() == 0 {}
}
#[inline(always)]
pub fn disable(&self) {
self.comp.tasks_stop.write(|w| unsafe { w.bits(1) });
self.comp.enable.write(|w| w.enable().disabled());
}
#[inline(always)]
pub fn is_up(&self) -> bool {
self.comp.events_up.read().bits() != 0
}
#[inline(always)]
pub fn is_down(&self) -> bool {
self.comp.events_down.read().bits() != 0
}
#[inline(always)]
pub fn is_cross(&self) -> bool {
self.comp.events_cross.read().bits() != 0
}
#[inline(always)]
pub fn event_up(&self) -> &EVENTS_UP {
&self.comp.events_up
}
#[inline(always)]
pub fn event_down(&self) -> &EVENTS_DOWN {
&self.comp.events_down
}
#[inline(always)]
pub fn event_cross(&self) -> &EVENTS_CROSS {
&self.comp.events_cross
}
#[inline(always)]
pub fn reset_event(&self, event: Transition) {
match event {
Transition::Cross => self.comp.events_cross.write(|w| w),
Transition::Down => self.comp.events_down.write(|w| w),
Transition::Up => self.comp.events_up.write(|w| w),
}
}
#[inline(always)]
pub fn reset_events(&self) {
self.comp.events_cross.write(|w| w);
self.comp.events_down.write(|w| w);
self.comp.events_up.write(|w| w);
}
#[inline(always)]
pub fn read(&self) -> CompResult {
self.comp.tasks_sample.write(|w| unsafe { w.bits(1) });
match self.comp.result.read().result().is_above() {
true => CompResult::Above,
false => CompResult::Below,
}
}
#[inline(always)]
pub fn free(self) -> COMP {
self.comp
}
}
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
pub enum OperationMode {
Differential,
SingleEnded,
}
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
pub enum PowerMode {
LowPower,
Normal,
HighSpeed,
}
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
pub enum CompResult {
Above,
Below,
}
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
pub enum Transition {
Up,
Down,
Cross,
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum VRef {
Int1V2,
Int1V8,
Int2V4,
Vdd,
ARef(EXTREFSEL_A),
}
impl VRef {
pub fn from_pin<P: CompRefPin>(pin: &P) -> Self {
VRef::ARef(pin.aref())
}
}
pub trait CompInputPin {
fn ain(&self) -> PSEL_A;
}
pub trait CompRefPin {
fn aref(&self) -> EXTREFSEL_A;
}
macro_rules! comp_input_pins {
($($pin:path => $ain:expr,)+) => {
$(
impl CompInputPin for $pin {
fn ain(&self) -> PSEL_A {
$ain
}
}
)*
};
}
macro_rules! comp_ref_pins {
($($pin:path => $aref:expr,)+) => {
$(
impl CompRefPin for $pin {
fn aref(&self) -> EXTREFSEL_A {
$aref
}
}
)*
};
}
comp_ref_pins! {
P0_02<Input<Floating>> => EXTREFSEL_A::ANALOG_REFERENCE0,
P0_03<Input<Floating>> => EXTREFSEL_A::ANALOG_REFERENCE1,
P0_04<Input<Floating>> => EXTREFSEL_A::ANALOG_REFERENCE2,
P0_05<Input<Floating>> => EXTREFSEL_A::ANALOG_REFERENCE3,
P0_28<Input<Floating>> => EXTREFSEL_A::ANALOG_REFERENCE4,
P0_29<Input<Floating>> => EXTREFSEL_A::ANALOG_REFERENCE5,
P0_30<Input<Floating>> => EXTREFSEL_A::ANALOG_REFERENCE6,
P0_31<Input<Floating>> => EXTREFSEL_A::ANALOG_REFERENCE7,
}
#[cfg(not(any(feature = "52811", feature = "52810")))]
comp_input_pins! {
P0_02<Input<Floating>> => PSEL_A::ANALOG_INPUT0,
P0_03<Input<Floating>> => PSEL_A::ANALOG_INPUT1,
P0_04<Input<Floating>> => PSEL_A::ANALOG_INPUT2,
P0_05<Input<Floating>> => PSEL_A::ANALOG_INPUT3,
P0_28<Input<Floating>> => PSEL_A::ANALOG_INPUT4,
P0_29<Input<Floating>> => PSEL_A::ANALOG_INPUT5,
P0_30<Input<Floating>> => PSEL_A::ANALOG_INPUT6,
P0_31<Input<Floating>> => PSEL_A::ANALOG_INPUT7,
}
#[cfg(any(feature = "52811", feature = "52810"))]
comp_input_pins! {
P0_02<Input<Floating>> => PSEL_A::ANALOG_INPUT0,
P0_03<Input<Floating>> => PSEL_A::ANALOG_INPUT1,
P0_04<Input<Floating>> => PSEL_A::ANALOG_INPUT2,
P0_05<Input<Floating>> => PSEL_A::ANALOG_INPUT3,
P0_28<Input<Floating>> => PSEL_A::ANALOG_INPUT4,
P0_29<Input<Floating>> => PSEL_A::ANALOG_INPUT5,
P0_30<Input<Floating>> => PSEL_A::ANALOG_INPUT6,
}