1use core::ops::Deref;
7
8use vorago_shared_hal::{
9 disable_peripheral_clock, enable_peripheral_clock, reset_peripheral_for_cycles,
10 PeripheralSelect,
11};
12
13use crate::{clock::Clocks, pac};
14
15pub type DacRegisterBlock = pac::dac0::RegisterBlock;
16
17pub trait DacInstance: Deref<Target = DacRegisterBlock> {
20 const IDX: u8;
21
22 fn ptr() -> *const DacRegisterBlock;
23}
24
25impl DacInstance for pac::Dac0 {
26 const IDX: u8 = 0;
27
28 #[inline(always)]
29 fn ptr() -> *const DacRegisterBlock {
30 Self::ptr()
31 }
32}
33
34impl DacInstance for pac::Dac1 {
35 const IDX: u8 = 1;
36
37 #[inline(always)]
38 fn ptr() -> *const DacRegisterBlock {
39 Self::ptr()
40 }
41}
42
43#[derive(Debug, PartialEq, Eq, Copy, Clone)]
44#[cfg_attr(feature = "defmt", derive(defmt::Format))]
45pub enum DacSettling {
46 NoSettling = 0,
47 Apb2Times25 = 1,
48 Apb2Times50 = 2,
49 Apb2Times75 = 3,
50 Apb2Times100 = 4,
51 Apb2Times125 = 5,
52 Apb2Times150 = 6,
53}
54
55pub struct Dac(*const DacRegisterBlock);
56
57#[derive(Debug, PartialEq, Eq, Copy, Clone)]
58#[cfg_attr(feature = "defmt", derive(defmt::Format))]
59pub struct ValueTooLarge;
60
61impl Dac {
62 pub fn new<Dac: DacInstance>(dac: Dac, dac_settling: DacSettling, _clocks: &Clocks) -> Self {
66 enable_peripheral_clock(PeripheralSelect::Dac);
67
68 dac.ctrl1().write(|w| {
69 w.dac_en().set_bit();
70 unsafe { w.dac_settling().bits(dac_settling as u8) }
72 });
73 let mut dac = Self(Dac::ptr());
74 dac.clear_fifo();
75 dac.clear_irqs();
76 dac
77 }
78
79 pub const fn regs(&self) -> &DacRegisterBlock {
80 unsafe { &*self.0 }
81 }
82
83 #[inline(always)]
84 pub fn clear_irqs(&mut self) {
85 self.regs().irq_clr().write(|w| {
86 w.fifo_oflow().set_bit();
87 w.fifo_uflow().set_bit();
88 w.dac_done().set_bit();
89 w.trig_error().set_bit()
90 });
91 }
92
93 #[inline(always)]
94 pub fn clear_fifo(&mut self) {
95 self.regs().fifo_clr().write(|w| unsafe { w.bits(1) });
96 }
97
98 #[inline(always)]
102 pub fn load_value(&mut self, val: u16) -> nb::Result<(), ValueTooLarge> {
103 if val > 2_u16.pow(12) - 1 {
104 return Err(nb::Error::Other(ValueTooLarge));
105 }
106 let regs = self.regs();
107 if regs.status().read().fifo_entry_cnt().bits() >= 32_u8 {
108 return Err(nb::Error::WouldBlock);
109 }
110 regs.fifo_data().write(|w| unsafe { w.bits(val.into()) });
111 Ok(())
112 }
113
114 #[inline(always)]
117 pub fn load_and_trigger_manually(&mut self, val: u16) -> Result<(), ValueTooLarge> {
118 if val > 2_u16.pow(12) - 1 {
119 return Err(ValueTooLarge);
120 }
121 self.clear_fifo();
122 nb::block!(self.load_value(val)).unwrap();
125 self.trigger_manually();
126 Ok(())
127 }
128
129 #[inline(always)]
132 pub fn trigger_manually(&self) {
133 self.regs().ctrl0().write(|w| w.man_trig_en().set_bit());
134 }
135
136 #[inline(always)]
137 pub fn enable_external_trigger(&self) {
138 self.regs().ctrl0().write(|w| w.ext_trig_en().set_bit());
139 }
140
141 pub fn is_settled(&self) -> nb::Result<(), ()> {
142 if self.regs().status().read().dac_busy().bit_is_set() {
143 return Err(nb::Error::WouldBlock);
144 }
145 Ok(())
146 }
147
148 #[inline(always)]
149 pub fn reset(&mut self) {
150 enable_peripheral_clock(PeripheralSelect::Dac);
151 reset_peripheral_for_cycles(PeripheralSelect::Dac, 2);
152 }
153
154 #[inline(always)]
156 pub fn stop(self) {
157 disable_peripheral_clock(PeripheralSelect::Dac);
158 }
159}