RKTK API Docs RKTK Home Repo

rktk_drivers_common/mouse/paw3395/
mod.rs

1//! PAW3395 optical sensor driver.
2
3#![allow(dead_code)]
4
5pub mod config;
6mod error;
7mod power_up;
8mod registers;
9
10use embassy_time::Timer;
11use embedded_hal::spi::Operation;
12use embedded_hal_async::spi::SpiDevice;
13use error::Paw3395Error;
14use registers as reg;
15use rktk::drivers::interface::mouse::MouseDriver;
16
17mod timing {
18    pub const NCS_SCLK: u32 = 120;
19    pub const SCLK_NCS_READ: u32 = 120;
20    pub const SCLK_NCS_WRITE: u32 = 1000;
21    pub const SRAD: u32 = 2 * 1000;
22    pub const SWW_R: u32 = 5 * 1000;
23    pub const SRW_R: u32 = 2 * 1000;
24    pub const BEXIT: u32 = 500;
25}
26
27#[derive(Default, Debug)]
28pub struct BurstData {
29    pub op_mode: u8,
30    pub lift_stat: bool,
31    pub mot: bool,
32    pub observation: u8,
33    pub dx: i16,
34    pub dy: i16,
35    pub surface_quality: u8,
36    pub raw_data_sum: u8,
37    pub max_raw_data: u8,
38    pub min_raw_data: u8,
39    pub shutter: u16,
40}
41
42pub struct Paw3395<S: SpiDevice> {
43    spi: S,
44    config: config::Config,
45}
46
47impl<S: SpiDevice> Paw3395<S> {
48    pub fn new(spi: S, config: config::Config) -> Self {
49        Self { spi, config }
50    }
51}
52
53impl<S: SpiDevice> MouseDriver for Paw3395<S> {
54    type Error = Paw3395Error<S::Error>;
55
56    async fn init(&mut self) -> Result<(), Self::Error> {
57        self.power_up().await
58    }
59
60    async fn read(&mut self) -> Result<(i8, i8), Self::Error> {
61        self.burst_read()
62            .await
63            .map(|data| (data.dx as i8, data.dy as i8))
64    }
65
66    async fn set_cpi(&mut self, cpi: u16) -> Result<(), Self::Error> {
67        self.set_cpi(cpi).await?;
68        Ok(())
69    }
70
71    async fn get_cpi(&mut self) -> Result<u16, Self::Error> {
72        Err(Paw3395Error::NotSupported)
73    }
74}
75
76impl<S: SpiDevice> Paw3395<S> {
77    async fn write(&mut self, address: u8, data: u8) -> Result<(), Paw3395Error<S::Error>> {
78        self.spi
79            .transaction(&mut [
80                Operation::DelayNs(timing::NCS_SCLK),
81                Operation::Write(&[address | 0x80, data]),
82                Operation::DelayNs(timing::SCLK_NCS_WRITE),
83            ])
84            .await
85            .map_err(Paw3395Error::Spi)?;
86
87        Timer::after_nanos((timing::SWW_R - timing::SCLK_NCS_WRITE) as u64).await;
88
89        Ok(())
90    }
91
92    async fn read(&mut self, address: u8) -> Result<u8, Paw3395Error<S::Error>> {
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                Operation::DelayNs(timing::SRAD),
100                Operation::Read(&mut buf),
101                Operation::DelayNs(timing::SCLK_NCS_READ),
102            ])
103            .await
104            .map_err(Paw3395Error::Spi)?;
105
106        //  tSRW/tSRR minus tSCLK-NCS
107        Timer::after_nanos((timing::SRW_R - timing::SCLK_NCS_WRITE) as u64).await;
108
109        Ok(buf[0])
110    }
111
112    pub async fn burst_read(&mut self) -> Result<BurstData, Paw3395Error<S::Error>> {
113        let mut buf = [0u8; 12];
114        self.spi
115            .transaction(&mut [
116                Operation::DelayNs(timing::NCS_SCLK),
117                Operation::Write(&[reg::MOTION_BURST]),
118                Operation::DelayNs(timing::SRAD),
119                Operation::Read(&mut buf),
120            ])
121            .await
122            .map_err(Paw3395Error::Spi)?;
123
124        Timer::after_nanos(timing::BEXIT as u64).await;
125
126        //combine the register values
127        let data = BurstData {
128            op_mode: buf[0] & 0b11,
129            lift_stat: (buf[0] >> 3) & 1 == 1,
130            mot: (buf[0] >> 7) & 1 == 1,
131            observation: buf[1],
132            dx: ((buf[3] as i16) << 8) | (buf[2] as i16),
133            dy: ((buf[5] as i16) << 8) | (buf[4] as i16),
134            surface_quality: buf[6],
135            raw_data_sum: buf[7],
136            max_raw_data: buf[8],
137            min_raw_data: buf[9],
138            shutter: ((buf[11] as u16) << 8) | (buf[10] as u16),
139        };
140
141        Ok(data)
142    }
143
144    pub async fn set_cpi(&mut self, cpi: u16) -> Result<(), Paw3395Error<S::Error>> {
145        let resolution = (cpi / 50) - 1;
146        let resolution_low = resolution as u8;
147        let resolution_high = (resolution >> 8) as u8;
148
149        self.write(reg::RESOLUTION_X_LOW, resolution_low).await?;
150        self.write(reg::RESOLUTION_X_HIGH, resolution_high).await?;
151        self.write(reg::RESOLUTION_Y_LOW, resolution_low).await?;
152        self.write(reg::RESOLUTION_Y_HIGH, resolution_high).await?;
153        self.write(reg::SET_RESOLUTION, 0x01).await?;
154
155        Ok(())
156    }
157
158    pub async fn get_cpi(&mut self) -> Result<u16, S::Error> {
159        let resolution_x_low = self.read(reg::RESOLUTION_X_LOW).await.unwrap_or_default();
160        let resolution_x_high = self.read(reg::RESOLUTION_X_HIGH).await.unwrap_or_default();
161        let resolution_x = ((resolution_x_high as u16) << 8) | resolution_x_low as u16;
162        Ok((resolution_x + 1) * 50)
163    }
164
165    pub async fn check_signature(&mut self) -> Result<bool, Paw3395Error<S::Error>> {
166        let pid = self.read(reg::PRODUCT_ID).await.unwrap_or(0);
167        let ipid = self.read(reg::INV_PRODUCT_ID).await.unwrap_or(0);
168
169        Ok(pid == 0x51 && ipid == 0xAE)
170    }
171
172    async fn shutdown(&mut self) -> Result<(), Paw3395Error<S::Error>> {
173        self.write(reg::SHUTDOWN, 0xB6).await?;
174        Timer::after_millis(5).await;
175        Ok(())
176    }
177
178    async fn power_up(&mut self) -> Result<(), Paw3395Error<S::Error>> {
179        Timer::after_micros(50).await;
180
181        self.write(reg::POWER_UP_RESET, 0x5A).await?;
182        Timer::after_millis(5).await;
183
184        for (addr, data) in power_up::POWER_UP_SEQS_1.iter() {
185            self.write(*addr, *data).await?;
186        }
187
188        'outer: {
189            for _ in 0..60 {
190                Timer::after_millis(1).await;
191                if self.read(0x6C).await? == 0x80 {
192                    break 'outer;
193                };
194            }
195
196            for (addr, data) in power_up::POWER_UP_SEQS_2.iter() {
197                self.write(*addr, *data).await?;
198            }
199        }
200
201        for (addr, data) in power_up::POWER_UP_SEQS_3.iter() {
202            self.write(*addr, *data).await?;
203        }
204
205        self.read(reg::MOTION).await?;
206        self.read(reg::DELTA_X_L).await?;
207        self.read(reg::DELTA_X_H).await?;
208        self.read(reg::DELTA_Y_L).await?;
209        self.read(reg::DELTA_Y_H).await?;
210
211        if !self.check_signature().await.unwrap_or(false) {
212            return Err(Paw3395Error::InvalidSignature);
213        }
214
215        Timer::after_micros(100).await;
216
217        // set mode
218        for (addr, data) in self.config.mode.commands.iter() {
219            self.write(*addr, *data).await?;
220        }
221        if let Some(c) = self.config.mode._0x40 {
222            let mut _0x40 = self.read(0x40).await?;
223            _0x40 |= c;
224            self.write(0x40, _0x40).await?;
225        }
226
227        // set lift cutoff config
228        self.write(0x7F, 0x0C).await?;
229        let lift_config = self.read(0x4E).await?;
230        self.write(0x7F, 0x00).await?;
231        let lift_config = lift_config | self.config.lift_cutoff as u8;
232        self.write(0x7F, 0x0C).await?;
233        self.write(0x4E, lift_config).await?;
234        self.write(0x7F, 0x00).await?;
235
236        Ok(())
237    }
238}