1use embassy_hal_internal::into_ref;
6
7use super::blocking_delay_us;
8use crate::adc::{Adc, AdcChannel, Instance, Resolution, SampleTime};
9use crate::pac::adc::vals::Extsel;
10use crate::pac::RCC;
11use crate::peripherals::ADC1;
12use crate::time::Hertz;
13use crate::{rcc, Peripheral};
14
15mod ringbuffered_v2;
16pub use ringbuffered_v2::{RingBufferedAdc, Sequence};
17
18pub const VREF_DEFAULT_MV: u32 = 3300;
20pub const VREF_CALIB_MV: u32 = 3300;
22
23pub struct VrefInt;
24impl AdcChannel<ADC1> for VrefInt {}
25impl super::SealedAdcChannel<ADC1> for VrefInt {
26 fn channel(&self) -> u8 {
27 17
28 }
29}
30
31impl VrefInt {
32 pub fn start_time_us() -> u32 {
34 10
35 }
36}
37
38pub struct Temperature;
39impl AdcChannel<ADC1> for Temperature {}
40impl super::SealedAdcChannel<ADC1> for Temperature {
41 fn channel(&self) -> u8 {
42 16
43 }
44}
45
46impl Temperature {
47 pub fn start_time_us() -> u32 {
49 10
50 }
51}
52
53pub enum Prescaler {
62 Div2,
63 Div4,
64 Div6,
65 Div8,
66}
67
68impl Prescaler {
69 fn from_pclk(freq: Hertz) -> Self {
70 #[cfg(py32f072)]
71 const MAX_FREQUENCY: Hertz = Hertz(16_000_000);
72 let raw_div = freq.0 / MAX_FREQUENCY.0;
73 match raw_div {
74 0..=1 => Self::Div2,
75 2..=3 => Self::Div4,
76 4..=5 => Self::Div6,
77 6..=7 => Self::Div8,
78 _ => panic!(
79 "Selected PCLK frequency is too high for ADC with largest possible prescaler."
80 ),
81 }
82 }
83
84 fn adcdiv(&self) -> crate::pac::rcc::vals::Adcdiv {
85 match self {
86 Prescaler::Div2 => crate::pac::rcc::vals::Adcdiv::DIV2,
87 Prescaler::Div4 => crate::pac::rcc::vals::Adcdiv::DIV4,
88 Prescaler::Div6 => crate::pac::rcc::vals::Adcdiv::DIV6,
89 Prescaler::Div8 => crate::pac::rcc::vals::Adcdiv::DIV8,
90 }
91 }
92}
93
94impl<'d, T> Adc<'d, T>
95where
96 T: Instance,
97{
98 pub fn new(adc: impl Peripheral<P = T> + 'd) -> Self {
99 let presc = Prescaler::from_pclk(T::frequency());
100 Self::new_with_prediv(adc, presc)
101 }
102
103 pub fn new_with_prediv(adc: impl Peripheral<P = T> + 'd, adc_div: Prescaler) -> Self {
105 into_ref!(adc);
106 rcc::enable_and_reset::<T>();
107
108 RCC.cr().modify(|reg| {
109 reg.set_adcdiv(adc_div.adcdiv());
110 });
111 T::regs().cr2().modify(|reg| {
112 reg.set_extsel(Extsel::SWSTART);
113 });
114
115 Self::calibrate();
116
117 T::regs().cr2().modify(|reg| {
118 reg.set_adon(true);
119 });
120
121 blocking_delay_us(3);
122
123 Self {
124 adc,
125 sample_time: SampleTime::from_bits(0),
126 }
127 }
128
129 pub fn set_sample_time(&mut self, sample_time: SampleTime) {
130 self.sample_time = sample_time;
131 }
132
133 pub fn set_resolution(&mut self, resolution: Resolution) {
134 T::regs().cr1().modify(|reg| reg.set_res(resolution.into()));
135 }
136
137 pub fn enable_vrefint(&self) -> VrefInt {
140 T::regs().cr2().modify(|reg| {
141 reg.set_tsvrefe(true);
142 });
143
144 VrefInt {}
145 }
146
147 pub fn enable_temperature(&self) -> Temperature {
153 T::regs().cr2().modify(|reg| {
154 reg.set_tsvrefe(true);
155 });
156
157 Temperature {}
158 }
159
160 fn convert(&mut self) -> u16 {
172 T::regs().sr().modify(|reg| {
174 reg.set_eoc(false);
175 });
176
177 T::regs().cr2().modify(|reg| {
179 reg.set_swstart(true);
180 reg.set_exttrig(true);
181 });
182
183 while T::regs().sr().read().strt() == false {
184 }
186 while T::regs().sr().read().eoc() == false {
187 }
189
190 T::regs().dr().read().0 as u16
191 }
192
193 pub fn blocking_read(&mut self, channel: &mut impl AdcChannel<T>) -> u16 {
194 channel.setup();
195
196 let channel = channel.channel();
198
199 T::regs().sqr3().write(|reg| reg.set_sq(0, channel));
201
202 Self::set_channel_sample_time(channel, self.sample_time);
204
205 self.convert()
206 }
207
208 fn set_channel_sample_time(ch: u8, sample_time: SampleTime) {
209 let sample_time = sample_time.into();
210 match ch {
211 ..=9 => T::regs()
212 .smpr3()
213 .modify(|reg| reg.set_smp(ch as _, sample_time)),
214 ..=19 => T::regs()
215 .smpr2()
216 .modify(|reg| reg.set_smp((ch - 10) as _, sample_time)),
217 _ => T::regs()
218 .smpr3()
219 .modify(|reg| reg.set_smp((ch - 20) as _, sample_time)),
220 }
221 }
222
223 pub fn calibrate() {
225 T::regs().cr2().modify(|reg| {
226 reg.set_adon(false);
227 });
228
229 while T::regs().cr2().read().adon() {}
230
231 let adc_clock_mhz = 72_u32; let cpu_clock_mhz = unsafe { rcc::get_freqs() }.sys.to_hertz().unwrap().0 / 1_000_000;
236 #[cfg(py32f072)]
237 let precalibration_cycles = 2_u32;
238
239 let delay_us = (precalibration_cycles * adc_clock_mhz) / cpu_clock_mhz;
240 blocking_delay_us(delay_us);
241
242 if T::regs().cr2().read().adon() {
244 panic!();
245 }
246
247 T::regs().cr2().modify(|reg| {
249 reg.set_rstcal(true);
250 });
251
252 while T::regs().cr2().read().rstcal() {}
254
255 T::regs().cr2().modify(|reg| {
257 reg.set_cal(true);
258 });
259
260 while T::regs().cr2().read().cal() {}
262 }
263}
264
265impl<'d, T: Instance> Drop for Adc<'d, T> {
266 fn drop(&mut self) {
267 T::regs().cr2().modify(|reg| {
268 reg.set_adon(false);
269 });
270
271 rcc::disable::<T>();
272 }
273}