Browse Source

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

Thomas Buck 1 year ago
parent
commit
b6171fac1e
6 changed files with 101 additions and 24 deletions
  1. 4
    0
      firmware/include/config.h
  2. 2
    0
      firmware/include/pmw3360.h
  3. 27
    10
      firmware/src/console.c
  4. 29
    1
      firmware/src/main.c
  5. 36
    12
      firmware/src/pmw3360.c
  6. 3
    1
      firmware/src/usb_hid.c

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

@@ -12,4 +12,8 @@
12 12
 //#define PMW_FEATURE_WIRELESS
13 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 19
 #endif // __CONFIG_H__

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

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

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

@@ -13,6 +13,9 @@
13 13
 #include "console.h"
14 14
 
15 15
 #define CNSL_BUFF_SIZE 1024
16
+#define CNSL_REPEAT_MS 500
17
+
18
+//#define CNSL_REPEAT_PMW_STATUS_BY_DEFAULT
16 19
 
17 20
 static char cnsl_line_buff[CNSL_BUFF_SIZE + 1];
18 21
 static uint32_t cnsl_buff_pos = 0;
@@ -25,10 +28,12 @@ static uint32_t last_repeat_time = 0;
25 28
 
26 29
 static void cnsl_interpret(const char *line) {
27 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 37
         return;
33 38
     } else if (strcmp(line, "repeat") == 0) {
34 39
         if (!repeat_command) {
@@ -50,7 +55,7 @@ static void cnsl_interpret(const char *line) {
50 55
         print("   pmwr - reset PMW3360");
51 56
         print("  reset - reset back into this firmware");
52 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 59
         print("   help - print this message");
55 60
         print("Press Enter with no input to repeat last command.");
56 61
         print("Use repeat to continuously execute last command.");
@@ -75,8 +80,7 @@ static void cnsl_interpret(const char *line) {
75 80
         if ((num < 100) || (num > 12000)) {
76 81
             print("invalid cpi %llu, needs to be %u <= cpi <= %u", num, 100, 12000);
77 82
         } else {
78
-            num /= 100;
79
-            num -= 1;
83
+            num = PMW_CPI_TO_SENSE(num);
80 84
             print("setting cpi to 0x%02llX", num);
81 85
             pmw_set_sensitivity(num);
82 86
         }
@@ -92,9 +96,16 @@ static void cnsl_interpret(const char *line) {
92 96
 
93 97
 void cnsl_init(void) {
94 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 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 111
 static int32_t cnsl_find_line_end(void) {
@@ -107,15 +118,21 @@ static int32_t cnsl_find_line_end(void) {
107 118
 }
108 119
 
109 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 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 125
             print("repeating command \"%s\"", cnsl_repeated_command);
114 126
             cnsl_interpret(cnsl_repeated_command);
115 127
             print();
116 128
 
117 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,6 +3,7 @@
3 3
  */
4 4
 
5 5
 #include "pico/stdlib.h"
6
+#include "hardware/watchdog.h"
6 7
 
7 8
 #include "config.h"
8 9
 #include "util.h"
@@ -11,17 +12,44 @@
11 12
 #include "usb.h"
12 13
 #include "pmw3360.h"
13 14
 
15
+#define HEALTH_CHECK_INTERVAL_MS 500
16
+static uint32_t last_health_check = 0;
17
+
14 18
 int main(void) {
15 19
     heartbeat_init();
20
+
16 21
     cnsl_init();
17 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 36
     debug("init done");
20 37
 
21 38
     while (1) {
39
+        watchdog_update();
40
+
22 41
         heartbeat_run();
23 42
         usb_run();
24 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 55
     return 0;

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

@@ -68,14 +68,14 @@ struct pmw_motion pmw_get(void) {
68 68
     r.delta_y = 0;
69 69
 
70 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 73
         r.delta_x = delta_x;
74 74
         r.delta_y = delta_y;
75 75
         delta_x = 0;
76 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 81
     return r;
@@ -288,8 +288,8 @@ static void pmw_handle_interrupt(void) {
288 288
 }
289 289
 
290 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 293
         pmw_handle_interrupt();
294 294
     }
295 295
 }
@@ -314,7 +314,37 @@ uint8_t pmw_get_sensitivity(void) {
314 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 346
 int pmw_init(void) {
347
+    pmw_irq_stop();
318 348
     pmw_spi_init();
319 349
 
320 350
     uint8_t srom_id = pmw_power_up();
@@ -357,18 +387,12 @@ int pmw_init(void) {
357 387
 
358 388
     // Set sensitivity for each axis
359 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 392
     // Set lift-detection threshold to 3mm (max)
363 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 397
     return 0;
374 398
 }

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

@@ -60,7 +60,9 @@ static void send_hid_report(uint8_t report_id, uint32_t btn) {
60 60
             struct pmw_motion mouse = pmw_get();
61 61
             if (mouse.motion) {
62 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 68
         break;

Loading…
Cancel
Save