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,6 +10,8 @@
10 10
 
11 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 15
 static const uint16_t pmw_fw_length = 4094;
14 16
 static const uint8_t pmw_fw_data[4094] = {
15 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,7 +21,9 @@
21 21
 #include "pico/binary_info.h"
22 22
 #include "hardware/spi.h"
23 23
 
24
+#define PMW_PRINT_IDS
24 25
 #define PMW_IRQ_COUNTERS
26
+//#define PMW_FEATURE_WIRELESS
25 27
 
26 28
 #include "log.h"
27 29
 #include "pmw3360_registers.h"
@@ -73,48 +75,68 @@ static inline void pmw_cs_deselect() {
73 75
 }
74 76
 
75 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 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 88
     pmw_cs_deselect();
82
-    sleep_ms(10);
89
+    busy_wait_us(100);
83 90
 }
84 91
 
85 92
 static uint8_t pmw_read_register(uint8_t reg) {
86
-    uint8_t buf = 0;
87
-    reg &= ~WRITE_BIT;
88 93
     pmw_cs_select();
94
+
95
+    reg &= ~WRITE_BIT;
89 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 101
     spi_read_blocking(spi_default, 0, &buf, 1);
102
+
103
+    busy_wait_us(1);
92 104
     pmw_cs_deselect();
93
-    sleep_ms(10);
105
+    busy_wait_us(20);
106
+
94 107
     return buf;
95 108
 }
96 109
 
97 110
 static void pmw_write_register_burst(uint8_t reg, const uint8_t *buf, uint16_t len) {
98
-    reg |= WRITE_BIT;
99 111
     pmw_cs_select();
112
+
113
+    reg |= WRITE_BIT;
100 114
     spi_write_blocking(spi_default, &reg, 1);
101
-    sleep_us(15);
115
+
116
+    busy_wait_us(15);
117
+
102 118
     for (uint16_t i = 0; i < len; i++) {
103 119
         spi_write_blocking(spi_default, buf + i, 1);
104
-        sleep_us(15);
120
+        busy_wait_us(15);
105 121
     }
122
+
106 123
     pmw_cs_deselect();
107
-    sleep_us(1);
124
+
125
+    busy_wait_us(1);
108 126
 }
109 127
 
110 128
 static void pmw_read_register_burst(uint8_t reg, uint8_t *buf, uint16_t len) {
111
-    reg &= ~WRITE_BIT;
112 129
     pmw_cs_select();
130
+
131
+    reg &= ~WRITE_BIT;
113 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 136
     spi_read_blocking(spi_default, 0, buf, len);
137
+
116 138
     pmw_cs_deselect();
117
-    sleep_us(1);
139
+    busy_wait_us(1);
118 140
 }
119 141
 
120 142
 static uint8_t pmw_srom_download(void) {
@@ -125,17 +147,17 @@ static uint8_t pmw_srom_download(void) {
125 147
     pmw_write_register(REG_SROM_ENABLE, 0x1D);
126 148
 
127 149
     // Wait for 10 ms
128
-    sleep_ms(10);
150
+    busy_wait_ms(10);
129 151
 
130 152
     // Write 0x18 to SROM_Enable register again to start SROM Download
131 153
     pmw_write_register(REG_SROM_ENABLE, 0x18);
132 154
 
133
-    sleep_us(120);
155
+    busy_wait_us(120);
134 156
 
135 157
     // Write SROM file into SROM_Load_Burst register, 1st data must start with SROM_Load_Burst address.
136 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 162
     // Read the SROM_ID register to verify the ID before any other register reads or writes
141 163
     uint8_t srom_id = pmw_read_register(REG_SROM_ID);
@@ -143,11 +165,15 @@ static uint8_t pmw_srom_download(void) {
143 165
 }
144 166
 
145 167
 static uint8_t pmw_power_up(void) {
168
+    pmw_cs_deselect();
169
+    pmw_cs_select();
170
+    pmw_cs_deselect();
171
+
146 172
     // Write 0x5A to Power_Up_Reset register
147 173
     pmw_write_register(REG_POWER_UP_RESET, 0x5A);
148 174
 
149 175
     // Wait for at least 50ms
150
-    sleep_ms(50);
176
+    busy_wait_ms(50);
151 177
 
152 178
     // Read from registers 0x02, 0x03, 0x04, 0x05 and 0x06 one time
153 179
     for (uint8_t reg = REG_MOTION; reg <= REG_DELTA_Y_H; reg++) {
@@ -174,10 +200,10 @@ static uint16_t pmw_srom_checksum(void) {
174 200
     pmw_write_register(REG_SROM_ENABLE, 0x15);
175 201
 
176 202
     // Wait for at least 10 ms
177
-    sleep_ms(10);
203
+    busy_wait_ms(10);
178 204
 
179 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 207
     return data;
182 208
 }
183 209
 
@@ -204,6 +230,16 @@ static void pmw_spi_init(void) {
204 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 243
 static void pmw_handle_interrupt(void) {
208 244
     struct pmw_motion_report motion_report = pmw_motion_read();
209 245
 
@@ -234,13 +270,13 @@ static void pmw_handle_interrupt(void) {
234 270
     }
235 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 277
 static void pmw_motion_irq(void) {
241 278
     if (gpio_get_irq_event_mask(PMW_MOTION_PIN) & GPIO_IRQ_EDGE_FALL) {
242 279
         gpio_acknowledge_irq(PMW_MOTION_PIN, GPIO_IRQ_EDGE_FALL);
243
-
244 280
         pmw_handle_interrupt();
245 281
     }
246 282
 }
@@ -252,29 +288,44 @@ int pmw_init(void) {
252 288
 
253 289
     uint8_t prod_id = pmw_read_register(REG_PRODUCT_ID);
254 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 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 296
     debug("SROM ID: 0x%02X", srom_id);
259 297
     debug("Product ID: 0x%02X", prod_id);
260 298
     debug("~ Prod. ID: 0x%02X", inv_prod_id);
261 299
     debug("Revision ID: 0x%02X", rev_id);
262 300
     debug("SROM CRC: 0x%04X", srom_checksum);
301
+#endif // PMW_PRINT_IDS
263 302
 
264 303
     if (prod_id != ((~inv_prod_id) & 0xFF)) {
265 304
         debug("SPI communication error (0x%02X != ~0x%02X)", prod_id, inv_prod_id);
266 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 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 320
     pmw_write_register(REG_CONFIG2, 0x20);
272
-#else
321
+#else // ! PMW_FEATURE_WIRELESS
273 322
     pmw_write_register(REG_CONFIG2, 0x00);
274
-#endif
323
+#endif // PMW_FEATURE_WIRELESS
275 324
 
276 325
     // setup MOTION pin interrupt to handle reading data
277 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 330
     // make MOTION pin available to picotool
280 331
     bi_decl(bi_1pin_with_name(PMW_MOTION_PIN, "PMW3360 MOTION"));

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

@@ -29,6 +29,9 @@
29 29
 #include "usb_descriptors.h"
30 30
 #include "usb_hid.h"
31 31
 
32
+// TODO
33
+extern int16_t delta_x, delta_y;
34
+
32 35
 static void send_hid_report(uint8_t report_id, uint32_t btn) {
33 36
     // skip if hid is not ready yet
34 37
     if ( !tud_hid_ready() ) return;
@@ -55,10 +58,12 @@ static void send_hid_report(uint8_t report_id, uint32_t btn) {
55 58
 
56 59
         case REPORT_ID_MOUSE:
57 60
         {
58
-            int8_t const delta = 5;
59
-
60 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 68
         break;
64 69
 
@@ -130,7 +135,8 @@ void hid_task(void) {
130 135
         tud_remote_wakeup();
131 136
     } else {
132 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