aboutsummaryrefslogtreecommitdiff
path: root/embassy-mcxa/src/adc.rs
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-mcxa/src/adc.rs')
-rw-r--r--embassy-mcxa/src/adc.rs703
1 files changed, 400 insertions, 303 deletions
diff --git a/embassy-mcxa/src/adc.rs b/embassy-mcxa/src/adc.rs
index d7d17cf5f..f88bb6b37 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
@@ -152,23 +173,127 @@ pub struct InterruptHandler<I: Instance> {
152} 173}
153 174
154/// ADC driver instance. 175/// ADC driver instance.
155pub struct Adc<'a, I: Instance, M: ModeAdc> { 176pub struct Adc<'a, M: ModeAdc> {
156 _inst: PhantomData<&'a mut I>, 177 _inst: PhantomData<&'a mut ()>,
157 _phantom: PhantomData<M>, 178 mode: M,
179
180 // The channel index of the pin used to create our ADC instance
181 channel_idx: u8,
182
183 // The register block of the ADC instance
184 info: &'static pac::adc0::RegisterBlock,
158} 185}
159 186
160impl<'a, I: Instance> Adc<'a, I, Blocking> { 187impl<'a> Adc<'a, Blocking> {
161 /// Create a new blocking instance of the ADC driver. 188 /// Create a new blocking instance of the ADC driver.
162 /// # Arguments 189 /// # Arguments
163 /// * `_inst` - ADC peripheral instance 190 /// * `_inst` - ADC peripheral instance
164 /// * `pin` - GPIO pin to use for ADC 191 /// * `pin` - GPIO pin to use for ADC
165 /// * `config` - ADC configuration 192 /// * `config` - ADC configuration
166 pub fn new_blocking(_inst: Peri<'a, I>, pin: Peri<'a, impl AdcPin<I>>, config: LpadcConfig) -> Result<Self> { 193 pub fn new_blocking<I: Instance>(
167 Self::new_inner(_inst, pin, config) 194 _inst: Peri<'a, I>,
195 pin: Peri<'a, impl AdcPin<I>>,
196 config: LpadcConfig,
197 ) -> Result<Self> {
198 Self::new_inner(_inst, pin, config, Blocking)
199 }
200
201 /// Enable ADC interrupts.
202 ///
203 /// Enables the interrupt sources specified in the bitmask.
204 ///
205 /// # Arguments
206 /// * `mask` - Bitmask of interrupt sources to enable
207 pub fn enable_interrupt(&mut self, mask: u32) {
208 self.info.ie().modify(|r, w| unsafe { w.bits(r.bits() | mask) });
209 }
210
211 /// Disable ADC interrupts.
212 ///
213 /// Disables the interrupt sources specified in the bitmask.
214 ///
215 /// # Arguments
216 /// * `mask` - Bitmask of interrupt sources to disable
217 pub fn disable_interrupt(&mut self, mask: u32) {
218 self.info.ie().modify(|r, w| unsafe { w.bits(r.bits() & !mask) });
219 }
220
221 pub fn set_fifo_watermark(&mut self, watermark: u8) -> Result<()> {
222 if watermark > 0b111 {
223 return Err(Error::InvalidConfig);
224 }
225 self.info.fctrl0().modify(|_r, w| unsafe { w.fwmark().bits(watermark) });
226 Ok(())
227 }
228
229 /// Trigger ADC conversion(s) via software.
230 ///
231 /// Initiates conversion(s) for the trigger(s) specified in the bitmask.
232 /// Each bit in the mask corresponds to a trigger ID (bit 0 = trigger 0, etc.).
233 ///
234 /// # Arguments
235 /// * `trigger_id_mask` - Bitmask of trigger IDs to activate (bit N = trigger N)
236 ///
237 /// # Returns
238 /// * `Ok(())` if the triger mask was valid
239 /// * `Err(Error::InvalidConfig)` if the mask was greater than `0b1111`
240 pub fn do_software_trigger(&self, trigger_id_mask: u8) -> Result<()> {
241 if trigger_id_mask > 0b1111 {
242 return Err(Error::InvalidConfig);
243 }
244 self.info.swtrig().write(|w| unsafe { w.bits(trigger_id_mask as u32) });
245 Ok(())
246 }
247
248 /// Set conversion command configuration.
249 ///
250 /// Configures a conversion command slot with the specified parameters.
251 /// Commands define how conversions are performed (channel, resolution, etc.).
252 ///
253 /// # Arguments
254 /// * `index` - Command index (Must be in range 1..=7)
255 /// * `config` - Command configuration
256 ///
257 /// # Returns
258 /// * `Ok(())` if the command was configured successfully
259 /// * `Err(Error::InvalidConfig)` if the index is out of range
260 pub fn set_conv_command_config(&self, index: usize, config: &ConvCommandConfig) -> Result<()> {
261 self.set_conv_command_config_inner(index, config)
262 }
263
264 /// Set conversion trigger configuration.
265 ///
266 /// Configures a trigger to initiate conversions. Triggers can be
267 /// activated by software or hardware signals.
268 ///
269 /// # Arguments
270 /// * `trigger_id` - Trigger index (0..=3)
271 /// * `config` - Trigger configuration
272 pub fn set_conv_trigger_config(&self, trigger_id: usize, config: &ConvTriggerConfig) -> Result<()> {
273 self.set_conv_trigger_config_inner(trigger_id, config)
274 }
275
276 /// Reset the FIFO buffer.
277 ///
278 /// Clears all pending conversion results from the FIFO.
279 pub fn do_reset_fifo(&self) {
280 self.info.ctrl().modify(|_, w| w.rstfifo0().trigger_reset());
281 }
282
283 /// Get conversion result from FIFO.
284 ///
285 /// Reads and returns the next conversion result from the FIFO.
286 /// Returns `None` if the FIFO is empty.
287 ///
288 /// # Returns
289 /// - `Some(ConvResult)` if a result is available
290 /// - `Err(Error::FifoEmpty)` if the FIFO is empty
291 pub fn get_conv_result(&self) -> Result<ConvResult> {
292 self.get_conv_result_inner()
168 } 293 }
169} 294}
170 295
171impl<'a, I: Instance> Adc<'a, I, Async> { 296impl<'a> Adc<'a, Async> {
172 /// Initialize ADC with interrupt support. 297 /// Initialize ADC with interrupt support.
173 /// 298 ///
174 /// # Arguments 299 /// # Arguments
@@ -176,18 +301,73 @@ impl<'a, I: Instance> Adc<'a, I, Async> {
176 /// * `pin` - GPIO pin to use for ADC 301 /// * `pin` - GPIO pin to use for ADC
177 /// * `_irq` - Interrupt binding for this ADC instance 302 /// * `_irq` - Interrupt binding for this ADC instance
178 /// * `config` - ADC configuration 303 /// * `config` - ADC configuration
179 pub fn new_async( 304 pub fn new_async<I: Instance>(
180 _inst: Peri<'a, I>, 305 _inst: Peri<'a, I>,
181 pin: Peri<'a, impl AdcPin<I>>, 306 pin: Peri<'a, impl AdcPin<I>>,
182 _irq: impl crate::interrupt::typelevel::Binding<I::Interrupt, InterruptHandler<I>> + 'a, 307 _irq: impl crate::interrupt::typelevel::Binding<I::Interrupt, InterruptHandler<I>> + 'a,
183 config: LpadcConfig, 308 config: LpadcConfig,
184 ) -> Result<Self> { 309 ) -> Result<Self> {
185 let adc = Self::new_inner(_inst, pin, config); 310 let adc = Self::new_inner(_inst, pin, config, Async { waiter: I::wait_cell() })?;
186 311
187 I::Interrupt::unpend(); 312 I::Interrupt::unpend();
188 unsafe { I::Interrupt::enable() }; 313 unsafe { I::Interrupt::enable() };
189 314
190 adc 315 let cfg = ConvCommandConfig {
316 chained_next_command_number: Next::NoNextCmdTerminateOnFinish,
317 enable_auto_channel_increment: false,
318 loop_count: 0,
319 hardware_average_mode: Avgs::NoAverage,
320 sample_time_mode: Sts::Sample3p5,
321 hardware_compare_mode: Cmpen::DisabledAlwaysStoreResult,
322 hardware_compare_value_high: 0,
323 hardware_compare_value_low: 0,
324 conversion_resolution_mode: Mode::Data16Bits,
325 enable_wait_trigger: false,
326 };
327
328 // We always use command 1, so this cannot fail
329 _ = adc.set_conv_command_config_inner(1, &cfg);
330
331 let cfg = ConvTriggerConfig {
332 target_command_id: Tcmd::ExecuteCmd1,
333 delay_power: 0,
334 priority: Tpri::HighestPriority,
335 enable_hardware_trigger: false,
336 };
337
338 // We always use trigger 0, so this cannot fail
339 _ = adc.set_conv_trigger_config_inner(0, &cfg);
340
341 // We always set the watermark to 0 (trigger when 1 is available)
342 I::ptr().fctrl0().modify(|_r, w| unsafe { w.fwmark().bits(0) });
343
344 Ok(adc)
345 }
346
347 /// Set the number of averages
348 pub fn set_averages(&mut self, avgs: Avgs) {
349 // TODO: we should probably return a result or wait for idle?
350 // "A write to a CMD buffer while that CMD buffer is controlling the ADC operation may cause unpredictable behavior."
351 self.info.cmdh1().modify(|_r, w| w.avgs().variant(avgs));
352 }
353
354 /// Set the sample time
355 pub fn set_sample_time(&mut self, st: Sts) {
356 // TODO: we should probably return a result or wait for idle?
357 // "A write to a CMD buffer while that CMD buffer is controlling the ADC operation may cause unpredictable behavior."
358 self.info.cmdh1().modify(|_r, w| w.sts().variant(st));
359 }
360
361 pub fn set_resolution(&mut self, mode: Mode) {
362 // TODO: we should probably return a result or wait for idle?
363 // "A write to a CMD buffer while that CMD buffer is controlling the ADC operation may cause unpredictable behavior."
364 self.info.cmdl1().modify(|_r, w| w.mode().variant(mode));
365 }
366
367 fn wait_idle(&mut self) -> impl Future<Output = core::result::Result<(), maitake_sync::Closed>> + use<'_> {
368 self.mode
369 .waiter
370 .wait_for(|| self.info.ie().read().fwmie0().bit_is_clear())
191 } 371 }
192 372
193 /// Read ADC value asynchronously. 373 /// Read ADC value asynchronously.
@@ -203,21 +383,32 @@ impl<'a, I: Instance> Adc<'a, I, Async> {
203 /// # Returns 383 /// # Returns
204 /// 16-bit ADC conversion value 384 /// 16-bit ADC conversion value
205 pub async fn read(&mut self) -> Result<u16> { 385 pub async fn read(&mut self) -> Result<u16> {
206 let wait = I::wait_cell().subscribe().await; 386 // If we cancelled a previous read, we might still be busy, wait
387 // until the interrupt is cleared (done by the interrupt)
388 _ = self.wait_idle().await;
389
390 // Clear the fifo
391 self.info.ctrl().modify(|_, w| w.rstfifo0().trigger_reset());
207 392
208 Adc::<'a, I, Async>::enable_interrupt(self, 0x1); 393 // Trigger a new conversion
209 Adc::<'a, I, Async>::do_software_trigger(self, 1); 394 self.info.ie().modify(|_r, w| w.fwmie0().set_bit());
395 self.info.swtrig().write(|w| w.swt0().set_bit());
210 396
211 let _ = wait.await; 397 // Wait for completion
398 _ = self.wait_idle().await;
212 399
213 let result = Adc::<'a, I, Async>::get_conv_result(self).unwrap().conv_value >> G_LPADC_RESULT_SHIFT; 400 self.get_conv_result_inner().map(|r| r.conv_value)
214 Ok(result)
215 } 401 }
216} 402}
217 403
218impl<'a, I: Instance, M: ModeAdc> Adc<'a, I, M> { 404impl<'a, M: ModeAdc> Adc<'a, M> {
219 /// Internal initialization function shared by `new_async` and `new_blocking`. 405 /// 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> { 406 fn new_inner<I: Instance, P: AdcPin<I>>(
407 _inst: Peri<'a, I>,
408 pin: Peri<'a, P>,
409 config: LpadcConfig,
410 mode: M,
411 ) -> Result<Self> {
221 let adc = I::ptr(); 412 let adc = I::ptr();
222 413
223 _ = unsafe { 414 _ = unsafe {
@@ -241,22 +432,14 @@ impl<'a, I: Instance, M: ModeAdc> Adc<'a, I, M> {
241 adc.ctrl().modify(|_, w| w.adcen().disabled()); 432 adc.ctrl().modify(|_, w| w.adcen().disabled());
242 433
243 /* Configure the module generally. */ 434 /* Configure the module generally. */
244 if config.enable_in_doze_mode { 435 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 436
250 /* Set calibration average mode. */ 437 /* Set calibration average mode. */
251 adc.ctrl() 438 adc.ctrl()
252 .modify(|_, w| w.cal_avgs().variant(config.conversion_average_mode)); 439 .modify(|_, w| w.cal_avgs().variant(config.conversion_average_mode));
253 440
254 adc.cfg().write(|w| unsafe { 441 adc.cfg().write(|w| unsafe {
255 let w = if config.enable_analog_preliminary { 442 w.pwren().bit(config.enable_analog_preliminary);
256 w.pwren().pre_enabled()
257 } else {
258 w
259 };
260 443
261 w.pudly() 444 w.pudly()
262 .bits(config.power_up_delay) 445 .bits(config.power_up_delay)
@@ -306,34 +489,29 @@ impl<'a, I: Instance, M: ModeAdc> Adc<'a, I, M> {
306 adc.pause().write(|w| unsafe { w.bits(0) }); 489 adc.pause().write(|w| unsafe { w.bits(0) });
307 } 490 }
308 491
309 adc.fctrl0() 492 adc.fctrl0().write(|w| unsafe { w.fwmark().bits(0) });
310 .write(|w| unsafe { w.fwmark().bits(config.fifo_watermark) });
311 493
312 // Enable ADC 494 // Enable ADC
313 adc.ctrl().modify(|_, w| w.adcen().enabled()); 495 adc.ctrl().modify(|_, w| w.adcen().enabled());
314 496
315 Ok(Self { 497 Ok(Self {
316 _inst: PhantomData, 498 _inst: PhantomData,
317 _phantom: PhantomData, 499 mode,
500 channel_idx: P::CHANNEL,
501 info: adc,
318 }) 502 })
319 } 503 }
320 504
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. 505 /// Perform offset calibration.
328 /// Waits for calibration to complete before returning. 506 /// Waits for calibration to complete before returning.
329 pub fn do_offset_calibration(&self) { 507 pub fn do_offset_calibration(&self) {
330 let adc = I::ptr();
331 // Enable calibration mode 508 // Enable calibration mode
332 adc.ctrl() 509 self.info
510 .ctrl()
333 .modify(|_, w| w.calofs().offset_calibration_request_pending()); 511 .modify(|_, w| w.calofs().offset_calibration_request_pending());
334 512
335 // Wait for calibration to complete (polling status register) 513 // Wait for calibration to complete (polling status register)
336 while adc.stat().read().cal_rdy().is_not_set() {} 514 while self.info.stat().read().cal_rdy().is_not_set() {}
337 } 515 }
338 516
339 /// Calculate gain conversion result from gain adjustment factor. 517 /// Calculate gain conversion result from gain adjustment factor.
@@ -363,148 +541,78 @@ impl<'a, I: Instance, M: ModeAdc> Adc<'a, I, M> {
363 541
364 /// Perform automatic gain calibration. 542 /// Perform automatic gain calibration.
365 pub fn do_auto_calibration(&self) { 543 pub fn do_auto_calibration(&self) {
366 let adc = I::ptr(); 544 self.info
367 adc.ctrl().modify(|_, w| w.cal_req().calibration_request_pending()); 545 .ctrl()
546 .modify(|_, w| w.cal_req().calibration_request_pending());
368 547
369 while adc.gcc0().read().rdy().is_gain_cal_not_valid() {} 548 while self.info.gcc0().read().rdy().is_gain_cal_not_valid() {}
370 549
371 let mut gcca = adc.gcc0().read().gain_cal().bits() as u32; 550 let mut gcca = self.info.gcc0().read().gain_cal().bits() as u32;
372 if gcca & ((0xFFFF + 1) >> 1) != 0 { 551 if gcca & 0x8000 != 0 {
373 gcca |= !0xFFFF; 552 gcca |= !0xFFFF;
374 } 553 }
375 554
376 let gcra = 131072.0 / (131072.0 - gcca as f32); 555 let gcra = 131072.0 / (131072.0 - gcca as f32);
377 556
378 // Write to GCR0 557 // Write to GCR0
379 adc.gcr0().write(|w| unsafe { w.bits(self.get_gain_conv_result(gcra)) }); 558 self.info
559 .gcr0()
560 .write(|w| unsafe { w.bits(self.get_gain_conv_result(gcra)) });
380 561
381 adc.gcr0().modify(|_, w| w.rdy().set_bit()); 562 self.info.gcr0().modify(|_, w| w.rdy().set_bit());
382 563
383 // Wait for calibration to complete (polling status register) 564 // Wait for calibration to complete (polling status register)
384 while adc.stat().read().cal_rdy().is_not_set() {} 565 while self.info.stat().read().cal_rdy().is_not_set() {}
385 }
386
387 /// Trigger ADC conversion(s) via software.
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();
396 adc.swtrig().write(|w| unsafe { w.bits(trigger_id_mask) });
397 } 566 }
398 567
399 /// Get default conversion command configuration. 568 fn set_conv_command_config_inner(&self, index: usize, config: &ConvCommandConfig) -> Result<()> {
400 /// # Returns 569 let (cmdl, cmdh) = match index {
401 /// Default conversion command configuration 570 1 => (self.info.cmdl1(), self.info.cmdh1()),
402 pub fn get_default_conv_command_config(&self) -> ConvCommandConfig { 571 2 => (self.info.cmdl2(), self.info.cmdh2()),
403 ConvCommandConfig { 572 3 => (self.info.cmdl3(), self.info.cmdh3()),
404 channel_number: Adch::SelectCh0, 573 4 => (self.info.cmdl4(), self.info.cmdh4()),
405 chained_next_command_number: Next::NoNextCmdTerminateOnFinish, 574 5 => (self.info.cmdl5(), self.info.cmdh5()),
406 enable_auto_channel_increment: false, 575 6 => (self.info.cmdl6(), self.info.cmdh6()),
407 loop_count: 0, 576 7 => (self.info.cmdl7(), self.info.cmdh7()),
408 hardware_average_mode: Avgs::NoAverage, 577 _ => return Err(Error::InvalidConfig),
409 sample_time_mode: Sts::Sample3p5, 578 };
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
418 /// Set conversion command configuration.
419 ///
420 /// Configures a conversion command slot with the specified parameters.
421 /// Commands define how conversions are performed (channel, resolution, etc.).
422 ///
423 /// # Arguments
424 /// * `index` - Command index
425 /// * `config` - Command configuration
426 ///
427 /// # Returns
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 579
437 macro_rules! write_cmd { 580 cmdl.write(|w| {
438 ($idx:expr) => {{ 581 unsafe {
439 paste! { 582 w.adch().bits(self.channel_idx);
440 adc.[<cmdl $idx>]().write(|w| { 583 }
441 w.adch() 584 w.mode().variant(config.conversion_resolution_mode)
442 .variant(config.channel_number) 585 });
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 586
466 match index { 587 cmdh.write(|w| {
467 1 => write_cmd!(1), 588 w.next().variant(config.chained_next_command_number);
468 2 => write_cmd!(2), 589 unsafe {
469 3 => write_cmd!(3), 590 w.loop_().bits(config.loop_count);
470 4 => write_cmd!(4), 591 }
471 5 => write_cmd!(5), 592 w.avgs().variant(config.hardware_average_mode);
472 6 => write_cmd!(6), 593 w.sts().variant(config.sample_time_mode);
473 7 => write_cmd!(7), 594 w.cmpen().variant(config.hardware_compare_mode);
474 _ => unreachable!(), 595 w.wait_trig().bit(config.enable_wait_trigger);
475 } 596 w.lwi().bit(config.enable_auto_channel_increment);
597 w
598 });
476 599
477 Ok(()) 600 Ok(())
478 } 601 }
479 602
480 /// Get default conversion trigger configuration. 603 fn set_conv_trigger_config_inner(&self, trigger_id: usize, config: &ConvTriggerConfig) -> Result<()> {
481 /// 604 // 0..4 are valid
482 /// # Returns 605 if trigger_id >= 4 {
483 /// Default conversion trigger configuration 606 return Err(Error::InvalidConfig);
484 pub fn get_default_conv_trigger_config(&self) -> ConvTriggerConfig {
485 ConvTriggerConfig {
486 target_command_id: Tcmd::NotValid,
487 delay_power: 0,
488 priority: Tpri::HighestPriority,
489 enable_hardware_trigger: false,
490 } 607 }
491 }
492 608
493 /// Set conversion trigger configuration. 609 let tctrl = &self.info.tctrl(trigger_id);
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);
504 610
505 tctrl.write(|w| unsafe { 611 tctrl.write(|w| {
506 let w = w.tcmd().variant(config.target_command_id); 612 w.tcmd().variant(config.target_command_id);
507 let w = w.tdly().bits(config.delay_power); 613 unsafe {
614 w.tdly().bits(config.delay_power);
615 }
508 w.tpri().variant(config.priority); 616 w.tpri().variant(config.priority);
509 if config.enable_hardware_trigger { 617 if config.enable_hardware_trigger {
510 w.hten().enabled() 618 w.hten().enabled()
@@ -512,36 +620,8 @@ impl<'a, I: Instance, M: ModeAdc> Adc<'a, I, M> {
512 w 620 w
513 } 621 }
514 }); 622 });
515 }
516 623
517 /// Reset the FIFO buffer. 624 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 } 625 }
546 626
547 /// Get conversion result from FIFO. 627 /// Get conversion result from FIFO.
@@ -552,9 +632,8 @@ impl<'a, I: Instance, M: ModeAdc> Adc<'a, I, M> {
552 /// # Returns 632 /// # Returns
553 /// - `Some(ConvResult)` if a result is available 633 /// - `Some(ConvResult)` if a result is available
554 /// - `Err(Error::FifoEmpty)` if the FIFO is empty 634 /// - `Err(Error::FifoEmpty)` if the FIFO is empty
555 pub fn get_conv_result(&self) -> Result<ConvResult> { 635 fn get_conv_result_inner(&self) -> Result<ConvResult> {
556 let adc = I::ptr(); 636 let fifo = self.info.resfifo0().read();
557 let fifo = adc.resfifo0().read();
558 if !fifo.valid().is_valid() { 637 if !fifo.valid().is_valid() {
559 return Err(Error::FifoEmpty); 638 return Err(Error::FifoEmpty);
560 } 639 }
@@ -570,7 +649,7 @@ impl<'a, I: Instance, M: ModeAdc> Adc<'a, I, M> {
570 649
571impl<T: Instance> Handler<T::Interrupt> for InterruptHandler<T> { 650impl<T: Instance> Handler<T::Interrupt> for InterruptHandler<T> {
572 unsafe fn on_interrupt() { 651 unsafe fn on_interrupt() {
573 T::ptr().ie().modify(|r, w| w.bits(r.bits() & !0x1)); 652 T::ptr().ie().modify(|_r, w| w.fwmie0().clear_bit());
574 T::wait_cell().wake(); 653 T::wait_cell().wake();
575 } 654 }
576} 655}
@@ -621,6 +700,8 @@ macro_rules! impl_instance {
621impl_instance!(0, 1, 2, 3); 700impl_instance!(0, 1, 2, 3);
622 701
623pub trait AdcPin<Instance>: GpioPin + sealed::Sealed + PeripheralType { 702pub trait AdcPin<Instance>: GpioPin + sealed::Sealed + PeripheralType {
703 const CHANNEL: u8;
704
624 /// Set the given pin to the correct muxing state 705 /// Set the given pin to the correct muxing state
625 fn mux(&self); 706 fn mux(&self);
626} 707}
@@ -635,13 +716,17 @@ impl sealed::Sealed for Blocking {}
635impl ModeAdc for Blocking {} 716impl ModeAdc for Blocking {}
636 717
637/// Async mode. 718/// Async mode.
638pub struct Async; 719pub struct Async {
720 waiter: &'static WaitCell,
721}
639impl sealed::Sealed for Async {} 722impl sealed::Sealed for Async {}
640impl ModeAdc for Async {} 723impl ModeAdc for Async {}
641 724
642macro_rules! impl_pin { 725macro_rules! impl_pin {
643 ($pin:ident, $peri:ident, $func:ident, $trait:ident) => { 726 ($pin:ident, $peri:ident, $func:ident, $channel:literal) => {
644 impl $trait<crate::peripherals::$peri> for crate::peripherals::$pin { 727 impl AdcPin<crate::peripherals::$peri> for crate::peripherals::$pin {
728 const CHANNEL: u8 = $channel;
729
645 fn mux(&self) { 730 fn mux(&self) {
646 self.set_pull(crate::gpio::Pull::Disabled); 731 self.set_pull(crate::gpio::Pull::Disabled);
647 self.set_slew_rate(crate::gpio::SlewRate::Fast.into()); 732 self.set_slew_rate(crate::gpio::SlewRate::Fast.into());
@@ -652,101 +737,113 @@ macro_rules! impl_pin {
652 }; 737 };
653} 738}
654 739
655impl_pin!(P2_0, ADC0, Mux0, AdcPin); 740impl_pin!(P2_0, ADC0, Mux0, 0);
656impl_pin!(P2_4, ADC0, Mux0, AdcPin); 741impl_pin!(P2_4, ADC0, Mux0, 1);
657impl_pin!(P2_15, ADC0, Mux0, AdcPin); 742impl_pin!(P2_15, ADC0, Mux0, 2);
658impl_pin!(P2_3, ADC0, Mux0, AdcPin); 743impl_pin!(P2_3, ADC0, Mux0, 3);
659impl_pin!(P2_2, ADC0, Mux0, AdcPin); 744impl_pin!(P2_2, ADC0, Mux0, 4);
660impl_pin!(P2_12, ADC0, Mux0, AdcPin); 745impl_pin!(P2_12, ADC0, Mux0, 5);
661impl_pin!(P2_16, ADC0, Mux0, AdcPin); 746impl_pin!(P2_16, ADC0, Mux0, 6);
662impl_pin!(P2_7, ADC0, Mux0, AdcPin); 747impl_pin!(P2_7, ADC0, Mux0, 7);
663impl_pin!(P0_18, ADC0, Mux0, AdcPin); 748impl_pin!(P0_18, ADC0, Mux0, 8);
664impl_pin!(P0_19, ADC0, Mux0, AdcPin); 749impl_pin!(P0_19, ADC0, Mux0, 9);
665impl_pin!(P0_20, ADC0, Mux0, AdcPin); 750impl_pin!(P0_20, ADC0, Mux0, 10);
666impl_pin!(P0_21, ADC0, Mux0, AdcPin); 751impl_pin!(P0_21, ADC0, Mux0, 11);
667impl_pin!(P0_22, ADC0, Mux0, AdcPin); 752impl_pin!(P0_22, ADC0, Mux0, 12);
668impl_pin!(P0_23, ADC0, Mux0, AdcPin); 753impl_pin!(P0_23, ADC0, Mux0, 13);
669impl_pin!(P0_3, ADC0, Mux0, AdcPin); 754impl_pin!(P0_3, ADC0, Mux0, 14);
670impl_pin!(P0_6, ADC0, Mux0, AdcPin); 755impl_pin!(P0_6, ADC0, Mux0, 15);
671impl_pin!(P1_0, ADC0, Mux0, AdcPin); 756impl_pin!(P1_0, ADC0, Mux0, 16);
672impl_pin!(P1_1, ADC0, Mux0, AdcPin); 757impl_pin!(P1_1, ADC0, Mux0, 17);
673impl_pin!(P1_2, ADC0, Mux0, AdcPin); 758impl_pin!(P1_2, ADC0, Mux0, 18);
674impl_pin!(P1_3, ADC0, Mux0, AdcPin); 759impl_pin!(P1_3, ADC0, Mux0, 19);
675impl_pin!(P1_4, ADC0, Mux0, AdcPin); 760impl_pin!(P1_4, ADC0, Mux0, 20);
676impl_pin!(P1_5, ADC0, Mux0, AdcPin); 761impl_pin!(P1_5, ADC0, Mux0, 21);
677impl_pin!(P1_6, ADC0, Mux0, AdcPin); 762impl_pin!(P1_6, ADC0, Mux0, 22);
678impl_pin!(P1_7, ADC0, Mux0, AdcPin); 763impl_pin!(P1_7, ADC0, Mux0, 23);
679impl_pin!(P1_10, ADC0, Mux0, AdcPin); 764
680 765// ???
681impl_pin!(P2_1, ADC1, Mux0, AdcPin); 766// impl_pin!(P1_10, ADC0, Mux0, 255);
682impl_pin!(P2_5, ADC1, Mux0, AdcPin); 767
683impl_pin!(P2_19, ADC1, Mux0, AdcPin); 768impl_pin!(P2_1, ADC1, Mux0, 0);
684impl_pin!(P2_6, ADC1, Mux0, AdcPin); 769impl_pin!(P2_5, ADC1, Mux0, 1);
685impl_pin!(P2_3, ADC1, Mux0, AdcPin); 770impl_pin!(P2_19, ADC1, Mux0, 2);
686impl_pin!(P2_13, ADC1, Mux0, AdcPin); 771impl_pin!(P2_6, ADC1, Mux0, 3);
687impl_pin!(P2_17, ADC1, Mux0, AdcPin); 772impl_pin!(P2_3, ADC1, Mux0, 4);
688impl_pin!(P2_7, ADC1, Mux0, AdcPin); 773impl_pin!(P2_13, ADC1, Mux0, 5);
689impl_pin!(P1_10, ADC1, Mux0, AdcPin); 774impl_pin!(P2_17, ADC1, Mux0, 6);
690impl_pin!(P1_11, ADC1, Mux0, AdcPin); 775impl_pin!(P2_7, ADC1, Mux0, 7);
691impl_pin!(P1_12, ADC1, Mux0, AdcPin); 776impl_pin!(P1_10, ADC1, Mux0, 8);
692impl_pin!(P1_13, ADC1, Mux0, AdcPin); 777impl_pin!(P1_11, ADC1, Mux0, 9);
693impl_pin!(P1_14, ADC1, Mux0, AdcPin); 778impl_pin!(P1_12, ADC1, Mux0, 10);
694impl_pin!(P1_15, ADC1, Mux0, AdcPin); 779impl_pin!(P1_13, ADC1, Mux0, 11);
695impl_pin!(P1_16, ADC1, Mux0, AdcPin); 780impl_pin!(P1_14, ADC1, Mux0, 12);
696impl_pin!(P1_17, ADC1, Mux0, AdcPin); 781impl_pin!(P1_15, ADC1, Mux0, 13);
697impl_pin!(P1_18, ADC1, Mux0, AdcPin); 782// ???
698impl_pin!(P1_19, ADC1, Mux0, AdcPin); 783// impl_pin!(P1_16, ADC1, Mux0, 255);
699impl_pin!(P3_31, ADC1, Mux0, AdcPin); 784// impl_pin!(P1_17, ADC1, Mux0, 255);
700impl_pin!(P3_30, ADC1, Mux0, AdcPin); 785// impl_pin!(P1_18, ADC1, Mux0, 255);
701impl_pin!(P3_29, ADC1, Mux0, AdcPin); 786// impl_pin!(P1_19, ADC1, Mux0, 255);
702 787// ???
703impl_pin!(P2_4, ADC2, Mux0, AdcPin); 788impl_pin!(P3_31, ADC1, Mux0, 20);
704impl_pin!(P2_10, ADC2, Mux0, AdcPin); 789impl_pin!(P3_30, ADC1, Mux0, 21);
705impl_pin!(P4_4, ADC2, Mux0, AdcPin); 790impl_pin!(P3_29, ADC1, Mux0, 22);
706impl_pin!(P2_24, ADC2, Mux0, AdcPin); 791
707impl_pin!(P2_16, ADC2, Mux0, AdcPin); 792impl_pin!(P2_4, ADC2, Mux0, 0);
708impl_pin!(P2_12, ADC2, Mux0, AdcPin); 793impl_pin!(P2_10, ADC2, Mux0, 1);
709impl_pin!(P2_20, ADC2, Mux0, AdcPin); 794impl_pin!(P4_4, ADC2, Mux0, 2);
710impl_pin!(P2_7, ADC2, Mux0, AdcPin); 795// impl_pin!(P2_24, ADC2, Mux0, 255); ???
711impl_pin!(P0_2, ADC2, Mux0, AdcPin); 796impl_pin!(P2_16, ADC2, Mux0, 4);
712impl_pin!(P0_4, ADC2, Mux0, AdcPin); 797impl_pin!(P2_12, ADC2, Mux0, 5);
713impl_pin!(P0_5, ADC2, Mux0, AdcPin); 798impl_pin!(P2_20, ADC2, Mux0, 6);
714impl_pin!(P0_6, ADC2, Mux0, AdcPin); 799impl_pin!(P2_7, ADC2, Mux0, 7);
715impl_pin!(P0_7, ADC2, Mux0, AdcPin); 800impl_pin!(P0_2, ADC2, Mux0, 8);
716impl_pin!(P0_12, ADC2, Mux0, AdcPin); 801// ???
717impl_pin!(P0_13, ADC2, Mux0, AdcPin); 802// impl_pin!(P0_4, ADC2, Mux0, 255);
718impl_pin!(P0_14, ADC2, Mux0, AdcPin); 803// impl_pin!(P0_5, ADC2, Mux0, 255);
719impl_pin!(P0_15, ADC2, Mux0, AdcPin); 804// impl_pin!(P0_6, ADC2, Mux0, 255);
720impl_pin!(P4_0, ADC2, Mux0, AdcPin); 805// impl_pin!(P0_7, ADC2, Mux0, 255);
721impl_pin!(P4_1, ADC2, Mux0, AdcPin); 806// impl_pin!(P0_12, ADC2, Mux0, 255);
722impl_pin!(P4_2, ADC2, Mux0, AdcPin); 807// impl_pin!(P0_13, ADC2, Mux0, 255);
723impl_pin!(P4_3, ADC2, Mux0, AdcPin); 808// ???
724//impl_pin!(P4_4, ADC2, Mux0, AdcPin); // Conflit with ADC2_A3 and ADC2_A20 using the same pin 809impl_pin!(P0_14, ADC2, Mux0, 14);
725impl_pin!(P4_5, ADC2, Mux0, AdcPin); 810impl_pin!(P0_15, ADC2, Mux0, 15);
726impl_pin!(P4_6, ADC2, Mux0, AdcPin); 811// ???
727impl_pin!(P4_7, ADC2, Mux0, AdcPin); 812// impl_pin!(P4_0, ADC2, Mux0, 255);
728 813// impl_pin!(P4_1, ADC2, Mux0, 255);
729impl_pin!(P2_5, ADC3, Mux0, AdcPin); 814// ???
730impl_pin!(P2_11, ADC3, Mux0, AdcPin); 815impl_pin!(P4_2, ADC2, Mux0, 18);
731impl_pin!(P2_23, ADC3, Mux0, AdcPin); 816impl_pin!(P4_3, ADC2, Mux0, 19);
732impl_pin!(P2_25, ADC3, Mux0, AdcPin); 817//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); 818impl_pin!(P4_5, ADC2, Mux0, 21);
734impl_pin!(P2_13, ADC3, Mux0, AdcPin); 819impl_pin!(P4_6, ADC2, Mux0, 22);
735impl_pin!(P2_21, ADC3, Mux0, AdcPin); 820impl_pin!(P4_7, ADC2, Mux0, 23);
736impl_pin!(P2_7, ADC3, Mux0, AdcPin); 821
737impl_pin!(P3_2, ADC3, Mux0, AdcPin); 822impl_pin!(P2_5, ADC3, Mux0, 0);
738impl_pin!(P3_3, ADC3, Mux0, AdcPin); 823impl_pin!(P2_11, ADC3, Mux0, 1);
739impl_pin!(P3_4, ADC3, Mux0, AdcPin); 824impl_pin!(P2_23, ADC3, Mux0, 2);
740impl_pin!(P3_5, ADC3, Mux0, AdcPin); 825// impl_pin!(P2_25, ADC3, Mux0, 255); // ???
741impl_pin!(P3_6, ADC3, Mux0, AdcPin); 826impl_pin!(P2_17, ADC3, Mux0, 4);
742impl_pin!(P3_7, ADC3, Mux0, AdcPin); 827impl_pin!(P2_13, ADC3, Mux0, 5);
743impl_pin!(P3_12, ADC3, Mux0, AdcPin); 828impl_pin!(P2_21, ADC3, Mux0, 6);
744impl_pin!(P3_13, ADC3, Mux0, AdcPin); 829impl_pin!(P2_7, ADC3, Mux0, 7);
745impl_pin!(P3_14, ADC3, Mux0, AdcPin); 830// ???
746impl_pin!(P3_15, ADC3, Mux0, AdcPin); 831// impl_pin!(P3_2, ADC3, Mux0, 255);
747impl_pin!(P3_20, ADC3, Mux0, AdcPin); 832// impl_pin!(P3_3, ADC3, Mux0, 255);
748impl_pin!(P3_21, ADC3, Mux0, AdcPin); 833// impl_pin!(P3_4, ADC3, Mux0, 255);
749impl_pin!(P3_22, ADC3, Mux0, AdcPin); 834// impl_pin!(P3_5, ADC3, Mux0, 255);
750impl_pin!(P3_23, ADC3, Mux0, AdcPin); 835// ???
751impl_pin!(P3_24, ADC3, Mux0, AdcPin); 836impl_pin!(P3_6, ADC3, Mux0, 12);
752impl_pin!(P3_25, ADC3, Mux0, AdcPin); 837impl_pin!(P3_7, ADC3, Mux0, 13);
838impl_pin!(P3_12, ADC3, Mux0, 14);
839impl_pin!(P3_13, ADC3, Mux0, 15);
840impl_pin!(P3_14, ADC3, Mux0, 16);
841impl_pin!(P3_15, ADC3, Mux0, 17);
842impl_pin!(P3_20, ADC3, Mux0, 18);
843impl_pin!(P3_21, ADC3, Mux0, 19);
844impl_pin!(P3_22, ADC3, Mux0, 20);
845// ???
846// impl_pin!(P3_23, ADC3, Mux0, 255);
847// impl_pin!(P3_24, ADC3, Mux0, 255);
848// impl_pin!(P3_25, ADC3, Mux0, 255);
849// ???