Browse Source

enable watchdog. trigger pmw irq on low level, fixes hanging mouse.

Thomas Buck 1 year ago
parent
commit
b6171fac1e

+ 4
- 0
firmware/include/config.h View File

12
 //#define PMW_FEATURE_WIRELESS
12
 //#define PMW_FEATURE_WIRELESS
13
 //#define DISABLE_CDC_DTR_CHECK
13
 //#define DISABLE_CDC_DTR_CHECK
14
 
14
 
15
+#define INVERT_MOUSE_X_AXIS false
16
+#define INVERT_MOUSE_Y_AXIS true
17
+#define DEFAULT_MOUSE_SENSITIVITY PMW_CPI_TO_SENSE(800)
18
+
15
 #endif // __CONFIG_H__
19
 #endif // __CONFIG_H__

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

12
 };
12
 };
13
 
13
 
14
 int pmw_init(void);
14
 int pmw_init(void);
15
+bool pmw_is_alive(void);
15
 
16
 
16
 struct pmw_motion pmw_get(void);
17
 struct pmw_motion pmw_get(void);
17
 
18
 
27
 void pmw_set_sensitivity(uint8_t sens);
28
 void pmw_set_sensitivity(uint8_t sens);
28
 uint8_t pmw_get_sensitivity(void);
29
 uint8_t pmw_get_sensitivity(void);
29
 #define PMW_SENSE_TO_CPI(sense) (100 + (sense * 100))
30
 #define PMW_SENSE_TO_CPI(sense) (100 + (sense * 100))
31
+#define PMW_CPI_TO_SENSE(cpi) ((cpi / 100) - 1)
30
 
32
 
31
 void pmw_print_status(void);
33
 void pmw_print_status(void);
32
 
34
 

+ 27
- 10
firmware/src/console.c View File

13
 #include "console.h"
13
 #include "console.h"
14
 
14
 
15
 #define CNSL_BUFF_SIZE 1024
15
 #define CNSL_BUFF_SIZE 1024
16
+#define CNSL_REPEAT_MS 500
17
+
18
+//#define CNSL_REPEAT_PMW_STATUS_BY_DEFAULT
16
 
19
 
17
 static char cnsl_line_buff[CNSL_BUFF_SIZE + 1];
20
 static char cnsl_line_buff[CNSL_BUFF_SIZE + 1];
18
 static uint32_t cnsl_buff_pos = 0;
21
 static uint32_t cnsl_buff_pos = 0;
25
 
28
 
26
 static void cnsl_interpret(const char *line) {
29
 static void cnsl_interpret(const char *line) {
27
     if (strlen(line) == 0) {
30
     if (strlen(line) == 0) {
28
-        // repeat last command once
29
-        print("repeating command \"%s\"", cnsl_last_command);
30
-        cnsl_interpret(cnsl_last_command);
31
-        print();
31
+        if ((strlen(cnsl_last_command) > 0) && (strcmp(cnsl_last_command, "repeat") != 0)) {
32
+            // repeat last command once
33
+            print("repeating command \"%s\"", cnsl_last_command);
34
+            cnsl_interpret(cnsl_last_command);
35
+            print();
36
+        }
32
         return;
37
         return;
33
     } else if (strcmp(line, "repeat") == 0) {
38
     } else if (strcmp(line, "repeat") == 0) {
34
         if (!repeat_command) {
39
         if (!repeat_command) {
50
         print("   pmwr - reset PMW3360");
55
         print("   pmwr - reset PMW3360");
51
         print("  reset - reset back into this firmware");
56
         print("  reset - reset back into this firmware");
52
         print("   \\x18 - reset to bootloader");
57
         print("   \\x18 - reset to bootloader");
53
-        print(" repeat - repeat last command once per second");
58
+        print(" repeat - repeat last command every %d milliseconds", CNSL_REPEAT_MS);
54
         print("   help - print this message");
59
         print("   help - print this message");
55
         print("Press Enter with no input to repeat last command.");
60
         print("Press Enter with no input to repeat last command.");
56
         print("Use repeat to continuously execute last command.");
61
         print("Use repeat to continuously execute last command.");
75
         if ((num < 100) || (num > 12000)) {
80
         if ((num < 100) || (num > 12000)) {
76
             print("invalid cpi %llu, needs to be %u <= cpi <= %u", num, 100, 12000);
81
             print("invalid cpi %llu, needs to be %u <= cpi <= %u", num, 100, 12000);
77
         } else {
82
         } else {
78
-            num /= 100;
79
-            num -= 1;
83
+            num = PMW_CPI_TO_SENSE(num);
80
             print("setting cpi to 0x%02llX", num);
84
             print("setting cpi to 0x%02llX", num);
81
             pmw_set_sensitivity(num);
85
             pmw_set_sensitivity(num);
82
         }
86
         }
92
 
96
 
93
 void cnsl_init(void) {
97
 void cnsl_init(void) {
94
     cnsl_buff_pos = 0;
98
     cnsl_buff_pos = 0;
95
-    for (int i = 0; i < sizeof(cnsl_line_buff); i++) {
99
+    for (int i = 0; i < CNSL_BUFF_SIZE + 1; i++) {
96
         cnsl_line_buff[i] = '\0';
100
         cnsl_line_buff[i] = '\0';
101
+        cnsl_last_command[i] = '\0';
102
+        cnsl_repeated_command[i] = '\0';
97
     }
103
     }
104
+
105
+#ifdef CNSL_REPEAT_PMW_STATUS_BY_DEFAULT
106
+    strcpy(cnsl_repeated_command, "pmws");
107
+    repeat_command = true;
108
+#endif // CNSL_REPEAT_PMW_STATUS_BY_DEFAULT
98
 }
109
 }
99
 
110
 
100
 static int32_t cnsl_find_line_end(void) {
111
 static int32_t cnsl_find_line_end(void) {
107
 }
118
 }
108
 
119
 
109
 void cnsl_run(void) {
120
 void cnsl_run(void) {
110
-    if (repeat_command) {
121
+    if (repeat_command && (strlen(cnsl_repeated_command) > 0)
122
+            && (strcmp(cnsl_repeated_command, "repeat") != 0)) {
111
         uint32_t now = to_ms_since_boot(get_absolute_time());
123
         uint32_t now = to_ms_since_boot(get_absolute_time());
112
-        if (now >= (last_repeat_time + 1000)) {
124
+        if (now >= (last_repeat_time + CNSL_REPEAT_MS)) {
113
             print("repeating command \"%s\"", cnsl_repeated_command);
125
             print("repeating command \"%s\"", cnsl_repeated_command);
114
             cnsl_interpret(cnsl_repeated_command);
126
             cnsl_interpret(cnsl_repeated_command);
115
             print();
127
             print();
116
 
128
 
117
             last_repeat_time = now;
129
             last_repeat_time = now;
118
         }
130
         }
131
+    } else {
132
+        if (repeat_command) {
133
+            print("nothing to repeat");
134
+        }
135
+        repeat_command = false;
119
     }
136
     }
120
 }
137
 }
121
 
138
 

+ 29
- 1
firmware/src/main.c View File

3
  */
3
  */
4
 
4
 
5
 #include "pico/stdlib.h"
5
 #include "pico/stdlib.h"
6
+#include "hardware/watchdog.h"
6
 
7
 
7
 #include "config.h"
8
 #include "config.h"
8
 #include "util.h"
9
 #include "util.h"
11
 #include "usb.h"
12
 #include "usb.h"
12
 #include "pmw3360.h"
13
 #include "pmw3360.h"
13
 
14
 
15
+#define HEALTH_CHECK_INTERVAL_MS 500
16
+static uint32_t last_health_check = 0;
17
+
14
 int main(void) {
18
 int main(void) {
15
     heartbeat_init();
19
     heartbeat_init();
20
+
16
     cnsl_init();
21
     cnsl_init();
17
     usb_init();
22
     usb_init();
18
-    pmw_init();
23
+
24
+    if (watchdog_caused_reboot()) {
25
+        debug("reset by watchdog");
26
+    }
27
+
28
+    if (pmw_init() != 0) {
29
+        debug("error initializing PMW3360");
30
+    }
31
+
32
+    // trigger after 500ms
33
+    // (PMW3360 initialization takes ~160ms)
34
+    watchdog_enable(500, 1);
35
+
19
     debug("init done");
36
     debug("init done");
20
 
37
 
21
     while (1) {
38
     while (1) {
39
+        watchdog_update();
40
+
22
         heartbeat_run();
41
         heartbeat_run();
23
         usb_run();
42
         usb_run();
24
         cnsl_run();
43
         cnsl_run();
44
+
45
+        uint32_t now = to_ms_since_boot(get_absolute_time());
46
+        if (now >= (last_health_check + HEALTH_CHECK_INTERVAL_MS)) {
47
+            last_health_check = now;
48
+            if (!pmw_is_alive()) {
49
+                debug("PMW3360 is dead. resetting!");
50
+                while (1) { }
51
+            }
52
+        }
25
     }
53
     }
26
 
54
 
27
     return 0;
55
     return 0;

+ 36
- 12
firmware/src/pmw3360.c View File

68
     r.delta_y = 0;
68
     r.delta_y = 0;
69
 
69
 
70
     if (r.motion) {
70
     if (r.motion) {
71
-        gpio_set_irq_enabled(PMW_MOTION_PIN, GPIO_IRQ_EDGE_FALL, false);
71
+        gpio_set_irq_enabled(PMW_MOTION_PIN, GPIO_IRQ_LEVEL_LOW, false);
72
 
72
 
73
         r.delta_x = delta_x;
73
         r.delta_x = delta_x;
74
         r.delta_y = delta_y;
74
         r.delta_y = delta_y;
75
         delta_x = 0;
75
         delta_x = 0;
76
         delta_y = 0;
76
         delta_y = 0;
77
 
77
 
78
-        gpio_set_irq_enabled(PMW_MOTION_PIN, GPIO_IRQ_EDGE_FALL, true);
78
+        gpio_set_irq_enabled(PMW_MOTION_PIN, GPIO_IRQ_LEVEL_LOW, true);
79
     }
79
     }
80
 
80
 
81
     return r;
81
     return r;
288
 }
288
 }
289
 
289
 
290
 static void pmw_motion_irq(void) {
290
 static void pmw_motion_irq(void) {
291
-    if (gpio_get_irq_event_mask(PMW_MOTION_PIN) & GPIO_IRQ_EDGE_FALL) {
292
-        gpio_acknowledge_irq(PMW_MOTION_PIN, GPIO_IRQ_EDGE_FALL);
291
+    if (gpio_get_irq_event_mask(PMW_MOTION_PIN) & GPIO_IRQ_LEVEL_LOW) {
292
+        gpio_acknowledge_irq(PMW_MOTION_PIN, GPIO_IRQ_LEVEL_LOW);
293
         pmw_handle_interrupt();
293
         pmw_handle_interrupt();
294
     }
294
     }
295
 }
295
 }
314
     return sense_y;
314
     return sense_y;
315
 }
315
 }
316
 
316
 
317
+static void pmw_irq_init(void) {
318
+    // setup MOTION pin interrupt to handle reading data
319
+    gpio_add_raw_irq_handler(PMW_MOTION_PIN, pmw_motion_irq);
320
+    gpio_set_irq_enabled(PMW_MOTION_PIN, GPIO_IRQ_LEVEL_LOW, true);
321
+    irq_set_enabled(IO_IRQ_BANK0, true);
322
+
323
+    // make MOTION pin available to picotool
324
+    bi_decl(bi_1pin_with_name(PMW_MOTION_PIN, "PMW3360 MOTION"));
325
+}
326
+
327
+static void pmw_irq_stop(void) {
328
+    gpio_set_irq_enabled(PMW_MOTION_PIN, GPIO_IRQ_LEVEL_LOW, false);
329
+    irq_set_enabled(IO_IRQ_BANK0, false);
330
+}
331
+
332
+bool pmw_is_alive(void) {
333
+    bool r = true;
334
+    gpio_set_irq_enabled(PMW_MOTION_PIN, GPIO_IRQ_LEVEL_LOW, false);
335
+
336
+    uint8_t prod_id = pmw_read_register(REG_PRODUCT_ID);
337
+    uint8_t inv_prod_id = pmw_read_register(REG_INVERSE_PRODUCT_ID);
338
+    if (prod_id != ((~inv_prod_id) & 0xFF)) {
339
+        r = false;
340
+    }
341
+
342
+    gpio_set_irq_enabled(PMW_MOTION_PIN, GPIO_IRQ_LEVEL_LOW, true);
343
+    return r;
344
+}
345
+
317
 int pmw_init(void) {
346
 int pmw_init(void) {
347
+    pmw_irq_stop();
318
     pmw_spi_init();
348
     pmw_spi_init();
319
 
349
 
320
     uint8_t srom_id = pmw_power_up();
350
     uint8_t srom_id = pmw_power_up();
357
 
387
 
358
     // Set sensitivity for each axis
388
     // Set sensitivity for each axis
359
     pmw_write_register(REG_CONFIG2, pmw_read_register(REG_CONFIG2) | 0x04);
389
     pmw_write_register(REG_CONFIG2, pmw_read_register(REG_CONFIG2) | 0x04);
360
-    pmw_set_sensitivity(0x31); // default: 5000cpi
390
+    pmw_set_sensitivity(DEFAULT_MOUSE_SENSITIVITY);
361
 
391
 
362
     // Set lift-detection threshold to 3mm (max)
392
     // Set lift-detection threshold to 3mm (max)
363
     pmw_write_register(REG_LIFT_CONFIG, 0x03);
393
     pmw_write_register(REG_LIFT_CONFIG, 0x03);
364
 
394
 
365
-    // setup MOTION pin interrupt to handle reading data
366
-    gpio_add_raw_irq_handler(PMW_MOTION_PIN, pmw_motion_irq);
367
-    gpio_set_irq_enabled(PMW_MOTION_PIN, GPIO_IRQ_EDGE_FALL, true);
368
-    irq_set_enabled(IO_IRQ_BANK0, true);
369
-
370
-    // make MOTION pin available to picotool
371
-    bi_decl(bi_1pin_with_name(PMW_MOTION_PIN, "PMW3360 MOTION"));
395
+    pmw_irq_init();
372
 
396
 
373
     return 0;
397
     return 0;
374
 }
398
 }

+ 3
- 1
firmware/src/usb_hid.c View File

60
             struct pmw_motion mouse = pmw_get();
60
             struct pmw_motion mouse = pmw_get();
61
             if (mouse.motion) {
61
             if (mouse.motion) {
62
                 tud_hid_mouse_report(REPORT_ID_MOUSE, 0x00,
62
                 tud_hid_mouse_report(REPORT_ID_MOUSE, 0x00,
63
-                        -mouse.delta_x, -mouse.delta_y, 0, 0);
63
+                        mouse.delta_x * (INVERT_MOUSE_X_AXIS ? -1 : 1),
64
+                        mouse.delta_y * (INVERT_MOUSE_Y_AXIS ? -1 : 1),
65
+                        0, 0);
64
             }
66
             }
65
         }
67
         }
66
         break;
68
         break;

Loading…
Cancel
Save