1#![no_std]
2use 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 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 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}