55
66#include "driver/pixart/pixart_pmw.h"
77
8+ /*
9+ * Pixar PMW33xx driver
10+ *
11+ * currently supports pmw3360, truemove3 and the pmw3389
12+ *
13+ * the pmw3330 is NOT supported, it does not share many
14+ * of the same registers, does not need SROM upload at
15+ * startup and is lacking some important features like
16+ * motion burst
17+ */
18+
19+ /* General Registers */
20+ #define PIXART_PMW_REG_PID 0x00
21+ #define PIXART_PMW_REG_REV_ID 0x01
22+ #define PIXART_PMW_REG_PWR_UP_RST 0x3A
23+
24+ #define PIXART_PMW_PID_PMW3360 0x42
25+ #define PIXART_PMW_PID_TRUEMOVE3 PIXART_PMW_PID_PMW3360 /* TRUEMOVE 3 Shares the same PID as PMW3360*/
26+ #define PIXART_PMW_PID_PMW3330 0x45
27+ #define PIXART_PMW_PID_PMW3389 0x47
28+
29+ /* Motion Registers */
30+ #define PIXART_PMW_REG_MOTION 0x02
31+ #define PIXART_PMW_REG_DELTA_X_L 0x03
32+ #define PIXART_PMW_REG_DELTA_X_H 0x04
33+ #define PIXART_PMW_REG_DELTA_Y_L 0x05
34+ #define PIXART_PMW_REG_DELTA_Y_H 0x06
35+ #define PIXART_PMW_REG_BURST 0x50
36+
37+ /* Motion bits */
38+ #define PIXART_PMW_MOTION (1 << 8)
39+ #define PIXART_PMW_OPMODE_RUN (0)
40+ #define PIXART_PMW_OPMODE_REST1 (0b01 << 1)
41+ #define PIXART_PMW_OPMODE_REST2 (0b10 << 1)
42+ #define PIXART_PMW_OPMODE_REST3 (0b11 << 1)
43+
44+ /* SROM Registers */
45+ #define PIXART_PMW_REG_SROM_EN 0x13
46+ #define PIXART_PMW_REG_SROM_ID 0x2A
47+ #define PIXART_PMW_REG_SROM_BURST 0x62
48+
49+ /* SROM CMDs */
50+ #define PIXART_PMW_SROM_CRC_CMD 0x15
51+ #define PIXART_PMW_SROM_DWNLD_CMD 0x1D
52+ #define PIXART_PMW_SROM_DWNLD_START_CMD 0x18
53+
54+ /* CPI Registers */
55+ #define PIXART_PMW3360_REG_CPI 0x0F
56+ #define PIXART_PMW3389_REG_CPI_L 0x0E
57+ #define PIXART_PMW3389_REG_CPI_H 0x0F
58+
59+ /* Config Registers */
60+ #define PIXART_PMW_REG_CONFIG2 0x10
61+ #define PIXART_PMW_REG_OBSERVATION 0x24
62+ #define PIXART_PMW_REG_DOUT_L 0x25
63+ #define PIXART_PMW_REG_DOUT_H 0x26
64+
65+ /* Config2 Bits */
66+ #define PIXART_PMW_RESTEN 0x20
67+ #define PIXART_PMW_RPT_MOD 0x04
68+
69+ /* Observation Bits */
70+ #define PIXART_PMW_SROM_RUN 0x40
71+
72+ /* power up reset cmd */
73+ #define PIXART_PMW_RESET_CMD 0x5A
74+
875struct motion_burst_t {
976 u8 motion ;
1077 u8 observation ;
1178 s16 dx ;
1279 s16 dy ;
1380} __attribute__((packed ));
1481
15- u8 pixart_pmw_read (struct pixart_pmw_driver_t driver , uint8_t address )
82+ u8 pixart_pmw_read (struct pixart_pmw_driver_t driver , u8 address )
1683{
1784 driver .spi_hal .select (driver .spi_hal , 1 );
1885
@@ -29,7 +96,7 @@ u8 pixart_pmw_read(struct pixart_pmw_driver_t driver, uint8_t address)
2996 return value ;
3097}
3198
32- void pixart_pmw_write (struct pixart_pmw_driver_t driver , uint8_t address , uint8_t value )
99+ void pixart_pmw_write (struct pixart_pmw_driver_t driver , u8 address , u8 value )
33100{
34101 driver .spi_hal .select (driver .spi_hal , 1 );
35102
@@ -44,6 +111,31 @@ void pixart_pmw_write(struct pixart_pmw_driver_t driver, uint8_t address, uint8_
44111 driver .ticks_hal .delay_us (160 );
45112}
46113
114+ void pixart_pmw_upload_srom (struct pixart_pmw_driver_t driver , u8 * firmware )
115+ {
116+ pixart_pmw_write (driver , PIXART_PMW_REG_SROM_EN , PIXART_PMW_SROM_DWNLD_CMD ); /* Initialize SROM download */
117+
118+ driver .ticks_hal .delay_ms (15 );
119+
120+ pixart_pmw_write (driver , PIXART_PMW_REG_SROM_EN , PIXART_PMW_SROM_DWNLD_START_CMD ); /* Start SROM download */
121+
122+ driver .spi_hal .select (driver .spi_hal , 1 );
123+
124+ driver .spi_hal .transfer (
125+ driver .spi_hal , PIXART_PMW_REG_SROM_BURST | 0x80 ); /* 7 bit srom_burst address + write bit(1) */
126+ driver .ticks_hal .delay_us (15 );
127+
128+ for (size_t b = 0 ; b < 4094 ; b ++ ) /* write firmware image (4094 bytes) */
129+ {
130+ driver .spi_hal .transfer (driver .spi_hal , firmware [b ]);
131+ driver .ticks_hal .delay_us (15 );
132+ }
133+
134+ driver .spi_hal .select (driver .spi_hal , 0 );
135+
136+ driver .ticks_hal .delay_ms (2 ); /* Tbexit */
137+ }
138+
47139struct motion_burst_t pixart_pmw_read_motion_burst (struct pixart_pmw_driver_t driver )
48140{
49141 struct motion_burst_t motion_burst ;
@@ -70,7 +162,7 @@ struct pixart_pmw_driver_t pixart_pmw_init(u8 *firmware, struct spi_hal_t spi_ha
70162 driver .ticks_hal = ticks_hal ;
71163
72164 if (!firmware )
73- return driver ;
165+ goto failed_init ;
74166
75167 spi_hal .select (spi_hal , 0 );
76168 ticks_hal .delay_ms (1 );
@@ -79,67 +171,34 @@ struct pixart_pmw_driver_t pixart_pmw_init(u8 *firmware, struct spi_hal_t spi_ha
79171 pixart_pmw_write (driver , PIXART_PMW_REG_PWR_UP_RST , PIXART_PMW_RESET_CMD );
80172 ticks_hal .delay_ms (50 );
81173
82- /* Check Known ID */
174+ /* Check Known and supported ID */
83175 u8 pid = pixart_pmw_read (driver , PIXART_PMW_REG_PID );
84- if (pid != PIXART_PMW_PID_PMW3360 && pid != PIXART_PMW_PID_PMW3330 && pid != PIXART_PMW_PID_PMW3389 )
85- return driver ;
86-
87- pixart_pmw_write (driver , PIXART_PMW_REG_CONFIG2 , 0x00 ); /* Clear REST enable bit */
88-
89- /* Upload firmware blob */
90- pixart_pmw_write (driver , PIXART_PMW_REG_SROM_EN , PIXART_PMW_SROM_DWNLD_CMD ); /* Initialize SROM download */
176+ if (pid != PIXART_PMW_PID_PMW3360 && pid != PIXART_PMW_PID_PMW3389 )
177+ goto failed_init ;
91178
92- ticks_hal . delay_ms ( 15 ) ;
179+ driver . pid = pid ;
93180
94- pixart_pmw_write (driver , PIXART_PMW_REG_SROM_EN , PIXART_PMW_SROM_DWNLD_START_CMD ); /* Start SROM download */
95-
96- spi_hal .select (spi_hal , 1 );
97-
98- spi_hal .transfer (spi_hal , PIXART_PMW_REG_SROM_BURST | 0x80 ); /* 7 bit srom_burst address + write bit(1) */
99- ticks_hal .delay_us (15 );
100-
101- for (size_t b = 0 ; b < 4094 ; b ++ ) /* write firmware image (4094 bytes) */
102- {
103- spi_hal .transfer (spi_hal , firmware [b ]);
104- ticks_hal .delay_us (15 );
105- }
181+ pixart_pmw_write (driver , PIXART_PMW_REG_CONFIG2 , 0x00 ); /* Clear REST enable bit */
106182
107- spi_hal . select ( spi_hal , 0 );
183+ pixart_pmw_upload_srom ( driver , firmware ); /* Upload firmware blob */
108184
109- ticks_hal . delay_ms ( 2 ); /* Tbexit */
110- /* End upload firmware blob */
185+ if (!( pixart_pmw_read ( driver , PIXART_PMW_REG_OBSERVATION ) & PIXART_PMW_SROM_RUN )) /* check SROM running bit */
186+ goto failed_init ;
111187
112188 u8 srom_id = pixart_pmw_read (driver , PIXART_PMW_REG_SROM_ID ); /* read srom firmware id */
113189 if (!srom_id )
114- return driver ;
115-
116- pixart_pmw_write (driver , PIXART_PMW_REG_SROM_EN , PIXART_PMW_SROM_CRC_CMD ); /* initialize CRC check */
117-
118- ticks_hal .delay_ms (15 ); /* Wait for CRC */
119-
120- u16 srom_crc = 0 ;
121- srom_crc |= (pixart_pmw_read (driver , PIXART_PMW_REG_DOUT_H ) << 8 );
122- srom_crc |= pixart_pmw_read (driver , PIXART_PMW_REG_DOUT_L );
123-
124- /* TODO: check CRC */
125- if (!srom_crc )
126- return driver ;
127-
128- if (!(pixart_pmw_read (driver , PIXART_PMW_REG_OBSERVATION ) & PIXART_PMW_SROM_RUN )) /* check SROM running bit */
129- return driver ;
190+ goto failed_init ;
130191
131192 pixart_pmw_write (driver , PIXART_PMW_REG_CONFIG2 , 0x00 ); /* clear REST enable bit */
132193
133194 pixart_pmw_write (driver , PIXART_PMW_REG_BURST , 0x01 );
134195
135- ticks_hal .delay_ms (10 );
136-
137- pixart_pmw_write (driver , PIXART_PMW_REG_OBSERVATION , 0x00 ); /* clear observation register */
138-
139- pixart_pmw_write (driver , PIXART_PMW_REG_BURST , 0x01 );
196+ pixart_pmw_read_motion_burst (driver ); /* Read motion and discard the data*/
140197
141- pixart_pmw_read_motion_burst ( driver ) ;
198+ return driver ;
142199
200+ failed_init :
201+ driver .pid = 0 ; /* pid == 0 means failed initialization */
143202 return driver ;
144203}
145204
@@ -167,3 +226,22 @@ struct deltas_t pixart_pmw_get_deltas(struct pixart_pmw_driver_t *driver)
167226
168227 return deltas ;
169228}
229+
230+ void pixart_pmw_set_cpi (struct pixart_pmw_driver_t driver , u16 cpi )
231+ {
232+ switch (driver .pid ) {
233+ case PIXART_PMW_PID_PMW3360 :
234+ if (cpi >= 100 && cpi <= 12000 )
235+ pixart_pmw_write (
236+ driver , PIXART_PMW3360_REG_CPI , ((cpi / 100 ) - 1 )); /* 100-12000, 100 cpi LSb */
237+ break ;
238+
239+ case PIXART_PMW_PID_PMW3389 :
240+ if (cpi >= 50 && cpi <= 16000 ) {
241+ cpi /= 50 ;
242+ pixart_pmw_write (driver , PIXART_PMW3389_REG_CPI_L , cpi & 0xFF ); /* 50-16000, 50 cpi LSb */
243+ pixart_pmw_write (driver , PIXART_PMW3389_REG_CPI_H , cpi >> 8 ); /* 50-16000, 50 cpi LSb */
244+ }
245+ break ;
246+ }
247+ }
0 commit comments