atsamd_hal/peripherals/adc/d5x/
mod.rs1pub mod pin;
2
3use pac::Supc;
4
5#[cfg(feature = "async")]
6use super::{FutureAdc, async_api};
7
8use super::{
9 ADC_SETTINGS_INTERNAL_READ, Accumulation, Adc, AdcInstance, AdcSettings, CpuVoltageSource,
10 Error, Flags, PrimaryAdc, SampleCount,
11};
12use crate::{calibration, pac};
13
14pub struct Adc0 {
16 _adc: pac::Adc0,
17}
18
19impl PrimaryAdc for Adc0 {}
20
21impl AdcInstance for Adc0 {
22 type Instance = pac::Adc0;
23
24 type ClockId = crate::clock::v2::pclk::ids::Adc0;
25
26 #[cfg(feature = "async")]
27 type Interrupt = crate::async_hal::interrupts::ADC0;
28
29 #[inline]
30 fn peripheral_reg_block(p: &mut pac::Peripherals) -> &pac::adc0::RegisterBlock {
31 &p.adc0
32 }
33
34 #[inline]
35 fn calibrate(instance: &Self::Instance) {
36 instance.calib().write(|w| unsafe {
37 w.biascomp().bits(calibration::adc0_biascomp_scale_cal());
38 w.biasrefbuf().bits(calibration::adc0_biasref_scale_cal());
39 w.biasr2r().bits(calibration::adc0_biasr2r_scale_cal())
40 });
41 }
42
43 #[cfg(feature = "async")]
44 #[inline]
45 fn waker() -> &'static embassy_sync::waitqueue::AtomicWaker {
46 use super::async_api;
47 &async_api::ADC_WAKERS[0]
48 }
49}
50
51#[inline]
52fn tp_tc_to_temp(tp: f32, tc: f32) -> f32 {
54 let tl = calibration::tl();
55 let th = calibration::th();
56 let vpl = calibration::vpl() as f32;
57 let vph = calibration::vph() as f32;
58 let vcl = calibration::vcl() as f32;
59 let vch = calibration::vch() as f32;
60
61 ((tl * vph * tc) - (vpl * th * tc) - (tl * vch * tp) + (th * vcl * tp))
62 / ((vcl * tp) - (vch * tp) - (vpl * tc) + (vph * tc))
63}
64
65pub struct Adc1 {
67 _adc: pac::Adc1,
68}
69
70impl AdcInstance for Adc1 {
71 type Instance = pac::Adc1;
72
73 type ClockId = crate::clock::v2::pclk::ids::Adc1;
74
75 #[cfg(feature = "async")]
76 type Interrupt = crate::async_hal::interrupts::ADC1;
77
78 #[inline]
79 fn peripheral_reg_block(p: &mut pac::Peripherals) -> &pac::adc0::RegisterBlock {
80 &p.adc1
81 }
82
83 #[inline]
84 fn calibrate(instance: &Self::Instance) {
85 instance.calib().write(|w| unsafe {
86 w.biascomp().bits(calibration::adc1_biascomp_scale_cal());
87 w.biasrefbuf().bits(calibration::adc1_biasref_scale_cal());
88 w.biasr2r().bits(calibration::adc1_biasr2r_scale_cal())
89 });
90 }
91
92 #[cfg(feature = "async")]
93 #[inline]
94 fn waker() -> &'static embassy_sync::waitqueue::AtomicWaker {
95 use super::async_api;
96 &async_api::ADC_WAKERS[1]
97 }
98}
99
100impl<I: AdcInstance> Adc<I> {
101 #[inline]
102 pub(crate) fn configure(&mut self, cfg: AdcSettings) {
104 if cfg != self.cfg {
105 self.discard = true;
107 }
108 self.power_down();
110 self.sync();
111 I::calibrate(&self.adc);
112 self.sync();
113 self.adc
114 .ctrla()
115 .modify(|_, w| w.prescaler().variant(cfg.clk_divider));
116 self.sync();
117 self.adc
118 .ctrlb()
119 .modify(|_, w| w.ressel().variant(cfg.accumulation.resolution()));
120 self.sync();
121
122 self.adc
123 .sampctrl()
124 .modify(|_, w| unsafe { w.samplen().bits(cfg.sample_clock_cycles.saturating_sub(1)) }); self.sync();
126 self.adc.inputctrl().modify(|_, w| {
127 w.muxneg().gnd();
128 w.diffmode().clear_bit()
129 }); self.sync();
131 let (sample_cnt, adjres) = match cfg.accumulation {
132 Accumulation::Single(_) => (SampleCount::_1, 0),
134 Accumulation::Average(cnt) => (cnt, core::cmp::min(cnt as u8, 0x04)),
138 Accumulation::Summed(cnt) => (cnt, 0),
141 };
142 self.adc.avgctrl().modify(|_, w| {
143 w.samplenum().variant(sample_cnt);
144 unsafe { w.adjres().bits(adjres) }
145 });
146 self.sync();
147 self.set_reference(cfg.vref);
148 self.sync();
149 self.adc.ctrla().modify(|_, w| w.enable().set_bit());
150 self.sync();
151 self.cfg = cfg;
152 self.power_up();
153 }
154}
155
156impl<I: AdcInstance + PrimaryAdc> Adc<I> {
157 #[inline]
158 pub fn read_cpu_temperature(&mut self, supc: &mut Supc) -> f32 {
164 let old_state = supc.vref().read().bits();
165 supc.vref().modify(|_, w| {
166 w.ondemand().set_bit();
167 w.tsen().set_bit()
168 });
169
170 let (tp, tc) = self.with_specific_settings(ADC_SETTINGS_INTERNAL_READ, |adc| {
171 (
172 adc.read_channel(0x1C) as f32, adc.read_channel(0x1D) as f32, )
175 });
176 supc.vref().write(|w| unsafe { w.bits(old_state) });
178
179 tp_tc_to_temp(tp, tc)
180 }
181
182 #[inline]
183 pub fn read_cpu_voltage(&mut self, src: CpuVoltageSource) -> u16 {
184 let voltage = self.with_specific_settings(ADC_SETTINGS_INTERNAL_READ, |adc| {
185 let res = adc.read_channel(src as u8);
186 adc.reading_to_f32(res) * 3.3 * 4.0 });
188 (voltage * 1000.0) as u16
189 }
190}
191
192impl<I: AdcInstance> Adc<I> {
193 #[inline]
194 pub(super) fn sync(&self) {
195 while self.adc.syncbusy().read().bits() != 0 {
198 core::hint::spin_loop();
199 }
200 }
201
202 #[inline]
203 pub(super) fn power_up(&mut self) {
204 self.adc.ctrla().modify(|_, w| w.enable().set_bit());
205 self.sync();
206 }
207
208 #[inline]
209 #[allow(dead_code)]
210 pub(super) fn power_down(&mut self) {
211 self.adc.ctrla().modify(|_, w| w.enable().clear_bit());
212 self.sync();
213 }
214
215 #[inline]
216 pub(super) fn start_conversion(&mut self) {
217 self.adc.swtrig().modify(|_, w| w.start().set_bit());
218 }
219
220 #[inline]
221 pub(super) fn enable_freerunning(&mut self) {
222 self.adc.ctrlb().modify(|_, w| w.freerun().set_bit());
223 self.sync();
224 }
225
226 #[inline]
227 pub(super) fn disable_freerunning(&mut self) {
228 self.adc.ctrlb().modify(|_, w| w.freerun().clear_bit());
229 self.sync();
230 }
231
232 #[inline]
233 pub(super) fn read_flags(&self) -> Flags {
234 let bits = self.adc.intflag().read().bits();
235 Flags::from_bits_truncate(bits)
236 }
237
238 #[cfg(feature="async")]
239 #[inline]
241 pub(super) fn clear_flags(&mut self, flags: &Flags) {
242 unsafe {
243 self.adc.intflag().write(|w| w.bits(flags.bits()));
244 }
245 }
246
247 #[inline]
249 pub(super) fn clear_all_flags(&mut self) {
250 unsafe {
251 self.adc.intflag().write(|w| w.bits(0b111));
252 }
253 }
254
255 #[inline]
257 pub(super) fn check_overrun(&mut self, flags: &Flags) -> Result<(), Error> {
258 if flags.contains(Flags::OVERRUN) {
259 Err(Error::BufferOverrun)
260 } else {
261 Ok(())
262 }
263 }
264
265 #[inline]
267 #[allow(dead_code)]
268 pub(super) fn enable_interrupts(&mut self, flags: Flags) {
269 unsafe { self.adc.intenset().write(|w| w.bits(flags.bits())) };
270 }
271
272 #[inline]
274 pub(super) fn disable_interrupts(&mut self, flags: Flags) {
275 unsafe { self.adc.intenclr().write(|w| w.bits(flags.bits())) };
276 }
277
278 #[inline]
279 pub(super) fn conversion_result(&self) -> u16 {
280 self.adc.result().read().result().bits()
281 }
282
283 #[inline]
284 pub(super) fn mux(&mut self, ch: u8) {
285 self.adc.inputctrl().modify(|r, w| {
286 if r.muxpos().bits() != ch {
287 self.discard = true;
288 }
289 unsafe { w.muxpos().bits(ch) }
290 });
291 self.sync()
292 }
293}
294
295#[cfg(feature = "async")]
296impl<I: AdcInstance + PrimaryAdc, F> FutureAdc<I, F>
297where
298 F: crate::async_hal::interrupts::Binding<I::Interrupt, async_api::InterruptHandler<I>>,
299{
300 pub async fn read_cpu_temperature(&mut self, supc: &mut Supc) -> f32 {
306 let old_adc_settings = self.inner.cfg;
309 let old_state = supc.vref().read().bits();
310 supc.vref().modify(|_, w| {
311 w.ondemand().set_bit();
312 w.tsen().set_bit()
313 });
314
315 self.inner.configure(ADC_SETTINGS_INTERNAL_READ);
316 let tp = self.read_channel(0x1C).await as f32;
317 let tc = self.read_channel(0x1D).await as f32;
318 supc.vref().write(|w| unsafe { w.bits(old_state) });
320 self.inner.configure(old_adc_settings);
321 tp_tc_to_temp(tp, tc)
322 }
323
324 pub async fn read_cpu_voltage(&mut self, src: CpuVoltageSource) -> u16 {
326 let old_adc_settings = self.inner.cfg;
327 self.inner.configure(ADC_SETTINGS_INTERNAL_READ);
328
329 let res = self.read_channel(src as u8).await;
330
331 let voltage = self.inner.reading_to_f32(res) * 3.3 * 4.0;
333
334 self.inner.configure(old_adc_settings);
335 (voltage * 1000.0) as u16
336 }
337}