Browse Source

fix debounce. add handling of different buttons. implement combined middle mouse and scroll lock button.

Thomas Buck 1 year ago
parent
commit
93c3178d27

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

16
 #define INVERT_MOUSE_Y_AXIS true
16
 #define INVERT_MOUSE_Y_AXIS true
17
 #define DEFAULT_MOUSE_SENSITIVITY PMW_CPI_TO_SENSE(500)
17
 #define DEFAULT_MOUSE_SENSITIVITY PMW_CPI_TO_SENSE(500)
18
 
18
 
19
+#define INVERT_SCROLL_X_AXIS false
20
+#define INVERT_SCROLL_Y_AXIS false
21
+#define MIN_SCROLL_SUPPRESS_CLICK 10
22
+
19
 #define DEBOUNCE_DELAY_MS 5
23
 #define DEBOUNCE_DELAY_MS 5
20
 
24
 
21
 #endif // __CONFIG_H__
25
 #endif // __CONFIG_H__

+ 21
- 2
firmware/include/controls.h View File

5
 #ifndef __CONTROLS_H__
5
 #ifndef __CONTROLS_H__
6
 #define __CONTROLS_H__
6
 #define __CONTROLS_H__
7
 
7
 
8
-void controls_new(int id, bool state);
9
-bool controls_button_read(void);
8
+enum mouse_buttons {
9
+    MOUSE_LEFT = 0,
10
+    MOUSE_MIDDLE,
11
+    MOUSE_RIGHT,
12
+    MOUSE_BACK,
13
+    MOUSE_FORWARD,
14
+    MOUSE_BUTTONS_COUNT
15
+};
16
+
17
+struct mouse_state {
18
+    bool changed;
19
+    bool button[MOUSE_BUTTONS_COUNT];
20
+    int16_t delta_x, delta_y;
21
+    int16_t scroll_x, scroll_y;
22
+    bool scroll_lock, fake_middle;
23
+};
24
+
25
+void controls_init(void);
26
+
27
+void controls_mouse_new(int id, bool state);
28
+struct mouse_state controls_mouse_read(void);
10
 
29
 
11
 #endif // __CONTROLS_H__
30
 #endif // __CONTROLS_H__
12
 
31
 

+ 3
- 0
firmware/include/log.h View File

18
 #define println(fmt, ...) debug_log(false, fmt "\r\n", ##__VA_ARGS__)
18
 #define println(fmt, ...) debug_log(false, fmt "\r\n", ##__VA_ARGS__)
19
 
19
 
20
 void debug_log(bool log, const char *format, ...) __attribute__((format(printf, 2, 3)));
20
 void debug_log(bool log, const char *format, ...) __attribute__((format(printf, 2, 3)));
21
+void debug_wait_input(const char *format, ...) __attribute__((format(printf, 1, 2)));
21
 
22
 
22
 void log_dump_to_usb(void);
23
 void log_dump_to_usb(void);
23
 void log_dump_to_disk(void);
24
 void log_dump_to_disk(void);
24
 
25
 
26
+void debug_handle_input(char *buff, uint32_t len);
27
+
25
 #endif // __LOG_H__
28
 #endif // __LOG_H__

+ 1
- 0
firmware/include/usb_cdc.h View File

6
 #define __USB_CDC_H__
6
 #define __USB_CDC_H__
7
 
7
 
8
 void usb_cdc_write(const char *buf, uint32_t count);
8
 void usb_cdc_write(const char *buf, uint32_t count);
9
+void usb_cdc_set_reroute(bool reroute);
9
 
10
 
10
 #endif // __USB_CDC_H__
11
 #endif // __USB_CDC_H__

+ 12
- 5
firmware/src/buttons.c View File

13
 
13
 
14
 struct button_state {
14
 struct button_state {
15
     uint32_t last_time;
15
     uint32_t last_time;
16
-    bool last_state;
16
+    bool current_state, last_state;
17
 };
17
 };
18
 
18
 
19
 struct button_state buttons[BUTTONS_COUNT];
19
 struct button_state buttons[BUTTONS_COUNT];
21
 void buttons_init(void) {
21
 void buttons_init(void) {
22
     for (int i = 0; i < BUTTONS_COUNT; i++) {
22
     for (int i = 0; i < BUTTONS_COUNT; i++) {
23
         gpio_init(gpio_num[i]);
23
         gpio_init(gpio_num[i]);
24
+        gpio_set_dir(gpio_num[i], GPIO_IN);
24
         gpio_pull_up(gpio_num[i]);
25
         gpio_pull_up(gpio_num[i]);
26
+
27
+        buttons[i].last_time = 0;
28
+        buttons[i].current_state = false;
29
+        buttons[i].last_state = false;
25
     }
30
     }
26
 }
31
 }
27
 
32
 
28
 void buttons_run(void) {
33
 void buttons_run(void) {
29
     for (int i = 0; i < BUTTONS_COUNT; i++) {
34
     for (int i = 0; i < BUTTONS_COUNT; i++) {
30
-        bool state = gpio_get(gpio_num[i]);
35
+        bool state = !gpio_get(gpio_num[i]);
31
         uint32_t now = to_ms_since_boot(get_absolute_time());
36
         uint32_t now = to_ms_since_boot(get_absolute_time());
32
 
37
 
33
         if (state != buttons[i].last_state) {
38
         if (state != buttons[i].last_state) {
35
         }
40
         }
36
 
41
 
37
         if ((now - buttons[i].last_time) > DEBOUNCE_DELAY_MS) {
42
         if ((now - buttons[i].last_time) > DEBOUNCE_DELAY_MS) {
38
-            if (state != buttons[i].last_state) {
39
-                buttons[i].last_state = state;
40
-                controls_new(i, state);
43
+            if (state != buttons[i].current_state) {
44
+                buttons[i].current_state = state;
45
+                controls_mouse_new(i, state);
41
             }
46
             }
42
         }
47
         }
48
+
49
+        buttons[i].last_state = state;
43
     }
50
     }
44
 }
51
 }
45
 
52
 

+ 103
- 6
firmware/src/controls.c View File

2
  * controls.c
2
  * controls.c
3
  */
3
  */
4
 
4
 
5
+#include <stdlib.h>
6
+
5
 #include "pico/stdlib.h"
7
 #include "pico/stdlib.h"
6
 
8
 
7
 #include "config.h"
9
 #include "config.h"
10
+#include "log.h"
11
+#include "pmw3360.h"
8
 #include "controls.h"
12
 #include "controls.h"
9
 
13
 
10
-static bool button_state = false;
14
+static struct mouse_state mouse, last_mouse;
15
+static uint64_t scroll_sum = 0;
16
+
17
+void controls_init(void) {
18
+    for (int i = 0; i < MOUSE_BUTTONS_COUNT; i++) {
19
+        mouse.button[i] = false;
20
+    }
21
+    mouse.changed = false;
22
+    mouse.delta_x = 0;
23
+    mouse.delta_y = 0;
24
+    mouse.scroll_x = 0;
25
+    mouse.scroll_y = 0;
26
+    mouse.scroll_lock = false;
27
+    mouse.fake_middle = false;
28
+
29
+    last_mouse = mouse;
30
+}
31
+
32
+void controls_mouse_new(int id, bool state) {
33
+    //debug("button %d %s", id, state ? "pressed" : "released");
11
 
34
 
12
-void controls_new(int id, bool state) {
13
-    (void)id;
14
-    button_state = state;
35
+    switch (id) {
36
+    case 0:
37
+        mouse.button[MOUSE_BACK] = state;
38
+        break;
39
+
40
+    case 1:
41
+        mouse.scroll_lock = state;
42
+        break;
43
+
44
+    case 2:
45
+        mouse.button[MOUSE_LEFT] = state;
46
+        break;
47
+
48
+    case 3:
49
+        mouse.button[MOUSE_RIGHT] = state;
50
+        break;
51
+    }
15
 }
52
 }
16
 
53
 
17
-bool controls_button_read(void) {
18
-    return button_state;
54
+static bool mouse_state_changed(struct mouse_state a, struct mouse_state b) {
55
+    for (int i = 0; i < MOUSE_BUTTONS_COUNT; i++) {
56
+        if (a.button[i] != b.button[i]) {
57
+            return true;
58
+        }
59
+    }
60
+
61
+    if ((a.delta_x != b.delta_x)
62
+            || (a.delta_y != b.delta_y)
63
+            || (a.scroll_x != b.scroll_x)
64
+            || (a.scroll_y != b.scroll_y)) {
65
+        return true;
66
+    }
67
+
68
+    return false;
69
+}
70
+
71
+struct mouse_state controls_mouse_read(void) {
72
+    struct pmw_motion motion = pmw_get();
73
+
74
+    if (motion.motion) {
75
+        mouse.delta_x = motion.delta_x;
76
+        mouse.delta_y = motion.delta_y;
77
+    }
78
+
79
+    if (mouse.scroll_lock) {
80
+        mouse.scroll_x = mouse.delta_x;
81
+        mouse.scroll_y = mouse.delta_y;
82
+        mouse.delta_x = 0;
83
+        mouse.delta_y = 0;
84
+
85
+        scroll_sum += abs(mouse.scroll_x);
86
+        scroll_sum += abs(mouse.scroll_y);
87
+    } else {
88
+        mouse.scroll_x = 0;
89
+        mouse.scroll_y = 0;
90
+    }
91
+
92
+    if (mouse.fake_middle) {
93
+        mouse.button[MOUSE_MIDDLE] = false;
94
+        mouse.fake_middle = false;
95
+    }
96
+
97
+    if (!mouse.scroll_lock && last_mouse.scroll_lock) {
98
+        // middle mouse button was held and has now been released
99
+        if (scroll_sum < MIN_SCROLL_SUPPRESS_CLICK) {
100
+            // fake middle mouse click, user was not scrolling
101
+            mouse.button[MOUSE_MIDDLE] = true;
102
+            mouse.fake_middle = true;
103
+        }
104
+    }
105
+
106
+    if (mouse_state_changed(mouse, last_mouse)
107
+            || (mouse.delta_x != 0)
108
+            || (mouse.delta_y != 0)
109
+            || (mouse.scroll_x != 0)
110
+            || (mouse.scroll_y != 0)) {
111
+        mouse.changed = true;
112
+    }
113
+
114
+    last_mouse = mouse;
115
+    return mouse;
19
 }
116
 }
20
 
117
 

+ 39
- 4
firmware/src/log.c View File

4
 
4
 
5
 #include <stdarg.h>
5
 #include <stdarg.h>
6
 #include <stdio.h>
6
 #include <stdio.h>
7
+
7
 #include "pico/stdlib.h"
8
 #include "pico/stdlib.h"
9
+#include "hardware/watchdog.h"
8
 #include "ff.h"
10
 #include "ff.h"
9
 
11
 
10
 #include "config.h"
12
 #include "config.h"
13
+#include "usb.h"
11
 #include "usb_cdc.h"
14
 #include "usb_cdc.h"
12
 #include "log.h"
15
 #include "log.h"
13
 
16
 
14
-char log_buff[4096];
15
-size_t head = 0, tail = 0;
16
-bool full = false;
17
+static char log_buff[4096];
18
+static size_t head = 0, tail = 0;
19
+static bool full = false;
20
+static bool got_input = false;
17
 
21
 
18
 static void add_to_log(const char *buff, int len) {
22
 static void add_to_log(const char *buff, int len) {
19
     for (int i = 0; i < len; i++) {
23
     for (int i = 0; i < len; i++) {
103
 }
107
 }
104
 
108
 
105
 void debug_log(bool log, const char* format, ...) {
109
 void debug_log(bool log, const char* format, ...) {
106
-    static char line_buff[256];
110
+    static char line_buff[512];
107
 
111
 
108
     va_list args;
112
     va_list args;
109
     va_start(args, format);
113
     va_start(args, format);
118
         }
122
         }
119
     }
123
     }
120
 }
124
 }
125
+
126
+void debug_handle_input(char *buff, uint32_t len) {
127
+    (void)buff;
128
+
129
+    if (len > 0) {
130
+        got_input = true;
131
+    }
132
+}
133
+
134
+void debug_wait_input(const char *format, ...) {
135
+    static char line_buff[512];
136
+
137
+    va_list args;
138
+    va_start(args, format);
139
+    int l = format_debug_log(line_buff, sizeof(line_buff), format, args);
140
+    va_end(args);
141
+
142
+    if ((l > 0) && (l <= (int)sizeof(line_buff))) {
143
+        usb_cdc_write(line_buff, l);
144
+    }
145
+
146
+    got_input = false;
147
+    usb_cdc_set_reroute(true);
148
+
149
+    while (!got_input) {
150
+        watchdog_update();
151
+        usb_run();
152
+    }
153
+
154
+    usb_cdc_set_reroute(false);
155
+}

+ 9
- 2
firmware/src/main.c View File

13
 #include "pmw3360.h"
13
 #include "pmw3360.h"
14
 #include "fat_disk.h"
14
 #include "fat_disk.h"
15
 #include "buttons.h"
15
 #include "buttons.h"
16
+#include "controls.h"
16
 
17
 
17
 int main(void) {
18
 int main(void) {
18
     heartbeat_init();
19
     heartbeat_init();
19
     buttons_init();
20
     buttons_init();
21
+    controls_init();
20
 
22
 
21
     cnsl_init();
23
     cnsl_init();
22
     usb_init();
24
     usb_init();
29
     fat_disk_init();
31
     fat_disk_init();
30
 
32
 
31
     debug("pmw_init");
33
     debug("pmw_init");
34
+    bool use_pmw = true;
32
     if (pmw_init() != 0) {
35
     if (pmw_init() != 0) {
33
         debug("error initializing PMW3360");
36
         debug("error initializing PMW3360");
37
+        use_pmw = false;
34
     }
38
     }
35
 
39
 
36
     // trigger after 500ms
40
     // trigger after 500ms
37
     // (PMW3360 initialization takes ~160ms)
41
     // (PMW3360 initialization takes ~160ms)
38
-    //watchdog_enable(500, 1);
42
+    watchdog_enable(500, 1);
39
 
43
 
40
     debug("init done");
44
     debug("init done");
41
 
45
 
46
         buttons_run();
50
         buttons_run();
47
         usb_run();
51
         usb_run();
48
         cnsl_run();
52
         cnsl_run();
49
-        pmw_run();
53
+
54
+        if (use_pmw) {
55
+            pmw_run();
56
+        }
50
     }
57
     }
51
 
58
 
52
     return 0;
59
     return 0;

+ 1
- 1
firmware/src/pmw3360.c View File

345
         // setup MOTION pin interrupt to handle reading data
345
         // setup MOTION pin interrupt to handle reading data
346
         gpio_add_raw_irq_handler(PMW_MOTION_PIN, pmw_motion_irq);
346
         gpio_add_raw_irq_handler(PMW_MOTION_PIN, pmw_motion_irq);
347
         irq_set_enabled(IO_IRQ_BANK0, true);
347
         irq_set_enabled(IO_IRQ_BANK0, true);
348
-	first_init = true;
348
+        first_init = true;
349
     }
349
     }
350
 
350
 
351
     pmw_irq_start();
351
     pmw_irq_start();

+ 8
- 0
firmware/src/usb_cdc.c View File

33
 #include "usb_descriptors.h"
33
 #include "usb_descriptors.h"
34
 #include "usb_cdc.h"
34
 #include "usb_cdc.h"
35
 
35
 
36
+static bool reroute_cdc_debug = false;
37
+
36
 void usb_cdc_write(const char *buf, uint32_t count) {
38
 void usb_cdc_write(const char *buf, uint32_t count) {
37
 #ifndef DISABLE_CDC_DTR_CHECK
39
 #ifndef DISABLE_CDC_DTR_CHECK
38
     if (!tud_cdc_connected()) {
40
     if (!tud_cdc_connected()) {
59
     }
61
     }
60
 }
62
 }
61
 
63
 
64
+void usb_cdc_set_reroute(bool reroute) {
65
+    reroute_cdc_debug = reroute;
66
+}
67
+
62
 void cdc_task(void) {
68
 void cdc_task(void) {
63
     const uint32_t cdc_buf_len = 64;
69
     const uint32_t cdc_buf_len = 64;
64
 
70
 
70
             // ASCII 0x18 = CAN (cancel)
76
             // ASCII 0x18 = CAN (cancel)
71
             debug("switching to bootloader");
77
             debug("switching to bootloader");
72
             reset_to_bootloader();
78
             reset_to_bootloader();
79
+        } else if (reroute_cdc_debug) {
80
+            debug_handle_input(buf, count);
73
         } else {
81
         } else {
74
             // echo back
82
             // echo back
75
             usb_cdc_write(buf, count);
83
             usb_cdc_write(buf, count);

+ 17
- 6
firmware/src/usb_hid.c View File

27
 #include "tusb.h"
27
 #include "tusb.h"
28
 
28
 
29
 #include "config.h"
29
 #include "config.h"
30
-#include "pmw3360.h"
31
 #include "controls.h"
30
 #include "controls.h"
32
 #include "usb_descriptors.h"
31
 #include "usb_descriptors.h"
33
 #include "usb_hid.h"
32
 #include "usb_hid.h"
58
 
57
 
59
         case REPORT_ID_MOUSE:
58
         case REPORT_ID_MOUSE:
60
         {
59
         {
61
-            struct pmw_motion mouse = pmw_get();
60
+            struct mouse_state mouse = controls_mouse_read();
61
+
62
             uint8_t buttons = 0x00;
62
             uint8_t buttons = 0x00;
63
-            if (btn) {
63
+            if (mouse.button[MOUSE_LEFT]) {
64
                 buttons |= MOUSE_BUTTON_LEFT;
64
                 buttons |= MOUSE_BUTTON_LEFT;
65
             }
65
             }
66
-            if (mouse.motion) {
66
+            if (mouse.button[MOUSE_RIGHT]) {
67
+                buttons |= MOUSE_BUTTON_RIGHT;
68
+            }
69
+            if (mouse.button[MOUSE_MIDDLE]) {
70
+                buttons |= MOUSE_BUTTON_MIDDLE;
71
+            }
72
+            if (mouse.button[MOUSE_BACK]) {
73
+                buttons |= MOUSE_BUTTON_BACKWARD;
74
+            }
75
+
76
+            if (mouse.changed) {
67
                 tud_hid_mouse_report(REPORT_ID_MOUSE, buttons,
77
                 tud_hid_mouse_report(REPORT_ID_MOUSE, buttons,
68
                         mouse.delta_x * (INVERT_MOUSE_X_AXIS ? -1 : 1),
78
                         mouse.delta_x * (INVERT_MOUSE_X_AXIS ? -1 : 1),
69
                         mouse.delta_y * (INVERT_MOUSE_Y_AXIS ? -1 : 1),
79
                         mouse.delta_y * (INVERT_MOUSE_Y_AXIS ? -1 : 1),
70
-                        0, 0);
80
+                        mouse.scroll_y * (INVERT_SCROLL_Y_AXIS ? -1 : 1),
81
+                        mouse.scroll_x * (INVERT_SCROLL_X_AXIS ? -1 : 1));
71
             }
82
             }
72
         }
83
         }
73
         break;
84
         break;
130
     if ( board_millis() - start_ms < interval_ms) return; // not enough time
141
     if ( board_millis() - start_ms < interval_ms) return; // not enough time
131
     start_ms += interval_ms;
142
     start_ms += interval_ms;
132
 
143
 
133
-    uint32_t const btn = controls_button_read();
144
+    uint32_t const btn = 0;
134
 
145
 
135
     // Remote wakeup
146
     // Remote wakeup
136
     if ( tud_suspended() && btn ) {
147
     if ( tud_suspended() && btn ) {

Loading…
Cancel
Save