1use core::marker::PhantomData;
8
9use embassy_hal_internal::{Peri, PeripheralType};
10use embassy_time::{Duration, block_for};
11
12use crate::{
13 gpio::{Basic, Flex, Pin},
14 module_stop::ModuleStop,
15 pac::dac12::vals::Ref,
16};
17
18#[allow(private_bounds)]
20pub struct Dac<'d, I: Instance> {
21 _output_pin: Flex<'d, Basic>,
22 _phantom: PhantomData<&'d I>,
23}
24
25#[cfg_attr(feature = "defmt", derive(defmt::Format))]
27#[derive(Copy, Clone, Default, Debug)]
28pub enum Align {
29 Left,
31
32 #[default]
34 Right,
35}
36
37pub enum Vref {
39 AnalogReference,
41
42 AnalogSupply,
44
45 Internal,
47
48 None,
50}
51
52#[allow(private_bounds)]
54pub trait DacOutputPin: SealedDacOutputPin {}
55
56pub(crate) trait SealedDacOutputPin: Pin + PeripheralType {}
58
59#[allow(private_bounds)]
61pub trait Instance: SealedInstance + ModuleStop + PeripheralType {}
62
63pub(crate) trait SealedInstance: PeripheralType {
64 fn regs() -> crate::pac::dac12::Dac12;
65}
66
67impl<'d, I: Instance> Dac<'d, I> {
68 pub fn new<P: DacOutputPin>(peri: Peri<'d, I>, output_pin: Peri<'d, P>) -> Self {
70 let _ = peri;
71
72 I::start_module();
73 output_pin.set_as_analog();
74
75 let mut this = Self {
76 _output_pin: Flex::new(output_pin),
77 _phantom: PhantomData,
78 };
79
80 this.set_vref(Vref::AnalogSupply);
81
82 this
83 }
84
85 #[inline(always)]
89 pub fn buffer(&self) -> *mut u16 {
90 let dac = I::regs();
91 dac.dadr0().as_ptr()
92 }
93
94 #[inline(always)]
96 pub fn set_align(&mut self, align: Align) {
97 let dac = I::regs();
98 match align {
99 Align::Left => dac.dadpr().modify(|r| r.set_dpsel(true)),
100 Align::Right => dac.dadpr().modify(|r| r.set_dpsel(false)),
101 }
102 }
103
104 #[inline(always)]
106 pub fn set_vref(&mut self, vref: Vref) {
107 let dac = I::regs();
112
113 dac.davrefcr().modify(|r| r.set_ref_(Ref::None));
115 dac.dadr0().write_value(0);
116 dac.dacr().modify(|r| r.set_daoe0(false));
117
118 block_for(Duration::from_micros(10));
119
120 let vref = match vref {
121 Vref::AnalogReference => Ref::Vref,
122 Vref::AnalogSupply => Ref::Avcc0,
123 Vref::Internal => Ref::Internal,
124 Vref::None => return,
125 };
126
127 dac.davrefcr().modify(|r| r.set_ref_(vref));
128 dac.dacr().modify(|r| r.set_daoe0(true));
129 block_for(Duration::from_micros(5));
130 }
131
132 #[inline(always)]
134 pub fn set(&mut self, value: u16) {
135 trace!("Set {}", value);
136 let dac = I::regs();
137
138 dac.dadr0().write_value(value);
139 }
140
141 #[inline(always)]
143 pub fn start(&mut self) {
144 let dac = I::regs();
145 dac.dacr().write(|w| w.set_daoe0(true));
146 }
147
148 #[inline(always)]
150 pub fn stop(&mut self) {
151 let dac = I::regs();
152 dac.dacr().write(|w| w.set_daoe0(false));
153 }
154}
155
156impl<'d, I: Instance> Drop for Dac<'d, I> {
157 fn drop(&mut self) {
159 warn!("DAC12: Drop");
160 let dac = I::regs();
161 dac.dacr().modify(|r| r.set_daoe0(false));
162 I::stop_module();
163 }
164}
165
166impl Instance for crate::peripherals::DAC12_0 {}
167impl SealedInstance for crate::peripherals::DAC12_0 {
168 #[inline(always)]
169 fn regs() -> crate::pac::dac12::Dac12 {
170 crate::pac::DAC12_0
171 }
172}
173
174macro_rules! dac_pin {
175 ($pin:ident) => {
176 impl crate::dac::DacOutputPin for crate::peripherals::$pin {}
177 impl crate::dac::SealedDacOutputPin for crate::peripherals::$pin {}
178 };
179}
180pub(crate) use dac_pin;