1use core::cell::RefCell;
15
16use stm32f7xx_hal::pac;
17
18pub struct Adc<ADC> {
20 adc: ADC,
21}
22
23impl<ADC> Adc<ADC> {
24 #[inline]
25 pub fn free(self) -> ADC {
26 self.adc
27 }
28}
29
30pub trait AdcRead {
32 fn read_channel(&mut self, ch: u8) -> u16;
33}
34
35fn configure_common() {
36 let common = unsafe { &*pac::ADC_COMMON::ptr() };
37
38 common.ccr.write(|w| w.adcpre().div4());
40}
41
42fn init_basic_adc(adc: &pac::adc1::RegisterBlock) {
43 adc.cr2.write(|w| {
46 w.cont().clear_bit();
47 w.align().right();
48 w.exten().disabled();
49 w
50 });
51
52 adc.cr1.write(|w| w.res().bits(0b00));
54
55 adc.smpr1.write(|w| unsafe { w.bits(0) });
57 adc.smpr2.write(|w| unsafe { w.bits(0) });
58
59 adc.sqr1.write(|w| w.l().bits(0));
61 adc.sqr2.write(|w| unsafe { w.bits(0) });
62 adc.sqr3.write(|w| unsafe { w.bits(0) });
63
64 adc.sr.write(|w| unsafe { w.bits(0) });
66
67 adc.cr2.modify(|_, w| w.adon().set_bit());
69}
70
71impl Adc<pac::ADC1> {
72 pub fn adc1(adc1: pac::ADC1) -> Self {
74 let rcc = unsafe { &*pac::RCC::ptr() };
75 rcc.apb2enr.modify(|_, w| w.adc1en().set_bit());
78 rcc.apb2rstr.modify(|_, w| w.adcrst().set_bit());
79 rcc.apb2rstr.modify(|_, w| w.adcrst().clear_bit());
80
81 configure_common();
82 init_basic_adc(&adc1);
83
84 Self { adc: adc1 }
85 }
86}
87
88impl Adc<pac::ADC2> {
89 pub fn adc2(adc2: pac::ADC2) -> Self {
91 let rcc = unsafe { &*pac::RCC::ptr() };
92 rcc.apb2enr.modify(|_, w| w.adc2en().set_bit());
93
94 configure_common();
95 init_basic_adc(&adc2);
96
97 Self { adc: adc2 }
98 }
99}
100
101impl Adc<pac::ADC3> {
102 pub fn adc3(adc3: pac::ADC3) -> Self {
104 let rcc = unsafe { &*pac::RCC::ptr() };
105 rcc.apb2enr.modify(|_, w| w.adc3en().set_bit());
106
107 configure_common();
108 init_basic_adc(&adc3);
109
110 Self { adc: adc3 }
111 }
112}
113
114fn read_channel(adc: &pac::adc1::RegisterBlock, channel: u8) -> u16 {
116 if channel <= 9 {
118 adc.smpr2.modify(|_, w| match channel {
119 0 => w.smp0().bits(0b111),
120 1 => w.smp1().bits(0b111),
121 2 => w.smp2().bits(0b111),
122 3 => w.smp3().bits(0b111),
123 4 => w.smp4().bits(0b111),
124 5 => w.smp5().bits(0b111),
125 6 => w.smp6().bits(0b111),
126 7 => w.smp7().bits(0b111),
127 8 => w.smp8().bits(0b111),
128 9 => w.smp9().bits(0b111),
129 _ => unreachable!(),
130 });
131 } else {
132 adc.smpr1.modify(|_, w| match channel {
133 10 => w.smp10().bits(0b111),
134 11 => w.smp11().bits(0b111),
135 12 => w.smp12().bits(0b111),
136 13 => w.smp13().bits(0b111),
137 14 => w.smp14().bits(0b111),
138 15 => w.smp15().bits(0b111),
139 _ => w,
140 });
141 }
142
143 adc.sqr1.modify(|_, w| w.l().bits(0));
145
146 adc.sqr3
148 .modify(|_, w| unsafe { w.sq1().bits(channel & 0x1F) });
149
150 let mut sum: u32 = 0;
151 const SAMPLES: u32 = 16;
152
153 for _ in 0..SAMPLES {
154 adc.cr2.modify(|_, w| w.swstart().set_bit());
156
157 while adc.sr.read().eoc().bit_is_clear() {}
159
160 sum += adc.dr.read().data().bits() as u32;
161 }
162
163 adc.sqr3.modify(|_, w| unsafe { w.sq1().bits(0x1F) });
165
166 (sum / SAMPLES) as u16
167}
168
169impl Adc<pac::ADC1> {
170 #[inline]
172 pub fn read(&self, channel: u8) -> u16 {
173 read_channel(&self.adc, channel)
174 }
175}
176
177impl Adc<pac::ADC2> {
178 #[inline]
180 pub fn read(&self, channel: u8) -> u16 {
181 read_channel(&self.adc, channel)
182 }
183}
184
185impl Adc<pac::ADC3> {
186 #[inline]
188 pub fn read(&self, channel: u8) -> u16 {
189 read_channel(&self.adc, channel)
190 }
191}
192
193impl AdcRead for Adc<pac::ADC1> {
194 fn read_channel(&mut self, ch: u8) -> u16 {
195 self.read(ch)
196 }
197}
198
199impl AdcRead for Adc<pac::ADC2> {
200 fn read_channel(&mut self, ch: u8) -> u16 {
201 self.read(ch)
202 }
203}
204
205impl AdcRead for Adc<pac::ADC3> {
206 fn read_channel(&mut self, ch: u8) -> u16 {
207 self.read(ch)
208 }
209}
210
211impl<ADC> Adc<ADC>
212where
213 Adc<ADC>: AdcRead,
214{
215 pub fn make_reader<'a>(adc_ref: &'a RefCell<Self>, channel: u8) -> impl FnMut() -> u16 + 'a {
217 move || adc_ref.borrow_mut().read_channel(channel)
218 }
219
220 pub fn make_multi_reader<'a, const N: usize>(
223 adc_ref: &'a RefCell<Self>,
224 channels: [u8; N],
225 ) -> impl FnMut() -> [u16; N] + 'a {
226 move || {
227 let mut adc = adc_ref.borrow_mut();
228 let mut out = [0u16; N];
229 for i in 0..N {
230 out[i] = adc.read_channel(channels[i]);
231 }
232 out
233 }
234 }
235}
236
237pub fn volts_from_adc(adc_value: u16, v_ref: f32) -> f32 {
239 let max_adc = (1 << 12) - 1;
240 (adc_value as f32 / max_adc as f32) * v_ref
241}