iqs323_driver/
lib.rs

1#![no_std]
2// #![warn(missing_docs)]
3
4//! An embedded async driver for the IQS323 capacitive/inductive sensing controller.
5
6use array_concat::concat_arrays;
7use embedded_hal::digital::{self, InputPin, OutputPin};
8use embedded_hal::i2c::Operation;
9use embedded_hal_async::delay::DelayNs;
10use embedded_hal_async::digital::Wait;
11use embedded_hal_async::i2c::{self, I2c};
12
13pub mod regs;
14
15const ADDR: u8 = 0x44;
16
17#[derive(Debug, Clone, Copy, PartialEq, Eq)]
18#[cfg_attr(feature = "defmt-03", derive(defmt::Format))]
19pub enum Error<D: i2c::Error, P: digital::Error> {
20    Reset,
21    I2cLockup,
22    Io(P),
23    I2c(D),
24}
25
26pub struct Iqs323<D, P> {
27    i2c: D,
28    rdy: P,
29}
30
31impl<D, P> Iqs323<D, P> {
32    pub fn new(i2c: D, rdy: P) -> Self {
33        Self { i2c, rdy }
34    }
35
36    pub fn mclr(&mut self) -> &mut P {
37        &mut self.rdy
38    }
39}
40
41impl<D: I2c, P: InputPin> Iqs323<D, P> {
42    /// Send a communication request to the device to force a RDY window to open.
43    pub async fn force_comms(&mut self) -> Result<(), Error<D::Error, P::Error>> {
44        if self.rdy.is_high().map_err(Error::Io)? {
45            self.i2c.write(ADDR, &[0xff]).await.map_err(Error::I2c)
46        } else {
47            Ok(())
48        }
49    }
50
51    /// Terminate the communication window when [`stop_bit_disabled`](i2c_settings::settings::W::stop_bit_disabled) is set.
52    ///
53    /// Normally the communication windows is closed when any I²C transaction completes. However if the `stop_bit_disabled`
54    /// bit is set, the device will ignore the I²C STOP and the communication window must be terminated by calling this method.
55    pub async fn terminate_comms(&mut self) -> Result<(), Error<D::Error, P::Error>> {
56        if self.rdy.is_low().map_err(Error::Io)? {
57            self.i2c.write(ADDR, &[0xff]).await.map_err(Error::I2c)
58        } else {
59            Ok(())
60        }
61    }
62}
63
64impl<D: I2c, P: Wait> Iqs323<D, P> {
65    pub fn regs(&mut self) -> regs::Registers<&mut Self> {
66        regs::Registers::new(self)
67    }
68
69    pub async fn reset<T: DelayNs>(
70        &mut self,
71        delay: &mut T,
72    ) -> Result<(), Error<D::Error, P::Error>> {
73        let mut regs = self.regs();
74        while !regs
75            .sys_info()
76            .system_status()
77            .read_async()
78            .await?
79            .reset_event()
80        {
81            regs.sys_control()
82                .control()
83                .write_async(|reg| reg.set_trigger_soft_reset(true))
84                .await?;
85            delay.delay_ms(100).await;
86        }
87
88        Ok(())
89    }
90
91    pub async fn ack_reset(&mut self) -> Result<(), Error<D::Error, P::Error>> {
92        self.regs()
93            .sys_control()
94            .control()
95            .modify_async(|w| w.set_ack_reset(true))
96            .await
97    }
98
99    pub async fn setup(&mut self, setup: &AddressedSetup) -> Result<(), Error<D::Error, P::Error>> {
100        self.rdy.wait_for_low().await.map_err(Error::Io)?;
101        self.i2c
102            .transaction(
103                ADDR,
104                &mut [
105                    Operation::Write(&setup.sensors[0]),
106                    Operation::Write(&setup.sensors[1]),
107                    Operation::Write(&setup.sensors[2]),
108                    Operation::Write(&setup.channels[0]),
109                    Operation::Write(&setup.channels[1]),
110                    Operation::Write(&setup.channels[2]),
111                    Operation::Write(&setup.slider),
112                    Operation::Write(&setup.gesture),
113                    Operation::Write(&setup.filter_betas),
114                    Operation::Write(&setup.system_control),
115                    Operation::Write(&setup.general),
116                    Operation::Write(&setup.i2c_settings),
117                ],
118            )
119            .await
120            .map_err(Error::I2c)?;
121        self.rdy.wait_for_high().await.map_err(Error::Io)
122    }
123
124    pub async fn read_setup(&mut self) -> Result<Setup, Error<D::Error, P::Error>> {
125        let mut setup = Setup::default();
126
127        fn as_bytes_mut(slice: &mut [u16]) -> &mut [u8] {
128            unsafe { core::slice::from_raw_parts_mut(slice.as_ptr() as *mut u8, 2 * slice.len()) }
129        }
130
131        let (s0, s1, s2) = match &mut setup.sensors {
132            [s0, s1, s2] => (as_bytes_mut(s0), as_bytes_mut(s1), as_bytes_mut(s2)),
133        };
134        let (c0, c1, c2) = match &mut setup.channels {
135            [c0, c1, c2] => (as_bytes_mut(c0), as_bytes_mut(c1), as_bytes_mut(c2)),
136        };
137
138        self.rdy.wait_for_low().await.map_err(Error::Io)?;
139        self.i2c
140            .transaction(
141                ADDR,
142                &mut [
143                    Operation::Write(&[0x30]),
144                    Operation::Read(s0),
145                    Operation::Write(&[0x40]),
146                    Operation::Read(s1),
147                    Operation::Write(&[0x50]),
148                    Operation::Read(s2),
149                    Operation::Write(&[0x60]),
150                    Operation::Read(c0),
151                    Operation::Write(&[0x70]),
152                    Operation::Read(c1),
153                    Operation::Write(&[0x80]),
154                    Operation::Read(c2),
155                    Operation::Write(&[0x90]),
156                    Operation::Read(as_bytes_mut(&mut setup.slider)),
157                    Operation::Write(&[0xa0]),
158                    Operation::Read(as_bytes_mut(&mut setup.gesture)),
159                    Operation::Write(&[0xb0]),
160                    Operation::Read(as_bytes_mut(&mut setup.filter_betas)),
161                    Operation::Write(&[0xc0]),
162                    Operation::Read(as_bytes_mut(&mut setup.system_control)),
163                    Operation::Write(&[0xd0]),
164                    Operation::Read(as_bytes_mut(&mut setup.general)),
165                    Operation::Write(&[0xe0]),
166                    Operation::Read(&mut setup.i2c_settings),
167                ],
168            )
169            .await
170            .map_err(Error::I2c)?;
171        self.rdy.wait_for_high().await.map_err(Error::Io)?;
172
173        Ok(setup)
174    }
175
176    pub async fn read_sys_info(&mut self) -> Result<SysInfo, Error<D::Error, P::Error>> {
177        let mut buf = [0; 19];
178        self.rdy.wait_for_low().await.map_err(Error::Io)?;
179        self.i2c
180            .write_read(ADDR, &[0x10], &mut buf)
181            .await
182            .map_err(Error::I2c)?;
183        self.rdy.wait_for_high().await.map_err(Error::Io)?;
184
185        if buf[18] != 0xee {
186            return Err(Error::I2cLockup);
187        }
188
189        #[inline]
190        fn as_array(slice: &[u8]) -> [u8; 2] {
191            slice.try_into().unwrap()
192        }
193
194        let system_status = regs::field_sets::SystemStatus::from(as_array(&buf[0..2]));
195
196        if system_status.reset_event() {
197            return Err(Error::Reset);
198        }
199
200        let gestures = regs::field_sets::Gestures::from(as_array(&buf[2..4]));
201        let slider_position = regs::field_sets::SliderPosition::from(as_array(&buf[4..6]));
202        let ch0_filtered_counts = regs::field_sets::Ch0FilteredCounts::from(as_array(&buf[6..8]));
203        let ch0_lta = regs::field_sets::Ch0Lta::from(as_array(&buf[8..10]));
204        let ch1_filtered_counts = regs::field_sets::Ch1FilteredCounts::from(as_array(&buf[10..12]));
205        let ch1_lta = regs::field_sets::Ch1Lta::from(as_array(&buf[12..14]));
206        let ch2_filtered_counts = regs::field_sets::Ch2FilteredCounts::from(as_array(&buf[14..16]));
207        let ch2_lta = regs::field_sets::Ch2Lta::from(as_array(&buf[16..18]));
208
209        Ok(SysInfo {
210            system_status,
211            gestures,
212            slider_position,
213            ch0_filtered_counts,
214            ch0_lta,
215            ch1_filtered_counts,
216            ch1_lta,
217            ch2_filtered_counts,
218            ch2_lta,
219        })
220    }
221}
222
223impl<D: I2c, P: Wait + OutputPin> Iqs323<D, P> {
224    pub async fn hard_reset<T: DelayNs>(&mut self, delay: &mut T) -> Result<(), P::Error> {
225        self.rdy.wait_for_high().await?;
226        self.rdy.set_low()?;
227        delay.delay_us(1).await;
228        self.rdy.set_high()?;
229        delay.delay_ms(100).await;
230        Ok(())
231    }
232}
233
234impl<'a, D: I2c, P: Wait> device_driver::AsyncRegisterInterface for &'a mut Iqs323<D, P> {
235    type AddressType = u8;
236    type Error = Error<D::Error, P::Error>;
237
238    async fn write_register(
239        &mut self,
240        address: Self::AddressType,
241        _size_bits: u32,
242        data: &[u8],
243    ) -> Result<(), Self::Error> {
244        const MAX_LEN: usize = 3;
245        assert!(data.len() < MAX_LEN);
246        let mut buf = heapless::Vec::<u8, MAX_LEN>::new();
247        let _ = buf.push(address);
248        let _ = buf.extend_from_slice(data);
249        self.rdy.wait_for_low().await.map_err(Error::Io)?;
250        self.i2c.write(ADDR, &buf).await.map_err(Error::I2c)?;
251        self.rdy.wait_for_high().await.map_err(Error::Io)
252    }
253
254    async fn read_register(
255        &mut self,
256        address: Self::AddressType,
257        _size_bits: u32,
258        data: &mut [u8],
259    ) -> Result<(), Self::Error> {
260        self.rdy.wait_for_low().await.map_err(Error::Io)?;
261        self.i2c
262            .write_read(ADDR, &[address], data)
263            .await
264            .map_err(Error::I2c)?;
265        self.rdy.wait_for_high().await.map_err(Error::Io)
266    }
267}
268
269#[derive(Default, Clone, Copy, PartialEq, Eq)]
270#[cfg_attr(feature = "defmt-03", derive(defmt::Format))]
271pub struct Setup {
272    pub sensors: [[u16; 10]; 3],
273    pub channels: [[u16; 4]; 3],
274    pub slider: [u16; 9],
275    pub gesture: [u16; 7],
276    pub filter_betas: [u16; 5],
277    pub system_control: [u16; 6],
278    pub general: [u16; 5],
279    pub i2c_settings: [u8; 1],
280}
281
282impl Setup {
283    pub const fn addressed(self) -> AddressedSetup {
284        AddressedSetup::from_setup(self)
285    }
286}
287
288#[derive(Default, Clone, Copy, PartialEq, Eq)]
289#[cfg_attr(feature = "defmt-03", derive(defmt::Format))]
290pub struct AddressedSetup {
291    sensors: [[u8; 21]; 3],
292    channels: [[u8; 9]; 3],
293    slider: [u8; 19],
294    gesture: [u8; 15],
295    filter_betas: [u8; 11],
296    system_control: [u8; 13],
297    general: [u8; 11],
298    i2c_settings: [u8; 2],
299}
300
301impl AddressedSetup {
302    pub const fn from_setup(setup: Setup) -> Self {
303        const unsafe fn as_bytes<const N: usize, const M: usize>(src: [u16; N]) -> [u8; M] {
304            const { assert!(M == 2 * N) }
305            *(src.as_ptr() as *const [u8; M])
306        }
307
308        unsafe {
309            AddressedSetup {
310                sensors: [
311                    concat_arrays!([0x30], as_bytes::<10, 20>(setup.sensors[0])),
312                    concat_arrays!([0x40], as_bytes::<10, 20>(setup.sensors[1])),
313                    concat_arrays!([0x50], as_bytes::<10, 20>(setup.sensors[2])),
314                ],
315                channels: [
316                    concat_arrays!([0x60], as_bytes::<4, 8>(setup.channels[0])),
317                    concat_arrays!([0x70], as_bytes::<4, 8>(setup.channels[1])),
318                    concat_arrays!([0x80], as_bytes::<4, 8>(setup.channels[2])),
319                ],
320                slider: concat_arrays!([0x90], as_bytes::<9, 18>(setup.slider)),
321                gesture: concat_arrays!([0xa0], as_bytes::<7, 14>(setup.gesture)),
322                filter_betas: concat_arrays!([0xb0], as_bytes::<5, 10>(setup.filter_betas)),
323                system_control: concat_arrays!([0xc0], as_bytes::<6, 12>(setup.system_control)),
324                general: concat_arrays!([0xd0], as_bytes::<5, 10>(setup.general)),
325                i2c_settings: concat_arrays!([0xe0], setup.i2c_settings),
326            }
327        }
328    }
329}
330
331impl From<Setup> for AddressedSetup {
332    fn from(value: Setup) -> Self {
333        Self::from_setup(value)
334    }
335}
336
337pub struct SysInfo {
338    pub system_status: regs::field_sets::SystemStatus,
339    pub gestures: regs::field_sets::Gestures,
340    pub slider_position: regs::field_sets::SliderPosition,
341    pub ch0_filtered_counts: regs::field_sets::Ch0FilteredCounts,
342    pub ch0_lta: regs::field_sets::Ch0Lta,
343    pub ch1_filtered_counts: regs::field_sets::Ch1FilteredCounts,
344    pub ch1_lta: regs::field_sets::Ch1Lta,
345    pub ch2_filtered_counts: regs::field_sets::Ch2FilteredCounts,
346    pub ch2_lta: regs::field_sets::Ch2Lta,
347}