embedded_c_sdk_bind_hal/
adc.rs

1use crate::common::atomic_ring_buffer::RingBuffer;
2use crate::ll_api::{ll_cmd::*, AdcCtrl};
3#[cfg(feature = "_adc-buffered")]
4use paste::paste;
5
6pub use crate::ll_api::AdcChannel;
7
8#[cfg(not(feature = "adc-data-type-u8"))]
9pub type AdcDataType = u16;
10
11#[cfg(feature = "adc-data-type-u8")]
12pub type AdcDataType = u8;
13
14#[derive(Clone, Debug)]
15pub struct Adc {
16    ch: AdcChannel,
17}
18
19impl Adc {
20    /// Creates a new instance of the ADC with the specified channel and optional configuration flags.
21    ///
22    /// # Arguments
23    /// * `ch` - The ADC channel to initialize.
24    /// * `flags` - Optional configuration flags for the ADC initialization.
25    ///
26    /// # Returns
27    /// A new `Adc` instance ready for conversion operations.
28    pub fn new(ch: AdcChannel, flags: Option<u32>) -> Self {
29        if let Some(val) = flags {
30            ll_invoke_inner!(INVOKE_ID_ADC_INIT, ch, val);
31        } else {
32            ll_invoke_inner!(INVOKE_ID_ADC_INIT, ch);
33        }
34
35        Adc { ch }
36    }
37
38    /// Performs a single conversion on the ADC.
39    ///
40    /// # Returns
41    /// The result of the conversion as an `AdcDataType`.
42    pub fn single_convert(&self) -> AdcDataType {
43        let mut buf = [0; 1];
44        let result = ll_invoke_inner!(
45            INVOKE_ID_ADC_CTRL,
46            self.ch,
47            AdcCtrl::Convert,
48            buf.as_mut_ptr(),
49            1
50        );
51        if result < 0 {
52            return 0;
53        }
54
55        buf[0]
56    }
57
58    /// Performs multiple conversions on the ADC into the provided buffer.
59    ///
60    /// # Arguments
61    /// * `buf` - The buffer to store the conversion results.
62    ///
63    /// # Returns
64    /// True if the operation was successful, false otherwise.
65    pub fn multiple_convert(&self, buf: &mut [AdcDataType]) -> bool {
66        let result = ll_invoke_inner!(
67            INVOKE_ID_ADC_CTRL,
68            self.ch,
69            AdcCtrl::Convert,
70            buf.as_mut_ptr(),
71            buf.len()
72        );
73        result >= 0
74    }
75}
76
77impl Drop for Adc {
78    fn drop(&mut self) {
79        ll_invoke_inner!(INVOKE_ID_ADC_DEINIT, self.ch);
80    }
81}
82
83pub struct AdcChData(RingBuffer<AdcDataType>);
84
85pub struct AdcBuffered<'a> {
86    ch: AdcChannel,
87    data: &'a AdcChData,
88}
89
90/// Creates a new instance of `AdcBuffered` with the specified channel and optional configuration flags.
91///
92/// # Arguments
93/// * `ch` - The ADC channel to initialize.
94/// * `data` - A reference to the ADC channel data.
95/// * `flags` - Optional configuration flags for the ADC initialization.
96///
97/// # Returns
98/// A new `AdcBuffered` instance ready for buffered conversion operations.
99impl<'a> AdcBuffered<'a> {
100    pub fn new(ch: AdcChannel, data: &'a AdcChData, flags: Option<u32>) -> Self {
101        if let Some(val) = flags {
102            ll_invoke_inner!(INVOKE_ID_ADC_INIT, ch, val);
103        } else {
104            ll_invoke_inner!(INVOKE_ID_ADC_INIT, ch);
105        }
106
107        AdcBuffered { ch, data }
108    }
109
110    /// Sets the buffer for storing conversion results.
111    ///
112    /// # Arguments
113    /// * `buffer` - The mutable buffer to be used for storing conversion results.
114    pub fn set_buf(&self, buffer: &mut [u16]) {
115        let len = buffer.len();
116        unsafe { self.data.0.init(buffer.as_mut_ptr(), len) };
117    }
118
119    /// Starts the ADC conversion process.
120    pub fn start(&self) {
121        ll_invoke_inner!(INVOKE_ID_ADC_CTRL, self.ch, AdcCtrl::Start);
122    }
123
124    /// Stops the ADC conversion process.
125    pub fn stop(&self) {
126        ll_invoke_inner!(INVOKE_ID_ADC_CTRL, self.ch, AdcCtrl::Stop);
127    }
128
129    /// Reads a single conversion result from the ADC data buffer.
130    ///
131    /// # Returns
132    /// An `Option<AdcDataType>` containing the conversion result if available, or `None` otherwise.
133    pub fn read(&self) -> Option<AdcDataType> {
134        let mut result = None;
135        critical_section::with(|_| result = unsafe { self.data.0.reader().pop_one() });
136        return result;
137    }
138
139    /// Reads multiple conversion results from the ADC data buffer into the provided buffer.
140    ///
141    /// # Arguments
142    /// * `buf` - The buffer to store the conversion results.
143    ///
144    /// # Returns
145    /// The number of conversion results read.
146    pub fn read_multiple(&self, buf: &mut [AdcDataType]) -> usize {
147        let mut result = 0;
148        critical_section::with(|_| {
149            let mut reader = unsafe { self.data.0.reader() };
150            for b in buf {
151                if let Some(data) = reader.pop_one() {
152                    *b = data;
153                    result += 1;
154                }
155            }
156        });
157
158        return result;
159    }
160}
161
162impl<'a> Drop for AdcBuffered<'a> {
163    fn drop(&mut self) {
164        ll_invoke_inner!(INVOKE_ID_ADC_DEINIT, self.ch);
165    }
166}
167
168#[cfg(feature = "_adc-buffered")]
169macro_rules! impl_adc_ch_data {
170    ($adc_ch:expr) => {
171        paste! {
172            pub static [<ADC_CH $adc_ch _DATA>]: AdcChData = AdcChData ( RingBuffer::new() );
173        }
174
175        paste! {
176            #[allow(non_snake_case)]
177            #[no_mangle]
178            #[inline]
179            unsafe extern "C" fn [<ADC_CH $adc_ch _EOC_hook_rs>] (val: AdcDataType) {//fn: ADC_CH{ch}_EOC_hook_rs(val)
180                paste! {
181                    let ch_data = &[<ADC_CH $adc_ch _DATA>].0;
182                    if ch_data.is_full() {
183                        ch_data.reader().pop_one();
184                    }
185                    ch_data.writer().push_one(val);
186                }
187            }
188        }
189    };
190}
191
192#[cfg(feature = "adc-buffered-ch0")]
193impl_adc_ch_data!(0);
194
195#[cfg(feature = "adc-buffered-ch1")]
196impl_adc_ch_data!(1);
197
198#[cfg(feature = "adc-buffered-ch2")]
199impl_adc_ch_data!(2);
200
201#[cfg(feature = "adc-buffered-ch3")]
202impl_adc_ch_data!(3);
203
204#[cfg(feature = "adc-buffered-ch4")]
205impl_adc_ch_data!(4);
206
207#[cfg(feature = "adc-buffered-ch5")]
208impl_adc_ch_data!(5);
209
210#[cfg(feature = "adc-buffered-ch6")]
211impl_adc_ch_data!(6);
212
213#[cfg(feature = "adc-buffered-ch7")]
214impl_adc_ch_data!(7);