atsamd_hal/peripherals/adc/
d5x.rs
1use atsamd_hal_macros::hal_cfg;
3
4use crate::clock::GenericClockController;
5#[rustfmt::skip]
6use crate::gpio::*;
7use crate::ehal_02::adc::{Channel, OneShot};
8use crate::pac::gclk::genctrl::Srcselect::Dfll;
9use crate::pac::gclk::pchctrl::Genselect;
10use crate::pac::{adc0, Adc0, Adc1, Mclk};
11
12use crate::calibration;
13
14pub use adc0::avgctrl::Samplenumselect as SampleRate;
16pub use adc0::ctrla::Prescalerselect as Prescaler;
18pub use adc0::ctrlb::Resselselect as Resolution;
20pub use adc0::refctrl::Refselselect as Reference;
22
23pub struct InterruptAdc<ADC, C>
25where
26 C: ConversionMode<ADC>,
27{
28 adc: Adc<ADC>,
29 m: core::marker::PhantomData<C>,
30}
31
32pub struct Adc<ADC> {
34 adc: ADC,
35}
36
37pub trait ConversionMode<ADC> {
40 fn on_start(adc: &mut Adc<ADC>);
41 fn on_complete(adc: &mut Adc<ADC>);
42 fn on_stop(adc: &mut Adc<ADC>);
43}
44
45pub struct SingleConversion;
46pub struct FreeRunning;
47
48macro_rules! adc_hal {
49 ($($ADC:ident: ($init:ident, $mclk:ident, $apmask:ident, $compcal:ident, $refcal:ident, $r2rcal:ident),)+) => {
50 $(
51impl Adc<$ADC> {
52 pub fn $init(adc: $ADC, mclk: &mut Mclk, clocks: &mut GenericClockController, gclk:Genselect) -> Self {
53 mclk.$mclk().modify(|_, w| w.$apmask().set_bit());
54 let adc_clock = clocks.configure_gclk_divider_and_source(gclk, 1, Dfll, false)
56 .expect("adc clock setup failed");
57 clocks.$init(&adc_clock).expect("adc clock setup failed");
58 adc.ctrla().modify(|_, w| w.prescaler().div32());
59 adc.ctrlb().modify(|_, w| w.ressel()._12bit());
60 while adc.syncbusy().read().ctrlb().bit_is_set() {}
61 adc.sampctrl().modify(|_, w| unsafe {w.samplen().bits(5)}); while adc.syncbusy().read().sampctrl().bit_is_set() {}
63 adc.inputctrl().modify(|_, w| w.muxneg().gnd()); while adc.syncbusy().read().inputctrl().bit_is_set() {}
65
66 adc.calib().write(|w| unsafe {
67 w.biascomp().bits(calibration::$compcal());
68 w.biasrefbuf().bits(calibration::$refcal());
69 w.biasr2r().bits(calibration::$r2rcal())
70 });
71
72 let mut newadc = Self { adc };
73 newadc.samples(adc0::avgctrl::Samplenumselect::_1);
74 newadc.reference(adc0::refctrl::Refselselect::Intvcc1);
75
76 newadc
77 }
78
79 pub fn samples(&mut self, samples: SampleRate) {
81 use adc0::avgctrl::Samplenumselect;
82 self.adc.avgctrl().modify(|_, w| {
83 w.samplenum().variant(samples);
84 unsafe {
85 w.adjres().bits(match samples {
88 Samplenumselect::_1 => 0,
89 Samplenumselect::_2 => 1,
90 Samplenumselect::_4 => 2,
91 Samplenumselect::_8 => 3,
92 _ => 4,
93 })
94 }
95 });
96 while self.adc.syncbusy().read().avgctrl().bit_is_set() {}
97 }
98
99 pub fn reference(&mut self, reference: Reference) {
101 self.adc
102 .refctrl()
103 .modify(|_, w| w.refsel().variant(reference));
104 while self.adc.syncbusy().read().refctrl().bit_is_set() {}
105 }
106
107 pub fn prescaler(&mut self, prescaler: Prescaler) {
109 self.adc
110 .ctrla()
111 .modify(|_, w| w.prescaler().variant(prescaler));
112 }
114
115 pub fn resolution(&mut self, resolution: Resolution) {
117 self.adc
118 .ctrlb()
119 .modify(|_, w| w.ressel().variant(resolution));
120 while self.adc.syncbusy().read().ctrlb().bit_is_set() {}
121 }
122
123 fn power_up(&mut self) {
124 while self.adc.syncbusy().read().enable().bit_is_set() {}
125 self.adc.ctrla().modify(|_, w| w.enable().set_bit());
126 while self.adc.syncbusy().read().enable().bit_is_set() {}
127 }
128
129 fn power_down(&mut self) {
130 while self.adc.syncbusy().read().enable().bit_is_set() {}
131 self.adc.ctrla().modify(|_, w| w.enable().clear_bit());
132 while self.adc.syncbusy().read().enable().bit_is_set() {}
133 }
134
135 #[inline(always)]
136 fn start_conversion(&mut self) {
137 self.adc.swtrig().modify(|_, w| w.start().set_bit());
139 self.adc.swtrig().modify(|_, w| w.start().set_bit());
141 }
142
143 fn enable_freerunning(&mut self) {
144 self.adc.ctrlb().modify(|_, w| w.freerun().set_bit());
145 while self.adc.syncbusy().read().ctrlb().bit_is_set() {}
146 }
147
148 fn disable_freerunning(&mut self) {
149 self.adc.ctrlb().modify(|_, w| w.freerun().set_bit());
150 while self.adc.syncbusy().read().ctrlb().bit_is_set() {}
151 }
152
153 fn synchronous_convert(&mut self) -> u16 {
154 self.start_conversion();
155 while self.adc.intflag().read().resrdy().bit_is_clear() {}
156
157 self.adc.result().read().result().bits()
158 }
159
160 fn enable_interrupts(&mut self) {
162 self.adc.intflag().write(|w| w.resrdy().set_bit());
163 self.adc.intenset().write(|w| w.resrdy().set_bit());
164 }
165
166 fn disable_interrupts(&mut self) {
168 self.adc.intenclr().write(|w| w.resrdy().set_bit());
169 }
170
171 fn service_interrupt_ready(&mut self) -> Option<u16> {
172 if self.adc.intflag().read().resrdy().bit_is_set() {
173 self.adc.intflag().write(|w| w.resrdy().set_bit());
174
175 Some(self.adc.result().read().result().bits())
176 } else {
177 None
178 }
179 }
180
181 fn mux<PIN: Channel<$ADC, ID=u8>>(&mut self, _pin: &mut PIN) {
184 let chan = PIN::channel();
185 while self.adc.syncbusy().read().inputctrl().bit_is_set() {}
186 self.adc.inputctrl().modify(|_, w| unsafe{ w.muxpos().bits(chan) });
187 }
188}
189
190impl ConversionMode<$ADC> for SingleConversion {
191 fn on_start(_adc: &mut Adc<$ADC>) {
192 }
193 fn on_complete(adc: &mut Adc<$ADC>) {
194 adc.disable_interrupts();
195 adc.power_down();
196 }
197 fn on_stop(_adc: &mut Adc<$ADC>) {
198 }
199}
200
201impl ConversionMode<$ADC> for FreeRunning {
202 fn on_start(adc: &mut Adc<$ADC>) {
203 adc.enable_freerunning();
204 }
205 fn on_complete(_adc: &mut Adc<$ADC>) {
206 }
207 fn on_stop(adc: &mut Adc<$ADC>) {
208 adc.disable_interrupts();
209 adc.power_down();
210 adc.disable_freerunning();
211 }
212}
213
214impl<C> InterruptAdc<$ADC, C>
215 where C: ConversionMode<$ADC>
216{
217 pub fn service_interrupt_ready(&mut self) -> Option<u16> {
218 if let Some(res) = self.adc.service_interrupt_ready() {
219 C::on_complete(&mut self.adc);
220 Some(res)
221 } else {
222 None
223 }
224 }
225
226 pub fn start_conversion<PIN: Channel<$ADC, ID=u8>>(&mut self, pin: &mut PIN) {
228 self.adc.mux(pin);
229 self.adc.power_up();
230 C::on_start(&mut self.adc);
231 self.adc.enable_interrupts();
232 self.adc.start_conversion();
233 }
234
235 pub fn stop_conversion(&mut self) {
236 C::on_stop(&mut self.adc);
237 }
238}
239
240impl<C> From<Adc<$ADC>> for InterruptAdc<$ADC, C>
241 where C: ConversionMode<$ADC>
242{
243 fn from(adc: Adc<$ADC>) -> Self {
244 Self {
245 adc,
246 m: core::marker::PhantomData{},
247 }
248 }
249}
250
251impl<WORD, PIN> OneShot<$ADC, WORD, PIN> for Adc<$ADC>
252where
253 WORD: From<u16>,
254 PIN: Channel<$ADC, ID=u8>,
255{
256 type Error = ();
257
258 fn read(&mut self, pin: &mut PIN) -> nb::Result<WORD, Self::Error> {
259 self.mux(pin);
260 self.power_up();
261 let result = self.synchronous_convert();
262 self.power_down();
263 Ok(result.into())
264 }
265}
266 )+
267 }
268}
269
270adc_hal! {
271 Adc0: (adc0, apbdmask, adc0_, adc0_biascomp_scale_cal, adc0_biasref_scale_cal, adc0_biasr2r_scale_cal),
272 Adc1: (adc1, apbdmask, adc1_, adc1_biascomp_scale_cal, adc1_biasref_scale_cal, adc1_biasr2r_scale_cal),
273}
274
275macro_rules! adc_pins {
276 (
277 $(
278 $( #[$cfg:meta] )?
279 $PinId:ident: ($ADC:ident, $CHAN:literal)
280 ),+
281 $(,)?
282 ) => {
283 $(
284 $( #[$cfg] )?
285 impl Channel<$ADC> for Pin<$PinId, AlternateB> {
286 type ID = u8;
287 fn channel() -> u8 { $CHAN }
288 }
289 )+
290 }
291}
292
293adc_pins! {
294 #[hal_cfg("pa02")]
295 PA02: (Adc0, 0),
296 #[hal_cfg("pa03")]
297 PA03: (Adc0, 1),
298 #[hal_cfg("pb08")]
299 PB08: (Adc0, 2),
300 #[hal_cfg("pb09")]
301 PB09: (Adc0, 3),
302 #[hal_cfg("pa04")]
303 PA04: (Adc0, 4),
304 #[hal_cfg("pa05")]
305 PA05: (Adc0, 5),
306 #[hal_cfg("pa06")]
307 PA06: (Adc0, 6),
308 #[hal_cfg("pa07")]
309 PA07: (Adc0, 7),
310 #[hal_cfg("pa08")]
311 PA08: (Adc0, 8),
312 #[hal_cfg("pa09")]
313 PA09: (Adc0, 9),
314 #[hal_cfg("pa10")]
315 PA10: (Adc0, 10),
316 #[hal_cfg("pa11")]
317 PA11: (Adc0, 11),
318 #[hal_cfg("pb00")]
319 PB00: (Adc0, 12),
320 #[hal_cfg("pb01")]
321 PB01: (Adc0, 13),
322 #[hal_cfg("pb02")]
323 PB02: (Adc0, 14),
324 #[hal_cfg("pb03")]
325 PB03: (Adc0, 15),
326
327 #[hal_cfg("pb08")]
328 PB08: (Adc1, 0),
329 #[hal_cfg("pb09")]
330 PB09: (Adc1, 1),
331 #[hal_cfg("pa08")]
332 PA08: (Adc1, 2),
333 #[hal_cfg("pa09")]
334 PA09: (Adc1, 3),
335 #[hal_cfg("pc02")]
336 PC02: (Adc1, 4),
337 #[hal_cfg("pc03")]
338 PC03: (Adc1, 5),
339 #[hal_cfg("pb04")]
340 PB04: (Adc1, 6),
341 #[hal_cfg("pb05")]
342 PB05: (Adc1, 7),
343 #[hal_cfg("pb06")]
344 PB06: (Adc1, 8),
345 #[hal_cfg("pb07")]
346 PB07: (Adc1, 9),
347 #[hal_cfg("pc00")]
348 PC00: (Adc1, 10),
349 #[hal_cfg("pc01")]
350 PC01: (Adc1, 11),
351 #[hal_cfg("pc30")]
352 PC30: (Adc1, 12),
353 #[hal_cfg("pc31")]
354 PC31: (Adc1, 13),
355 #[hal_cfg("pd00")]
356 PD00: (Adc1, 14),
357 #[hal_cfg("pd01")]
358 PD01: (Adc1, 15),
359}