aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src/adc/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-stm32/src/adc/mod.rs')
-rw-r--r--embassy-stm32/src/adc/mod.rs467
1 files changed, 424 insertions, 43 deletions
diff --git a/embassy-stm32/src/adc/mod.rs b/embassy-stm32/src/adc/mod.rs
index ea986f4cf..da432f6ce 100644
--- a/embassy-stm32/src/adc/mod.rs
+++ b/embassy-stm32/src/adc/mod.rs
@@ -17,38 +17,44 @@
17#[cfg_attr(adc_c0, path = "c0.rs")] 17#[cfg_attr(adc_c0, path = "c0.rs")]
18mod _version; 18mod _version;
19 19
20#[cfg(any(adc_v2, adc_g4, adc_v3, adc_g0, adc_u0))]
21mod ringbuffered;
22
20use core::marker::PhantomData; 23use core::marker::PhantomData;
21 24
22#[allow(unused)] 25#[allow(unused)]
23#[cfg(not(any(adc_f3v3, adc_wba)))] 26#[cfg(not(any(adc_f3v3, adc_wba)))]
24pub use _version::*; 27pub use _version::*;
25use embassy_hal_internal::{impl_peripheral, PeripheralType}; 28#[allow(unused)]
29use embassy_hal_internal::PeripheralType;
26#[cfg(any(adc_f1, adc_f3v1, adc_v1, adc_l0, adc_f3v2))] 30#[cfg(any(adc_f1, adc_f3v1, adc_v1, adc_l0, adc_f3v2))]
27use embassy_sync::waitqueue::AtomicWaker; 31use embassy_sync::waitqueue::AtomicWaker;
32#[cfg(any(adc_v2, adc_g4, adc_v3, adc_g0, adc_u0))]
33pub use ringbuffered::RingBufferedAdc;
34
35#[cfg(adc_u5)]
36use crate::pac::adc::vals::Adc4SampleTime;
37#[cfg(adc_wba)]
38use crate::pac::adc::vals::SampleTime as Adc4SampleTime;
28 39
29#[cfg(any(adc_u5, adc_wba))] 40#[cfg(any(adc_u5, adc_wba))]
30#[path = "adc4.rs"] 41#[path = "adc4.rs"]
31pub mod adc4; 42pub mod adc4;
32 43
44#[allow(unused)]
45pub(self) use crate::block_for_us as blocking_delay_us;
33pub use crate::pac::adc::vals; 46pub use crate::pac::adc::vals;
34#[cfg(not(any(adc_f1, adc_f3v3)))] 47#[cfg(not(any(adc_f1, adc_f3v3)))]
35pub use crate::pac::adc::vals::Res as Resolution; 48pub use crate::pac::adc::vals::Res as Resolution;
36pub use crate::pac::adc::vals::SampleTime; 49pub use crate::pac::adc::vals::SampleTime;
37use crate::peripherals; 50use crate::peripherals;
38 51
39#[cfg(not(adc_wba))]
40dma_trait!(RxDma, Instance); 52dma_trait!(RxDma, Instance);
41#[cfg(adc_u5)]
42dma_trait!(RxDma4, adc4::Instance);
43#[cfg(adc_wba)]
44dma_trait!(RxDma4, adc4::Instance);
45 53
46/// Analog to Digital driver. 54/// Analog to Digital driver.
47pub struct Adc<'d, T: Instance> { 55pub struct Adc<'d, T: Instance> {
48 #[allow(unused)] 56 #[allow(unused)]
49 adc: crate::Peri<'d, T>, 57 adc: crate::Peri<'d, T>,
50 #[cfg(not(any(adc_f3v3, adc_f3v2, adc_wba)))]
51 sample_time: SampleTime,
52} 58}
53 59
54#[cfg(any(adc_f1, adc_f3v1, adc_v1, adc_l0, adc_f3v2))] 60#[cfg(any(adc_f1, adc_f3v1, adc_v1, adc_l0, adc_f3v2))]
@@ -65,10 +71,53 @@ impl State {
65 } 71 }
66} 72}
67 73
68trait SealedInstance { 74#[cfg(any(adc_f1, adc_f3v1, adc_f3v2, adc_v1, adc_l0))]
69 #[cfg(not(adc_wba))] 75trait_set::trait_set! {
70 #[allow(unused)] 76 pub trait DefaultInstance = Instance;
77}
78
79#[cfg(any(adc_v2, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_g4, adc_c0))]
80trait_set::trait_set! {
81 pub trait DefaultInstance = Instance<Regs = crate::pac::adc::Adc>;
82}
83
84#[cfg(adc_wba)]
85trait_set::trait_set! {
86 pub trait DefaultInstance = Instance<Regs = crate::pac::adc::Adc4>;
87}
88
89pub trait BasicAdcRegs {
90 type SampleTime;
91}
92
93#[cfg(any(
94 adc_v2, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_wba, adc_g4, adc_c0
95))]
96trait AdcRegs: BasicAdcRegs {
97 fn enable(&self);
98 fn start(&self);
99 fn stop(&self);
100 fn convert(&self);
101 fn configure_dma(&self, conversion_mode: ConversionMode);
102 fn configure_sequence(&self, sequence: impl ExactSizeIterator<Item = ((u8, bool), Self::SampleTime)>);
103 fn data(&self) -> *mut u16;
104}
105
106#[allow(private_bounds)]
107pub trait BasicInstance {
108 #[cfg(any(
109 adc_v2, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_wba, adc_g4, adc_c0
110 ))]
111 type Regs: AdcRegs;
112}
113
114trait SealedInstance: BasicInstance {
115 #[cfg(any(adc_f1, adc_f3v1, adc_f3v2, adc_v1, adc_l0))]
71 fn regs() -> crate::pac::adc::Adc; 116 fn regs() -> crate::pac::adc::Adc;
117 #[cfg(any(
118 adc_v2, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_wba, adc_g4, adc_c0
119 ))]
120 fn regs() -> Self::Regs;
72 #[cfg(not(any(adc_f1, adc_v1, adc_l0, adc_f3v3, adc_f3v2, adc_g0)))] 121 #[cfg(not(any(adc_f1, adc_v1, adc_l0, adc_f3v3, adc_f3v2, adc_g0)))]
73 #[allow(unused)] 122 #[allow(unused)]
74 fn common_regs() -> crate::pac::adccommon::AdcCommon; 123 fn common_regs() -> crate::pac::adccommon::AdcCommon;
@@ -77,27 +126,278 @@ trait SealedInstance {
77} 126}
78 127
79pub(crate) trait SealedAdcChannel<T> { 128pub(crate) trait SealedAdcChannel<T> {
80 #[cfg(any(adc_v1, adc_c0, adc_l0, adc_v2, adc_g4, adc_v4, adc_u5, adc_wba))] 129 #[cfg(any(adc_v1, adc_c0, adc_l0, adc_v2, adc_g4, adc_v3, adc_v4, adc_u5, adc_wba))]
81 fn setup(&mut self) {} 130 fn setup(&mut self) {}
82 131
83 #[allow(unused)] 132 #[allow(unused)]
84 fn channel(&self) -> u8; 133 fn channel(&self) -> u8;
134
135 #[allow(unused)]
136 fn is_differential(&self) -> bool {
137 false
138 }
85} 139}
86 140
87/// Performs a busy-wait delay for a specified number of microseconds. 141#[cfg(any(adc_c0, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5))]
88#[allow(unused)] 142/// Number of samples used for averaging.
89pub(crate) fn blocking_delay_us(us: u32) { 143#[derive(Copy, Clone, Debug)]
90 #[cfg(feature = "time")] 144#[cfg_attr(feature = "defmt", derive(defmt::Format))]
91 embassy_time::block_for(embassy_time::Duration::from_micros(us as u64)); 145pub enum Averaging {
92 #[cfg(not(feature = "time"))] 146 Disabled,
93 { 147 Samples2,
94 let freq = unsafe { crate::rcc::get_freqs() }.sys.to_hertz().unwrap().0 as u64; 148 Samples4,
95 let us = us as u64; 149 Samples8,
96 let cycles = freq * us / 1_000_000; 150 Samples16,
97 cortex_m::asm::delay(cycles as u32); 151 Samples32,
152 Samples64,
153 Samples128,
154 Samples256,
155 #[cfg(any(adc_c0, adc_v4, adc_u5))]
156 Samples512,
157 #[cfg(any(adc_c0, adc_v4, adc_u5))]
158 Samples1024,
159}
160
161#[cfg(any(
162 adc_v2, adc_g4, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_wba, adc_c0
163))]
164pub(crate) enum ConversionMode {
165 // Should match the cfg on "read" below
166 #[cfg(any(adc_g4, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_wba, adc_c0))]
167 Singular,
168 // Should match the cfg on "into_ring_buffered" below
169 #[cfg(any(adc_v2, adc_g4, adc_v3, adc_g0, adc_u0))]
170 Repeated(RegularConversionMode),
171}
172
173// Should match the cfg on "into_ring_buffered" below
174#[cfg(any(adc_v2, adc_g4, adc_v3, adc_g0, adc_u0))]
175// Conversion mode for regular ADC channels
176#[derive(Copy, Clone)]
177pub enum RegularConversionMode {
178 // Samples as fast as possible
179 Continuous,
180 #[cfg(adc_g4)]
181 // Sample at rate determined by external trigger
182 Triggered(ConversionTrigger),
183}
184
185impl<'d, T: Instance> Adc<'d, T> {
186 #[cfg(any(
187 adc_v2, adc_g4, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_u5, adc_v3, adc_v4, adc_wba, adc_c0
188 ))]
189 /// Read an ADC pin.
190 pub fn blocking_read(
191 &mut self,
192 channel: &mut impl AdcChannel<T>,
193 sample_time: <T::Regs as BasicAdcRegs>::SampleTime,
194 ) -> u16 {
195 #[cfg(any(adc_v1, adc_c0, adc_l0, adc_v2, adc_g4, adc_v3, adc_v4, adc_u5, adc_wba))]
196 channel.setup();
197
198 // Ensure no conversions are ongoing
199 T::regs().stop();
200 #[cfg(any(adc_v2, adc_v3, adc_g0, adc_h7rs, adc_u0, adc_u5, adc_wba, adc_c0))]
201 T::regs().enable();
202 T::regs().configure_sequence([((channel.channel(), channel.is_differential()), sample_time)].into_iter());
203
204 // On chips with differential channels, enable after configure_sequence to allow setting differential channels
205 //
206 // TODO: If hardware allows, enable after configure_sequence on all chips
207 #[cfg(any(adc_g4, adc_h5))]
208 T::regs().enable();
209 T::regs().convert();
210
211 unsafe { core::ptr::read_volatile(T::regs().data()) }
212 }
213
214 #[cfg(any(adc_g4, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_wba, adc_c0))]
215 /// Read one or multiple ADC regular channels using DMA.
216 ///
217 /// `sequence` iterator and `readings` must have the same length.
218 ///
219 /// Example
220 /// ```rust,ignore
221 /// use embassy_stm32::adc::{Adc, AdcChannel}
222 ///
223 /// let mut adc = Adc::new(p.ADC1);
224 /// let mut adc_pin0 = p.PA0.into();
225 /// let mut adc_pin1 = p.PA1.into();
226 /// let mut measurements = [0u16; 2];
227 ///
228 /// adc.read(
229 /// p.DMA1_CH2.reborrow(),
230 /// [
231 /// (&mut *adc_pin0, SampleTime::CYCLES160_5),
232 /// (&mut *adc_pin1, SampleTime::CYCLES160_5),
233 /// ]
234 /// .into_iter(),
235 /// &mut measurements,
236 /// )
237 /// .await;
238 /// defmt::info!("measurements: {}", measurements);
239 /// ```
240 ///
241 /// Note: This is not very efficient as the ADC needs to be reconfigured for each read. Use
242 /// `into_ring_buffered`, `into_ring_buffered_and_injected`
243 ///
244 /// Note: Depending on hardware limitations, this method may require channels to be passed
245 /// in order or require the sequence to have the same sample time for all channnels, depending
246 /// on the number and properties of the channels in the sequence. This method will panic if
247 /// the hardware cannot deliver the requested configuration.
248 pub async fn read<'a, 'b: 'a>(
249 &mut self,
250 rx_dma: embassy_hal_internal::Peri<'_, impl RxDma<T>>,
251 sequence: impl ExactSizeIterator<Item = (&'a mut AnyAdcChannel<'b, T>, <T::Regs as BasicAdcRegs>::SampleTime)>,
252 readings: &mut [u16],
253 ) {
254 assert!(sequence.len() != 0, "Asynchronous read sequence cannot be empty");
255 assert!(
256 sequence.len() == readings.len(),
257 "Sequence length must be equal to readings length"
258 );
259 assert!(
260 sequence.len() <= 16,
261 "Asynchronous read sequence cannot be more than 16 in length"
262 );
263
264 // Ensure no conversions are ongoing
265 T::regs().stop();
266 #[cfg(any(adc_g0, adc_v3, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_wba, adc_c0))]
267 T::regs().enable();
268
269 T::regs().configure_sequence(
270 sequence.map(|(channel, sample_time)| ((channel.channel, channel.is_differential), sample_time)),
271 );
272
273 // On chips with differential channels, enable after configure_sequence to allow setting differential channels
274 //
275 // TODO: If hardware allows, enable after configure_sequence on all chips
276 #[cfg(any(adc_g4, adc_h5))]
277 T::regs().enable();
278 T::regs().configure_dma(ConversionMode::Singular);
279
280 let request = rx_dma.request();
281 let transfer =
282 unsafe { crate::dma::Transfer::new_read(rx_dma, request, T::regs().data(), readings, Default::default()) };
283
284 T::regs().start();
285
286 // Wait for conversion sequence to finish.
287 transfer.await;
288
289 // Ensure conversions are finished.
290 T::regs().stop();
291 }
292
293 #[cfg(any(adc_v2, adc_g4, adc_v3, adc_g0, adc_u0))]
294 /// Configures the ADC to use a DMA ring buffer for continuous data acquisition.
295 ///
296 /// Use the [`read`] method to retrieve measurements from the DMA ring buffer. The read buffer
297 /// should be exactly half the size of `dma_buf`. When using triggered mode, it is recommended
298 /// to configure `dma_buf` as a double buffer so that one half can be read while the other half
299 /// is being filled by the DMA, preventing data loss. The trigger period of the ADC effectively
300 /// defines the period at which the buffer should be read.
301 ///
302 /// If continous conversion mode is selected, the provided `dma_buf` must be large enough to prevent
303 /// DMA buffer overruns. Its length should be a multiple of the number of ADC channels being measured.
304 /// For example, if 3 channels are measured and you want to store 40 samples per channel,
305 /// the buffer length should be `3 * 40 = 120`.
306 ///
307 /// # Parameters
308 /// - `dma`: The DMA peripheral used to transfer ADC data into the buffer.
309 /// - `dma_buf`: The buffer where DMA stores ADC samples.
310 /// - `regular_sequence`: Sequence of channels and sample times for regular ADC conversions.
311 /// - `regular_conversion_mode`: Mode for regular conversions (continuous or triggered).
312 ///
313 /// # Returns
314 /// A `RingBufferedAdc<'a, T>` instance configured for continuous DMA-based sampling.
315 ///
316 /// Note: Depending on hardware limitations, this method may require channels to be passed
317 /// in order or require the sequence to have the same sample time for all channnels, depending
318 /// on the number and properties of the channels in the sequence. This method will panic if
319 /// the hardware cannot deliver the requested configuration.
320 pub fn into_ring_buffered<'a, 'b>(
321 self,
322 dma: embassy_hal_internal::Peri<'a, impl RxDma<T>>,
323 dma_buf: &'a mut [u16],
324 sequence: impl ExactSizeIterator<Item = (AnyAdcChannel<'b, T>, <T::Regs as BasicAdcRegs>::SampleTime)>,
325 mode: RegularConversionMode,
326 ) -> RingBufferedAdc<'a, T> {
327 assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF);
328 assert!(sequence.len() != 0, "Asynchronous read sequence cannot be empty");
329 assert!(
330 sequence.len() <= 16,
331 "Asynchronous read sequence cannot be more than 16 in length"
332 );
333 // Ensure no conversions are ongoing
334 T::regs().stop();
335 #[cfg(any(adc_g0, adc_v3, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_wba, adc_c0))]
336 T::regs().enable();
337
338 T::regs().configure_sequence(
339 sequence.map(|(channel, sample_time)| ((channel.channel, channel.is_differential), sample_time)),
340 );
341
342 // On chips with differential channels, enable after configure_sequence to allow setting differential channels
343 //
344 // TODO: If hardware allows, enable after configure_sequence on all chips
345 #[cfg(any(adc_g4, adc_h5))]
346 T::regs().enable();
347 T::regs().configure_dma(ConversionMode::Repeated(mode));
348
349 core::mem::forget(self);
350
351 RingBufferedAdc::new(dma, dma_buf)
352 }
353}
354
355pub(self) trait SpecialChannel {}
356
357/// Implemented for ADCs that have a special channel
358trait SealedSpecialConverter<T: SpecialChannel + Sized> {
359 const CHANNEL: u8;
360}
361
362#[allow(private_bounds)]
363pub trait SpecialConverter<T: SpecialChannel + Sized>: SealedSpecialConverter<T> {}
364
365impl<C: SpecialChannel + Sized, T: SealedSpecialConverter<C>> SpecialConverter<C> for T {}
366
367impl<C: SpecialChannel, T: Instance + SealedSpecialConverter<C>> AdcChannel<T> for C {}
368impl<C: SpecialChannel, T: Instance + SealedSpecialConverter<C>> SealedAdcChannel<T> for C {
369 fn channel(&self) -> u8 {
370 T::CHANNEL
98 } 371 }
99} 372}
100 373
374pub struct VrefInt;
375impl SpecialChannel for VrefInt {}
376
377impl VrefInt {
378 #[cfg(any(adc_f3v1, adc_f3v2))]
379 /// The value that vref would be if vdda was at 3300mv
380 pub fn calibrated_value(&self) -> u16 {
381 crate::pac::VREFINTCAL.data().read()
382 }
383}
384
385/// Internal temperature channel.
386pub struct Temperature;
387impl SpecialChannel for Temperature {}
388
389/// Internal battery voltage channel.
390pub struct Vbat;
391impl SpecialChannel for Vbat {}
392
393/// Vcore channel.
394pub struct Vcore;
395impl SpecialChannel for Vcore {}
396
397/// Internal dac channel.
398pub struct Dac;
399impl SpecialChannel for Dac {}
400
101/// ADC instance. 401/// ADC instance.
102#[cfg(not(any( 402#[cfg(not(any(
103 adc_f1, adc_v1, adc_l0, adc_v2, adc_v3, adc_v4, adc_g4, adc_f3v1, adc_f3v2, adc_g0, adc_u0, adc_h5, adc_h7rs, 403 adc_f1, adc_v1, adc_l0, adc_v2, adc_v3, adc_v4, adc_g4, adc_f3v1, adc_f3v2, adc_g0, adc_u0, adc_h5, adc_h7rs,
@@ -121,12 +421,16 @@ pub trait Instance: SealedInstance + crate::PeripheralType + crate::rcc::RccPeri
121#[allow(private_bounds)] 421#[allow(private_bounds)]
122pub trait AdcChannel<T>: SealedAdcChannel<T> + Sized { 422pub trait AdcChannel<T>: SealedAdcChannel<T> + Sized {
123 #[allow(unused_mut)] 423 #[allow(unused_mut)]
124 fn degrade_adc(mut self) -> AnyAdcChannel<T> { 424 fn degrade_adc<'a>(mut self) -> AnyAdcChannel<'a, T>
125 #[cfg(any(adc_v1, adc_l0, adc_v2, adc_g4, adc_v4, adc_u5, adc_wba))] 425 where
426 Self: 'a,
427 {
428 #[cfg(any(adc_v1, adc_l0, adc_v2, adc_g4, adc_v3, adc_v4, adc_u5, adc_wba))]
126 self.setup(); 429 self.setup();
127 430
128 AnyAdcChannel { 431 AnyAdcChannel {
129 channel: self.channel(), 432 channel: self.channel(),
433 is_differential: self.is_differential(),
130 _phantom: PhantomData, 434 _phantom: PhantomData,
131 } 435 }
132 } 436 }
@@ -136,34 +440,57 @@ pub trait AdcChannel<T>: SealedAdcChannel<T> + Sized {
136/// 440///
137/// This is useful in scenarios where you need the ADC channels to have the same type, such as 441/// This is useful in scenarios where you need the ADC channels to have the same type, such as
138/// storing them in an array. 442/// storing them in an array.
139pub struct AnyAdcChannel<T> { 443pub struct AnyAdcChannel<'a, T> {
140 channel: u8, 444 channel: u8,
141 _phantom: PhantomData<T>, 445 is_differential: bool,
446 _phantom: PhantomData<&'a mut T>,
142} 447}
143impl_peripheral!(AnyAdcChannel<T: Instance>); 448impl<T: Instance> AdcChannel<T> for AnyAdcChannel<'_, T> {}
144impl<T: Instance> AdcChannel<T> for AnyAdcChannel<T> {} 449impl<T: Instance> SealedAdcChannel<T> for AnyAdcChannel<'_, T> {
145impl<T: Instance> SealedAdcChannel<T> for AnyAdcChannel<T> {
146 fn channel(&self) -> u8 { 450 fn channel(&self) -> u8 {
147 self.channel 451 self.channel
148 } 452 }
453
454 fn is_differential(&self) -> bool {
455 self.is_differential
456 }
149} 457}
150 458
151impl<T> AnyAdcChannel<T> { 459impl<T> AnyAdcChannel<'_, T> {
152 #[allow(unused)] 460 #[allow(unused)]
153 pub fn get_hw_channel(&self) -> u8 { 461 pub fn get_hw_channel(&self) -> u8 {
154 self.channel 462 self.channel
155 } 463 }
156} 464}
465
466#[cfg(not(adc_wba))]
467impl BasicAdcRegs for crate::pac::adc::Adc {
468 type SampleTime = SampleTime;
469}
470
471#[cfg(any(adc_wba, adc_u5))]
472impl BasicAdcRegs for crate::pac::adc::Adc4 {
473 type SampleTime = Adc4SampleTime;
474}
475
157#[cfg(adc_wba)] 476#[cfg(adc_wba)]
158foreach_adc!( 477foreach_adc!(
159 (ADC4, $common_inst:ident, $clock:ident) => { 478 (ADC4, $common_inst:ident, $clock:ident) => {
160 impl crate::adc::adc4::SealedInstance for peripherals::ADC4 { 479 impl crate::adc::BasicInstance for peripherals::ADC4 {
161 fn regs() -> crate::pac::adc::Adc4 { 480 type Regs = crate::pac::adc::Adc4;
481 }
482
483 impl crate::adc::SealedInstance for peripherals::ADC4 {
484 fn regs() -> Self::Regs {
162 crate::pac::ADC4 485 crate::pac::ADC4
163 } 486 }
487
488 fn common_regs() -> crate::pac::adccommon::AdcCommon {
489 return crate::pac::$common_inst
490 }
164 } 491 }
165 492
166 impl crate::adc::adc4::Instance for peripherals::ADC4 { 493 impl crate::adc::Instance for peripherals::ADC4 {
167 type Interrupt = crate::_generated::peripheral_interrupts::ADC4::GLOBAL; 494 type Interrupt = crate::_generated::peripheral_interrupts::ADC4::GLOBAL;
168 } 495 }
169 }; 496 };
@@ -188,20 +515,32 @@ foreach_adc!(
188#[cfg(adc_u5)] 515#[cfg(adc_u5)]
189foreach_adc!( 516foreach_adc!(
190 (ADC4, $common_inst:ident, $clock:ident) => { 517 (ADC4, $common_inst:ident, $clock:ident) => {
191 impl crate::adc::adc4::SealedInstance for peripherals::ADC4 { 518 impl crate::adc::BasicInstance for peripherals::ADC4 {
192 fn regs() -> crate::pac::adc::Adc4 { 519 type Regs = crate::pac::adc::Adc4;
520 }
521
522 impl crate::adc::SealedInstance for peripherals::ADC4 {
523 fn regs() -> Self::Regs {
193 crate::pac::ADC4 524 crate::pac::ADC4
194 } 525 }
526
527 fn common_regs() -> crate::pac::adccommon::AdcCommon {
528 return crate::pac::$common_inst
529 }
195 } 530 }
196 531
197 impl crate::adc::adc4::Instance for peripherals::ADC4 { 532 impl crate::adc::Instance for peripherals::ADC4 {
198 type Interrupt = crate::_generated::peripheral_interrupts::ADC4::GLOBAL; 533 type Interrupt = crate::_generated::peripheral_interrupts::ADC4::GLOBAL;
199 } 534 }
200 }; 535 };
201 536
202 ($inst:ident, $common_inst:ident, $clock:ident) => { 537 ($inst:ident, $common_inst:ident, $clock:ident) => {
538 impl crate::adc::BasicInstance for peripherals::$inst {
539 type Regs = crate::pac::adc::Adc;
540 }
541
203 impl crate::adc::SealedInstance for peripherals::$inst { 542 impl crate::adc::SealedInstance for peripherals::$inst {
204 fn regs() -> crate::pac::adc::Adc { 543 fn regs() -> Self::Regs {
205 crate::pac::$inst 544 crate::pac::$inst
206 } 545 }
207 546
@@ -219,14 +558,23 @@ foreach_adc!(
219#[cfg(not(any(adc_u5, adc_wba)))] 558#[cfg(not(any(adc_u5, adc_wba)))]
220foreach_adc!( 559foreach_adc!(
221 ($inst:ident, $common_inst:ident, $clock:ident) => { 560 ($inst:ident, $common_inst:ident, $clock:ident) => {
561 impl crate::adc::BasicInstance for peripherals::$inst {
562 #[cfg(any(
563 adc_v2, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_wba, adc_g4, adc_c0
564 ))]
565 type Regs = crate::pac::adc::Adc;
566 }
567
222 impl crate::adc::SealedInstance for peripherals::$inst { 568 impl crate::adc::SealedInstance for peripherals::$inst {
223 #[cfg(not(adc_wba))] 569 #[cfg(any(
224 fn regs() -> crate::pac::adc::Adc { 570 adc_v2, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_wba, adc_g4, adc_c0
571 ))]
572 fn regs() -> Self::Regs {
225 crate::pac::$inst 573 crate::pac::$inst
226 } 574 }
227 575
228 #[cfg(adc_wba)] 576 #[cfg(any(adc_f1, adc_f3v1, adc_f3v2, adc_v1, adc_l0))]
229 fn regs() -> crate::pac::adc::Adc4 { 577 fn regs() -> crate::pac::adc::Adc {
230 crate::pac::$inst 578 crate::pac::$inst
231 } 579 }
232 580
@@ -252,7 +600,7 @@ macro_rules! impl_adc_pin {
252 ($inst:ident, $pin:ident, $ch:expr) => { 600 ($inst:ident, $pin:ident, $ch:expr) => {
253 impl crate::adc::AdcChannel<peripherals::$inst> for crate::Peri<'_, crate::peripherals::$pin> {} 601 impl crate::adc::AdcChannel<peripherals::$inst> for crate::Peri<'_, crate::peripherals::$pin> {}
254 impl crate::adc::SealedAdcChannel<peripherals::$inst> for crate::Peri<'_, crate::peripherals::$pin> { 602 impl crate::adc::SealedAdcChannel<peripherals::$inst> for crate::Peri<'_, crate::peripherals::$pin> {
255 #[cfg(any(adc_v1, adc_c0, adc_l0, adc_v2, adc_g4, adc_v4, adc_u5, adc_wba))] 603 #[cfg(any(adc_v1, adc_c0, adc_l0, adc_v2, adc_g4, adc_v3, adc_v4, adc_u5, adc_wba))]
256 fn setup(&mut self) { 604 fn setup(&mut self) {
257 <crate::peripherals::$pin as crate::gpio::SealedPin>::set_as_analog(self); 605 <crate::peripherals::$pin as crate::gpio::SealedPin>::set_as_analog(self);
258 } 606 }
@@ -264,6 +612,39 @@ macro_rules! impl_adc_pin {
264 }; 612 };
265} 613}
266 614
615#[allow(unused_macros)]
616macro_rules! impl_adc_pair {
617 ($inst:ident, $pin:ident, $npin:ident, $ch:expr) => {
618 impl crate::adc::AdcChannel<peripherals::$inst>
619 for (
620 crate::Peri<'_, crate::peripherals::$pin>,
621 crate::Peri<'_, crate::peripherals::$npin>,
622 )
623 {
624 }
625 impl crate::adc::SealedAdcChannel<peripherals::$inst>
626 for (
627 crate::Peri<'_, crate::peripherals::$pin>,
628 crate::Peri<'_, crate::peripherals::$npin>,
629 )
630 {
631 #[cfg(any(adc_v1, adc_c0, adc_l0, adc_v2, adc_g4, adc_v3, adc_v4, adc_u5, adc_wba))]
632 fn setup(&mut self) {
633 <crate::peripherals::$pin as crate::gpio::SealedPin>::set_as_analog(&mut self.0);
634 <crate::peripherals::$npin as crate::gpio::SealedPin>::set_as_analog(&mut self.1);
635 }
636
637 fn channel(&self) -> u8 {
638 $ch
639 }
640
641 fn is_differential(&self) -> bool {
642 true
643 }
644 }
645 };
646}
647
267/// Get the maximum reading value for this resolution. 648/// Get the maximum reading value for this resolution.
268/// 649///
269/// This is `2**n - 1`. 650/// This is `2**n - 1`.