1use crate::*;
2use core::marker::PhantomData;
3use embedded_hal::spi::{Operation, SpiDevice};
4
5pub struct Touchpad<S: SpiDevice<u8>, M: Mode> {
6 spi: S,
7 phantom_: PhantomData<M>,
8}
9
10#[derive(Copy, Clone, Debug)]
14pub enum PowerMode {
15 Active,
23
24 Sleep,
28
29 Shutdown,
32}
33
34#[expect(clippy::struct_excessive_bools)]
35pub struct Calibration {
36 pub background_comp: bool,
37 pub nerd_comp: bool,
38 pub track_error_comp: bool,
39 pub tap_comp: bool,
40 pub palm_error_comp: bool,
41 pub calibration_matrix: bool,
42 pub force_precalibration_noise_check: bool,
43}
44
45impl Default for Calibration {
46 fn default() -> Self {
47 Self {
48 background_comp: false,
49 nerd_comp: false,
50 track_error_comp: false,
51 tap_comp: false,
52 palm_error_comp: false,
53 calibration_matrix: true,
54 force_precalibration_noise_check: true,
55 }
56 }
57}
58
59pub struct Status {
60 pub command_complete: bool,
64
65 pub data_ready: bool,
69}
70
71impl<S: SpiDevice<u8>, M: Mode> Touchpad<S, M> {
72 pub(crate) const fn new(spi: S) -> Self {
73 Self {
74 spi,
75 phantom_: PhantomData,
76 }
77 }
78
79 pub fn product_id(&mut self) -> Result<u8, S::Error> {
80 self.read(PRODUCT_ID_ADDR)
81 }
82
83 pub fn firmware_id(&mut self) -> Result<u8, S::Error> {
84 self.read(FIRMWARE_ID_ADDR)
85 }
86
87 pub fn firmware_version(&mut self) -> Result<u8, S::Error> {
88 self.read(FIRMWARE_VERSION_ADDR)
89 }
90
91 pub fn status(&mut self) -> Result<Status, S::Error> {
96 let status = self.read(STATUS1_ADDR)?;
97 Ok(Status {
98 command_complete: status & 0b1000 != 0,
99 data_ready: status & 0b0100 != 0,
100 })
101 }
102
103 pub fn calibrate(&mut self, c: &Calibration) -> Result<(), S::Error> {
113 let mut data = 1;
114 if c.background_comp {
115 data |= 0x02;
116 }
117 if c.nerd_comp {
118 data |= 0x04;
119 }
120 if c.track_error_comp {
121 data |= 0x08;
122 }
123 if c.tap_comp {
124 data |= 0x10;
125 }
126 if c.palm_error_comp {
127 data |= 0x20;
128 }
129 if !c.calibration_matrix {
130 data |= 0x40;
131 }
132 if c.force_precalibration_noise_check {
133 data |= 0x80;
134 }
135 self.disable_feed()?;
136 self.write(CAL_CONFIG1_ADDR, data)
137 }
138
139 pub fn calibrated(&mut self) -> Result<bool, S::Error> {
141 let config = self.read(CAL_CONFIG1_ADDR)?;
142 Ok((config & 1) != 0)
143 }
144
145 pub fn clear_flags(&mut self) -> Result<(), S::Error> {
147 self.write_with_delay(STATUS1_ADDR, 0x00)
148 }
149
150 pub fn sample_rate(&mut self) -> Result<u8, S::Error> {
152 self.read(SAMPLE_RATE_ADDR)
153 }
154
155 pub fn set_sample_rate(&mut self, sample_rate: u8) -> Result<(), S::Error> {
157 self.write(SAMPLE_RATE_ADDR, sample_rate)
158 }
159
160 pub fn z_idle(&mut self) -> Result<u8, S::Error> {
173 self.read(Z_IDLE_ADDR)
174 }
175
176 pub fn set_z_idle(&mut self, z_idle: u8) -> Result<(), S::Error> {
178 self.write(Z_IDLE_ADDR, z_idle)
179 }
180
181 pub fn z_scaler(&mut self) -> Result<u8, S::Error> {
183 self.read(Z_SCALER_ADDR)
184 }
185
186 pub fn set_z_scaler(&mut self, z_scaler: u8) -> Result<(), S::Error> {
188 self.write(Z_SCALER_ADDR, z_scaler)
189 }
190
191 pub fn sleep_timer(&mut self) -> Result<u8, S::Error> {
192 self.read(SLEEP_TIMER_ADDR)
193 }
194
195 pub fn set_sleep_timer(&mut self, sleep_timer: u8) -> Result<(), S::Error> {
196 self.write(SLEEP_TIMER_ADDR, sleep_timer)
197 }
198
199 pub fn sleep_interval(&mut self) -> Result<u8, S::Error> {
200 self.read(SLEEP_INTERVAL_ADDR)
201 }
202
203 pub fn set_sleep_interval(&mut self, sleep_interval: u8) -> Result<(), S::Error> {
204 self.write(SLEEP_INTERVAL_ADDR, sleep_interval)
205 }
206
207 pub fn disable_feed(&mut self) -> Result<(), S::Error> {
208 let config = self.read(FEED_CONFIG1_ADDR)?;
209 let config = config & !0x01;
210 self.write(FEED_CONFIG1_ADDR, config)
211 }
212
213 pub fn enable_feed(&mut self) -> Result<(), S::Error> {
214 let config = self.read(FEED_CONFIG1_ADDR)?;
215 let config = config | 0x01;
216 self.write(FEED_CONFIG1_ADDR, config)
217 }
218
219 pub fn power_mode(&mut self) -> Result<PowerMode, S::Error> {
221 let mode = self.read(SYS_CONFIG1_ADDR)?;
222 if mode & 0b10 != 0 {
223 return Ok(PowerMode::Shutdown);
224 }
225 if mode & 0b100 != 0 {
226 return Ok(PowerMode::Sleep);
227 }
228 Ok(PowerMode::Active)
229 }
230
231 pub fn set_power_mode(&mut self, mode: PowerMode) -> Result<(), S::Error> {
233 let mode = match mode {
234 PowerMode::Sleep => 0b100,
235 PowerMode::Shutdown => 0b10,
236 PowerMode::Active => 0b0,
237 };
238 self.write(SYS_CONFIG1_ADDR, mode)
239 }
240
241 fn read(&mut self, addr: u8) -> Result<u8, S::Error> {
242 let addr = READ_BITS | (addr & ADDR_MASK);
243 let mut buf = [addr, READ_FILL, READ_FILL, READ_FILL];
244 self.spi.transfer_in_place(&mut buf)?;
245 Ok(buf[3])
246 }
247
248 fn read_multi<const N: usize>(&mut self, addr: u8) -> Result<[u8; N], S::Error> {
249 let addr = READ_BITS | (addr & ADDR_MASK);
250 let mut addr_buf = [addr, READ_CONTINUE, READ_CONTINUE];
251 let mut buf = [READ_CONTINUE; N];
252 buf[N - 1] = READ_FILL;
253 self.spi.transaction(&mut [
254 Operation::TransferInPlace(&mut addr_buf),
255 Operation::TransferInPlace(&mut buf),
256 ])?;
257 Ok(buf)
258 }
259
260 pub(crate) fn write(&mut self, addr: u8, data: u8) -> Result<(), S::Error> {
261 let addr = WRITE_BITS | (addr & ADDR_MASK);
262 let buf = [addr, data];
263 self.spi.write(&buf)
264 }
265
266 fn write_with_delay(&mut self, addr: u8, data: u8) -> Result<(), S::Error> {
267 const US: u32 = 1000; let addr = WRITE_BITS | (addr & ADDR_MASK);
269 let buf = [addr, data];
270 self.spi.transaction(&mut [
271 Operation::Write(&buf),
272 Operation::DelayNs(50 * US),
274 ])
275 }
276}
277
278impl<S: SpiDevice<u8>> Touchpad<S, Absolute> {
279 pub fn read_absolute(&mut self) -> Result<AbsoluteData, S::Error> {
280 let btn = self.read(0x12)?;
287 let xlow = self.read(0x14)?;
288 let ylow = self.read(0x15)?;
289 let high = self.read(0x16)?;
290 let z = self.read(0x17)?;
291
292 let data = AbsoluteData {
293 x: u16::from(xlow) | (u16::from(high & 0b_1111) << 8),
294 y: u16::from(ylow) | (u16::from(high & 0b_0111_0000) << 4),
295 z: z & 0b_0011_1111,
296 button_flags: btn & 0b_0011_1111,
297 };
298 self.clear_flags()?;
299 Ok(data)
300 }
301}
302
303impl<S: SpiDevice<u8>> Touchpad<S, Relative> {
304 pub fn read_relative(&mut self) -> Result<RelativeData, S::Error> {
305 let data = self.read_multi::<4>(PACKET_BYTE_0_ADDR)?;
306 let mut x = i16::from(data[1]);
307 let mut y = i16::from(data[2]);
308 if (data[0] & 0x10) > 0 {
309 x -= 256;
310 }
311 if (data[0] & 0x20) > 0 {
312 y -= 256;
313 }
314 let data = RelativeData {
315 x,
316 y,
317 buttons: Buttons {
318 primary: data[0] & 0b001 != 0,
319 secondary: data[0] & 0b010 != 0,
320 auxiliary: data[0] & 0b100 != 0,
321 },
322 #[expect(clippy::cast_possible_wrap)]
323 wheel: data[3] as i8,
324 };
325 self.clear_flags()?;
326 Ok(data)
327 }
328}