ad7124_rs/ad7124/
async.rs

1//! Asynchronous AD7124 driver implementation
2//!
3//! Provides async/await API for AD7124 driver
4
5use crate::ad7124::{AD7124Config, AD7124Core, ChannelConfig, FilterConfig, SetupConfig};
6use crate::device_type::DeviceType;
7use crate::errors::{AD7124CoreError, AD7124Error};
8use crate::registers::{DeviceStatus, Register};
9
10use crate::transport::AsyncSpiTransport;
11
12/// Asynchronous AD7124 driver
13#[derive(Debug)]
14pub struct AD7124Async<T> {
15    /// SPI transport interface
16    transport: T,
17    /// Core driver logic
18    core: AD7124Core,
19}
20
21impl<T> AD7124Async<T>
22where
23    T: AsyncSpiTransport,
24{
25    /// Create new AD7124 driver instance
26    pub fn new(transport: T, device_type: DeviceType) -> Result<Self, AD7124Error<T::Error, ()>> {
27        let core = AD7124Core::new(device_type).map_err(AD7124Error::Core)?;
28
29        Ok(Self { transport, core })
30    }
31
32    /// Create new AD7124 driver with auto-detection
33    pub async fn new_with_detection(mut transport: T) -> Result<Self, AD7124Error<T::Error, ()>> {
34        // Read device ID to detect type
35        let device_id = Self::read_device_id_raw(&mut transport).await?;
36        let device_type = DeviceType::from_device_id(device_id);
37
38        if device_type == DeviceType::Unknown {
39            return Err(AD7124Error::Core(AD7124CoreError::InvalidDeviceId));
40        }
41
42        let core = AD7124Core::new(device_type).map_err(AD7124Error::Core)?;
43
44        Ok(Self { transport, core })
45    }
46
47    /// Initialize the AD7124 device
48    pub async fn init(&mut self) -> Result<(), AD7124Error<T::Error, ()>> {
49        if self.core.is_initialized() {
50            return Err(AD7124Error::Core(AD7124CoreError::InvalidConfiguration));
51        }
52
53        // Verify device ID
54        let device_id = self.read_device_id().await?;
55        self.core
56            .verify_device_id(device_id)
57            .map_err(AD7124Error::Core)?;
58
59        // Execute initialization sequence
60        let sequence = self
61            .core
62            .initialization_sequence()
63            .map_err(AD7124Error::Core)?;
64
65        self.execute_sequence(&sequence).await?;
66
67        // Wait for device to be ready
68        self.transport
69            .delay_ms(10)
70            .await
71            .map_err(AD7124Error::Transport)?;
72
73        self.core.set_initialized();
74        Ok(())
75    }
76
77    /// Read device ID register
78    pub async fn read_device_id(&mut self) -> Result<u8, AD7124Error<T::Error, ()>> {
79        Self::read_device_id_raw(&mut self.transport).await
80    }
81
82    /// Read device status
83    pub async fn read_status(&mut self) -> Result<DeviceStatus, AD7124Error<T::Error, ()>> {
84        let raw_status = self.read_register(Register::Status).await?;
85        Ok(DeviceStatus::new(raw_status as u8))
86    }
87
88    /// Configure ADC control settings
89    pub async fn configure_adc(
90        &mut self,
91        config: AD7124Config,
92    ) -> Result<(), AD7124Error<T::Error, ()>> {
93        self.core.set_config(config);
94
95        // Build ADC control value directly without reset
96        let adc_ctrl_value = self.core.build_adc_control_value_public();
97
98        // Write to ADC control register
99        self.write_register(Register::AdcCtrl, adc_ctrl_value)
100            .await?;
101
102        // If internal reference is enabled, wait for it to stabilize
103        if config.internal_ref_enabled {
104            // Add a small delay for reference stabilization
105            self.transport
106                .delay_ms(10)
107                .await
108                .map_err(AD7124Error::Transport)?;
109        }
110
111        Ok(())
112    }
113
114    /// Configure channel
115    pub async fn configure_channel(
116        &mut self,
117        channel: u8,
118        config: ChannelConfig,
119    ) -> Result<(), AD7124Error<T::Error, ()>> {
120        let sequence = self
121            .core
122            .configure_channel(channel, config)
123            .map_err(AD7124Error::Core)?;
124
125        self.execute_sequence(&sequence).await
126    }
127
128    /// Configure setup (PGA, reference, etc.)
129    pub async fn configure_setup(
130        &mut self,
131        setup_index: u8,
132        config: SetupConfig,
133    ) -> Result<(), AD7124Error<T::Error, ()>> {
134        let sequence = self
135            .core
136            .configure_setup(setup_index, config)
137            .map_err(AD7124Error::Core)?;
138
139        self.execute_sequence(&sequence).await
140    }
141
142    /// Configure filter
143    pub async fn configure_filter(
144        &mut self,
145        setup_index: u8,
146        config: FilterConfig,
147    ) -> Result<(), AD7124Error<T::Error, ()>> {
148        let sequence = self
149            .core
150            .configure_filter(setup_index, config)
151            .map_err(AD7124Error::Core)?;
152
153        self.execute_sequence(&sequence).await
154    }
155
156    /// Read raw ADC data (24-bit)
157    pub async fn read_data(&mut self) -> Result<u32, AD7124Error<T::Error, ()>> {
158        let raw_data = self.read_register(Register::Data).await?;
159        Ok(raw_data & 0xFFFFFF) // Mask to 24-bit
160    }
161
162    /// Read ADC data and convert to voltage
163    pub async fn read_voltage(
164        &mut self,
165        setup_index: u8,
166    ) -> Result<f32, AD7124Error<T::Error, ()>> {
167        let raw_data = self.read_data().await?;
168
169        // For simplicity, assume default setup configuration
170        // In a real application, you would track the setup configuration
171        let pga_gain = crate::registers::PgaGain::Gain1;
172        let bipolar = true;
173        let vref = 2.5; // Internal reference
174
175        let voltage =
176            self.core
177                .raw_to_voltage_with_setup(raw_data, setup_index, bipolar, pga_gain, vref);
178        Ok(voltage)
179    }
180
181    /// Wait for data ready
182    pub async fn wait_for_data_ready(
183        &mut self,
184        timeout_ms: u32,
185    ) -> Result<(), AD7124Error<T::Error, ()>> {
186        let mut elapsed = 0u32;
187
188        loop {
189            let status = self.read_status().await?;
190            if status.rdy() {
191                return Ok(());
192            }
193
194            if elapsed >= timeout_ms {
195                return Err(AD7124Error::Core(AD7124CoreError::Timeout));
196            }
197
198            self.transport
199                .delay_ms(1)
200                .await
201                .map_err(AD7124Error::Transport)?;
202            elapsed += 1;
203        }
204    }
205
206    // ==================== Enhanced Channel Management (Async) ====================
207
208    /// Check if data is ready (non-blocking)
209    pub async fn is_data_ready(&mut self) -> Result<bool, AD7124Error<T::Error, ()>> {
210        let status = self.read_status().await?;
211        Ok(status.is_ready())
212    }
213
214    /// Wait for conversion ready with optional timeout
215    pub async fn wait_conv_ready(
216        &mut self,
217        timeout_ms: Option<u32>,
218    ) -> Result<(), AD7124Error<T::Error, ()>> {
219        let timeout = timeout_ms.unwrap_or(AD7124Core::get_default_timeout());
220        self.wait_for_data_ready(timeout).await
221    }
222
223    /// Enable or disable a specific channel (requires I/O to read-modify-write register)
224    pub async fn enable_channel(
225        &mut self,
226        channel: u8,
227        enable: bool,
228    ) -> Result<(), AD7124Error<T::Error, ()>> {
229        if !self.core.validate_channel(channel) {
230            return Err(AD7124Error::Core(AD7124CoreError::InvalidParameter));
231        }
232
233        let channel_reg = AD7124Core::get_channel_register(channel).map_err(AD7124Error::Core)?;
234
235        // Read current register value
236        let mut current_value = self.read_register(channel_reg).await?;
237
238        // Modify enable bit (bit 15)
239        if enable {
240            current_value |= 1 << 15;
241        } else {
242            current_value &= !(1 << 15);
243        }
244
245        // Write back
246        self.write_register(channel_reg, current_value).await
247    }
248
249    /// Check if a channel is enabled (requires I/O to read register for accuracy)
250    pub async fn is_channel_enabled(
251        &mut self,
252        channel: u8,
253    ) -> Result<bool, AD7124Error<T::Error, ()>> {
254        if !self.core.validate_channel(channel) {
255            return Ok(false);
256        }
257
258        let channel_reg = AD7124Core::get_channel_register(channel).map_err(AD7124Error::Core)?;
259
260        let reg_value = self.read_register(channel_reg).await?;
261        Ok((reg_value & (1 << 15)) != 0)
262    }
263
264    /// Get all enabled channels (requires I/O to read each channel register)
265    pub async fn get_enabled_channels(
266        &mut self,
267    ) -> Result<heapless::Vec<u8, 8>, AD7124Error<T::Error, ()>> {
268        let mut enabled_channels = heapless::Vec::new();
269
270        for channel in 0..self.core.capabilities().max_channels {
271            if self.is_channel_enabled(channel).await? {
272                let _ = enabled_channels.push(channel);
273            }
274        }
275
276        Ok(enabled_channels)
277    }
278
279    /// Validate channel number for this device (pure logic)
280    pub fn validate_channel(&self, channel: u8) -> bool {
281        self.core.validate_channel(channel)
282    }
283
284    /// Get the currently active channel (requires I/O to read status register)
285    pub async fn get_active_channel(&mut self) -> Result<u8, AD7124Error<T::Error, ()>> {
286        let status_value = self.read_register(Register::Status).await?;
287        Ok((status_value as u8) & 0x0F) // Bits 3:0 contain channel
288    }
289
290    /// Get current channel from status register directly
291    pub async fn current_channel(&mut self) -> Result<u8, AD7124Error<T::Error, ()>> {
292        let status = self.read_status().await?;
293        Ok(status.channel())
294    }
295
296    // ==================== Enhanced Data Reading (Async) ====================
297
298    /// Read data from a specific channel
299    pub async fn read_channel_data(
300        &mut self,
301        channel: u8,
302    ) -> Result<u32, AD7124Error<T::Error, ()>> {
303        // 1. Validate channel
304        if !self.core.validate_channel(channel) {
305            return Err(AD7124Error::Core(AD7124CoreError::InvalidParameter));
306        }
307
308        // 2. Check if channel is enabled
309        if !self.is_channel_enabled(channel).await? {
310            return Err(AD7124Error::Core(AD7124CoreError::ChannelNotEnabled));
311        }
312
313        // 3. In continuous mode with multiple channels enabled,
314        // the ADC automatically cycles through enabled channels.
315        // We should wait for the target channel's data to be ready.
316
317        // Wait for data and check which channel it's from
318        let mut attempts = 0;
319        const MAX_ATTEMPTS: u32 = 10;
320
321        loop {
322            // Wait for any data to be ready
323            self.wait_conv_ready(Some(AD7124Core::get_default_timeout()))
324                .await?;
325
326            // Check which channel the data is from
327            let active_channel = self.get_active_channel().await?;
328
329            if active_channel == channel {
330                // This is our channel's data, read it
331                return self.read_data().await;
332            } else {
333                // This is another channel's data, read and discard it
334                let _ = self.read_data().await?;
335
336                attempts += 1;
337                if attempts >= MAX_ATTEMPTS {
338                    // Too many attempts, something might be wrong
339                    return Err(AD7124Error::Core(AD7124CoreError::Timeout));
340                }
341            }
342        }
343    }
344
345    /// Simple read for already active channel (no channel switching)
346    pub async fn read_active_channel_data(&mut self) -> Result<u32, AD7124Error<T::Error, ()>> {
347        // Wait for data ready
348        self.wait_conv_ready(None).await?;
349        // Read the data
350        self.read_data().await
351    }
352
353    /// Start continuous conversions (useful after configuration)
354    pub async fn start_continuous_conversion(&mut self) -> Result<(), AD7124Error<T::Error, ()>> {
355        // Read current ADC control register
356        let mut adc_ctrl = self.read_register(Register::AdcCtrl).await?;
357
358        // Clear mode bits (bits 5:2) and set to continuous mode (0b0000)
359        adc_ctrl &= !(0xF << 2); // Clear bits 5:2
360                                 // Continuous mode is 0b0000, so we don't need to set any bits
361
362        // Ensure power is on (clear power down bit 6)
363        adc_ctrl &= !(1 << 6);
364
365        // Write back to start conversions
366        self.write_register(Register::AdcCtrl, adc_ctrl).await?;
367
368        // Small delay to let conversions start
369        self.transport
370            .delay_ms(10)
371            .await
372            .map_err(AD7124Error::Transport)?;
373
374        Ok(())
375    }
376
377    /// Read data register directly without waiting (for debugging)
378    pub async fn read_data_no_wait(&mut self) -> Result<u32, AD7124Error<T::Error, ()>> {
379        self.read_data().await
380    }
381
382    /// Read next available data from any enabled channel in continuous mode
383    /// Returns tuple of (channel_number, data_value)
384    pub async fn read_next_available(&mut self) -> Result<(u8, u32), AD7124Error<T::Error, ()>> {
385        // Wait for any data to be ready
386        self.wait_conv_ready(None).await?;
387
388        // Get the channel that has data ready
389        let channel = self.get_active_channel().await?;
390
391        // Read the data
392        let data = self.read_data().await?;
393
394        Ok((channel, data))
395    }
396
397    /// Read data from multiple channels efficiently in continuous mode
398    /// Reads one sample from each specified channel
399    pub async fn read_channels_continuous(
400        &mut self,
401        channels: &[u8],
402    ) -> Result<heapless::Vec<(u8, u32), 8>, AD7124Error<T::Error, ()>> {
403        let mut results = heapless::Vec::new();
404        let mut channels_read = heapless::Vec::<u8, 16>::new();
405
406        // Validate all channels first
407        for &ch in channels {
408            if !self.core.validate_channel(ch) {
409                return Err(AD7124Error::Core(AD7124CoreError::InvalidParameter));
410            }
411            if !self.is_channel_enabled(ch).await? {
412                return Err(AD7124Error::Core(AD7124CoreError::ChannelNotEnabled));
413            }
414        }
415
416        // Read data until we have all requested channels
417        let max_attempts = channels.len() * 3; // Allow some extra attempts
418        for _ in 0..max_attempts {
419            let (ch, data) = self.read_next_available().await?;
420
421            // If this channel is in our list and we haven't read it yet
422            if channels.contains(&ch) && !channels_read.contains(&ch) {
423                let _ = results.push((ch, data));
424                let _ = channels_read.push(ch);
425
426                // If we've read all requested channels, we're done
427                if channels_read.len() == channels.len() {
428                    break;
429                }
430            }
431        }
432
433        Ok(results)
434    }
435
436    /// Read voltage from a specific channel
437    pub async fn read_channel_voltage(
438        &mut self,
439        channel: u8,
440    ) -> Result<f32, AD7124Error<T::Error, ()>> {
441        let raw_data = self.read_channel_data(channel).await?;
442
443        // Get channel configuration to determine setup
444        let channel_reg = AD7124Core::get_channel_register(channel).map_err(AD7124Error::Core)?;
445        let channel_value = self.read_register(channel_reg).await?;
446        let setup_index = ((channel_value >> 12) & 0x07) as u8; // Bits[14:12]
447
448        // Get setup configuration
449        let config_reg = AD7124Core::get_config_register(setup_index).map_err(AD7124Error::Core)?;
450        let config_value = self.read_register(config_reg).await?;
451
452        let bipolar = (config_value & (1 << 11)) != 0;
453        let gain_bits = config_value & 0x07;
454        let gain = crate::registers::PgaGain::from_bits(gain_bits as u8)
455            .map_err(|_| AD7124Error::Core(AD7124CoreError::InvalidParameter))?;
456
457        // Assume internal 2.5V reference
458        let vref = 2.5;
459
460        let voltage =
461            self.core
462                .raw_to_voltage_with_setup(raw_data, setup_index, bipolar, gain, vref);
463
464        Ok(voltage)
465    }
466
467    /// Read multiple channels sequentially
468    pub async fn read_multi_channel(
469        &mut self,
470        channels: &[u8],
471    ) -> Result<heapless::Vec<(u8, u32), 8>, AD7124Error<T::Error, ()>> {
472        let mut results = heapless::Vec::new();
473
474        for &channel in channels {
475            let data = self.read_channel_data(channel).await?;
476            results
477                .push((channel, data))
478                .map_err(|_| AD7124Error::Core(AD7124CoreError::InvalidParameter))?;
479        }
480
481        Ok(results)
482    }
483
484    /// Read voltage from multiple channels
485    pub async fn read_multi_voltage(
486        &mut self,
487        channels: &[u8],
488    ) -> Result<heapless::Vec<(u8, f32), 8>, AD7124Error<T::Error, ()>> {
489        let mut results = heapless::Vec::new();
490
491        for &channel in channels {
492            let voltage = self.read_channel_voltage(channel).await?;
493            results
494                .push((channel, voltage))
495                .map_err(|_| AD7124Error::Core(AD7124CoreError::InvalidParameter))?;
496        }
497
498        Ok(results)
499    }
500
501    /// Scan all enabled channels and read their data
502    pub async fn scan_enabled_channels(
503        &mut self,
504    ) -> Result<heapless::Vec<(u8, u32), 8>, AD7124Error<T::Error, ()>> {
505        let channels = self.get_enabled_channels().await?;
506        let channel_slice: &[u8] = &channels;
507        self.read_multi_channel(channel_slice).await
508    }
509
510    /// Read data with channel information from status
511    pub async fn read_data_with_status(&mut self) -> Result<(u8, u32), AD7124Error<T::Error, ()>> {
512        self.wait_conv_ready(None).await?;
513        let channel = self.get_active_channel().await?;
514        let data = self.read_data().await?;
515        Ok((channel, data))
516    }
517
518    /// Fast data read (no status check)
519    pub async fn read_data_fast(&mut self) -> Result<u32, AD7124Error<T::Error, ()>> {
520        // Direct read of data register without status checks
521        self.read_register(Register::Data).await
522    }
523
524    /// Perform software reset
525    pub async fn reset(&mut self) -> Result<(), AD7124Error<T::Error, ()>> {
526        self.write_register(Register::AdcCtrl, 0x8000).await?;
527        self.transport
528            .delay_ms(10)
529            .await
530            .map_err(AD7124Error::Transport)?;
531        Ok(())
532    }
533
534    /// Get device capabilities
535    pub fn capabilities(&self) -> &crate::device_type::DeviceCapabilities {
536        self.core.capabilities()
537    }
538
539    /// Get current configuration
540    pub fn config(&self) -> &AD7124Config {
541        self.core.config()
542    }
543
544    /// Get device type
545    pub fn device_type(&self) -> DeviceType {
546        self.core.device_type()
547    }
548
549    /// Check if driver is initialized
550    pub fn is_initialized(&self) -> bool {
551        self.core.is_initialized()
552    }
553
554    /// Get reference to transport layer (for advanced usage)
555    pub fn transport(&self) -> &T {
556        &self.transport
557    }
558
559    /// Get mutable reference to transport layer (for advanced usage)
560    pub fn transport_mut(&mut self) -> &mut T {
561        &mut self.transport
562    }
563
564    // Private helper methods
565    async fn read_device_id_raw(transport: &mut T) -> Result<u8, AD7124Error<T::Error, ()>> {
566        let mut read_buf = [0u8; 2];
567        let write_buf = [(Register::Id.addr() | 0x40), 0x00]; // Read command
568
569        transport
570            .transfer(&mut read_buf, &write_buf)
571            .await
572            .map_err(AD7124Error::Transport)?;
573        Ok(read_buf[1])
574    }
575
576    /// Read value from specified register
577    pub async fn read_register(
578        &mut self,
579        register: Register,
580    ) -> Result<u32, AD7124Error<T::Error, ()>> {
581        let size = register.size() as usize;
582        let mut read_buf = [0u8; 8]; // Max size for any register
583        let mut write_buf = [0u8; 8];
584        write_buf[0] = register.addr() | 0x40; // Read command
585
586        self.transport
587            .transfer(&mut read_buf[..size + 1], &write_buf[..size + 1])
588            .await
589            .map_err(AD7124Error::Transport)?;
590
591        // Convert bytes to u32 (big-endian)
592        let mut value = 0u32;
593        for i in 1..=size {
594            value = (value << 8) | (read_buf[i] as u32);
595        }
596
597        Ok(value)
598    }
599
600    /// Write value to specified register
601    pub async fn write_register(
602        &mut self,
603        register: Register,
604        value: u32,
605    ) -> Result<(), AD7124Error<T::Error, ()>> {
606        if register.is_readonly() {
607            return Err(AD7124Error::Core(AD7124CoreError::InvalidParameter));
608        }
609
610        let size = register.size() as usize;
611        let mut write_buf = [0u8; 8]; // Max size for any register
612        write_buf[0] = register.addr(); // Write command
613
614        // According to AD7124 datasheet, all registers use big-endian format (MSB first)
615        // Use big-endian format for all registers consistently
616        for i in 0..size {
617            // Big-endian: most significant byte first
618            write_buf[1 + i] = ((value >> ((size - 1 - i) * 8)) & 0xFF) as u8;
619        }
620
621        self.transport
622            .write(&write_buf[..size + 1])
623            .await
624            .map_err(AD7124Error::Transport)?;
625
626        Ok(())
627    }
628
629    async fn execute_sequence(
630        &mut self,
631        sequence: &crate::ad7124::CommandSequence,
632    ) -> Result<(), AD7124Error<T::Error, ()>> {
633        for (i, (register, value)) in sequence.commands().iter().enumerate() {
634            self.write_register(*register, *value).await?;
635
636            // Add delay after software reset (first command)
637            if i == 0 && *register == Register::AdcCtrl && *value == 0x8000 {
638                // Software reset requires longer delay
639                self.transport
640                    .delay_ms(100)
641                    .await
642                    .map_err(AD7124Error::Transport)?;
643            } else if *register == Register::AdcCtrl {
644                // Allow time for ADC configuration to settle
645                self.transport
646                    .delay_ms(10)
647                    .await
648                    .map_err(AD7124Error::Transport)?;
649            }
650        }
651        Ok(())
652    }
653}
654
655/// High-level convenience functions for common operations
656impl<T> AD7124Async<T>
657where
658    T: AsyncSpiTransport,
659{
660    /// Quick setup for single-ended measurement
661    pub async fn setup_single_ended(
662        &mut self,
663        channel: u8,
664        positive_input: crate::registers::ChannelInput,
665        setup_index: u8,
666    ) -> Result<(), AD7124Error<T::Error, ()>> {
667        // Configure channel for single-ended measurement
668        let channel_config = ChannelConfig {
669            enabled: true,
670            positive_input,
671            negative_input: crate::registers::ChannelInput::Dgnd,
672            setup_index,
673        };
674        self.configure_channel(channel, channel_config).await?;
675
676        // Configure setup with default values
677        let setup_config = SetupConfig::default();
678        self.configure_setup(setup_index, setup_config).await?;
679
680        // Configure filter with default values
681        let filter_config = FilterConfig::default();
682        self.configure_filter(setup_index, filter_config).await?;
683
684        Ok(())
685    }
686
687    /// Quick setup for differential measurement
688    pub async fn setup_differential(
689        &mut self,
690        channel: u8,
691        positive_input: crate::registers::ChannelInput,
692        negative_input: crate::registers::ChannelInput,
693        setup_index: u8,
694    ) -> Result<(), AD7124Error<T::Error, ()>> {
695        // Configure channel for differential measurement
696        let channel_config = ChannelConfig {
697            enabled: true,
698            positive_input,
699            negative_input,
700            setup_index,
701        };
702        self.configure_channel(channel, channel_config).await?;
703
704        // Don't configure setup and filter if they're passed as parameters
705        // The user should configure them separately if needed
706        // This was causing issues by overwriting user configurations
707
708        Ok(())
709    }
710}