Skip to content

Commit b5dd4c2

Browse files
committed
driver: pixar_pmw: initialization changes and cpi change support
Signed-off-by: Rafael Silva <perigoso@riseup.net>
1 parent 1c8ea38 commit b5dd4c2

2 files changed

Lines changed: 130 additions & 101 deletions

File tree

src/driver/pixart/pixart_pmw.c

Lines changed: 127 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,81 @@
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+
875
struct 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+
47139
struct 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+
}

src/driver/pixart/pixart_pmw.h

Lines changed: 3 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -10,64 +10,13 @@
1010
#include "hal/ticks.h"
1111
#include "util/types.h"
1212

13-
/* General Registers */
14-
#define PIXART_PMW_REG_PID 0x00
15-
#define PIXART_PMW_REG_REV_ID 0x01
16-
#define PIXART_PMW_REG_PWR_UP_RST 0x3A
17-
18-
#define PIXART_PMW_PID_PMW3360 0x42
19-
#define PIXART_PMW_PID_TRUEMOVE3 PIXART_PMW_PID_PMW3360 /* TRUEMOVE 3 Shares the same PID as PMW3360*/
20-
#define PIXART_PMW_PID_PMW3330 0x45
21-
#define PIXART_PMW_PID_PMW3389 0x47
22-
23-
/* Motion Registers */
24-
#define PIXART_PMW_REG_MOTION 0x02
25-
#define PIXART_PMW_REG_DELTA_X_L 0x03
26-
#define PIXART_PMW_REG_DELTA_X_H 0x04
27-
#define PIXART_PMW_REG_DELTA_Y_L 0x05
28-
#define PIXART_PMW_REG_DELTA_Y_H 0x06
29-
#define PIXART_PMW_REG_BURST 0x50
30-
31-
/* Motion bits */
32-
#define PIXART_PMW_MOTION 0x80
33-
#define PIXART_PMW_OPMODE_RUN 0x00
34-
#define PIXART_PMW_OPMODE_REST1 0x02
35-
#define PIXART_PMW_OPMODE_REST2 0x04
36-
#define PIXART_PMW_OPMODE_REST3 0x06
37-
38-
/* SROM Registers */
39-
#define PIXART_PMW_REG_SROM_EN 0x13
40-
#define PIXART_PMW_REG_SROM_ID 0x2A
41-
#define PIXART_PMW_REG_SROM_BURST 0x62
42-
43-
/* SROM CMDs */
44-
#define PIXART_PMW_SROM_CRC_CMD 0x15
45-
#define PIXART_PMW_SROM_DWNLD_CMD 0x1D
46-
#define PIXART_PMW_SROM_DWNLD_START_CMD 0x18
47-
48-
/* Config Registers */
49-
#define PIXART_PMW_REG_CONFIG1 0x0F
50-
#define PIXART_PMW_REG_CONFIG2 0x10
51-
#define PIXART_PMW_REG_OBSERVATION 0x24
52-
#define PIXART_PMW_REG_DOUT_L 0x25
53-
#define PIXART_PMW_REG_DOUT_H 0x26
54-
55-
/* Config2 Bits */
56-
#define PIXART_PMW_RESTEN 0x20
57-
#define PIXART_PMW_RPT_MOD 0x04
58-
59-
/* Observation Bits */
60-
#define PIXART_PMW_SROM_RUN 0x40
61-
62-
/* power up reset cmd */
63-
#define PIXART_PMW_RESET_CMD 0x5A
64-
6513
struct deltas_t {
6614
s16 dx;
6715
s16 dy;
6816
};
6917

7018
struct pixart_pmw_driver_t {
19+
u8 pid;
7120
u8 motion_flag;
7221
struct deltas_t deltas;
7322
struct spi_hal_t spi_hal;
@@ -81,3 +30,5 @@ void pixart_pmw_read_motion(struct pixart_pmw_driver_t *driver);
8130
void pixart_pmw_motion_event(struct pixart_pmw_driver_t *driver);
8231

8332
struct deltas_t pixart_pmw_get_deltas(struct pixart_pmw_driver_t *driver);
33+
34+
void pixart_pmw_set_cpi(struct pixart_pmw_driver_t driver, u16 cpi);

0 commit comments

Comments
 (0)