Browse Source

mouse sensor is working and sending HID reports

Thomas Buck 1 year ago
parent
commit
25c8a9aa27
3 changed files with 91 additions and 32 deletions
  1. 2
    0
      firmware/include/pmw3360_srom.h
  2. 79
    28
      firmware/src/pmw3360.c
  3. 10
    4
      firmware/src/usb_hid.c

+ 2
- 0
firmware/include/pmw3360_srom.h View File

10
 
10
 
11
 // Firmware "PMW3360DM_srom_0x04"
11
 // Firmware "PMW3360DM_srom_0x04"
12
 
12
 
13
+static const uint8_t pmw_fw_id = 0x04;
14
+static const uint16_t pmw_fw_crc = 0xBEEF;
13
 static const uint16_t pmw_fw_length = 4094;
15
 static const uint16_t pmw_fw_length = 4094;
14
 static const uint8_t pmw_fw_data[4094] = {
16
 static const uint8_t pmw_fw_data[4094] = {
15
 0x01, 0x04, 0x8e, 0x96, 0x6e, 0x77, 0x3e, 0xfe, 0x7e, 0x5f, 0x1d, 0xb8, 0xf2, 0x66, 0x4e,
17
 0x01, 0x04, 0x8e, 0x96, 0x6e, 0x77, 0x3e, 0xfe, 0x7e, 0x5f, 0x1d, 0xb8, 0xf2, 0x66, 0x4e,

+ 79
- 28
firmware/src/pmw3360.c View File

21
 #include "pico/binary_info.h"
21
 #include "pico/binary_info.h"
22
 #include "hardware/spi.h"
22
 #include "hardware/spi.h"
23
 
23
 
24
+#define PMW_PRINT_IDS
24
 #define PMW_IRQ_COUNTERS
25
 #define PMW_IRQ_COUNTERS
26
+//#define PMW_FEATURE_WIRELESS
25
 
27
 
26
 #include "log.h"
28
 #include "log.h"
27
 #include "pmw3360_registers.h"
29
 #include "pmw3360_registers.h"
73
 }
75
 }
74
 
76
 
75
 static void pmw_write_register(uint8_t reg, uint8_t data) {
77
 static void pmw_write_register(uint8_t reg, uint8_t data) {
76
-    uint8_t buf[2];
77
-    buf[0] = reg | WRITE_BIT;
78
-    buf[1] = data;
79
     pmw_cs_select();
78
     pmw_cs_select();
80
-    spi_write_blocking(spi_default, buf, 2);
79
+
80
+    reg |= WRITE_BIT;
81
+    spi_write_blocking(spi_default, &reg, 1);
82
+
83
+    busy_wait_us(15);
84
+
85
+    spi_write_blocking(spi_default, &data, 1);
86
+
87
+    busy_wait_us(20);
81
     pmw_cs_deselect();
88
     pmw_cs_deselect();
82
-    sleep_ms(10);
89
+    busy_wait_us(100);
83
 }
90
 }
84
 
91
 
85
 static uint8_t pmw_read_register(uint8_t reg) {
92
 static uint8_t pmw_read_register(uint8_t reg) {
86
-    uint8_t buf = 0;
87
-    reg &= ~WRITE_BIT;
88
     pmw_cs_select();
93
     pmw_cs_select();
94
+
95
+    reg &= ~WRITE_BIT;
89
     spi_write_blocking(spi_default, &reg, 1);
96
     spi_write_blocking(spi_default, &reg, 1);
90
-    sleep_ms(10);
97
+
98
+    busy_wait_us(160);
99
+
100
+    uint8_t buf = 0;
91
     spi_read_blocking(spi_default, 0, &buf, 1);
101
     spi_read_blocking(spi_default, 0, &buf, 1);
102
+
103
+    busy_wait_us(1);
92
     pmw_cs_deselect();
104
     pmw_cs_deselect();
93
-    sleep_ms(10);
105
+    busy_wait_us(20);
106
+
94
     return buf;
107
     return buf;
95
 }
108
 }
96
 
109
 
97
 static void pmw_write_register_burst(uint8_t reg, const uint8_t *buf, uint16_t len) {
110
 static void pmw_write_register_burst(uint8_t reg, const uint8_t *buf, uint16_t len) {
98
-    reg |= WRITE_BIT;
99
     pmw_cs_select();
111
     pmw_cs_select();
112
+
113
+    reg |= WRITE_BIT;
100
     spi_write_blocking(spi_default, &reg, 1);
114
     spi_write_blocking(spi_default, &reg, 1);
101
-    sleep_us(15);
115
+
116
+    busy_wait_us(15);
117
+
102
     for (uint16_t i = 0; i < len; i++) {
118
     for (uint16_t i = 0; i < len; i++) {
103
         spi_write_blocking(spi_default, buf + i, 1);
119
         spi_write_blocking(spi_default, buf + i, 1);
104
-        sleep_us(15);
120
+        busy_wait_us(15);
105
     }
121
     }
122
+
106
     pmw_cs_deselect();
123
     pmw_cs_deselect();
107
-    sleep_us(1);
124
+
125
+    busy_wait_us(1);
108
 }
126
 }
109
 
127
 
110
 static void pmw_read_register_burst(uint8_t reg, uint8_t *buf, uint16_t len) {
128
 static void pmw_read_register_burst(uint8_t reg, uint8_t *buf, uint16_t len) {
111
-    reg &= ~WRITE_BIT;
112
     pmw_cs_select();
129
     pmw_cs_select();
130
+
131
+    reg &= ~WRITE_BIT;
113
     spi_write_blocking(spi_default, &reg, 1);
132
     spi_write_blocking(spi_default, &reg, 1);
114
-    sleep_ms(1);//sleep_us(15); // TODO tSRAD_MOTBR
133
+
134
+    busy_wait_us(35);
135
+
115
     spi_read_blocking(spi_default, 0, buf, len);
136
     spi_read_blocking(spi_default, 0, buf, len);
137
+
116
     pmw_cs_deselect();
138
     pmw_cs_deselect();
117
-    sleep_us(1);
139
+    busy_wait_us(1);
118
 }
140
 }
119
 
141
 
120
 static uint8_t pmw_srom_download(void) {
142
 static uint8_t pmw_srom_download(void) {
125
     pmw_write_register(REG_SROM_ENABLE, 0x1D);
147
     pmw_write_register(REG_SROM_ENABLE, 0x1D);
126
 
148
 
127
     // Wait for 10 ms
149
     // Wait for 10 ms
128
-    sleep_ms(10);
150
+    busy_wait_ms(10);
129
 
151
 
130
     // Write 0x18 to SROM_Enable register again to start SROM Download
152
     // Write 0x18 to SROM_Enable register again to start SROM Download
131
     pmw_write_register(REG_SROM_ENABLE, 0x18);
153
     pmw_write_register(REG_SROM_ENABLE, 0x18);
132
 
154
 
133
-    sleep_us(120);
155
+    busy_wait_us(120);
134
 
156
 
135
     // Write SROM file into SROM_Load_Burst register, 1st data must start with SROM_Load_Burst address.
157
     // Write SROM file into SROM_Load_Burst register, 1st data must start with SROM_Load_Burst address.
136
     pmw_write_register_burst(REG_SROM_LOAD_BURST, pmw_fw_data, pmw_fw_length);
158
     pmw_write_register_burst(REG_SROM_LOAD_BURST, pmw_fw_data, pmw_fw_length);
137
 
159
 
138
-    sleep_us(200);
160
+    busy_wait_us(200);
139
 
161
 
140
     // Read the SROM_ID register to verify the ID before any other register reads or writes
162
     // Read the SROM_ID register to verify the ID before any other register reads or writes
141
     uint8_t srom_id = pmw_read_register(REG_SROM_ID);
163
     uint8_t srom_id = pmw_read_register(REG_SROM_ID);
143
 }
165
 }
144
 
166
 
145
 static uint8_t pmw_power_up(void) {
167
 static uint8_t pmw_power_up(void) {
168
+    pmw_cs_deselect();
169
+    pmw_cs_select();
170
+    pmw_cs_deselect();
171
+
146
     // Write 0x5A to Power_Up_Reset register
172
     // Write 0x5A to Power_Up_Reset register
147
     pmw_write_register(REG_POWER_UP_RESET, 0x5A);
173
     pmw_write_register(REG_POWER_UP_RESET, 0x5A);
148
 
174
 
149
     // Wait for at least 50ms
175
     // Wait for at least 50ms
150
-    sleep_ms(50);
176
+    busy_wait_ms(50);
151
 
177
 
152
     // Read from registers 0x02, 0x03, 0x04, 0x05 and 0x06 one time
178
     // Read from registers 0x02, 0x03, 0x04, 0x05 and 0x06 one time
153
     for (uint8_t reg = REG_MOTION; reg <= REG_DELTA_Y_H; reg++) {
179
     for (uint8_t reg = REG_MOTION; reg <= REG_DELTA_Y_H; reg++) {
174
     pmw_write_register(REG_SROM_ENABLE, 0x15);
200
     pmw_write_register(REG_SROM_ENABLE, 0x15);
175
 
201
 
176
     // Wait for at least 10 ms
202
     // Wait for at least 10 ms
177
-    sleep_ms(10);
203
+    busy_wait_ms(10);
178
 
204
 
179
     uint16_t data = pmw_read_register(REG_DATA_OUT_LOWER);
205
     uint16_t data = pmw_read_register(REG_DATA_OUT_LOWER);
180
-    data &= pmw_read_register(REG_DATA_OUT_UPPER) << 8;
206
+    data |= pmw_read_register(REG_DATA_OUT_UPPER) << 8;
181
     return data;
207
     return data;
182
 }
208
 }
183
 
209
 
204
     bi_decl(bi_1pin_with_name(PICO_DEFAULT_SPI_CSN_PIN, "SPI CS"));
230
     bi_decl(bi_1pin_with_name(PICO_DEFAULT_SPI_CSN_PIN, "SPI CS"));
205
 }
231
 }
206
 
232
 
233
+// TODO
234
+int16_t delta_x = 0, delta_y = 0;
235
+int convTwosComp(int b){
236
+    //Convert from 2's complement
237
+    if(b & 0x8000){
238
+        b = -1 * ((b ^ 0xffff) + 1);
239
+    }
240
+    return b;
241
+}
242
+
207
 static void pmw_handle_interrupt(void) {
243
 static void pmw_handle_interrupt(void) {
208
     struct pmw_motion_report motion_report = pmw_motion_read();
244
     struct pmw_motion_report motion_report = pmw_motion_read();
209
 
245
 
234
     }
270
     }
235
 #endif // PMW_IRQ_COUNTERS
271
 #endif // PMW_IRQ_COUNTERS
236
 
272
 
237
-    // TODO
273
+    delta_x += convTwosComp(motion_report.delta_x_l | (motion_report.delta_x_h << 8));
274
+    delta_y += convTwosComp(motion_report.delta_y_l | (motion_report.delta_y_h << 8));
238
 }
275
 }
239
 
276
 
240
 static void pmw_motion_irq(void) {
277
 static void pmw_motion_irq(void) {
241
     if (gpio_get_irq_event_mask(PMW_MOTION_PIN) & GPIO_IRQ_EDGE_FALL) {
278
     if (gpio_get_irq_event_mask(PMW_MOTION_PIN) & GPIO_IRQ_EDGE_FALL) {
242
         gpio_acknowledge_irq(PMW_MOTION_PIN, GPIO_IRQ_EDGE_FALL);
279
         gpio_acknowledge_irq(PMW_MOTION_PIN, GPIO_IRQ_EDGE_FALL);
243
-
244
         pmw_handle_interrupt();
280
         pmw_handle_interrupt();
245
     }
281
     }
246
 }
282
 }
252
 
288
 
253
     uint8_t prod_id = pmw_read_register(REG_PRODUCT_ID);
289
     uint8_t prod_id = pmw_read_register(REG_PRODUCT_ID);
254
     uint8_t inv_prod_id = pmw_read_register(REG_INVERSE_PRODUCT_ID);
290
     uint8_t inv_prod_id = pmw_read_register(REG_INVERSE_PRODUCT_ID);
255
-    uint8_t rev_id = pmw_read_register(REG_REVISION_ID);
256
     uint16_t srom_checksum = pmw_srom_checksum();
291
     uint16_t srom_checksum = pmw_srom_checksum();
257
 
292
 
293
+#ifdef PMW_PRINT_IDS
294
+    uint8_t rev_id = pmw_read_register(REG_REVISION_ID);
295
+
258
     debug("SROM ID: 0x%02X", srom_id);
296
     debug("SROM ID: 0x%02X", srom_id);
259
     debug("Product ID: 0x%02X", prod_id);
297
     debug("Product ID: 0x%02X", prod_id);
260
     debug("~ Prod. ID: 0x%02X", inv_prod_id);
298
     debug("~ Prod. ID: 0x%02X", inv_prod_id);
261
     debug("Revision ID: 0x%02X", rev_id);
299
     debug("Revision ID: 0x%02X", rev_id);
262
     debug("SROM CRC: 0x%04X", srom_checksum);
300
     debug("SROM CRC: 0x%04X", srom_checksum);
301
+#endif // PMW_PRINT_IDS
263
 
302
 
264
     if (prod_id != ((~inv_prod_id) & 0xFF)) {
303
     if (prod_id != ((~inv_prod_id) & 0xFF)) {
265
         debug("SPI communication error (0x%02X != ~0x%02X)", prod_id, inv_prod_id);
304
         debug("SPI communication error (0x%02X != ~0x%02X)", prod_id, inv_prod_id);
266
         return -1;
305
         return -1;
267
     }
306
     }
268
 
307
 
308
+    if (srom_id != pmw_fw_id) {
309
+        debug("PMW3360 error: invalid SROM ID (0x%02X != 0x%02X)", srom_id, pmw_fw_id);
310
+        return -1;
311
+    }
312
+
313
+    if (srom_checksum != pmw_fw_crc) {
314
+        debug("PMW3360 error: invalid SROM CRC (0x%04X != 0x%04X)", srom_checksum, pmw_fw_crc);
315
+        return -1;
316
+    }
317
+
269
     // Write 0x00 to Config2 register for wired mouse or 0x20 for wireless mouse design
318
     // Write 0x00 to Config2 register for wired mouse or 0x20 for wireless mouse design
270
-#ifdef FEATURE_WIRELESS
319
+#ifdef PMW_FEATURE_WIRELESS
271
     pmw_write_register(REG_CONFIG2, 0x20);
320
     pmw_write_register(REG_CONFIG2, 0x20);
272
-#else
321
+#else // ! PMW_FEATURE_WIRELESS
273
     pmw_write_register(REG_CONFIG2, 0x00);
322
     pmw_write_register(REG_CONFIG2, 0x00);
274
-#endif
323
+#endif // PMW_FEATURE_WIRELESS
275
 
324
 
276
     // setup MOTION pin interrupt to handle reading data
325
     // setup MOTION pin interrupt to handle reading data
277
     gpio_add_raw_irq_handler(PMW_MOTION_PIN, pmw_motion_irq);
326
     gpio_add_raw_irq_handler(PMW_MOTION_PIN, pmw_motion_irq);
327
+    gpio_set_irq_enabled(PMW_MOTION_PIN, GPIO_IRQ_EDGE_FALL, true);
328
+    irq_set_enabled(IO_IRQ_BANK0, true);
278
 
329
 
279
     // make MOTION pin available to picotool
330
     // make MOTION pin available to picotool
280
     bi_decl(bi_1pin_with_name(PMW_MOTION_PIN, "PMW3360 MOTION"));
331
     bi_decl(bi_1pin_with_name(PMW_MOTION_PIN, "PMW3360 MOTION"));

+ 10
- 4
firmware/src/usb_hid.c View File

29
 #include "usb_descriptors.h"
29
 #include "usb_descriptors.h"
30
 #include "usb_hid.h"
30
 #include "usb_hid.h"
31
 
31
 
32
+// TODO
33
+extern int16_t delta_x, delta_y;
34
+
32
 static void send_hid_report(uint8_t report_id, uint32_t btn) {
35
 static void send_hid_report(uint8_t report_id, uint32_t btn) {
33
     // skip if hid is not ready yet
36
     // skip if hid is not ready yet
34
     if ( !tud_hid_ready() ) return;
37
     if ( !tud_hid_ready() ) return;
55
 
58
 
56
         case REPORT_ID_MOUSE:
59
         case REPORT_ID_MOUSE:
57
         {
60
         {
58
-            int8_t const delta = 5;
59
-
60
             // no button, right + down, no scroll, no pan
61
             // no button, right + down, no scroll, no pan
61
-            tud_hid_mouse_report(REPORT_ID_MOUSE, 0x00, delta, delta, 0, 0);
62
+            tud_hid_mouse_report(REPORT_ID_MOUSE, 0x00, delta_x, delta_y, 0, 0);
63
+
64
+            // TODO
65
+            delta_x = 0;
66
+            delta_y = 0;
62
         }
67
         }
63
         break;
68
         break;
64
 
69
 
130
         tud_remote_wakeup();
135
         tud_remote_wakeup();
131
     } else {
136
     } else {
132
         // Send the 1st of report chain, the rest will be sent by tud_hid_report_complete_cb()
137
         // Send the 1st of report chain, the rest will be sent by tud_hid_report_complete_cb()
133
-        send_hid_report(REPORT_ID_KEYBOARD, btn);
138
+        //send_hid_report(REPORT_ID_KEYBOARD, btn);
139
+        send_hid_report(REPORT_ID_MOUSE, btn);
134
     }
140
     }
135
 }
141
 }
136
 
142
 

Loading…
Cancel
Save