stm32g0xx_hal/analog/
dac.rs1use core::marker::PhantomData;
4use core::mem::MaybeUninit;
5
6use crate::gpio::{DefaultMode, PA4, PA5};
7use crate::rcc::*;
8use crate::stm32::DAC;
9use hal::blocking::delay::DelayUs;
10
11pub trait DacOut<V> {
12 fn set_value(&mut self, val: V);
13 fn get_value(&mut self) -> V;
14}
15
16pub struct GeneratorConfig {
17 mode: u8,
18 amp: u8,
19}
20
21impl GeneratorConfig {
22 pub fn triangle(amplitude: u8) -> Self {
23 Self {
24 mode: 0b10,
25 amp: amplitude,
26 }
27 }
28
29 pub fn noise(seed: u8) -> Self {
30 Self {
31 mode: 0b01,
32 amp: seed,
33 }
34 }
35}
36
37pub struct Enabled;
39pub struct EnabledUnbuffered;
41pub struct WaveGenerator;
43pub struct Disabled;
45
46pub trait ED {}
47impl ED for Enabled {}
48impl ED for EnabledUnbuffered {}
49impl ED for WaveGenerator {}
50impl ED for Disabled {}
51
52pub struct Channel1<ED> {
53 _enabled: PhantomData<ED>,
54}
55pub struct Channel2<ED> {
56 _enabled: PhantomData<ED>,
57}
58
59pub trait Pins<DAC> {
61 type Output;
62}
63
64impl Pins<DAC> for PA4<DefaultMode> {
65 type Output = Channel1<Disabled>;
66}
67
68impl Pins<DAC> for PA5<DefaultMode> {
69 type Output = Channel2<Disabled>;
70}
71
72impl Pins<DAC> for (PA4<DefaultMode>, PA5<DefaultMode>) {
73 type Output = (Channel1<Disabled>, Channel2<Disabled>);
74}
75
76pub fn dac<PINS>(_dac: DAC, _pins: PINS, rcc: &mut Rcc) -> PINS::Output
77where
78 PINS: Pins<DAC>,
79{
80 DAC::enable(rcc);
81 DAC::reset(rcc);
82
83 #[allow(clippy::uninit_assumed_init)]
84 unsafe {
85 MaybeUninit::uninit().assume_init()
86 }
87}
88
89macro_rules! dac {
90 ($($CX:ident: (
91 $en:ident,
92 $cen:ident,
93 $cal_flag:ident,
94 $trim:ident,
95 $mode:ident,
96 $dhrx:ident,
97 $dac_dor:ident,
98 $daccxdhr:ident,
99 $wave:ident,
100 $mamp:ident,
101 $ten:ident,
102 $swtrig:ident
103 ),)+) => {
104 $(
105 impl $CX<Disabled> {
106 pub fn enable(self) -> $CX<Enabled> {
107 let dac = unsafe { &(*DAC::ptr()) };
108
109 dac.dac_mcr.modify(|_, w| unsafe { w.$mode().bits(1) });
110 dac.dac_cr.modify(|_, w| w.$en().set_bit());
111
112 $CX {
113 _enabled: PhantomData,
114 }
115 }
116
117 pub fn enable_unbuffered(self) -> $CX<EnabledUnbuffered> {
118 let dac = unsafe { &(*DAC::ptr()) };
119
120 dac.dac_mcr.modify(|_, w| unsafe { w.$mode().bits(2) });
121 dac.dac_cr.modify(|_, w| w.$en().set_bit());
122
123 $CX {
124 _enabled: PhantomData,
125 }
126 }
127
128 pub fn enable_generator(self, config: GeneratorConfig) -> $CX<WaveGenerator> {
129 let dac = unsafe { &(*DAC::ptr()) };
130
131 dac.dac_mcr.modify(|_, w| unsafe { w.$mode().bits(1) });
132 dac.dac_cr.modify(|_, w| unsafe {
133 w.$wave().bits(config.mode);
134 w.$ten().set_bit();
135 w.$mamp().bits(config.amp);
136 w.$en().set_bit()
137 });
138
139 $CX {
140 _enabled: PhantomData,
141 }
142 }
143 }
144
145 impl<ED> $CX<ED> {
146 pub fn calibrate_buffer<T>(self, delay: &mut T) -> $CX<Disabled>
158 where
159 T: DelayUs<u32>,
160 {
161 let dac = unsafe { &(*DAC::ptr()) };
162 dac.dac_cr.modify(|_, w| w.$en().clear_bit());
163 dac.dac_mcr.modify(|_, w| unsafe { w.$mode().bits(0) });
164 dac.dac_cr.modify(|_, w| w.$cen().set_bit());
165 let mut trim = 0;
166 while true {
167 dac.dac_ccr.modify(|_, w| unsafe { w.$trim().bits(trim) });
168 delay.delay_us(64_u32);
169 if dac.dac_sr.read().$cal_flag().bit() {
170 break;
171 }
172 trim += 1;
173 }
174 dac.dac_cr.modify(|_, w| w.$cen().clear_bit());
175
176 $CX {
177 _enabled: PhantomData,
178 }
179 }
180
181 pub fn disable(self) -> $CX<Disabled> {
183 let dac = unsafe { &(*DAC::ptr()) };
184 dac.dac_cr.modify(|_, w| unsafe {
185 w.$en().clear_bit().$wave().bits(0).$ten().clear_bit()
186 });
187
188 $CX {
189 _enabled: PhantomData,
190 }
191 }
192 }
193
194 impl<ED> DacOut<u16> for $CX<ED> {
197 fn set_value(&mut self, val: u16) {
198 let dac = unsafe { &(*DAC::ptr()) };
199 dac.$dhrx.write(|w| unsafe { w.bits(val as u32) });
200 }
201
202 fn get_value(&mut self) -> u16 {
203 let dac = unsafe { &(*DAC::ptr()) };
204 dac.$dac_dor.read().bits() as u16
205 }
206 }
207
208 impl $CX<WaveGenerator> {
210 pub fn trigger(&mut self) {
211 let dac = unsafe { &(*DAC::ptr()) };
212 dac.dac_swtrgr.write(|w| { w.$swtrig().set_bit() });
213 }
214 }
215 )+
216 };
217}
218
219pub trait DacExt {
220 fn constrain<PINS>(self, pins: PINS, rcc: &mut Rcc) -> PINS::Output
221 where
222 PINS: Pins<DAC>;
223}
224
225impl DacExt for DAC {
226 fn constrain<PINS>(self, pins: PINS, rcc: &mut Rcc) -> PINS::Output
227 where
228 PINS: Pins<DAC>,
229 {
230 dac(self, pins, rcc)
231 }
232}
233
234dac!(
235 Channel1:
236 (
237 en1,
238 cen1,
239 cal_flag1,
240 otrim1,
241 mode1,
242 dac_dhr12r1,
243 dac_dor1,
244 dacc1dhr,
245 wave1,
246 mamp1,
247 ten1,
248 swtrig1
249 ),
250 Channel2:
251 (
252 en2,
253 cen2,
254 cal_flag2,
255 otrim2,
256 mode2,
257 dac_dhr12r2,
258 dac_dor2,
259 dacc2dhr,
260 wave2,
261 mamp2,
262 ten2,
263 swtrig2
264 ),
265);