Skip to main content
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().await.map(|data| (data.dx as i8, data.dy as i8))
62    }
63
64    async fn set_cpi(&mut self, cpi: u16) -> Result<(), Self::Error> {
65        self.set_cpi(cpi).await?;
66        Ok(())
67    }
68
69    async fn get_cpi(&mut self) -> Result<u16, Self::Error> {
70        Err(Paw3395Error::NotSupported)
71    }
72}
73
74impl<S: SpiDevice> Paw3395<S> {
75    async fn write(&mut self, address: u8, data: u8) -> Result<(), Paw3395Error<S::Error>> {
76        self.spi
77            .transaction(&mut [
78                Operation::DelayNs(timing::NCS_SCLK),
79                Operation::Write(&[address | 0x80, data]),
80                Operation::DelayNs(timing::SCLK_NCS_WRITE),
81            ])
82            .await
83            .map_err(Paw3395Error::Spi)?;
84
85        Timer::after_nanos((timing::SWW_R - timing::SCLK_NCS_WRITE) as u64).await;
86
87        Ok(())
88    }
89
90    async fn read(&mut self, address: u8) -> Result<u8, Paw3395Error<S::Error>> {
91        let mut buf = [0x00];
92        self.spi
93            .transaction(&mut [
94                Operation::DelayNs(timing::NCS_SCLK),
95                // send adress of the register, with MSBit = 0 to indicate it's a read
96                Operation::Write(&[address & 0x7f]),
97                Operation::DelayNs(timing::SRAD),
98                Operation::Read(&mut buf),
99                Operation::DelayNs(timing::SCLK_NCS_READ),
100            ])
101            .await
102            .map_err(Paw3395Error::Spi)?;
103
104        //  tSRW/tSRR minus tSCLK-NCS
105        Timer::after_nanos((timing::SRW_R - timing::SCLK_NCS_WRITE) as u64).await;
106
107        Ok(buf[0])
108    }
109
110    pub async fn burst_read(&mut self) -> Result<BurstData, Paw3395Error<S::Error>> {
111        let mut buf = [0u8; 12];
112        self.spi
113            .transaction(&mut [
114                Operation::DelayNs(timing::NCS_SCLK),
115                Operation::Write(&[reg::MOTION_BURST]),
116                Operation::DelayNs(timing::SRAD),
117                Operation::Read(&mut buf),
118            ])
119            .await
120            .map_err(Paw3395Error::Spi)?;
121
122        Timer::after_nanos(timing::BEXIT as u64).await;
123
124        //combine the register values
125        let data = BurstData {
126            op_mode: buf[0] & 0b11,
127            lift_stat: (buf[0] >> 3) & 1 == 1,
128            mot: (buf[0] >> 7) & 1 == 1,
129            observation: buf[1],
130            dx: ((buf[3] as i16) << 8) | (buf[2] as i16),
131            dy: ((buf[5] as i16) << 8) | (buf[4] as i16),
132            surface_quality: buf[6],
133            raw_data_sum: buf[7],
134            max_raw_data: buf[8],
135            min_raw_data: buf[9],
136            shutter: ((buf[11] as u16) << 8) | (buf[10] as u16),
137        };
138
139        Ok(data)
140    }
141
142    pub async fn set_cpi(&mut self, cpi: u16) -> Result<(), Paw3395Error<S::Error>> {
143        let resolution = (cpi / 50) - 1;
144        let resolution_low = resolution as u8;
145        let resolution_high = (resolution >> 8) as u8;
146
147        self.write(reg::RESOLUTION_X_LOW, resolution_low).await?;
148        self.write(reg::RESOLUTION_X_HIGH, resolution_high).await?;
149        self.write(reg::RESOLUTION_Y_LOW, resolution_low).await?;
150        self.write(reg::RESOLUTION_Y_HIGH, resolution_high).await?;
151        self.write(reg::SET_RESOLUTION, 0x01).await?;
152
153        Ok(())
154    }
155
156    pub async fn get_cpi(&mut self) -> Result<u16, S::Error> {
157        let resolution_x_low = self.read(reg::RESOLUTION_X_LOW).await.unwrap_or_default();
158        let resolution_x_high = self.read(reg::RESOLUTION_X_HIGH).await.unwrap_or_default();
159        let resolution_x = ((resolution_x_high as u16) << 8) | resolution_x_low as u16;
160        Ok((resolution_x + 1) * 50)
161    }
162
163    pub async fn check_signature(&mut self) -> Result<bool, Paw3395Error<S::Error>> {
164        let pid = self.read(reg::PRODUCT_ID).await.unwrap_or(0);
165        let ipid = self.read(reg::INV_PRODUCT_ID).await.unwrap_or(0);
166
167        Ok(pid == 0x51 && ipid == 0xAE)
168    }
169
170    async fn shutdown(&mut self) -> Result<(), Paw3395Error<S::Error>> {
171        self.write(reg::SHUTDOWN, 0xB6).await?;
172        Timer::after_millis(5).await;
173        Ok(())
174    }
175
176    async fn power_up(&mut self) -> Result<(), Paw3395Error<S::Error>> {
177        Timer::after_millis(50).await;
178
179        self.write(reg::POWER_UP_RESET, 0x5A).await?;
180        Timer::after_millis(5).await;
181
182        for (addr, data) in power_up::POWER_UP_SEQS_1.iter() {
183            self.write(*addr, *data).await?;
184        }
185
186        'outer: {
187            for _ in 0..60 {
188                Timer::after_millis(1).await;
189                if self.read(0x6C).await? == 0x80 {
190                    break 'outer;
191                };
192            }
193
194            for (addr, data) in power_up::POWER_UP_SEQS_2.iter() {
195                self.write(*addr, *data).await?;
196            }
197        }
198
199        for (addr, data) in power_up::POWER_UP_SEQS_3.iter() {
200            self.write(*addr, *data).await?;
201        }
202
203        self.read(reg::MOTION).await?;
204        self.read(reg::DELTA_X_L).await?;
205        self.read(reg::DELTA_X_H).await?;
206        self.read(reg::DELTA_Y_L).await?;
207        self.read(reg::DELTA_Y_H).await?;
208
209        if !self.check_signature().await.unwrap_or(false) {
210            return Err(Paw3395Error::InvalidSignature);
211        }
212
213        Timer::after_micros(100).await;
214
215        // set mode
216        for (addr, data) in self.config.mode.commands.iter() {
217            self.write(*addr, *data).await?;
218        }
219        if let Some(c) = self.config.mode._0x40 {
220            let mut _0x40 = self.read(0x40).await?;
221            _0x40 |= c;
222            self.write(0x40, _0x40).await?;
223        }
224
225        // set lift cutoff config
226        self.write(0x7F, 0x0C).await?;
227        let lift_config = self.read(0x4E).await?;
228        self.write(0x7F, 0x00).await?;
229        let lift_config = lift_config | self.config.lift_cutoff as u8;
230        self.write(0x7F, 0x0C).await?;
231        self.write(0x4E, lift_config).await?;
232        self.write(0x7F, 0x00).await?;
233
234        Ok(())
235    }
236}