diff options
author | Dasky <32983009+daskygit@users.noreply.github.com> | 2021-08-19 19:58:17 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-08-19 11:58:17 -0700 |
commit | 7f1c90b7a8d66b806f87229fb96e5c69ee9fb1a4 (patch) | |
tree | 4c4d1fc9be221d4f008f77463bfc02fe4b1bfa4c /drivers | |
parent | e988f58374a138a1af79a141dc8eda54c8782907 (diff) | |
download | qmk_firmware-7f1c90b7a8d66b806f87229fb96e5c69ee9fb1a4.tar.gz qmk_firmware-7f1c90b7a8d66b806f87229fb96e5c69ee9fb1a4.zip |
[Core] Speed up pimoroni trackball driver (#13823)
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/sensors/pimoroni_trackball.c | 213 | ||||
-rw-r--r-- | drivers/sensors/pimoroni_trackball.h | 30 |
2 files changed, 153 insertions, 90 deletions
diff --git a/drivers/sensors/pimoroni_trackball.c b/drivers/sensors/pimoroni_trackball.c index c0ac644f7..48098ff0c 100644 --- a/drivers/sensors/pimoroni_trackball.c +++ b/drivers/sensors/pimoroni_trackball.c | |||
@@ -1,4 +1,5 @@ | |||
1 | /* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com> | 1 | /* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com> |
2 | * Copyright 2021 Dasky (@daskygit) | ||
2 | * | 3 | * |
3 | * This program is free software: you can redistribute it and/or modify | 4 | * This program is free software: you can redistribute it and/or modify |
4 | * it under the terms of the GNU General Public License as published by | 5 | * it under the terms of the GNU General Public License as published by |
@@ -13,128 +14,188 @@ | |||
13 | * You should have received a copy of the GNU General Public License | 14 | * You should have received a copy of the GNU General Public License |
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 15 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
15 | */ | 16 | */ |
16 | |||
17 | #include "pimoroni_trackball.h" | 17 | #include "pimoroni_trackball.h" |
18 | #include "i2c_master.h" | 18 | #include "i2c_master.h" |
19 | #include "print.h" | ||
19 | 20 | ||
20 | static uint8_t scrolling = 0; | 21 | #ifndef PIMORONI_TRACKBALL_ADDRESS |
21 | static int16_t x_offset = 0; | 22 | # define PIMORONI_TRACKBALL_ADDRESS 0x0A |
22 | static int16_t y_offset = 0; | 23 | #endif |
23 | static int16_t h_offset = 0; | 24 | #ifndef PIMORONI_TRACKBALL_INTERVAL_MS |
24 | static int16_t v_offset = 0; | 25 | # define PIMORONI_TRACKBALL_INTERVAL_MS 8 |
25 | static float precisionSpeed = 1; | 26 | #endif |
27 | #ifndef PIMORONI_TRACKBALL_MOUSE_SCALE | ||
28 | # define PIMORONI_TRACKBALL_MOUSE_SCALE 5 | ||
29 | #endif | ||
30 | #ifndef PIMORONI_TRACKBALL_SCROLL_SCALE | ||
31 | # define PIMORONI_TRACKBALL_SCROLL_SCALE 1 | ||
32 | #endif | ||
33 | #ifndef PIMORONI_TRACKBALL_DEBOUNCE_CYCLES | ||
34 | # define PIMORONI_TRACKBALL_DEBOUNCE_CYCLES 20 | ||
35 | #endif | ||
36 | #ifndef PIMORONI_TRACKBALL_ERROR_COUNT | ||
37 | # define PIMORONI_TRACKBALL_ERROR_COUNT 10 | ||
38 | #endif | ||
26 | 39 | ||
27 | static uint16_t i2c_timeout_timer; | 40 | #define TRACKBALL_TIMEOUT 100 |
41 | #define TRACKBALL_REG_LED_RED 0x00 | ||
42 | #define TRACKBALL_REG_LED_GRN 0x01 | ||
43 | #define TRACKBALL_REG_LED_BLU 0x02 | ||
44 | #define TRACKBALL_REG_LED_WHT 0x03 | ||
45 | #define TRACKBALL_REG_LEFT 0x04 | ||
46 | #define TRACKBALL_REG_RIGHT 0x05 | ||
47 | #define TRACKBALL_REG_UP 0x06 | ||
48 | #define TRACKBALL_REG_DOWN 0x07 | ||
28 | 49 | ||
29 | #ifndef PIMORONI_I2C_TIMEOUT | 50 | static pimoroni_data current_pimoroni_data; |
30 | # define PIMORONI_I2C_TIMEOUT 100 | 51 | static report_mouse_t mouse_report; |
31 | #endif | 52 | static bool scrolling = false; |
32 | #ifndef I2C_WAITCHECK | 53 | static int16_t x_offset = 0; |
33 | # define I2C_WAITCHECK 1000 | 54 | static int16_t y_offset = 0; |
55 | static int16_t h_offset = 0; | ||
56 | static int16_t v_offset = 0; | ||
57 | static uint16_t precision = 128; | ||
58 | static uint8_t error_count = 0; | ||
59 | |||
60 | float trackball_get_precision(void) { return ((float)precision / 128); } | ||
61 | void trackball_set_precision(float floatprecision) { precision = (floatprecision * 128); } | ||
62 | bool trackball_is_scrolling(void) { return scrolling; } | ||
63 | void trackball_set_scrolling(bool scroll) { scrolling = scroll; } | ||
64 | |||
65 | void trackball_set_rgbw(uint8_t r, uint8_t g, uint8_t b, uint8_t w) { | ||
66 | uint8_t data[4] = {r, g, b, w}; | ||
67 | __attribute__((unused)) i2c_status_t status = i2c_writeReg(PIMORONI_TRACKBALL_ADDRESS << 1, TRACKBALL_REG_LED_RED, data, sizeof(data), TRACKBALL_TIMEOUT); | ||
68 | #ifdef TRACKBALL_DEBUG | ||
69 | dprintf("Trackball RGBW i2c_status_t: %d\n", status); | ||
34 | #endif | 70 | #endif |
35 | #ifndef MOUSE_DEBOUNCE | 71 | } |
36 | # define MOUSE_DEBOUNCE 5 | 72 | |
73 | i2c_status_t read_pimoroni_trackball(pimoroni_data* data) { | ||
74 | i2c_status_t status = i2c_readReg(PIMORONI_TRACKBALL_ADDRESS << 1, TRACKBALL_REG_LEFT, (uint8_t*)data, sizeof(*data), TRACKBALL_TIMEOUT); | ||
75 | #ifdef TRACKBALL_DEBUG | ||
76 | dprintf("Trackball READ i2c_status_t: %d\nLeft: %d\nRight: %d\nUp: %d\nDown: %d\nSwtich: %d\n", status, data->left, data->right, data->up, data->down, data->click); | ||
37 | #endif | 77 | #endif |
78 | return status; | ||
79 | } | ||
38 | 80 | ||
39 | void trackball_set_rgbw(uint8_t red, uint8_t green, uint8_t blue, uint8_t white) { | 81 | __attribute__((weak)) void pointing_device_init(void) { |
40 | uint8_t data[] = {0x00, red, green, blue, white}; | 82 | i2c_init(); |
41 | i2c_transmit(TRACKBALL_WRITE, data, sizeof(data), PIMORONI_I2C_TIMEOUT); | 83 | trackball_set_rgbw(0x00, 0x00, 0x00, 0x00); |
42 | } | 84 | } |
43 | 85 | ||
44 | int16_t mouse_offset(uint8_t positive, uint8_t negative, int16_t scale) { | 86 | int16_t trackball_get_offsets(uint8_t negative_dir, uint8_t positive_dir, uint8_t scale) { |
45 | int16_t offset = (int16_t)positive - (int16_t)negative; | 87 | uint8_t offset = 0; |
46 | int16_t magnitude = (int16_t)(scale * offset * offset * precisionSpeed); | 88 | bool isnegative = false; |
47 | return offset < 0 ? -magnitude : magnitude; | 89 | if (negative_dir > positive_dir) { |
90 | offset = negative_dir - positive_dir; | ||
91 | isnegative = true; | ||
92 | } else { | ||
93 | offset = positive_dir - negative_dir; | ||
94 | } | ||
95 | uint16_t magnitude = (scale * offset * offset * precision) >> 7; | ||
96 | return isnegative ? -(int16_t)(magnitude) : (int16_t)(magnitude); | ||
48 | } | 97 | } |
49 | 98 | ||
50 | void update_member(int8_t* member, int16_t* offset) { | 99 | void trackball_adapt_values(int8_t* mouse, int16_t* offset) { |
51 | if (*offset > 127) { | 100 | if (*offset > 127) { |
52 | *member = 127; | 101 | *mouse = 127; |
53 | *offset -= 127; | 102 | *offset -= 127; |
54 | } else if (*offset < -127) { | 103 | } else if (*offset < -127) { |
55 | *member = -127; | 104 | *mouse = -127; |
56 | *offset += 127; | 105 | *offset += 127; |
57 | } else { | 106 | } else { |
58 | *member = *offset; | 107 | *mouse = *offset; |
59 | *offset = 0; | 108 | *offset = 0; |
60 | } | 109 | } |
61 | } | 110 | } |
62 | 111 | ||
63 | __attribute__((weak)) void trackball_check_click(bool pressed, report_mouse_t* mouse) { | 112 | __attribute__((weak)) void trackball_click(bool pressed, report_mouse_t* mouse) { |
113 | #ifdef PIMORONI_TRACKBALL_CLICK | ||
64 | if (pressed) { | 114 | if (pressed) { |
65 | mouse->buttons |= MOUSE_BTN1; | 115 | mouse->buttons |= MOUSE_BTN1; |
66 | } else { | 116 | } else { |
67 | mouse->buttons &= ~MOUSE_BTN1; | 117 | mouse->buttons &= ~MOUSE_BTN1; |
68 | } | 118 | } |
119 | #endif | ||
69 | } | 120 | } |
70 | 121 | ||
71 | float trackball_get_precision(void) { return precisionSpeed; } | 122 | __attribute__((weak)) bool pointing_device_task_user(pimoroni_data* trackball_data) { return true; }; |
72 | void trackball_set_precision(float precision) { precisionSpeed = precision; } | ||
73 | bool trackball_is_scrolling(void) { return scrolling; } | ||
74 | void trackball_set_scrolling(bool scroll) { scrolling = scroll; } | ||
75 | 123 | ||
76 | __attribute__((weak)) void pointing_device_init(void) { i2c_init(); trackball_set_rgbw(0x00, 0x00, 0x00, 0x00); } | 124 | __attribute__((weak)) void pointing_device_task() { |
125 | static fast_timer_t throttle = 0; | ||
126 | static uint16_t debounce = 0; | ||
77 | 127 | ||
78 | void pointing_device_task(void) { | 128 | if (error_count < PIMORONI_TRACKBALL_ERROR_COUNT && timer_elapsed_fast(throttle) >= PIMORONI_TRACKBALL_INTERVAL_MS) { |
79 | static bool debounce; | 129 | i2c_status_t status = read_pimoroni_trackball(¤t_pimoroni_data); |
80 | static uint16_t debounce_timer; | 130 | |
81 | uint8_t state[5] = {}; | 131 | if (status == I2C_STATUS_SUCCESS) { |
82 | if (timer_elapsed(i2c_timeout_timer) > I2C_WAITCHECK) { | 132 | error_count = 0; |
83 | if (i2c_readReg(TRACKBALL_READ, 0x04, state, 5, PIMORONI_I2C_TIMEOUT) == I2C_STATUS_SUCCESS) { | 133 | |
84 | if (!state[4] && !debounce) { | 134 | if (pointing_device_task_user(¤t_pimoroni_data)) { |
85 | if (scrolling) { | 135 | mouse_report = pointing_device_get_report(); |
136 | |||
137 | if (!(current_pimoroni_data.click & 128)) { | ||
138 | trackball_click(false, &mouse_report); | ||
139 | if (!debounce) { | ||
140 | if (scrolling) { | ||
86 | #ifdef PIMORONI_TRACKBALL_INVERT_X | 141 | #ifdef PIMORONI_TRACKBALL_INVERT_X |
87 | h_offset += mouse_offset(state[2], state[3], 1); | 142 | h_offset += trackball_get_offsets(current_pimoroni_data.right, current_pimoroni_data.left, PIMORONI_TRACKBALL_SCROLL_SCALE); |
88 | #else | 143 | #else |
89 | h_offset -= mouse_offset(state[2], state[3], 1); | 144 | h_offset -= trackball_get_offsets(current_pimoroni_data.right, current_pimoroni_data.left, PIMORONI_TRACKBALL_SCROLL_SCALE); |
90 | #endif | 145 | #endif |
91 | #ifdef PIMORONI_TRACKBALL_INVERT_Y | 146 | #ifdef PIMORONI_TRACKBALL_INVERT_Y |
92 | v_offset += mouse_offset(state[1], state[0], 1); | 147 | v_offset += trackball_get_offsets(current_pimoroni_data.down, current_pimoroni_data.up, PIMORONI_TRACKBALL_SCROLL_SCALE); |
93 | #else | 148 | #else |
94 | v_offset -= mouse_offset(state[1], state[0], 1); | 149 | v_offset -= trackball_get_offsets(current_pimoroni_data.down, current_pimoroni_data.up, PIMORONI_TRACKBALL_SCROLL_SCALE); |
95 | #endif | 150 | #endif |
96 | } else { | 151 | } else { |
97 | #ifdef PIMORONI_TRACKBALL_INVERT_X | 152 | #ifdef PIMORONI_TRACKBALL_INVERT_X |
98 | x_offset -= mouse_offset(state[2], state[3], 5); | 153 | x_offset -= trackball_get_offsets(current_pimoroni_data.right, current_pimoroni_data.left, PIMORONI_TRACKBALL_MOUSE_SCALE); |
99 | #else | 154 | #else |
100 | x_offset += mouse_offset(state[2], state[3], 5); | 155 | x_offset += trackball_get_offsets(current_pimoroni_data.right, current_pimoroni_data.left, PIMORONI_TRACKBALL_MOUSE_SCALE); |
101 | #endif | 156 | #endif |
102 | #ifdef PIMORONI_TRACKBALL_INVERT_Y | 157 | #ifdef PIMORONI_TRACKBALL_INVERT_Y |
103 | y_offset -= mouse_offset(state[1], state[0], 5); | 158 | y_offset -= trackball_get_offsets(current_pimoroni_data.down, current_pimoroni_data.up, PIMORONI_TRACKBALL_MOUSE_SCALE); |
104 | #else | 159 | #else |
105 | y_offset += mouse_offset(state[1], state[0], 5); | 160 | y_offset += trackball_get_offsets(current_pimoroni_data.down, current_pimoroni_data.up, PIMORONI_TRACKBALL_MOUSE_SCALE); |
106 | #endif | 161 | #endif |
107 | } | 162 | } |
108 | } else { | 163 | if (scrolling) { |
109 | if (state[4]) { | 164 | #ifndef PIMORONI_TRACKBALL_ROTATE |
110 | debounce = true; | 165 | trackball_adapt_values(&mouse_report.h, &h_offset); |
111 | debounce_timer = timer_read(); | 166 | trackball_adapt_values(&mouse_report.v, &v_offset); |
167 | #else | ||
168 | trackball_adapt_values(&mouse_report.h, &v_offset); | ||
169 | trackball_adapt_values(&mouse_report.v, &h_offset); | ||
170 | #endif | ||
171 | mouse_report.x = 0; | ||
172 | mouse_report.y = 0; | ||
173 | } else { | ||
174 | #ifndef PIMORONI_TRACKBALL_ROTATE | ||
175 | trackball_adapt_values(&mouse_report.x, &x_offset); | ||
176 | trackball_adapt_values(&mouse_report.y, &y_offset); | ||
177 | #else | ||
178 | trackball_adapt_values(&mouse_report.x, &y_offset); | ||
179 | trackball_adapt_values(&mouse_report.y, &x_offset); | ||
180 | #endif | ||
181 | mouse_report.h = 0; | ||
182 | mouse_report.v = 0; | ||
183 | } | ||
184 | } else { | ||
185 | debounce--; | ||
186 | } | ||
187 | } else { | ||
188 | trackball_click(true, &mouse_report); | ||
189 | debounce = PIMORONI_TRACKBALL_DEBOUNCE_CYCLES; | ||
112 | } | 190 | } |
113 | } | 191 | } |
114 | } else { | 192 | } else { |
115 | i2c_timeout_timer = timer_read(); | 193 | error_count++; |
116 | } | 194 | } |
117 | } | ||
118 | |||
119 | if (timer_elapsed(debounce_timer) > MOUSE_DEBOUNCE) debounce = false; | ||
120 | 195 | ||
121 | report_mouse_t mouse = pointing_device_get_report(); | 196 | pointing_device_set_report(mouse_report); |
122 | 197 | pointing_device_send(); | |
123 | #ifdef PIMORONI_TRACKBALL_CLICK | ||
124 | trackball_check_click(state[4] & (1 << 7), &mouse); | ||
125 | #endif | ||
126 | 198 | ||
127 | #ifndef PIMORONI_TRACKBALL_ROTATE | 199 | throttle = timer_read_fast(); |
128 | update_member(&mouse.x, &x_offset); | 200 | } |
129 | update_member(&mouse.y, &y_offset); | ||
130 | update_member(&mouse.h, &h_offset); | ||
131 | update_member(&mouse.v, &v_offset); | ||
132 | #else | ||
133 | update_member(&mouse.x, &y_offset); | ||
134 | update_member(&mouse.y, &x_offset); | ||
135 | update_member(&mouse.h, &v_offset); | ||
136 | update_member(&mouse.v, &h_offset); | ||
137 | #endif | ||
138 | pointing_device_set_report(mouse); | ||
139 | pointing_device_send(); | ||
140 | } | 201 | } |
diff --git a/drivers/sensors/pimoroni_trackball.h b/drivers/sensors/pimoroni_trackball.h index 9e3c64c19..6b2a41425 100644 --- a/drivers/sensors/pimoroni_trackball.h +++ b/drivers/sensors/pimoroni_trackball.h | |||
@@ -1,4 +1,5 @@ | |||
1 | /* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com> | 1 | /* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com> |
2 | * Copyright 2021 Dasky (@daskygit) | ||
2 | * | 3 | * |
3 | * This program is free software: you can redistribute it and/or modify | 4 | * This program is free software: you can redistribute it and/or modify |
4 | * it under the terms of the GNU General Public License as published by | 5 | * it under the terms of the GNU General Public License as published by |
@@ -13,23 +14,24 @@ | |||
13 | * You should have received a copy of the GNU General Public License | 14 | * You should have received a copy of the GNU General Public License |
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 15 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
15 | */ | 16 | */ |
16 | |||
17 | #pragma once | 17 | #pragma once |
18 | 18 | ||
19 | #include "quantum.h" | 19 | #include "quantum.h" |
20 | #include "pointing_device.h" | 20 | #include "pointing_device.h" |
21 | 21 | ||
22 | #ifndef TRACKBALL_ADDRESS | 22 | typedef struct pimoroni_data { |
23 | # define TRACKBALL_ADDRESS 0x0A | 23 | uint8_t left; |
24 | #endif | 24 | uint8_t right; |
25 | #define TRACKBALL_WRITE ((TRACKBALL_ADDRESS << 1) | I2C_WRITE) | 25 | uint8_t up; |
26 | #define TRACKBALL_READ (TRACKBALL_ADDRESS << 1) | 26 | uint8_t down; |
27 | 27 | uint8_t click; | |
28 | void trackball_set_rgbw(uint8_t red, uint8_t green, uint8_t blue, uint8_t white); | 28 | } pimoroni_data; |
29 | void trackball_check_click(bool pressed, report_mouse_t *mouse); | ||
30 | void trackball_register_button(bool pressed, enum mouse_buttons button); | ||
31 | 29 | ||
32 | float trackball_get_precision(void); | 30 | void trackball_set_rgbw(uint8_t red, uint8_t green, uint8_t blue, uint8_t white); |
33 | void trackball_set_precision(float precision); | 31 | void trackball_click(bool pressed, report_mouse_t* mouse); |
34 | bool trackball_is_scrolling(void); | 32 | int16_t trackball_get_offsets(uint8_t negative_dir, uint8_t positive_dir, uint8_t scale); |
35 | void trackball_set_scrolling(bool scroll); | 33 | void trackball_adapt_values(int8_t* mouse, int16_t* offset); |
34 | float trackball_get_precision(void); | ||
35 | void trackball_set_precision(float precision); | ||
36 | bool trackball_is_scrolling(void); | ||
37 | void trackball_set_scrolling(bool scroll); | ||