aboutsummaryrefslogtreecommitdiff
path: root/drivers/sensors/pmw3360.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/sensors/pmw3360.c')
-rw-r--r--drivers/sensors/pmw3360.c140
1 files changed, 74 insertions, 66 deletions
diff --git a/drivers/sensors/pmw3360.c b/drivers/sensors/pmw3360.c
index 79b653e45..2b27dccbb 100644
--- a/drivers/sensors/pmw3360.c
+++ b/drivers/sensors/pmw3360.c
@@ -20,62 +20,71 @@
20#include "wait.h" 20#include "wait.h"
21#include "debug.h" 21#include "debug.h"
22#include "print.h" 22#include "print.h"
23#include "pmw3360_firmware.h" 23#include PMW3360_FIRMWARE_H
24 24
25// Registers 25// Registers
26#define REG_Product_ID 0x00 26// clang-format off
27#define REG_Revision_ID 0x01 27#define REG_Product_ID 0x00
28#define REG_Motion 0x02 28#define REG_Revision_ID 0x01
29#define REG_Delta_X_L 0x03 29#define REG_Motion 0x02
30#define REG_Delta_X_H 0x04 30#define REG_Delta_X_L 0x03
31#define REG_Delta_Y_L 0x05 31#define REG_Delta_X_H 0x04
32#define REG_Delta_Y_H 0x06 32#define REG_Delta_Y_L 0x05
33#define REG_SQUAL 0x07 33#define REG_Delta_Y_H 0x06
34#define REG_Raw_Data_Sum 0x08 34#define REG_SQUAL 0x07
35#define REG_Maximum_Raw_data 0x09 35#define REG_Raw_Data_Sum 0x08
36#define REG_Minimum_Raw_data 0x0A 36#define REG_Maximum_Raw_data 0x09
37#define REG_Shutter_Lower 0x0B 37#define REG_Minimum_Raw_data 0x0A
38#define REG_Shutter_Upper 0x0C 38#define REG_Shutter_Lower 0x0B
39#define REG_Control 0x0D 39#define REG_Shutter_Upper 0x0C
40#define REG_Config1 0x0F 40#define REG_Control 0x0D
41#define REG_Config2 0x10 41#define REG_Config1 0x0F
42#define REG_Angle_Tune 0x11 42#define REG_Config2 0x10
43#define REG_Frame_Capture 0x12 43#define REG_Angle_Tune 0x11
44#define REG_SROM_Enable 0x13 44#define REG_Frame_Capture 0x12
45#define REG_Run_Downshift 0x14 45#define REG_SROM_Enable 0x13
46#define REG_Rest1_Rate_Lower 0x15 46#define REG_Run_Downshift 0x14
47#define REG_Rest1_Rate_Upper 0x16 47#define REG_Rest1_Rate_Lower 0x15
48#define REG_Rest1_Downshift 0x17 48#define REG_Rest1_Rate_Upper 0x16
49#define REG_Rest2_Rate_Lower 0x18 49#define REG_Rest1_Downshift 0x17
50#define REG_Rest2_Rate_Upper 0x19 50#define REG_Rest2_Rate_Lower 0x18
51#define REG_Rest2_Downshift 0x1A 51#define REG_Rest2_Rate_Upper 0x19
52#define REG_Rest3_Rate_Lower 0x1B 52#define REG_Rest2_Downshift 0x1A
53#define REG_Rest3_Rate_Upper 0x1C 53#define REG_Rest3_Rate_Lower 0x1B
54#define REG_Observation 0x24 54#define REG_Rest3_Rate_Upper 0x1C
55#define REG_Data_Out_Lower 0x25 55#define REG_Observation 0x24
56#define REG_Data_Out_Upper 0x26 56#define REG_Data_Out_Lower 0x25
57#define REG_Raw_Data_Dump 0x29 57#define REG_Data_Out_Upper 0x26
58#define REG_SROM_ID 0x2A 58#define REG_Raw_Data_Dump 0x29
59#define REG_Min_SQ_Run 0x2B 59#define REG_SROM_ID 0x2A
60#define REG_Raw_Data_Threshold 0x2C 60#define REG_Min_SQ_Run 0x2B
61#define REG_Config5 0x2F 61#define REG_Raw_Data_Threshold 0x2C
62#define REG_Power_Up_Reset 0x3A 62#define REG_Config5 0x2F
63#define REG_Shutdown 0x3B 63#define REG_Power_Up_Reset 0x3A
64#define REG_Inverse_Product_ID 0x3F 64#define REG_Shutdown 0x3B
65#define REG_LiftCutoff_Tune3 0x41 65#define REG_Inverse_Product_ID 0x3F
66#define REG_Angle_Snap 0x42 66#define REG_LiftCutoff_Tune3 0x41
67#define REG_LiftCutoff_Tune1 0x4A 67#define REG_Angle_Snap 0x42
68#define REG_Motion_Burst 0x50 68#define REG_LiftCutoff_Tune1 0x4A
69#define REG_LiftCutoff_Tune_Timeout 0x58 69#define REG_Motion_Burst 0x50
70#define REG_LiftCutoff_Tune_Timeout 0x58
70#define REG_LiftCutoff_Tune_Min_Length 0x5A 71#define REG_LiftCutoff_Tune_Min_Length 0x5A
71#define REG_SROM_Load_Burst 0x62 72#define REG_SROM_Load_Burst 0x62
72#define REG_Lift_Config 0x63 73#define REG_Lift_Config 0x63
73#define REG_Raw_Data_Burst 0x64 74#define REG_Raw_Data_Burst 0x64
74#define REG_LiftCutoff_Tune2 0x65 75#define REG_LiftCutoff_Tune2 0x65
76// clang-format on
77
78#ifndef MAX_CPI
79# define MAX_CPI 0x77 // limits to 0--119, should be max cpi/100
80#endif
75 81
76bool _inBurst = false; 82bool _inBurst = false;
77 83
84#ifdef CONSOLE_ENABLE
78void print_byte(uint8_t byte) { dprintf("%c%c%c%c%c%c%c%c|", (byte & 0x80 ? '1' : '0'), (byte & 0x40 ? '1' : '0'), (byte & 0x20 ? '1' : '0'), (byte & 0x10 ? '1' : '0'), (byte & 0x08 ? '1' : '0'), (byte & 0x04 ? '1' : '0'), (byte & 0x02 ? '1' : '0'), (byte & 0x01 ? '1' : '0')); } 85void print_byte(uint8_t byte) { dprintf("%c%c%c%c%c%c%c%c|", (byte & 0x80 ? '1' : '0'), (byte & 0x40 ? '1' : '0'), (byte & 0x20 ? '1' : '0'), (byte & 0x10 ? '1' : '0'), (byte & 0x08 ? '1' : '0'), (byte & 0x04 ? '1' : '0'), (byte & 0x02 ? '1' : '0'), (byte & 0x01 ? '1' : '0')); }
86#endif
87#define constrain(amt, low, high) ((amt) < (low) ? (low) : ((amt) > (high) ? (high) : (amt)))
79 88
80bool spi_start_adv(void) { 89bool spi_start_adv(void) {
81 bool status = spi_start(PMW3360_CS_PIN, PMW3360_SPI_LSBFIRST, PMW3360_SPI_MODE, PMW3360_SPI_DIVISOR); 90 bool status = spi_start(PMW3360_CS_PIN, PMW3360_SPI_LSBFIRST, PMW3360_SPI_MODE, PMW3360_SPI_DIVISOR);
@@ -124,20 +133,20 @@ uint8_t spi_read_adv(uint8_t reg_addr) {
124 return data; 133 return data;
125} 134}
126 135
127void pmw_set_cpi(uint16_t cpi) { 136void pmw3360_set_cpi(uint16_t cpi) {
128 uint8_t cpival = constrain((cpi / 100) - 1, 0, 0x77); // limits to 0--119 137 uint8_t cpival = constrain((cpi / 100) - 1, 0, MAX_CPI);
129 138
130 spi_start_adv(); 139 spi_start_adv();
131 spi_write_adv(REG_Config1, cpival); 140 spi_write_adv(REG_Config1, cpival);
132 spi_stop(); 141 spi_stop();
133} 142}
134 143
135uint16_t pmw_get_cpi(void) { 144uint16_t pmw3360_get_cpi(void) {
136 uint8_t cpival = spi_read_adv(REG_Config1); 145 uint8_t cpival = spi_read_adv(REG_Config1);
137 return (uint16_t)(cpival & 0xFF) * 100; 146 return (uint16_t)(cpival & 0xFF) * 100;
138} 147}
139 148
140bool pmw_spi_init(void) { 149bool pmw3360_init(void) {
141 setPinOutput(PMW3360_CS_PIN); 150 setPinOutput(PMW3360_CS_PIN);
142 151
143 spi_init(); 152 spi_init();
@@ -164,12 +173,12 @@ bool pmw_spi_init(void) {
164 spi_read_adv(REG_Delta_Y_L); 173 spi_read_adv(REG_Delta_Y_L);
165 spi_read_adv(REG_Delta_Y_H); 174 spi_read_adv(REG_Delta_Y_H);
166 175
167 pmw_upload_firmware(); 176 pmw3360_upload_firmware();
168 177
169 spi_stop_adv(); 178 spi_stop_adv();
170 179
171 wait_ms(10); 180 wait_ms(10);
172 pmw_set_cpi(PMW3360_CPI); 181 pmw3360_set_cpi(PMW3360_CPI);
173 182
174 wait_ms(1); 183 wait_ms(1);
175 184
@@ -177,14 +186,14 @@ bool pmw_spi_init(void) {
177 186
178 spi_write_adv(REG_Angle_Tune, constrain(ROTATIONAL_TRANSFORM_ANGLE, -30, 30)); 187 spi_write_adv(REG_Angle_Tune, constrain(ROTATIONAL_TRANSFORM_ANGLE, -30, 30));
179 188
180 bool init_success = pmw_check_signature(); 189 bool init_success = pmw3360_check_signature();
181 190
182 writePinLow(PMW3360_CS_PIN); 191 writePinLow(PMW3360_CS_PIN);
183 192
184 return init_success; 193 return init_success;
185} 194}
186 195
187void pmw_upload_firmware(void) { 196void pmw3360_upload_firmware(void) {
188 spi_write_adv(REG_SROM_Enable, 0x1d); 197 spi_write_adv(REG_SROM_Enable, 0x1d);
189 198
190 wait_ms(10); 199 wait_ms(10);
@@ -211,16 +220,18 @@ void pmw_upload_firmware(void) {
211 wait_ms(10); 220 wait_ms(10);
212} 221}
213 222
214bool pmw_check_signature(void) { 223bool pmw3360_check_signature(void) {
215 uint8_t pid = spi_read_adv(REG_Product_ID); 224 uint8_t pid = spi_read_adv(REG_Product_ID);
216 uint8_t iv_pid = spi_read_adv(REG_Inverse_Product_ID); 225 uint8_t iv_pid = spi_read_adv(REG_Inverse_Product_ID);
217 uint8_t SROM_ver = spi_read_adv(REG_SROM_ID); 226 uint8_t SROM_ver = spi_read_adv(REG_SROM_ID);
218 return (pid == 0x42 && iv_pid == 0xBD && SROM_ver == 0x04); // signature for SROM 0x04 227 return (pid == firmware_signature[0] && iv_pid == firmware_signature[1] && SROM_ver == firmware_signature[2]); // signature for SROM 0x04
219} 228}
220 229
221report_pmw_t pmw_read_burst(void) { 230report_pmw3360_t pmw3360_read_burst(void) {
222 if (!_inBurst) { 231 if (!_inBurst) {
232#ifdef CONSOLE_ENABLE
223 dprintf("burst on"); 233 dprintf("burst on");
234#endif
224 spi_write_adv(REG_Motion_Burst, 0x00); 235 spi_write_adv(REG_Motion_Burst, 0x00);
225 _inBurst = true; 236 _inBurst = true;
226 } 237 }
@@ -229,12 +240,7 @@ report_pmw_t pmw_read_burst(void) {
229 spi_write(REG_Motion_Burst); 240 spi_write(REG_Motion_Burst);
230 wait_us(35); // waits for tSRAD 241 wait_us(35); // waits for tSRAD
231 242
232 report_pmw_t data; 243 report_pmw3360_t data = {0};
233 data.motion = 0;
234 data.dx = 0;
235 data.mdx = 0;
236 data.dy = 0;
237 data.mdx = 0;
238 244
239 data.motion = spi_read(); 245 data.motion = spi_read();
240 spi_write(0x00); // skip Observation 246 spi_write(0x00); // skip Observation
@@ -245,6 +251,7 @@ report_pmw_t pmw_read_burst(void) {
245 251
246 spi_stop(); 252 spi_stop();
247 253
254#ifdef CONSOLE_ENABLE
248 if (debug_mouse) { 255 if (debug_mouse) {
249 print_byte(data.motion); 256 print_byte(data.motion);
250 print_byte(data.dx); 257 print_byte(data.dx);
@@ -253,6 +260,7 @@ report_pmw_t pmw_read_burst(void) {
253 print_byte(data.mdy); 260 print_byte(data.mdy);
254 dprintf("\n"); 261 dprintf("\n");
255 } 262 }
263#endif
256 264
257 data.isMotion = (data.motion & 0x80) != 0; 265 data.isMotion = (data.motion & 0x80) != 0;
258 data.isOnSurface = (data.motion & 0x08) == 0; 266 data.isOnSurface = (data.motion & 0x08) == 0;