use crate::{
pac::{self, RCC},
traits::SingleChannelDac,
};
use cfg_if::cfg_if;
#[derive(Clone, Copy)]
pub enum Channel {
One,
Two,
}
#[derive(Clone, Copy)]
pub enum Bits {
EightR,
TwelveL,
TwelveR,
}
#[derive(Clone, Copy)]
pub enum Trigger {
Tim6,
Tim3_8,
Tim7,
Tim15,
Tim2,
Tim4,
Exti9,
Swtrig,
}
impl Trigger {
pub fn bits(&self) -> u8 {
match self {
Self::Tim6 => 0b000,
Self::Tim3_8 => 0b001,
Self::Tim7 => 0b010,
Self::Tim15 => 0b011,
Self::Tim2 => 0b100,
Self::Tim4 => 0b101,
Self::Exti9 => 0b110,
Self::Swtrig => 0b111,
}
}
}
macro_rules! hal {
($DAC:ident, $cr:ident, $d81:ident, $d12l1:ident, $d12r1:ident, $d82:ident, $d12l2:ident, $d12r2:ident) => {
pub struct Dac {
regs: pac::$DAC,
channel: Channel,
bits: Bits,
vref: f32,
}
impl Dac {
pub fn new(
regs: pac::$DAC,
channel: Channel,
bits: Bits,
vref: f32,
) -> Self {
Self {
regs,
channel,
bits,
vref,
}
}
pub fn enable(&mut self, rcc: &mut RCC) {
cfg_if! {
if #[cfg(feature = "f3")] {
rcc.apb1enr.modify(|_, w| w.dac1en().set_bit());
} else if #[cfg(any(feature = "l4", feature = "l5"))] {
rcc.apb1enr1.modify(|_, w| w.dac1en().set_bit());
} else if #[cfg(feature = "h7")] {
rcc.apb1lenr.modify(|_, w| w.dac12en().set_bit());
}
}
match self.channel {
Channel::One => self.regs.$cr.modify(|_, w| w.en1().set_bit()),
Channel::Two => self.regs.$cr.modify(|_, w| w.en2().set_bit()),
}
}
pub fn disable(&mut self, rcc: &mut RCC) {
cfg_if! {
if #[cfg(feature = "f3")] {
rcc.apb1enr.modify(|_, w| w.dac1en().clear_bit());
} else if #[cfg(any(feature = "l4", feature = "l5"))] {
rcc.apb1enr1.modify(|_, w| w.dac1en().clear_bit());
} else if #[cfg(feature = "h7")] {
rcc.apb1lenr.modify(|_, w| w.dac12en().clear_bit());
}
}
match self.channel {
Channel::One => self.regs.$cr.modify(|_, w| w.en1().clear_bit()),
Channel::Two => self.regs.$cr.modify(|_, w| w.en2().clear_bit()),
}
}
pub fn set_value(&mut self, val: u32) {
match self.channel {
Channel::One => match self.bits {
Bits::EightR => self.regs.$d81.modify(|_, w| unsafe { w.bits(val) }),
Bits::TwelveL => self.regs.$d12l1.modify(|_, w| unsafe { w.bits(val) }),
Bits::TwelveR => self.regs.$d12r1.modify(|_, w| unsafe { w.bits(val) }),
},
Channel::Two => match self.bits {
Bits::EightR => self.regs.$d82.modify(|_, w| unsafe { w.bits(val) }),
Bits::TwelveL => self.regs.$d12l2.modify(|_, w| unsafe { w.bits(val) }),
Bits::TwelveR => self.regs.$d12r2.modify(|_, w| unsafe { w.bits(val) }),
},
}
}
pub fn set_voltage(&mut self, volts: f32) {
let val = match self.bits {
Bits::EightR => ((volts / self.vref) * 255.) as u32,
Bits::TwelveL => ((volts / self.vref) * 4_095.) as u32,
Bits::TwelveR => ((volts / self.vref) * 4_095.) as u32,
};
self.set_value(val);
}
#[cfg(not(feature = "l5"))]
pub fn set_trigger(&mut self, trigger: Trigger) {
match self.channel {
Channel::One => {
self.regs.$cr.modify(|_, w| w.ten1().set_bit());
self.regs
.$cr
.modify(|_, w| unsafe { w.tsel1().bits(trigger.bits()) });
}
Channel::Two => {
self.regs.$cr.modify(|_, w| w.ten2().set_bit());
self.regs
.$cr
.modify(|_, w| unsafe { w.tsel2().bits(trigger.bits()) });
}
}
}
#[cfg(not(feature = "l5"))]
pub fn trigger_lfsr(&mut self, trigger: Trigger, data: u32) {
match self.channel {
Channel::One => {
self.regs.$cr.modify(|_, w| unsafe { w.wave1().bits(0b01) });
self.regs.$cr.modify(|_, w| unsafe { w.mamp1().bits(0b01) });
}
Channel::Two => {
self.regs.$cr.modify(|_, w| unsafe { w.wave2().bits(0b01) });
self.regs.$cr.modify(|_, w| unsafe { w.mamp2().bits(0b01) });
}
}
self.set_trigger(trigger);
self.set_value(data);
}
#[cfg(not(feature = "l5"))]
pub fn trigger_triangle(&mut self, trigger: Trigger, data: u32) {
match self.channel {
Channel::One => {
self.regs.$cr.modify(|_, w| unsafe { w.wave1().bits(0b10) });
self.regs.$cr.modify(|_, w| unsafe { w.mamp1().bits(0b10) });
}
Channel::Two => {
self.regs.$cr.modify(|_, w| unsafe { w.wave2().bits(0b10) });
self.regs.$cr.modify(|_, w| unsafe { w.mamp2().bits(0b10) });
}
}
self.set_trigger(trigger);
self.set_value(data);
}
}
pub struct DacError {}
impl SingleChannelDac<u32> for Dac {
type Error = DacError;
fn try_set_value(&mut self, val: u32) -> Result<(), DacError> {
self.set_value(val);
Ok(())
}
}
};
}
#[cfg(feature = "l5")]
hal!(
DAC,
dac_cr,
dac_dhr8r2,
dac_dhr12l2,
dac_dhr12r2,
dac_dhr8r2,
dac_dhr12l2,
dac_dhr12r2
);
#[cfg(feature = "l4")]
hal!(DAC1, cr, dhr8r1, dhr12l1, dhr12r1, dhr8r2, dhr12l2, dhr12r2);
#[cfg(all(feature = "f3", not(feature = "f302")))]
hal!(DAC1, cr, dhr8r1, dhr12l1, dhr12r1, dhr8r2, dhr12l2, dhr12r2);
#[cfg(feature = "f302")]
hal!(DAC, cr, dhr8r1, dhr12l1, dhr12r1, dhr8r2, dhr12l2, dhr12r2);
#[cfg(feature = "h7")]
hal!(DAC, cr, dhr8r1, dhr12l1, dhr12r1, dhr8r2, dhr12l2, dhr12r2);