RKTK API Docs RKTK Home Repo

rktk_drivers_common/mouse/pmw3360/
mod.rs

1//! PMW3360 optical sensor driver.
2
3#![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, SpiDevice};
12use error::Pmw3360Error;
13use registers as reg;
14use rktk::drivers::interface::mouse::MouseDriver;
15
16mod timing {
17    /// NCS To SCLK Active
18    pub const NCS_SCLK: u32 = 120;
19}
20
21#[derive(Default)]
22pub struct BurstData {
23    pub motion: bool,
24    pub on_surface: bool,
25    pub dx: i16,
26    pub dy: i16,
27    pub surface_quality: u8,
28    pub raw_data_sum: u8,
29    pub max_raw_data: u8,
30    pub min_raw_data: u8,
31    pub shutter: u16,
32}
33
34pub struct Pmw3360<S: SpiDevice> {
35    spi: S,
36    in_burst_mode: bool,
37}
38
39impl<S: SpiDevice> Pmw3360<S> {
40    pub fn new(spi: S) -> Self {
41        Self {
42            spi,
43            in_burst_mode: false,
44        }
45    }
46}
47
48impl<S: SpiDevice> MouseDriver for Pmw3360<S> {
49    type Error = Pmw3360Error<S::Error>;
50
51    async fn init(&mut self) -> Result<(), Self::Error> {
52        self.power_up().await
53    }
54
55    async fn read(&mut self) -> Result<(i8, i8), Self::Error> {
56        self.burst_read()
57            .await
58            .map(|data| (data.dx as i8, data.dy as i8))
59    }
60
61    async fn set_cpi(&mut self, cpi: u16) -> Result<(), Self::Error> {
62        self.set_cpi(cpi).await?;
63        Ok(())
64    }
65
66    async fn get_cpi(&mut self) -> Result<u16, Self::Error> {
67        Err(Self::Error::NotSupported)
68    }
69}
70
71impl<S: SpiDevice> Pmw3360<S> {
72    async fn write(&mut self, address: u8, data: u8) -> Result<(), Pmw3360Error<S::Error>> {
73        self.in_burst_mode = false;
74        self.spi
75            .transaction(&mut [
76                Operation::DelayNs(timing::NCS_SCLK),
77                // send adress of the register, with MSBit = 1 to indicate it's a write and send data
78                Operation::TransferInPlace(&mut [address | 0x80, data]),
79                // tSCLK-NCS (write)
80                Operation::DelayNs(35 * 1000),
81            ])
82            .await
83            .map_err(Pmw3360Error::Spi)?;
84
85        // tSWW/tSWR minus tSCLK-NCS (write)
86        Timer::after_micros(145).await;
87
88        Ok(())
89    }
90
91    async fn read(&mut self, address: u8) -> Result<u8, Pmw3360Error<S::Error>> {
92        self.in_burst_mode = false;
93        let mut buf = [0x00];
94        self.spi
95            .transaction(&mut [
96                Operation::DelayNs(timing::NCS_SCLK),
97                // send adress of the register, with MSBit = 0 to indicate it's a read
98                Operation::Write(&[address & 0x7f]),
99                // tSRAD
100                Operation::DelayNs(160 * 1000),
101                // read the data
102                Operation::Read(&mut buf),
103                // tSCLK-NCS (read)
104                Operation::DelayNs(120),
105            ])
106            .await
107            .map_err(Pmw3360Error::Spi)?;
108
109        //  tSRW/tSRR
110        Timer::after_micros(20).await;
111
112        Ok(buf[0])
113    }
114
115    pub async fn burst_read(&mut self) -> Result<BurstData, Pmw3360Error<S::Error>> {
116        if !self.in_burst_mode {
117            self.write(reg::MOTION_BURST, 0x00).await?;
118            self.in_burst_mode = true;
119        }
120
121        let mut data = [0u8; 12];
122
123        self.spi
124            .transaction(&mut [
125                Operation::DelayNs(timing::NCS_SCLK),
126                Operation::Write(&[reg::MOTION_BURST]),
127                // tSRAD-MOTBR
128                Operation::DelayNs(35 * 1000),
129                Operation::Read(&mut data),
130            ])
131            .await
132            .map_err(Pmw3360Error::Spi)?;
133
134        // tBEXIT
135        Timer::after_micros(1).await;
136
137        //combine the register values
138        let data = BurstData {
139            motion: (data[0] & 0x80) != 0,
140            on_surface: (data[0] & 0x08) == 0,
141            dx: ((data[3] as i16) << 8) | (data[2] as i16),
142            dy: ((data[5] as i16) << 8) | (data[4] as i16),
143            surface_quality: data[6],
144            raw_data_sum: data[7],
145            max_raw_data: data[8],
146            min_raw_data: data[9],
147            shutter: ((data[11] as u16) << 8) | (data[10] as u16),
148        };
149
150        Ok(data)
151    }
152
153    pub async fn set_cpi(&mut self, cpi: u16) -> Result<(), Pmw3360Error<S::Error>> {
154        let val: u16;
155        if cpi < 100 {
156            val = 0
157        } else if cpi > 12000 {
158            val = 0x77
159        } else {
160            val = (cpi - 100) / 100;
161        }
162        self.write(reg::CONFIG_1, val as u8).await?;
163        Ok(())
164    }
165
166    pub async fn get_cpi(&mut self) -> Result<u16, S::Error> {
167        let val = self.read(reg::CONFIG_1).await.unwrap_or_default() as u16;
168        Ok((val + 1) * 100)
169    }
170
171    pub async fn check_signature(&mut self) -> Result<bool, Pmw3360Error<S::Error>> {
172        let srom = self.read(reg::SROM_ID).await.unwrap_or(0);
173        let pid = self.read(reg::PRODUCT_ID).await.unwrap_or(0);
174        let ipid = self.read(reg::INVERSE_PRODUCT_ID).await.unwrap_or(0);
175
176        // signature for SROM 0x04
177        Ok(srom == 0x00 && pid == 0x42 && ipid == 0xBD)
178    }
179
180    #[allow(dead_code)]
181    pub async fn self_test(&mut self) -> Result<bool, Pmw3360Error<S::Error>> {
182        self.write(reg::SROM_ENABLE, 0x15).await?;
183        Timer::after_micros(10000).await;
184
185        let u = self.read(reg::DATA_OUT_UPPER).await.unwrap_or(0); // should be 0xBE
186        let l = self.read(reg::DATA_OUT_LOWER).await.unwrap_or(0); // should be 0xEF
187
188        Ok(u == 0xBE && l == 0xEF)
189    }
190
191    async fn power_up(&mut self) -> Result<(), Pmw3360Error<S::Error>> {
192        let is_valid_signature = self.power_up_inner().await?;
193        if is_valid_signature {
194            Ok(())
195        } else {
196            Err(Pmw3360Error::InvalidSignature)
197        }
198    }
199
200    async fn power_up_inner(&mut self) -> Result<bool, Pmw3360Error<S::Error>> {
201        // reset spi port
202        self.spi
203            .transaction(&mut [])
204            .await
205            .map_err(Pmw3360Error::Spi)?;
206
207        // Write to reset register
208        self.write(reg::POWER_UP_RESET, 0x5A).await?;
209
210        // Wait at least 50ms
211        Timer::after_millis(100).await;
212
213        // read registers 0x02 to 0x06
214        self.read(reg::MOTION).await?;
215        self.read(reg::DELTA_X_L).await?;
216        self.read(reg::DELTA_X_H).await?;
217        self.read(reg::DELTA_Y_L).await?;
218        self.read(reg::DELTA_Y_H).await?;
219
220        // perform SROM download
221        // self.srom_download().await?;
222
223        let is_valid_signature = self.check_signature().await.unwrap_or(false);
224
225        // Write 0x00 (rest disable) to Config2 register for wired mouse or 0x20 for
226        // wireless mouse design.
227        self.write(reg::CONFIG_2, 0x00).await?;
228
229        Timer::after_micros(100).await;
230
231        Ok(is_valid_signature)
232    }
233
234    // TODO: To implement srom download, access to cs pin is needed.
235    //
236    // async fn srom_download(&mut self) -> Result<(), Pmw3360Error<S::Error>> {
237    //     // Write 0 to Rest_En bit of Config2 register to disable Rest mode.
238    //     self.write(reg::CONFIG_2, 0x00).await?;
239    //
240    //     // write 0x1d in SROM_enable reg for initializing
241    //     self.write(reg::SROM_ENABLE, 0x1d).await?;
242    //
243    //     // wait for 10 ms
244    //     Timer::after_micros(10000).await;
245    //
246    //     // Write 0x18 to SROM_Enable register again to start SROM Download
247    //     self.write(reg::SROM_ENABLE, 0x18).await?;
248    //
249    //     self.spi
250    //         .transaction(&mut srom_tracking::FW_OPS)
251    //         .await
252    //         .map_err(Pmw3360Error::Spi)?;
253    //
254    //     Timer::after_micros(185).await;
255    //
256    //     Ok(())
257    // }
258}