rktk_drivers_common/mouse/pmw3360/
mod.rs1#![allow(dead_code)]
4
5mod error;
6mod registers;
7mod srom_liftoff;
8mod srom_tracking;
9
10use embassy_time::Timer;
11use embedded_hal_async::spi::Operation;
12
13use error::Pmw3360Error;
14use registers as reg;
15use rktk::drivers::interface::mouse::MouseDriver;
16
17use crate::spi::{ExtendedSpi, IterOperation};
18
19mod timing {
20 pub const NCS_SCLK: u32 = 120;
22}
23
24#[derive(Default, Debug)]
25#[cfg_attr(feature = "defmt", derive(defmt::Format))]
26pub struct BurstData {
27 pub motion: bool,
28 pub on_surface: bool,
29 pub op_mode: u8,
30 pub frame_data_first: bool,
31 pub dx: i16,
32 pub dy: i16,
33 pub surface_quality: u8,
34 pub raw_data_sum: u8,
35 pub max_raw_data: u8,
36 pub min_raw_data: u8,
37 pub shutter: u16,
38}
39
40#[derive(Debug, Default)]
41#[cfg_attr(feature = "defmt", derive(defmt::Format))]
42pub enum Pmw3360Srom {
43 #[default]
44 None,
45 Liftoff,
46 Tracking,
47}
48
49impl Pmw3360Srom {
50 fn id(&self) -> u8 {
51 match self {
52 Pmw3360Srom::None => 0x00,
53 Pmw3360Srom::Liftoff => 0x81,
54 Pmw3360Srom::Tracking => 0x04,
55 }
56 }
57}
58
59#[derive(Debug)]
60#[cfg_attr(feature = "defmt", derive(defmt::Format))]
61pub struct Pmw3360Config {
62 pub srom: Pmw3360Srom,
63 pub cpi: u16,
64 pub auto_reset: bool,
65}
66
67impl Default for Pmw3360Config {
68 fn default() -> Self {
69 Self {
70 srom: Pmw3360Srom::default(),
71 cpi: 1000,
72 auto_reset: true,
73 }
74 }
75}
76
77pub struct Pmw3360<S: ExtendedSpi> {
87 spi_device: S,
88 in_burst_mode: bool,
89 config: Pmw3360Config,
90}
91
92impl<S: ExtendedSpi> Pmw3360<S> {
93 pub fn new(spi_device: S, config: Pmw3360Config) -> Self {
94 Self {
95 spi_device,
96 in_burst_mode: false,
97 config,
98 }
99 }
100}
101
102impl<S: ExtendedSpi> MouseDriver for Pmw3360<S> {
103 type Error = Pmw3360Error<S::Error>;
104
105 async fn init(&mut self) -> Result<(), Self::Error> {
106 self.power_up().await
107 }
108
109 async fn read(&mut self) -> Result<(i8, i8), Self::Error> {
110 self.burst_read()
111 .await
112 .map(|data| (data.dx as i8, data.dy as i8))
113 }
114
115 async fn set_cpi(&mut self, cpi: u16) -> Result<(), Self::Error> {
116 self.set_cpi(cpi).await?;
117 Ok(())
118 }
119
120 async fn get_cpi(&mut self) -> Result<u16, Self::Error> {
121 Err(Self::Error::NotSupported)
122 }
123}
124
125impl<S: ExtendedSpi> Pmw3360<S> {
126 async fn write(&mut self, address: u8, data: u8) -> Result<(), <Self as MouseDriver>::Error> {
127 self.in_burst_mode = false;
128 self.spi_device
129 .transaction(&mut [
130 Operation::DelayNs(timing::NCS_SCLK),
131 Operation::TransferInPlace(&mut [address | 0x80, data]),
133 Operation::DelayNs(35 * 1000),
135 ])
136 .await
137 .map_err(Pmw3360Error::Spi)?;
138
139 Timer::after_micros(145).await;
141
142 Ok(())
143 }
144
145 async fn read(&mut self, address: u8) -> Result<u8, <Self as MouseDriver>::Error> {
146 self.in_burst_mode = false;
147 let mut buf = [0x00];
148 self.spi_device
149 .transaction(&mut [
150 Operation::DelayNs(timing::NCS_SCLK),
151 Operation::Write(&[address & 0x7f]),
153 Operation::DelayNs(160 * 1000),
155 Operation::Read(&mut buf),
157 Operation::DelayNs(120),
159 ])
160 .await
161 .map_err(Pmw3360Error::Spi)?;
162
163 Timer::after_micros(20).await;
165
166 Ok(buf[0])
167 }
168
169 pub async fn burst_read(&mut self) -> Result<BurstData, <Self as MouseDriver>::Error> {
170 if !self.in_burst_mode {
171 self.write(reg::MOTION_BURST, 0x00).await?;
172 self.in_burst_mode = true;
173 }
174
175 let mut data = [0u8; 12];
176
177 self.spi_device
178 .transaction(&mut [
179 Operation::DelayNs(timing::NCS_SCLK),
180 Operation::Write(&[reg::MOTION_BURST]),
181 Operation::DelayNs(35 * 1000),
183 Operation::Read(&mut data),
184 ])
185 .await
186 .map_err(Pmw3360Error::Spi)?;
187
188 Timer::after_micros(1).await;
190
191 let data = BurstData {
193 motion: (data[0] & 0x80) != 0,
194 on_surface: (data[0] & 0x08) == 0,
195 op_mode: (data[0] >> 1) & 0x03,
196 frame_data_first: data[0] & 0x01 != 0,
197 dx: ((data[3] as i16) << 8) | (data[2] as i16),
198 dy: ((data[5] as i16) << 8) | (data[4] as i16),
199 surface_quality: data[6],
200 raw_data_sum: data[7],
201 max_raw_data: data[8],
202 min_raw_data: data[9],
203 shutter: ((data[11] as u16) << 8) | (data[10] as u16),
204 };
205
206 if data.motion
210 && data.op_mode == 0x01
211 && data.on_surface
212 && data.dx == 0
213 && data.dy == 0
214 && self.config.auto_reset
215 {
216 rktk_log::warn!("Invalid motion detected. Performing reset:\n{:?}", data);
217 self.power_up().await?;
218 }
219
220 Ok(data)
221 }
222
223 pub async fn set_cpi(&mut self, cpi: u16) -> Result<(), <Self as MouseDriver>::Error> {
224 self.config.cpi = cpi;
225 let val: u16;
226 if cpi < 100 {
227 val = 0
228 } else if cpi > 12000 {
229 val = 0x77
230 } else {
231 val = (cpi - 100) / 100;
232 }
233 self.write(reg::CONFIG_1, val as u8).await?;
234 Ok(())
235 }
236
237 pub async fn get_cpi(&mut self) -> Result<u16, <Self as MouseDriver>::Error> {
238 let val = self.read(reg::CONFIG_1).await.unwrap_or_default() as u16;
239 Ok((val + 1) * 100)
240 }
241
242 pub async fn check_signature(&mut self) -> Result<bool, <Self as MouseDriver>::Error> {
243 let srom = self.read(reg::SROM_ID).await.unwrap_or(0);
244 let pid = self.read(reg::PRODUCT_ID).await.unwrap_or(0);
245 let ipid = self.read(reg::INVERSE_PRODUCT_ID).await.unwrap_or(0);
246
247 Ok(srom == self.config.srom.id() && pid == 0x42 && ipid == 0xBD)
248 }
249
250 #[allow(dead_code)]
251 pub async fn self_test(&mut self) -> Result<bool, <Self as MouseDriver>::Error> {
252 self.write(reg::SROM_ENABLE, 0x15).await?;
253 Timer::after_micros(10000).await;
254
255 let u = self.read(reg::DATA_OUT_UPPER).await.unwrap_or(0); let l = self.read(reg::DATA_OUT_LOWER).await.unwrap_or(0); Ok(u == 0xBE && l == 0xEF)
259 }
260
261 async fn power_up(&mut self) -> Result<(), <Self as MouseDriver>::Error> {
262 let is_valid_signature = self.power_up_inner().await?;
263 if is_valid_signature {
264 self.set_cpi(self.config.cpi).await?;
265 Ok(())
266 } else {
267 Err(Pmw3360Error::InvalidSignature)
268 }
269 }
270
271 async fn power_up_inner(&mut self) -> Result<bool, <Self as MouseDriver>::Error> {
272 self.spi_device
274 .transaction(&mut [])
275 .await
276 .map_err(Pmw3360Error::Spi)?;
277
278 self.write(reg::POWER_UP_RESET, 0x5A).await?;
280
281 Timer::after_millis(100).await;
283
284 self.read(reg::MOTION).await?;
286 self.read(reg::DELTA_X_L).await?;
287 self.read(reg::DELTA_X_H).await?;
288 self.read(reg::DELTA_Y_L).await?;
289 self.read(reg::DELTA_Y_H).await?;
290
291 self.srom_download().await?;
293
294 let is_valid_signature = self.check_signature().await.unwrap_or(false);
295
296 self.write(reg::CONFIG_2, 0x00).await?;
299
300 Timer::after_micros(100).await;
301
302 Ok(is_valid_signature)
303 }
304
305 async fn srom_download(&mut self) -> Result<(), <Self as MouseDriver>::Error> {
306 let fw = match self.config.srom {
307 Pmw3360Srom::None => {
308 rktk_log::info!("SROM download skipped: no SROM selected");
309 return Ok(());
310 }
311 Pmw3360Srom::Liftoff => &srom_liftoff::FW,
312 Pmw3360Srom::Tracking => &srom_tracking::FW,
313 };
314 if !self.spi_device.transaction_iter_supported() {
315 rktk_log::warn!("SROM download skipped: transaction_iter not supported");
316 return Ok(());
317 }
318
319 self.write(reg::CONFIG_2, 0x00).await?;
321
322 self.write(reg::SROM_ENABLE, 0x1d).await?;
324
325 Timer::after_micros(10000).await;
327
328 self.write(reg::SROM_ENABLE, 0x18).await?;
330
331 let operations = [IterOperation::Write(reg::SROM_LOAD_BURST | 0x80)]
332 .into_iter()
333 .chain(fw.iter().flat_map(|byte| {
334 [
335 IterOperation::Write(*byte),
336 IterOperation::DelayNs(15 * 1000),
337 ]
338 }));
339
340 self.spi_device
341 .transaction_iter(operations)
342 .await
343 .map_err(Pmw3360Error::Spi)?;
344
345 Timer::after_micros(185).await;
346
347 let srom_id = self.read(reg::SROM_ID).await?;
348 if srom_id != self.config.srom.id() {
349 rktk_log::error!("SROM Download failed. ID: 0x{:02x}", srom_id);
350 return Err(Pmw3360Error::InvalidSignature);
351 }
352 rktk_log::debug!("SROM Download succeeded. ID: 0x{:02x}", srom_id);
353
354 Ok(())
355 }
356}