aboutsummaryrefslogtreecommitdiff
path: root/embassy-mcxa
diff options
context:
space:
mode:
authorJames Munns <[email protected]>2025-12-11 15:34:38 +0100
committerJames Munns <[email protected]>2025-12-11 15:34:38 +0100
commitefdfb3c0892f45223e8d8527e5f032fef475944e (patch)
tree1dbcae8f17a065bb307d4a95a330c6413571c0ac /embassy-mcxa
parente932dc131e94f30db32b3fc9fbce8cd929555820 (diff)
Refactor the API
Diffstat (limited to 'embassy-mcxa')
-rw-r--r--embassy-mcxa/src/adc.rs642
1 files changed, 365 insertions, 277 deletions
diff --git a/embassy-mcxa/src/adc.rs b/embassy-mcxa/src/adc.rs
index d7d17cf5f..e4b24cffa 100644
--- a/embassy-mcxa/src/adc.rs
+++ b/embassy-mcxa/src/adc.rs
@@ -1,4 +1,5 @@
1//! ADC driver 1//! ADC driver
2use core::future::Future;
2use core::marker::PhantomData; 3use core::marker::PhantomData;
3 4
4use embassy_hal_internal::{Peri, PeripheralType}; 5use embassy_hal_internal::{Peri, PeripheralType};
@@ -12,12 +13,10 @@ use crate::interrupt::typelevel::{Handler, Interrupt};
12use crate::pac; 13use crate::pac;
13use crate::pac::adc1::cfg::{HptExdi, Pwrsel, Refsel, Tcmdres, Tprictrl, Tres}; 14use crate::pac::adc1::cfg::{HptExdi, Pwrsel, Refsel, Tcmdres, Tprictrl, Tres};
14use crate::pac::adc1::cmdh1::{Avgs, Cmpen, Next, Sts}; 15use crate::pac::adc1::cmdh1::{Avgs, Cmpen, Next, Sts};
15use crate::pac::adc1::cmdl1::{Adch, Mode}; 16use crate::pac::adc1::cmdl1::Mode;
16use crate::pac::adc1::ctrl::CalAvgs; 17use crate::pac::adc1::ctrl::CalAvgs;
17use crate::pac::adc1::tctrl::{Tcmd, Tpri}; 18use crate::pac::adc1::tctrl::{Tcmd, Tpri};
18 19
19const G_LPADC_RESULT_SHIFT: u32 = 0;
20
21/// Trigger priority policy for ADC conversions. 20/// Trigger priority policy for ADC conversions.
22#[derive(Debug, Clone, Copy, PartialEq, Eq)] 21#[derive(Debug, Clone, Copy, PartialEq, Eq)]
23#[repr(u8)] 22#[repr(u8)]
@@ -59,10 +58,6 @@ pub struct LpadcConfig {
59 /// Controls the duration of pausing during command execution sequencing. The pause delay is a count of (convPauseDelay*4) ADCK cycles. 58 /// Controls the duration of pausing during command execution sequencing. The pause delay is a count of (convPauseDelay*4) ADCK cycles.
60 /// Only available when ADC pausing function is enabled. The available value range is in 9-bit. 59 /// Only available when ADC pausing function is enabled. The available value range is in 9-bit.
61 pub conv_pause_delay: u16, 60 pub conv_pause_delay: u16,
62 /// FIFO watermark level for interrupt generation.
63 /// When the number of datawords stored in the ADC Result FIFO is greater than the value in this field,
64 /// the ready flag would be asserted to indicate stored data has reached the programmable threshold.
65 pub fifo_watermark: u8,
66 /// Power configuration (normal/deep sleep behavior) 61 /// Power configuration (normal/deep sleep behavior)
67 pub power: PoweredClock, 62 pub power: PoweredClock,
68 /// ADC clock source selection 63 /// ADC clock source selection
@@ -83,7 +78,6 @@ impl Default for LpadcConfig {
83 trigger_priority_policy: TriggerPriorityPolicy::ConvPreemptImmediatelyNotAutoResumed, 78 trigger_priority_policy: TriggerPriorityPolicy::ConvPreemptImmediatelyNotAutoResumed,
84 enable_conv_pause: false, 79 enable_conv_pause: false,
85 conv_pause_delay: 0, 80 conv_pause_delay: 0,
86 fifo_watermark: 0,
87 power: PoweredClock::NormalEnabledDeepSleepDisabled, 81 power: PoweredClock::NormalEnabledDeepSleepDisabled,
88 source: AdcClockSel::FroLfDiv, 82 source: AdcClockSel::FroLfDiv,
89 div: Div4::no_div(), 83 div: Div4::no_div(),
@@ -96,7 +90,6 @@ impl Default for LpadcConfig {
96/// Defines the parameters for a single ADC conversion operation. 90/// Defines the parameters for a single ADC conversion operation.
97#[derive(Debug, Clone, Copy, PartialEq, Eq)] 91#[derive(Debug, Clone, Copy, PartialEq, Eq)]
98pub struct ConvCommandConfig { 92pub struct ConvCommandConfig {
99 pub channel_number: Adch,
100 pub chained_next_command_number: Next, 93 pub chained_next_command_number: Next,
101 pub enable_auto_channel_increment: bool, 94 pub enable_auto_channel_increment: bool,
102 pub loop_count: u8, 95 pub loop_count: u8,
@@ -109,6 +102,23 @@ pub struct ConvCommandConfig {
109 pub enable_wait_trigger: bool, 102 pub enable_wait_trigger: bool,
110} 103}
111 104
105impl Default for ConvCommandConfig {
106 fn default() -> Self {
107 ConvCommandConfig {
108 chained_next_command_number: Next::NoNextCmdTerminateOnFinish,
109 enable_auto_channel_increment: false,
110 loop_count: 0,
111 hardware_average_mode: Avgs::NoAverage,
112 sample_time_mode: Sts::Sample3p5,
113 hardware_compare_mode: Cmpen::DisabledAlwaysStoreResult,
114 hardware_compare_value_high: 0,
115 hardware_compare_value_low: 0,
116 conversion_resolution_mode: Mode::Data12Bits,
117 enable_wait_trigger: false,
118 }
119 }
120}
121
112/// Configuration for a conversion trigger. 122/// Configuration for a conversion trigger.
113/// 123///
114/// Defines how a trigger initiates ADC conversions. 124/// Defines how a trigger initiates ADC conversions.
@@ -120,6 +130,17 @@ pub struct ConvTriggerConfig {
120 pub enable_hardware_trigger: bool, 130 pub enable_hardware_trigger: bool,
121} 131}
122 132
133impl Default for ConvTriggerConfig {
134 fn default() -> Self {
135 ConvTriggerConfig {
136 target_command_id: Tcmd::NotValid,
137 delay_power: 0,
138 priority: Tpri::HighestPriority,
139 enable_hardware_trigger: false,
140 }
141 }
142}
143
123/// Shorthand for `Result<T>`. 144/// Shorthand for `Result<T>`.
124pub type Result<T> = core::result::Result<T, Error>; 145pub type Result<T> = core::result::Result<T, Error>;
125 146
@@ -155,6 +176,7 @@ pub struct InterruptHandler<I: Instance> {
155pub struct Adc<'a, I: Instance, M: ModeAdc> { 176pub struct Adc<'a, I: Instance, M: ModeAdc> {
156 _inst: PhantomData<&'a mut I>, 177 _inst: PhantomData<&'a mut I>,
157 _phantom: PhantomData<M>, 178 _phantom: PhantomData<M>,
179 index: u8,
158} 180}
159 181
160impl<'a, I: Instance> Adc<'a, I, Blocking> { 182impl<'a, I: Instance> Adc<'a, I, Blocking> {
@@ -166,6 +188,104 @@ impl<'a, I: Instance> Adc<'a, I, Blocking> {
166 pub fn new_blocking(_inst: Peri<'a, I>, pin: Peri<'a, impl AdcPin<I>>, config: LpadcConfig) -> Result<Self> { 188 pub fn new_blocking(_inst: Peri<'a, I>, pin: Peri<'a, impl AdcPin<I>>, config: LpadcConfig) -> Result<Self> {
167 Self::new_inner(_inst, pin, config) 189 Self::new_inner(_inst, pin, config)
168 } 190 }
191
192 /// Enable ADC interrupts.
193 ///
194 /// Enables the interrupt sources specified in the bitmask.
195 ///
196 /// # Arguments
197 /// * `mask` - Bitmask of interrupt sources to enable
198 pub fn enable_interrupt(&mut self, mask: u32) {
199 let adc = I::ptr();
200 adc.ie().modify(|r, w| unsafe { w.bits(r.bits() | mask) });
201 }
202
203 /// Disable ADC interrupts.
204 ///
205 /// Disables the interrupt sources specified in the bitmask.
206 ///
207 /// # Arguments
208 /// * `mask` - Bitmask of interrupt sources to disable
209 pub fn disable_interrupt(&mut self, mask: u32) {
210 let adc = I::ptr();
211 adc.ie().modify(|r, w| unsafe { w.bits(r.bits() & !mask) });
212 }
213
214 pub fn set_fifo_watermark(&mut self, watermark: u8) -> Result<()> {
215 if watermark > 0b111 {
216 return Err(Error::InvalidConfig);
217 }
218 I::ptr().fctrl0().modify(|_r, w| unsafe { w.fwmark().bits(watermark) });
219 Ok(())
220 }
221
222 /// Trigger ADC conversion(s) via software.
223 ///
224 /// Initiates conversion(s) for the trigger(s) specified in the bitmask.
225 /// Each bit in the mask corresponds to a trigger ID (bit 0 = trigger 0, etc.).
226 ///
227 /// # Arguments
228 /// * `trigger_id_mask` - Bitmask of trigger IDs to activate (bit N = trigger N)
229 ///
230 /// # Returns
231 /// * `Ok(())` if the triger mask was valid
232 /// * `Err(Error::InvalidConfig)` if the mask was greater than `0b1111`
233 pub fn do_software_trigger(&self, trigger_id_mask: u8) -> Result<()> {
234 if trigger_id_mask > 0b1111 {
235 return Err(Error::InvalidConfig);
236 }
237 let adc = I::ptr();
238 adc.swtrig().write(|w| unsafe { w.bits(trigger_id_mask as u32) });
239 Ok(())
240 }
241
242 /// Set conversion command configuration.
243 ///
244 /// Configures a conversion command slot with the specified parameters.
245 /// Commands define how conversions are performed (channel, resolution, etc.).
246 ///
247 /// # Arguments
248 /// * `index` - Command index (Must be in range 1..=7)
249 /// * `config` - Command configuration
250 ///
251 /// # Returns
252 /// * `Ok(())` if the command was configured successfully
253 /// * `Err(Error::InvalidConfig)` if the index is out of range
254 pub fn set_conv_command_config(&self, index: usize, config: &ConvCommandConfig) -> Result<()> {
255 self.set_conv_command_config_inner(index, config)
256 }
257
258 /// Set conversion trigger configuration.
259 ///
260 /// Configures a trigger to initiate conversions. Triggers can be
261 /// activated by software or hardware signals.
262 ///
263 /// # Arguments
264 /// * `trigger_id` - Trigger index (0..=3)
265 /// * `config` - Trigger configuration
266 pub fn set_conv_trigger_config(&self, trigger_id: usize, config: &ConvTriggerConfig) -> Result<()> {
267 self.set_conv_trigger_config_inner(trigger_id, config)
268 }
269
270 /// Reset the FIFO buffer.
271 ///
272 /// Clears all pending conversion results from the FIFO.
273 pub fn do_reset_fifo(&self) {
274 let adc = I::ptr();
275 adc.ctrl().modify(|_, w| w.rstfifo0().trigger_reset());
276 }
277
278 /// Get conversion result from FIFO.
279 ///
280 /// Reads and returns the next conversion result from the FIFO.
281 /// Returns `None` if the FIFO is empty.
282 ///
283 /// # Returns
284 /// - `Some(ConvResult)` if a result is available
285 /// - `Err(Error::FifoEmpty)` if the FIFO is empty
286 pub fn get_conv_result(&self) -> Result<ConvResult> {
287 self.get_conv_result_inner()
288 }
169} 289}
170 290
171impl<'a, I: Instance> Adc<'a, I, Async> { 291impl<'a, I: Instance> Adc<'a, I, Async> {
@@ -182,12 +302,65 @@ impl<'a, I: Instance> Adc<'a, I, Async> {
182 _irq: impl crate::interrupt::typelevel::Binding<I::Interrupt, InterruptHandler<I>> + 'a, 302 _irq: impl crate::interrupt::typelevel::Binding<I::Interrupt, InterruptHandler<I>> + 'a,
183 config: LpadcConfig, 303 config: LpadcConfig,
184 ) -> Result<Self> { 304 ) -> Result<Self> {
185 let adc = Self::new_inner(_inst, pin, config); 305 let adc = Self::new_inner(_inst, pin, config)?;
186 306
187 I::Interrupt::unpend(); 307 I::Interrupt::unpend();
188 unsafe { I::Interrupt::enable() }; 308 unsafe { I::Interrupt::enable() };
189 309
190 adc 310 let cfg = ConvCommandConfig {
311 chained_next_command_number: Next::NoNextCmdTerminateOnFinish,
312 enable_auto_channel_increment: false,
313 loop_count: 0,
314 hardware_average_mode: Avgs::NoAverage, // todo: good config?
315 sample_time_mode: Sts::Sample3p5, // todo: good config?
316 hardware_compare_mode: Cmpen::DisabledAlwaysStoreResult,
317 hardware_compare_value_high: 0,
318 hardware_compare_value_low: 0,
319 conversion_resolution_mode: Mode::Data16Bits, // todo: good config?
320 enable_wait_trigger: false,
321 };
322
323 // We always use command 1, so this cannot fail
324 _ = adc.set_conv_command_config_inner(1, &cfg);
325
326 let cfg = ConvTriggerConfig {
327 target_command_id: Tcmd::ExecuteCmd1,
328 delay_power: 0,
329 priority: Tpri::HighestPriority,
330 enable_hardware_trigger: false,
331 };
332
333 // We always use trigger 0, so this cannot fail
334 _ = adc.set_conv_trigger_config_inner(0, &cfg);
335
336 // We always set the watermark to 0 (trigger when 1 is available)
337 I::ptr().fctrl0().modify(|_r, w| unsafe { w.fwmark().bits(0) });
338
339 Ok(adc)
340 }
341
342 /// Set the number of averages
343 pub fn set_averages(&mut self, avgs: Avgs) {
344 // TODO: we should probably return a result or wait for idle?
345 // "A write to a CMD buffer while that CMD buffer is controlling the ADC operation may cause unpredictable behavior."
346 I::ptr().cmdh1().modify(|_r, w| w.avgs().variant(avgs));
347 }
348
349 /// Set the sample time
350 pub fn set_sample_time(&mut self, st: Sts) {
351 // TODO: we should probably return a result or wait for idle?
352 // "A write to a CMD buffer while that CMD buffer is controlling the ADC operation may cause unpredictable behavior."
353 I::ptr().cmdh1().modify(|_r, w| w.sts().variant(st));
354 }
355
356 pub fn set_resolution(&mut self, mode: Mode) {
357 // TODO: we should probably return a result or wait for idle?
358 // "A write to a CMD buffer while that CMD buffer is controlling the ADC operation may cause unpredictable behavior."
359 I::ptr().cmdl1().modify(|_r, w| w.mode().variant(mode));
360 }
361
362 fn wait_idle(&mut self) -> impl Future<Output = core::result::Result<(), maitake_sync::Closed>> + use<'_, I> {
363 I::wait_cell().wait_for(|| I::ptr().ie().read().fwmie0().bit_is_clear())
191 } 364 }
192 365
193 /// Read ADC value asynchronously. 366 /// Read ADC value asynchronously.
@@ -203,21 +376,29 @@ impl<'a, I: Instance> Adc<'a, I, Async> {
203 /// # Returns 376 /// # Returns
204 /// 16-bit ADC conversion value 377 /// 16-bit ADC conversion value
205 pub async fn read(&mut self) -> Result<u16> { 378 pub async fn read(&mut self) -> Result<u16> {
206 let wait = I::wait_cell().subscribe().await; 379 let adc = I::ptr();
207 380
208 Adc::<'a, I, Async>::enable_interrupt(self, 0x1); 381 // If we cancelled a previous read, we might still be busy, wait
209 Adc::<'a, I, Async>::do_software_trigger(self, 1); 382 // until the interrupt is cleared (done by the interrupt)
383 _ = self.wait_idle().await;
210 384
211 let _ = wait.await; 385 // Clear the fifo
386 adc.ctrl().modify(|_, w| w.rstfifo0().trigger_reset());
387
388 // Trigger a new conversion
389 adc.ie().modify(|_r, w| w.fwmie0().set_bit());
390 adc.swtrig().write(|w| w.swt0().set_bit());
212 391
213 let result = Adc::<'a, I, Async>::get_conv_result(self).unwrap().conv_value >> G_LPADC_RESULT_SHIFT; 392 // Wait for completion
214 Ok(result) 393 _ = self.wait_idle().await;
394
395 self.get_conv_result_inner().map(|r| r.conv_value)
215 } 396 }
216} 397}
217 398
218impl<'a, I: Instance, M: ModeAdc> Adc<'a, I, M> { 399impl<'a, I: Instance, M: ModeAdc> Adc<'a, I, M> {
219 /// Internal initialization function shared by `new_async` and `new_blocking`. 400 /// Internal initialization function shared by `new_async` and `new_blocking`.
220 fn new_inner(_inst: Peri<'a, I>, pin: Peri<'a, impl AdcPin<I>>, config: LpadcConfig) -> Result<Self> { 401 fn new_inner<P: AdcPin<I>>(_inst: Peri<'a, I>, pin: Peri<'a, P>, config: LpadcConfig) -> Result<Self> {
221 let adc = I::ptr(); 402 let adc = I::ptr();
222 403
223 _ = unsafe { 404 _ = unsafe {
@@ -241,22 +422,16 @@ impl<'a, I: Instance, M: ModeAdc> Adc<'a, I, M> {
241 adc.ctrl().modify(|_, w| w.adcen().disabled()); 422 adc.ctrl().modify(|_, w| w.adcen().disabled());
242 423
243 /* Configure the module generally. */ 424 /* Configure the module generally. */
244 if config.enable_in_doze_mode { 425 adc.ctrl().modify(|_, w| w.dozen().bit(config.enable_in_doze_mode));
245 adc.ctrl().modify(|_, w| w.dozen().enabled());
246 } else {
247 adc.ctrl().modify(|_, w| w.dozen().disabled());
248 }
249 426
250 /* Set calibration average mode. */ 427 /* Set calibration average mode. */
251 adc.ctrl() 428 adc.ctrl()
252 .modify(|_, w| w.cal_avgs().variant(config.conversion_average_mode)); 429 .modify(|_, w| w.cal_avgs().variant(config.conversion_average_mode));
253 430
254 adc.cfg().write(|w| unsafe { 431 adc.cfg().write(|w| unsafe {
255 let w = if config.enable_analog_preliminary { 432 if config.enable_analog_preliminary {
256 w.pwren().pre_enabled() 433 w.pwren().pre_enabled();
257 } else { 434 }
258 w
259 };
260 435
261 w.pudly() 436 w.pudly()
262 .bits(config.power_up_delay) 437 .bits(config.power_up_delay)
@@ -306,8 +481,7 @@ impl<'a, I: Instance, M: ModeAdc> Adc<'a, I, M> {
306 adc.pause().write(|w| unsafe { w.bits(0) }); 481 adc.pause().write(|w| unsafe { w.bits(0) });
307 } 482 }
308 483
309 adc.fctrl0() 484 adc.fctrl0().write(|w| unsafe { w.fwmark().bits(0) });
310 .write(|w| unsafe { w.fwmark().bits(config.fifo_watermark) });
311 485
312 // Enable ADC 486 // Enable ADC
313 adc.ctrl().modify(|_, w| w.adcen().enabled()); 487 adc.ctrl().modify(|_, w| w.adcen().enabled());
@@ -315,15 +489,10 @@ impl<'a, I: Instance, M: ModeAdc> Adc<'a, I, M> {
315 Ok(Self { 489 Ok(Self {
316 _inst: PhantomData, 490 _inst: PhantomData,
317 _phantom: PhantomData, 491 _phantom: PhantomData,
492 index: P::CHANNEL,
318 }) 493 })
319 } 494 }
320 495
321 /// Deinitialize the ADC peripheral.
322 pub fn deinit(&self) {
323 let adc = I::ptr();
324 adc.ctrl().modify(|_, w| w.adcen().disabled());
325 }
326
327 /// Perform offset calibration. 496 /// Perform offset calibration.
328 /// Waits for calibration to complete before returning. 497 /// Waits for calibration to complete before returning.
329 pub fn do_offset_calibration(&self) { 498 pub fn do_offset_calibration(&self) {
@@ -369,7 +538,7 @@ impl<'a, I: Instance, M: ModeAdc> Adc<'a, I, M> {
369 while adc.gcc0().read().rdy().is_gain_cal_not_valid() {} 538 while adc.gcc0().read().rdy().is_gain_cal_not_valid() {}
370 539
371 let mut gcca = adc.gcc0().read().gain_cal().bits() as u32; 540 let mut gcca = adc.gcc0().read().gain_cal().bits() as u32;
372 if gcca & ((0xFFFF + 1) >> 1) != 0 { 541 if gcca & 0x8000 != 0 {
373 gcca |= !0xFFFF; 542 gcca |= !0xFFFF;
374 } 543 }
375 544
@@ -384,127 +553,58 @@ impl<'a, I: Instance, M: ModeAdc> Adc<'a, I, M> {
384 while adc.stat().read().cal_rdy().is_not_set() {} 553 while adc.stat().read().cal_rdy().is_not_set() {}
385 } 554 }
386 555
387 /// Trigger ADC conversion(s) via software. 556 fn set_conv_command_config_inner(&self, index: usize, config: &ConvCommandConfig) -> Result<()> {
388 ///
389 /// Initiates conversion(s) for the trigger(s) specified in the bitmask.
390 /// Each bit in the mask corresponds to a trigger ID (bit 0 = trigger 0, etc.).
391 ///
392 /// # Arguments
393 /// * `trigger_id_mask` - Bitmask of trigger IDs to activate (bit N = trigger N)
394 pub fn do_software_trigger(&self, trigger_id_mask: u32) {
395 let adc = I::ptr(); 557 let adc = I::ptr();
396 adc.swtrig().write(|w| unsafe { w.bits(trigger_id_mask) });
397 }
398
399 /// Get default conversion command configuration.
400 /// # Returns
401 /// Default conversion command configuration
402 pub fn get_default_conv_command_config(&self) -> ConvCommandConfig {
403 ConvCommandConfig {
404 channel_number: Adch::SelectCh0,
405 chained_next_command_number: Next::NoNextCmdTerminateOnFinish,
406 enable_auto_channel_increment: false,
407 loop_count: 0,
408 hardware_average_mode: Avgs::NoAverage,
409 sample_time_mode: Sts::Sample3p5,
410 hardware_compare_mode: Cmpen::DisabledAlwaysStoreResult,
411 hardware_compare_value_high: 0,
412 hardware_compare_value_low: 0,
413 conversion_resolution_mode: Mode::Data12Bits,
414 enable_wait_trigger: false,
415 }
416 }
417 558
418 /// Set conversion command configuration. 559 let (cmdl, cmdh) = match index {
419 /// 560 1 => (adc.cmdl1(), adc.cmdh1()),
420 /// Configures a conversion command slot with the specified parameters. 561 2 => (adc.cmdl2(), adc.cmdh2()),
421 /// Commands define how conversions are performed (channel, resolution, etc.). 562 3 => (adc.cmdl3(), adc.cmdh3()),
422 /// 563 4 => (adc.cmdl4(), adc.cmdh4()),
423 /// # Arguments 564 5 => (adc.cmdl5(), adc.cmdh5()),
424 /// * `index` - Command index 565 6 => (adc.cmdl6(), adc.cmdh6()),
425 /// * `config` - Command configuration 566 7 => (adc.cmdl7(), adc.cmdh7()),
426 /// 567 _ => return Err(Error::InvalidConfig),
427 /// # Returns 568 };
428 /// * `Ok(())` if the command was configured successfully
429 /// * `Err(Error::InvalidConfig)` if the index is out of range
430 pub fn set_conv_command_config(&self, index: u32, config: &ConvCommandConfig) -> Result<()> {
431 let adc = I::ptr();
432
433 if index < 1 || index > 7 {
434 return Err(Error::InvalidConfig);
435 }
436 569
437 macro_rules! write_cmd { 570 cmdl.write(|w| {
438 ($idx:expr) => {{ 571 unsafe {
439 paste! { 572 w.adch().bits(self.index);
440 adc.[<cmdl $idx>]().write(|w| { 573 }
441 w.adch() 574 w.mode().variant(config.conversion_resolution_mode)
442 .variant(config.channel_number) 575 });
443 .mode()
444 .variant(config.conversion_resolution_mode)
445 });
446 adc.[<cmdh $idx>]().write(|w| unsafe {
447 w.next()
448 .variant(config.chained_next_command_number)
449 .loop_()
450 .bits(config.loop_count)
451 .avgs()
452 .variant(config.hardware_average_mode)
453 .sts()
454 .variant(config.sample_time_mode)
455 .cmpen()
456 .variant(config.hardware_compare_mode)
457 .wait_trig()
458 .bit(config.enable_wait_trigger)
459 .lwi()
460 .bit(config.enable_auto_channel_increment)
461 });
462 }
463 }};
464 }
465 576
466 match index { 577 cmdh.write(|w| {
467 1 => write_cmd!(1), 578 w.next().variant(config.chained_next_command_number);
468 2 => write_cmd!(2), 579 unsafe {
469 3 => write_cmd!(3), 580 w.loop_().bits(config.loop_count);
470 4 => write_cmd!(4), 581 }
471 5 => write_cmd!(5), 582 w.avgs().variant(config.hardware_average_mode);
472 6 => write_cmd!(6), 583 w.sts().variant(config.sample_time_mode);
473 7 => write_cmd!(7), 584 w.cmpen().variant(config.hardware_compare_mode);
474 _ => unreachable!(), 585 w.wait_trig().bit(config.enable_wait_trigger);
475 } 586 w.lwi().bit(config.enable_auto_channel_increment);
587 w
588 });
476 589
477 Ok(()) 590 Ok(())
478 } 591 }
479 592
480 /// Get default conversion trigger configuration. 593 fn set_conv_trigger_config_inner(&self, trigger_id: usize, config: &ConvTriggerConfig) -> Result<()> {
481 /// 594 let adc = I::ptr();
482 /// # Returns 595
483 /// Default conversion trigger configuration 596 // 0..4 are valid
484 pub fn get_default_conv_trigger_config(&self) -> ConvTriggerConfig { 597 if trigger_id >= 4 {
485 ConvTriggerConfig { 598 return Err(Error::InvalidConfig);
486 target_command_id: Tcmd::NotValid,
487 delay_power: 0,
488 priority: Tpri::HighestPriority,
489 enable_hardware_trigger: false,
490 } 599 }
491 }
492 600
493 /// Set conversion trigger configuration.
494 ///
495 /// Configures a trigger to initiate conversions. Triggers can be
496 /// activated by software or hardware signals.
497 ///
498 /// # Arguments
499 /// * `trigger_id` - Trigger index (0-15)
500 /// * `config` - Trigger configuration
501 pub fn set_conv_trigger_config(&self, trigger_id: usize, config: &ConvTriggerConfig) {
502 let adc = I::ptr();
503 let tctrl = &adc.tctrl(trigger_id); 601 let tctrl = &adc.tctrl(trigger_id);
504 602
505 tctrl.write(|w| unsafe { 603 tctrl.write(|w| {
506 let w = w.tcmd().variant(config.target_command_id); 604 w.tcmd().variant(config.target_command_id);
507 let w = w.tdly().bits(config.delay_power); 605 unsafe {
606 w.tdly().bits(config.delay_power);
607 }
508 w.tpri().variant(config.priority); 608 w.tpri().variant(config.priority);
509 if config.enable_hardware_trigger { 609 if config.enable_hardware_trigger {
510 w.hten().enabled() 610 w.hten().enabled()
@@ -512,36 +612,8 @@ impl<'a, I: Instance, M: ModeAdc> Adc<'a, I, M> {
512 w 612 w
513 } 613 }
514 }); 614 });
515 }
516 615
517 /// Reset the FIFO buffer. 616 Ok(())
518 ///
519 /// Clears all pending conversion results from the FIFO.
520 pub fn do_reset_fifo(&self) {
521 let adc = I::ptr();
522 adc.ctrl().modify(|_, w| w.rstfifo0().trigger_reset());
523 }
524
525 /// Enable ADC interrupts.
526 ///
527 /// Enables the interrupt sources specified in the bitmask.
528 ///
529 /// # Arguments
530 /// * `mask` - Bitmask of interrupt sources to enable
531 pub fn enable_interrupt(&self, mask: u32) {
532 let adc = I::ptr();
533 adc.ie().modify(|r, w| unsafe { w.bits(r.bits() | mask) });
534 }
535
536 /// Disable ADC interrupts.
537 ///
538 /// Disables the interrupt sources specified in the bitmask.
539 ///
540 /// # Arguments
541 /// * `mask` - Bitmask of interrupt sources to disable
542 pub fn disable_interrupt(&self, mask: u32) {
543 let adc = I::ptr();
544 adc.ie().modify(|r, w| unsafe { w.bits(r.bits() & !mask) });
545 } 617 }
546 618
547 /// Get conversion result from FIFO. 619 /// Get conversion result from FIFO.
@@ -552,7 +624,7 @@ impl<'a, I: Instance, M: ModeAdc> Adc<'a, I, M> {
552 /// # Returns 624 /// # Returns
553 /// - `Some(ConvResult)` if a result is available 625 /// - `Some(ConvResult)` if a result is available
554 /// - `Err(Error::FifoEmpty)` if the FIFO is empty 626 /// - `Err(Error::FifoEmpty)` if the FIFO is empty
555 pub fn get_conv_result(&self) -> Result<ConvResult> { 627 fn get_conv_result_inner(&self) -> Result<ConvResult> {
556 let adc = I::ptr(); 628 let adc = I::ptr();
557 let fifo = adc.resfifo0().read(); 629 let fifo = adc.resfifo0().read();
558 if !fifo.valid().is_valid() { 630 if !fifo.valid().is_valid() {
@@ -570,7 +642,7 @@ impl<'a, I: Instance, M: ModeAdc> Adc<'a, I, M> {
570 642
571impl<T: Instance> Handler<T::Interrupt> for InterruptHandler<T> { 643impl<T: Instance> Handler<T::Interrupt> for InterruptHandler<T> {
572 unsafe fn on_interrupt() { 644 unsafe fn on_interrupt() {
573 T::ptr().ie().modify(|r, w| w.bits(r.bits() & !0x1)); 645 T::ptr().ie().modify(|_r, w| w.fwmie0().clear_bit());
574 T::wait_cell().wake(); 646 T::wait_cell().wake();
575 } 647 }
576} 648}
@@ -621,6 +693,8 @@ macro_rules! impl_instance {
621impl_instance!(0, 1, 2, 3); 693impl_instance!(0, 1, 2, 3);
622 694
623pub trait AdcPin<Instance>: GpioPin + sealed::Sealed + PeripheralType { 695pub trait AdcPin<Instance>: GpioPin + sealed::Sealed + PeripheralType {
696 const CHANNEL: u8;
697
624 /// Set the given pin to the correct muxing state 698 /// Set the given pin to the correct muxing state
625 fn mux(&self); 699 fn mux(&self);
626} 700}
@@ -640,8 +714,10 @@ impl sealed::Sealed for Async {}
640impl ModeAdc for Async {} 714impl ModeAdc for Async {}
641 715
642macro_rules! impl_pin { 716macro_rules! impl_pin {
643 ($pin:ident, $peri:ident, $func:ident, $trait:ident) => { 717 ($pin:ident, $peri:ident, $func:ident, $channel:literal) => {
644 impl $trait<crate::peripherals::$peri> for crate::peripherals::$pin { 718 impl AdcPin<crate::peripherals::$peri> for crate::peripherals::$pin {
719 const CHANNEL: u8 = $channel;
720
645 fn mux(&self) { 721 fn mux(&self) {
646 self.set_pull(crate::gpio::Pull::Disabled); 722 self.set_pull(crate::gpio::Pull::Disabled);
647 self.set_slew_rate(crate::gpio::SlewRate::Fast.into()); 723 self.set_slew_rate(crate::gpio::SlewRate::Fast.into());
@@ -652,101 +728,113 @@ macro_rules! impl_pin {
652 }; 728 };
653} 729}
654 730
655impl_pin!(P2_0, ADC0, Mux0, AdcPin); 731impl_pin!(P2_0, ADC0, Mux0, 0);
656impl_pin!(P2_4, ADC0, Mux0, AdcPin); 732impl_pin!(P2_4, ADC0, Mux0, 1);
657impl_pin!(P2_15, ADC0, Mux0, AdcPin); 733impl_pin!(P2_15, ADC0, Mux0, 2);
658impl_pin!(P2_3, ADC0, Mux0, AdcPin); 734impl_pin!(P2_3, ADC0, Mux0, 3);
659impl_pin!(P2_2, ADC0, Mux0, AdcPin); 735impl_pin!(P2_2, ADC0, Mux0, 4);
660impl_pin!(P2_12, ADC0, Mux0, AdcPin); 736impl_pin!(P2_12, ADC0, Mux0, 5);
661impl_pin!(P2_16, ADC0, Mux0, AdcPin); 737impl_pin!(P2_16, ADC0, Mux0, 6);
662impl_pin!(P2_7, ADC0, Mux0, AdcPin); 738impl_pin!(P2_7, ADC0, Mux0, 7);
663impl_pin!(P0_18, ADC0, Mux0, AdcPin); 739impl_pin!(P0_18, ADC0, Mux0, 8);
664impl_pin!(P0_19, ADC0, Mux0, AdcPin); 740impl_pin!(P0_19, ADC0, Mux0, 9);
665impl_pin!(P0_20, ADC0, Mux0, AdcPin); 741impl_pin!(P0_20, ADC0, Mux0, 10);
666impl_pin!(P0_21, ADC0, Mux0, AdcPin); 742impl_pin!(P0_21, ADC0, Mux0, 11);
667impl_pin!(P0_22, ADC0, Mux0, AdcPin); 743impl_pin!(P0_22, ADC0, Mux0, 12);
668impl_pin!(P0_23, ADC0, Mux0, AdcPin); 744impl_pin!(P0_23, ADC0, Mux0, 13);
669impl_pin!(P0_3, ADC0, Mux0, AdcPin); 745impl_pin!(P0_3, ADC0, Mux0, 14);
670impl_pin!(P0_6, ADC0, Mux0, AdcPin); 746impl_pin!(P0_6, ADC0, Mux0, 15);
671impl_pin!(P1_0, ADC0, Mux0, AdcPin); 747impl_pin!(P1_0, ADC0, Mux0, 16);
672impl_pin!(P1_1, ADC0, Mux0, AdcPin); 748impl_pin!(P1_1, ADC0, Mux0, 17);
673impl_pin!(P1_2, ADC0, Mux0, AdcPin); 749impl_pin!(P1_2, ADC0, Mux0, 18);
674impl_pin!(P1_3, ADC0, Mux0, AdcPin); 750impl_pin!(P1_3, ADC0, Mux0, 19);
675impl_pin!(P1_4, ADC0, Mux0, AdcPin); 751impl_pin!(P1_4, ADC0, Mux0, 20);
676impl_pin!(P1_5, ADC0, Mux0, AdcPin); 752impl_pin!(P1_5, ADC0, Mux0, 21);
677impl_pin!(P1_6, ADC0, Mux0, AdcPin); 753impl_pin!(P1_6, ADC0, Mux0, 22);
678impl_pin!(P1_7, ADC0, Mux0, AdcPin); 754impl_pin!(P1_7, ADC0, Mux0, 23);
679impl_pin!(P1_10, ADC0, Mux0, AdcPin); 755
680 756// ???
681impl_pin!(P2_1, ADC1, Mux0, AdcPin); 757// impl_pin!(P1_10, ADC0, Mux0, 255);
682impl_pin!(P2_5, ADC1, Mux0, AdcPin); 758
683impl_pin!(P2_19, ADC1, Mux0, AdcPin); 759impl_pin!(P2_1, ADC1, Mux0, 0);
684impl_pin!(P2_6, ADC1, Mux0, AdcPin); 760impl_pin!(P2_5, ADC1, Mux0, 1);
685impl_pin!(P2_3, ADC1, Mux0, AdcPin); 761impl_pin!(P2_19, ADC1, Mux0, 2);
686impl_pin!(P2_13, ADC1, Mux0, AdcPin); 762impl_pin!(P2_6, ADC1, Mux0, 3);
687impl_pin!(P2_17, ADC1, Mux0, AdcPin); 763impl_pin!(P2_3, ADC1, Mux0, 4);
688impl_pin!(P2_7, ADC1, Mux0, AdcPin); 764impl_pin!(P2_13, ADC1, Mux0, 5);
689impl_pin!(P1_10, ADC1, Mux0, AdcPin); 765impl_pin!(P2_17, ADC1, Mux0, 6);
690impl_pin!(P1_11, ADC1, Mux0, AdcPin); 766impl_pin!(P2_7, ADC1, Mux0, 7);
691impl_pin!(P1_12, ADC1, Mux0, AdcPin); 767impl_pin!(P1_10, ADC1, Mux0, 8);
692impl_pin!(P1_13, ADC1, Mux0, AdcPin); 768impl_pin!(P1_11, ADC1, Mux0, 9);
693impl_pin!(P1_14, ADC1, Mux0, AdcPin); 769impl_pin!(P1_12, ADC1, Mux0, 10);
694impl_pin!(P1_15, ADC1, Mux0, AdcPin); 770impl_pin!(P1_13, ADC1, Mux0, 11);
695impl_pin!(P1_16, ADC1, Mux0, AdcPin); 771impl_pin!(P1_14, ADC1, Mux0, 12);
696impl_pin!(P1_17, ADC1, Mux0, AdcPin); 772impl_pin!(P1_15, ADC1, Mux0, 13);
697impl_pin!(P1_18, ADC1, Mux0, AdcPin); 773// ???
698impl_pin!(P1_19, ADC1, Mux0, AdcPin); 774// impl_pin!(P1_16, ADC1, Mux0, 255);
699impl_pin!(P3_31, ADC1, Mux0, AdcPin); 775// impl_pin!(P1_17, ADC1, Mux0, 255);
700impl_pin!(P3_30, ADC1, Mux0, AdcPin); 776// impl_pin!(P1_18, ADC1, Mux0, 255);
701impl_pin!(P3_29, ADC1, Mux0, AdcPin); 777// impl_pin!(P1_19, ADC1, Mux0, 255);
702 778// ???
703impl_pin!(P2_4, ADC2, Mux0, AdcPin); 779impl_pin!(P3_31, ADC1, Mux0, 20);
704impl_pin!(P2_10, ADC2, Mux0, AdcPin); 780impl_pin!(P3_30, ADC1, Mux0, 21);
705impl_pin!(P4_4, ADC2, Mux0, AdcPin); 781impl_pin!(P3_29, ADC1, Mux0, 22);
706impl_pin!(P2_24, ADC2, Mux0, AdcPin); 782
707impl_pin!(P2_16, ADC2, Mux0, AdcPin); 783impl_pin!(P2_4, ADC2, Mux0, 0);
708impl_pin!(P2_12, ADC2, Mux0, AdcPin); 784impl_pin!(P2_10, ADC2, Mux0, 1);
709impl_pin!(P2_20, ADC2, Mux0, AdcPin); 785impl_pin!(P4_4, ADC2, Mux0, 2);
710impl_pin!(P2_7, ADC2, Mux0, AdcPin); 786// impl_pin!(P2_24, ADC2, Mux0, 255); ???
711impl_pin!(P0_2, ADC2, Mux0, AdcPin); 787impl_pin!(P2_16, ADC2, Mux0, 4);
712impl_pin!(P0_4, ADC2, Mux0, AdcPin); 788impl_pin!(P2_12, ADC2, Mux0, 5);
713impl_pin!(P0_5, ADC2, Mux0, AdcPin); 789impl_pin!(P2_20, ADC2, Mux0, 6);
714impl_pin!(P0_6, ADC2, Mux0, AdcPin); 790impl_pin!(P2_7, ADC2, Mux0, 7);
715impl_pin!(P0_7, ADC2, Mux0, AdcPin); 791impl_pin!(P0_2, ADC2, Mux0, 8);
716impl_pin!(P0_12, ADC2, Mux0, AdcPin); 792// ???
717impl_pin!(P0_13, ADC2, Mux0, AdcPin); 793// impl_pin!(P0_4, ADC2, Mux0, 255);
718impl_pin!(P0_14, ADC2, Mux0, AdcPin); 794// impl_pin!(P0_5, ADC2, Mux0, 255);
719impl_pin!(P0_15, ADC2, Mux0, AdcPin); 795// impl_pin!(P0_6, ADC2, Mux0, 255);
720impl_pin!(P4_0, ADC2, Mux0, AdcPin); 796// impl_pin!(P0_7, ADC2, Mux0, 255);
721impl_pin!(P4_1, ADC2, Mux0, AdcPin); 797// impl_pin!(P0_12, ADC2, Mux0, 255);
722impl_pin!(P4_2, ADC2, Mux0, AdcPin); 798// impl_pin!(P0_13, ADC2, Mux0, 255);
723impl_pin!(P4_3, ADC2, Mux0, AdcPin); 799// ???
724//impl_pin!(P4_4, ADC2, Mux0, AdcPin); // Conflit with ADC2_A3 and ADC2_A20 using the same pin 800impl_pin!(P0_14, ADC2, Mux0, 14);
725impl_pin!(P4_5, ADC2, Mux0, AdcPin); 801impl_pin!(P0_15, ADC2, Mux0, 15);
726impl_pin!(P4_6, ADC2, Mux0, AdcPin); 802// ???
727impl_pin!(P4_7, ADC2, Mux0, AdcPin); 803// impl_pin!(P4_0, ADC2, Mux0, 255);
728 804// impl_pin!(P4_1, ADC2, Mux0, 255);
729impl_pin!(P2_5, ADC3, Mux0, AdcPin); 805// ???
730impl_pin!(P2_11, ADC3, Mux0, AdcPin); 806impl_pin!(P4_2, ADC2, Mux0, 18);
731impl_pin!(P2_23, ADC3, Mux0, AdcPin); 807impl_pin!(P4_3, ADC2, Mux0, 19);
732impl_pin!(P2_25, ADC3, Mux0, AdcPin); 808//impl_pin!(P4_4, ADC2, Mux0, 20); // Conflit with ADC2_A3 and ADC2_A20 using the same pin
733impl_pin!(P2_17, ADC3, Mux0, AdcPin); 809impl_pin!(P4_5, ADC2, Mux0, 21);
734impl_pin!(P2_13, ADC3, Mux0, AdcPin); 810impl_pin!(P4_6, ADC2, Mux0, 22);
735impl_pin!(P2_21, ADC3, Mux0, AdcPin); 811impl_pin!(P4_7, ADC2, Mux0, 23);
736impl_pin!(P2_7, ADC3, Mux0, AdcPin); 812
737impl_pin!(P3_2, ADC3, Mux0, AdcPin); 813impl_pin!(P2_5, ADC3, Mux0, 0);
738impl_pin!(P3_3, ADC3, Mux0, AdcPin); 814impl_pin!(P2_11, ADC3, Mux0, 1);
739impl_pin!(P3_4, ADC3, Mux0, AdcPin); 815impl_pin!(P2_23, ADC3, Mux0, 2);
740impl_pin!(P3_5, ADC3, Mux0, AdcPin); 816// impl_pin!(P2_25, ADC3, Mux0, 255); // ???
741impl_pin!(P3_6, ADC3, Mux0, AdcPin); 817impl_pin!(P2_17, ADC3, Mux0, 4);
742impl_pin!(P3_7, ADC3, Mux0, AdcPin); 818impl_pin!(P2_13, ADC3, Mux0, 5);
743impl_pin!(P3_12, ADC3, Mux0, AdcPin); 819impl_pin!(P2_21, ADC3, Mux0, 6);
744impl_pin!(P3_13, ADC3, Mux0, AdcPin); 820impl_pin!(P2_7, ADC3, Mux0, 7);
745impl_pin!(P3_14, ADC3, Mux0, AdcPin); 821// ???
746impl_pin!(P3_15, ADC3, Mux0, AdcPin); 822// impl_pin!(P3_2, ADC3, Mux0, 255);
747impl_pin!(P3_20, ADC3, Mux0, AdcPin); 823// impl_pin!(P3_3, ADC3, Mux0, 255);
748impl_pin!(P3_21, ADC3, Mux0, AdcPin); 824// impl_pin!(P3_4, ADC3, Mux0, 255);
749impl_pin!(P3_22, ADC3, Mux0, AdcPin); 825// impl_pin!(P3_5, ADC3, Mux0, 255);
750impl_pin!(P3_23, ADC3, Mux0, AdcPin); 826// ???
751impl_pin!(P3_24, ADC3, Mux0, AdcPin); 827impl_pin!(P3_6, ADC3, Mux0, 12);
752impl_pin!(P3_25, ADC3, Mux0, AdcPin); 828impl_pin!(P3_7, ADC3, Mux0, 13);
829impl_pin!(P3_12, ADC3, Mux0, 14);
830impl_pin!(P3_13, ADC3, Mux0, 15);
831impl_pin!(P3_14, ADC3, Mux0, 16);
832impl_pin!(P3_15, ADC3, Mux0, 17);
833impl_pin!(P3_20, ADC3, Mux0, 18);
834impl_pin!(P3_21, ADC3, Mux0, 19);
835impl_pin!(P3_22, ADC3, Mux0, 20);
836// ???
837// impl_pin!(P3_23, ADC3, Mux0, 255);
838// impl_pin!(P3_24, ADC3, Mux0, 255);
839// impl_pin!(P3_25, ADC3, Mux0, 255);
840// ???