22
22
#include "debug.h"
23
23
#include "gpio.h"
24
24
25
- void pmw3320_init (void ) {
25
+ typedef enum {
26
+ PMW3320_REG_Product_ID = 0x00 ,
27
+ PMW3320_REG_Revision_ID = 0x01 ,
28
+ PMW3320_REG_Motion = 0x02 ,
29
+ PMW3320_REG_Delta_X = 0x03 ,
30
+ PMW3320_REG_Delta_Y = 0x04 ,
31
+ PMW3320_REG_SQUAL = 0x05 ,
32
+ PMW3320_REG_Shutter_Upper = 0x06 ,
33
+ PMW3320_REG_Shutter_Lower = 0x07 ,
34
+ PMW3320_REG_Maximum_Pixel = 0x08 ,
35
+ PMW3320_REG_Pixel_Accum = 0x09 ,
36
+ PMW3320_REG_Minimum_Pixel = 0x0a ,
37
+ PMW3320_REG_Pixel_Grab = 0x0b ,
38
+ PMW3320_REG_Delta_XY = 0x0c ,
39
+ PMW3320_REG_Resolution = 0x0d ,
40
+ PMW3320_REG_Run_Downshift = 0x0e ,
41
+ PMW3320_REG_Rest1_Period = 0x0f ,
42
+ PMW3320_REG_Rest1_Downshift = 0x10 ,
43
+ PMW3320_REG_Rest2_Preiod = 0x11 ,
44
+ PMW3320_REG_Rest2_Downshift = 0x12 ,
45
+ PMW3320_REG_Rest3_Period = 0x13 ,
46
+ PMW3320_REG_Min_SQ_Run = 0x17 ,
47
+ PMW3320_REG_Axis_Control = 0x1a ,
48
+ PMW3320_REG_Performance = 0x22 ,
49
+ PMW3320_REG_Low_Motion_Jitter = 0x23 ,
50
+ PMW3320_REG_Shutter_Max_HI = 0x36 ,
51
+ PMW3320_REG_Shutter_Max_LO = 0x37 ,
52
+ PMW3320_REG_Frame_Rate = 0x39 ,
53
+ PMW3320_REG_Power_Up_Reset = 0x3a ,
54
+ PMW3320_REG_Shutdown = 0x3b ,
55
+ PMW3320_REG_Inverse_Revision_ID = 0x3f ,
56
+ PMW3320_REG_Led_Control = 0x40 ,
57
+ PMW3320_REG_Motion_Control = 0x41 ,
58
+ PMW3320_REG_Burst_Read_First = 0x42 ,
59
+ PMW3320_REG_Rest_Mode_Status = 0x45 ,
60
+ PMW3320_REG_Inverse_Product_ID = 0x4f ,
61
+ PMW3320_REG_Motion_Burst = 0x63 ,
62
+ } pmw3320_regs ;
63
+
64
+ const pointing_device_driver_t pmw3320_driver_default = {.init = pmw3320_init , .get_report = pmw3320_get_report , .set_cpi = pmw3320_set_cpi , .get_cpi = pmw3320_get_cpi };
65
+ #if defined(PMW3320_SCLK_PIN ) & defined(PMW3320_SDIO_PIN ) & defined(PMW3320_CS_PIN )
66
+ const pointing_device_3wire_spi_config_t pmw3320_config_default = {.cs = PMW3320_CS_PIN , .sclk = PMW3320_SCLK_PIN , .sdio = PMW3320_SDIO_PIN };
67
+ #endif
68
+
69
+ void pmw3320_sync (pin_t cs );
70
+ uint8_t pmw3320_serial_read (pointing_device_3wire_spi_config_t * pmw3320_config );
71
+ void pmw3320_serial_write (pointing_device_3wire_spi_config_t * pmw3320_config , uint8_t data );
72
+ uint8_t pmw3320_read_reg (pointing_device_3wire_spi_config_t * pmw3320_config , pmw3320_regs reg_addr );
73
+ void pmw3320_write_reg (pointing_device_3wire_spi_config_t * pmw3320_config , pmw3320_regs reg_addr , uint8_t data );
74
+ report_pmw3320_t pmw3320_read_burst (pointing_device_3wire_spi_config_t * pmw3320_config );
75
+
76
+ void pmw3320_init (const void * config ) {
77
+ pointing_device_3wire_spi_config_t * pmw3320_config = (pointing_device_3wire_spi_config_t * )config ;
26
78
// Initialize sensor serial pins.
27
- setPinOutput (PMW3320_SCLK_PIN );
28
- setPinOutput (PMW3320_SDIO_PIN );
29
- setPinOutput (PMW3320_CS_PIN );
79
+ setPinOutput (pmw3320_config -> sclk );
80
+ setPinOutput (pmw3320_config -> sdio );
81
+ setPinOutput (pmw3320_config -> cs );
30
82
31
83
// reboot the sensor.
32
- pmw3320_write_reg (REG_Power_Up_Reset , 0x5a );
84
+ pmw3320_write_reg (pmw3320_config , PMW3320_REG_Power_Up_Reset , 0x5a );
33
85
34
86
// wait maximum time before sensor is ready.
35
87
// this ensures that the sensor is actually ready after reset.
@@ -38,66 +90,66 @@ void pmw3320_init(void) {
38
90
// read a burst from the sensor and then discard it.
39
91
// gets the sensor ready for write commands
40
92
// (for example, setting the dpi).
41
- pmw3320_read_burst ();
93
+ pmw3320_read_burst (pmw3320_config );
42
94
43
95
// Pretty sure that this shouldn't be in the driver.
44
96
// Probably device specific?
45
97
// Set rest mode to default
46
- pmw3320_write_reg (REG_Rest_Mode_Status , 0x00 );
98
+ pmw3320_write_reg (pmw3320_config , PMW3320_REG_Rest_Mode_Status , 0x00 );
47
99
// Set LED to be always on
48
- pmw3320_write_reg (REG_Led_Control , 0x4 );
100
+ pmw3320_write_reg (pmw3320_config , PMW3320_REG_Led_Control , 0x4 );
49
101
// Disable rest mode
50
- pmw3320_write_reg (REG_Performance , 0x80 );
102
+ pmw3320_write_reg (pmw3320_config , PMW3320_REG_Performance , 0x80 );
51
103
}
52
104
53
105
// Perform a synchronization with sensor.
54
106
// Just as with the serial protocol, this is used by the slave to send a
55
107
// synchronization signal to the master.
56
- void pmw3320_sync (void ) {
57
- writePinLow (PMW3320_CS_PIN );
108
+ void pmw3320_sync (pin_t cs ) {
109
+ writePinLow (cs );
58
110
wait_us (1 );
59
- writePinHigh (PMW3320_CS_PIN );
111
+ writePinHigh (cs );
60
112
}
61
113
62
- void pmw3320_cs_select (void ) {
63
- writePinLow (PMW3320_CS_PIN );
114
+ void pmw3320_cs_select (pin_t cs ) {
115
+ writePinLow (cs );
64
116
}
65
117
66
- void pmw3320_cs_deselect (void ) {
67
- writePinHigh (PMW3320_CS_PIN );
118
+ void pmw3320_cs_deselect (pin_t cs ) {
119
+ writePinHigh (cs );
68
120
}
69
121
70
- uint8_t pmw3320_serial_read (void ) {
71
- setPinInput (PMW3320_SDIO_PIN );
122
+ uint8_t pmw3320_serial_read (pointing_device_3wire_spi_config_t * pmw3320_config ) {
123
+ setPinInput (pmw3320_config -> sdio );
72
124
uint8_t byte = 0 ;
73
125
74
126
for (uint8_t i = 0 ; i < 8 ; ++ i ) {
75
- writePinLow (PMW3320_SCLK_PIN );
127
+ writePinLow (pmw3320_config -> sclk );
76
128
wait_us (1 );
77
129
78
- byte = (byte << 1 ) | readPin (PMW3320_SDIO_PIN );
130
+ byte = (byte << 1 ) | readPin (pmw3320_config -> sdio );
79
131
80
- writePinHigh (PMW3320_SCLK_PIN );
132
+ writePinHigh (pmw3320_config -> sclk );
81
133
wait_us (1 );
82
134
}
83
135
84
136
return byte ;
85
137
}
86
138
87
- void pmw3320_serial_write (uint8_t data ) {
88
- setPinOutput (PMW3320_SDIO_PIN );
139
+ void pmw3320_serial_write (pointing_device_3wire_spi_config_t * pmw3320_config , uint8_t data ) {
140
+ setPinOutput (pmw3320_config -> sdio );
89
141
90
142
for (int8_t b = 7 ; b >= 0 ; b -- ) {
91
- writePinLow (PMW3320_SCLK_PIN );
143
+ writePinLow (pmw3320_config -> sclk );
92
144
93
145
if (data & (1 << b ))
94
- writePinHigh (PMW3320_SDIO_PIN );
146
+ writePinHigh (pmw3320_config -> sdio );
95
147
else
96
- writePinLow (PMW3320_SDIO_PIN );
148
+ writePinLow (pmw3320_config -> sdio );
97
149
98
150
wait_us (2 );
99
151
100
- writePinHigh (PMW3320_SCLK_PIN );
152
+ writePinHigh (pmw3320_config -> sclk );
101
153
}
102
154
103
155
// This was taken from ADNS5050 driver.
@@ -112,12 +164,12 @@ void pmw3320_serial_write(uint8_t data) {
112
164
}
113
165
114
166
// Read a byte of data from a register on the sensor.
115
- uint8_t pmw3320_read_reg (uint8_t reg_addr ) {
116
- pmw3320_cs_select ();
167
+ uint8_t pmw3320_read_reg (pointing_device_3wire_spi_config_t * pmw3320_config , pmw3320_regs reg_addr ) {
168
+ pmw3320_cs_select (pmw3320_config -> cs );
117
169
118
- pmw3320_serial_write (reg_addr );
170
+ pmw3320_serial_write (pmw3320_config , reg_addr );
119
171
120
- uint8_t byte = pmw3320_serial_read ();
172
+ uint8_t byte = pmw3320_serial_read (pmw3320_config );
121
173
122
174
// This was taken directly from ADNS5050 driver...
123
175
// tSRW & tSRR. See page 15 of the ADNS5050 spec sheet.
@@ -126,67 +178,85 @@ uint8_t pmw3320_read_reg(uint8_t reg_addr) {
126
178
// Honestly, this wait could probably be removed.
127
179
wait_us (1 );
128
180
129
- pmw3320_cs_deselect ();
181
+ pmw3320_cs_deselect (pmw3320_config -> cs );
130
182
131
183
return byte ;
132
184
}
133
185
134
- void pmw3320_write_reg (uint8_t reg_addr , uint8_t data ) {
135
- pmw3320_cs_select ();
136
- pmw3320_serial_write (0b10000000 | reg_addr );
137
- pmw3320_serial_write (data );
138
- pmw3320_cs_deselect ();
186
+ void pmw3320_write_reg (pointing_device_3wire_spi_config_t * pmw3320_config , pmw3320_regs reg_addr , uint8_t data ) {
187
+ pmw3320_cs_select (pmw3320_config -> cs );
188
+ pmw3320_serial_write (pmw3320_config , 0b10000000 | reg_addr );
189
+ pmw3320_serial_write (pmw3320_config , data );
190
+ pmw3320_cs_deselect (pmw3320_config -> cs );
139
191
}
140
192
141
- report_pmw3320_t pmw3320_read_burst (void ) {
142
- pmw3320_cs_select ();
193
+ report_pmw3320_t pmw3320_read_burst (pointing_device_3wire_spi_config_t * pmw3320_config ) {
194
+ pmw3320_cs_select (pmw3320_config -> cs );
143
195
144
196
report_pmw3320_t data ;
145
197
data .dx = 0 ;
146
198
data .dy = 0 ;
147
199
148
- pmw3320_serial_write (REG_Motion_Burst );
200
+ pmw3320_serial_write (pmw3320_config , PMW3320_REG_Motion_Burst );
149
201
150
- uint8_t x = pmw3320_serial_read ();
151
- uint8_t y = pmw3320_serial_read ();
202
+ uint8_t x = pmw3320_serial_read (pmw3320_config );
203
+ uint8_t y = pmw3320_serial_read (pmw3320_config );
152
204
153
205
// Probably burst mode may include contents of delta_xy register,
154
206
// which contain HI parts of x/y deltas, but I had no luck finding it.
155
207
// Probably it's required to activate 12-bit mode to access this data.
156
208
// So we end burst mode early to not read unneeded information.
157
- pmw3320_cs_deselect ();
209
+ pmw3320_cs_deselect (pmw3320_config -> cs );
158
210
159
- data .dx = convert_twoscomp (x );
160
- data .dy = convert_twoscomp (y );
211
+ data .dx = paw3320_convert_twoscomp (x );
212
+ data .dy = paw3320_convert_twoscomp (y );
161
213
162
214
return data ;
163
215
}
164
216
165
217
// Convert a two's complement byte from an unsigned data type into a signed
166
218
// data type.
167
- int8_t convert_twoscomp (uint8_t data ) {
219
+ int8_t paw3320_convert_twoscomp (uint8_t data ) {
168
220
if ((data & 0x80 ) == 0x80 )
169
221
return -128 + (data & 0x7F );
170
222
else
171
223
return data ;
172
224
}
173
225
174
- uint16_t pmw3320_get_cpi (void ) {
175
- uint8_t cpival = pmw3320_read_reg (REG_Resolution );
226
+ uint16_t pmw3320_get_cpi (const void * config ) {
227
+ pointing_device_3wire_spi_config_t * pmw3320_config = (pointing_device_3wire_spi_config_t * )config ;
228
+
229
+ uint8_t cpival = pmw3320_read_reg (pmw3320_config , PMW3320_REG_Resolution );
176
230
// 0x1F is an inversion of 0x20 which is 0b100000
177
231
return (uint16_t )((cpival & 0x1F ) * PMW3320_CPI_STEP );
178
232
}
179
233
180
- void pmw3320_set_cpi (uint16_t cpi ) {
234
+ void pmw3320_set_cpi (const void * config , uint16_t cpi ) {
235
+ pointing_device_3wire_spi_config_t * pmw3320_config = (pointing_device_3wire_spi_config_t * )config ;
236
+
181
237
uint8_t cpival = constrain ((cpi / PMW3320_CPI_STEP ) - 1U , 0 , (PMW3320_CPI_MAX / PMW3320_CPI_STEP ) - 1U );
182
238
// Fifth bit is probably a control bit.
183
239
// PMW3320 datasheet don't have any info on this, so this is a pure guess.
184
- pmw3320_write_reg (REG_Resolution , 0x20 | cpival );
240
+ pmw3320_write_reg (pmw3320_config , PMW3320_REG_Resolution , 0x20 | cpival );
185
241
}
186
242
187
- bool pmw3320_check_signature (void ) {
188
- uint8_t pid = pmw3320_read_reg (REG_Product_ID );
189
- uint8_t pid2 = pmw3320_read_reg (REG_Inverse_Product_ID );
243
+ bool pmw3320_check_signature (pointing_device_3wire_spi_config_t * pmw3320_config ) {
244
+ uint8_t pid = pmw3320_read_reg (pmw3320_config , PMW3320_REG_Product_ID );
245
+ uint8_t pid2 = pmw3320_read_reg (pmw3320_config , PMW3320_REG_Inverse_Product_ID );
190
246
191
247
return (pid == 0x3b && pid2 == 0xc4 );
192
248
}
249
+
250
+ report_mouse_t pmw3320_get_report (const void * config ) {
251
+ pointing_device_3wire_spi_config_t * pmw3320_config = (pointing_device_3wire_spi_config_t * )config ;
252
+ report_pmw3320_t data = pmw3320_read_burst (pmw3320_config );
253
+ report_mouse_t mouse_report = {0 };
254
+
255
+ if (data .dx != 0 || data .dy != 0 ) {
256
+ pd_dprintf ("Raw ] X: %d, Y: %d\n" , data .dx , data .dy );
257
+ mouse_report .x = (mouse_xy_report_t )data .dx ;
258
+ mouse_report .y = (mouse_xy_report_t )data .dy ;
259
+ }
260
+
261
+ return mouse_report ;
262
+ }
0 commit comments