use core::marker::PhantomData;
use cfg_if::cfg_if;
use paste::paste;
use crate::pac;
#[cfg(any(feature = "g473"))]
use crate::pac::comp::{C1CSR, C2CSR, C3CSR, C4CSR, C5CSR, C6CSR, C7CSR};
#[cfg(any(feature = "l4x6"))]
use crate::pac::comp::{COMP1_CSR, COMP2_CSR};
#[cfg(any(feature = "h747cm4", feature = "h747cm7"))]
use crate::pac::comp1::{CFGR1, CFGR2};
#[cfg(any(feature = "l4"))]
pub enum PowerMode {
HighSpeed = 0x00000000,
MediumSpeed = 0x00000004,
LowSpeed = 0x0000000c,
}
#[cfg(any(feature = "g473", feature = "h7"))]
#[derive(Clone, Copy)]
#[repr(u8)]
pub enum NonInvertingInput {
Io1 = 0b0,
Io2 = 0b1,
}
#[cfg(any(feature = "l4"))]
pub enum NonInvertingInput {
Io1 = 0x00000000,
Io2 = 0x00000080,
#[cfg(any(feature = "stm32l4x1", feature = "stm32l4x2", feature = "stm32l4x3",))]
Io3 = 0x00000100,
}
#[cfg(any(feature = "g473", feature = "h7", feature = "l4"))]
#[derive(Clone, Copy)]
#[repr(u8)]
pub enum InvertingInput {
OneQuarterVref = 0b000,
OneHalfVref = 0b001,
ThreeQuarterVref = 0b010,
Vref = 0b011,
Dac1 = 0b100,
Dac2 = 0b101,
Io1 = 0b110,
Io2 = 0b111,
}
#[cfg(any(feature = "g473"))]
#[derive(Clone, Copy)]
pub enum Hysterisis {
None = 0b000,
TenMilliVolt = 0b001,
TwentyMilliVolt = 0b010,
ThirtyMilliVolt = 0b011,
FourtyMilliVolt = 0b100,
FiftyMilliVolt = 0b101,
SixtyMilliVolt = 0b110,
SeventyMilliVolt = 0b111,
}
#[cfg(any(feature = "l4", feature = "h7"))]
pub enum Hysterisis {
NoHysterisis = 0b00,
LowHysteresis = 0b01,
MediumHysteresis = 0b10,
HighHysteresis = 0b11,
}
#[cfg(any(feature = "g473", feature = "h7"))]
#[derive(Clone, Copy)]
pub enum OutputPolarity {
NotInverted = 0b0,
Inverted = 0b1,
}
#[cfg(any(feature = "l4"))]
pub enum OutputPolarity {
NotInverted = 0x00000000,
Inverted = 0x00008000,
}
pub enum BlankingSource {
None = 0x00000000,
Timloc5 = 0x400000,
}
#[cfg(any(feature = "g473"))]
pub enum CompDevice {
One,
Two,
Three,
Four,
Five,
Six,
Seven,
}
#[cfg(any(feature = "g473"))]
#[derive(Clone, Copy)]
pub struct CompConfig {
pub inpsel: NonInvertingInput,
pub inmsel: InvertingInput,
pub hyst: Hysterisis,
pub polarity: OutputPolarity,
}
#[cfg(any(feature = "l4"))]
pub struct CompConfig {
pub pwrmode: PowerMode,
pub inpsel: NonInvertingInput,
pub inmsel: InvertingInput,
pub hyst: Hysterisis,
pub polarity: OutputPolarity,
}
pub struct Comp<T> {
phantom: PhantomData<T>,
is_locked: bool,
}
macro_rules! make_comp {
($csr_type:ident, $csr_reg:ident, $comp:ident) => {
impl Comp<$csr_type> {
paste! {
pub fn [<new_ $comp>]() -> Self {
unsafe {
Self {
phantom: PhantomData,
is_locked: false
}
}
}
}
pub fn csr(&self) -> &$csr_type {
#[cfg(any(feature = "g473", feature = "l4"))]
unsafe {
&(*pac::COMP::ptr()).$csr_reg
}
#[cfg(any(feature = "h747cm4", feature = "h747cm7"))]
unsafe {
&(*pac::COMP1::ptr()).$csr_reg
}
}
pub fn enable(&self) {
self.csr().modify(|_, w| w.en().bit(true));
}
pub fn disable(&self) {
self.csr().modify(|_, w| w.en().clear_bit());
}
pub fn set_inverting_input(&self, input: InvertingInput) {
cfg_if! {
if #[cfg(feature = "l4")] {
unsafe { self.csr().modify(|_,w| w.inmsel().bits(input as u8)) };
} else {
self.csr().modify(|_,w| w.inmsel().variant(input as u8));
}
}
}
pub fn set_non_inverting_input(&self, input: NonInvertingInput) {
cfg_if! {
if #[cfg(feature = "l4")] {
self.csr().modify(|_,w| w.inpsel().bit(input as u8 != 0));
} else {
self.csr().modify(|_,w| w.inpsel().variant(input as u8 != 0));
}
}
}
pub fn set_polarity(&self, polarity: OutputPolarity) {
cfg_if! {
if #[cfg(feature = "l4")] {
self.csr().modify(|_,w| w.polarity().bit((polarity as u8) != 0));
} else {
#[cfg(feature = "g4")]
self.csr().modify(|_,w| w.pol().variant((polarity as u8) != 0));
#[cfg(feature = "h7")]
self.csr().modify(|_,w| w.polarity().variant((polarity as u8) != 0));
}
}
}
pub fn set_hysterisis(&self, hyst: Hysterisis) {
cfg_if! {
if #[cfg(feature = "l4")] {
self.csr().modify(|_,w| w.hyst().bits((hyst as u8)));
} else {
self.csr().modify(|_,w| w.hyst().variant((hyst as u8)));
}
}
}
pub fn set_blanking_source(&self, source: u8) {
#[cfg(feature = "g473")]
self.csr().modify(|_, w| w.blanksel().variant(source));
#[cfg(feature = "h7")]
self.csr().modify(|_, w| w.blanking().variant(source));
}
pub fn lock(&mut self) {
self.is_locked = true;
self.csr().modify(|_, w| w.lock().bit(true));
}
pub fn get_output_level(&self) -> bool {
cfg_if! {
if #[cfg(any(feature = "g4", feature = "l4"))] {
self.csr().read().value().bit()
}
else if #[cfg(feature = "h7")] {
let status = unsafe { &(*pac::COMP1::ptr()).sr().read() };
match "$csr_reg" {
"c1csr" => {
status.c1val().bit_is_set()
}
"c2csr" => {
status.c2val().bit_is_set()
}
_ => todo!(),
}
}
}
}
}
};
}
cfg_if! {
if #[cfg(any(feature = "g4"))] {
make_comp!(C1CSR, c1csr, comp1);
make_comp!(C2CSR, c2csr, comp2);
make_comp!(C3CSR, c3csr, comp3);
make_comp!(C4CSR, c4csr, comp4);
make_comp!(C5CSR, c5csr, comp5);
make_comp!(C6CSR, c6csr, comp6);
make_comp!(C7CSR, c7csr, comp7);
} else if #[cfg(any(feature = "l4x6"))] {
make_comp!(COMP1_CSR, comp1_csr, comp1);
make_comp!(COMP2_CSR, comp2_csr, comp2);
} else if #[cfg(any(feature = "h747cm4", feature = "h747cm7"))] {
make_comp!(CFGR1, cfgr1, comp1);
make_comp!(CFGR2, cfgr2, comp2);
}
}