summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDasky <32983009+daskygit@users.noreply.github.com>2021-12-27 01:05:51 +0000
committerGitHub <noreply@github.com>2021-12-27 12:05:51 +1100
commit7f7364c55912879baaff8fafca550d02f17b4d44 (patch)
tree8afd414f6b202a126632a8c047dcf200312c78ff
parent76a673233c8cb3d97130a6dece364c24b29f5fd7 (diff)
[Core] Split support for pointing devices. (#15304)
* Draft implementation * formatting * fix combined buttons * remove pimoroni throttle * sync pointing on a throttle loop with checksum * no longer used * doh Co-authored-by: Drashna Jaelre <drashna@live.com> * switch pimoroni to a cpi equivalent * add cpi support * allow user modification of seperate mouse reports * a little tidy up * add *_RIGHT defines. * docs * doxygen comments * basic changelog * clean up pimoroni * small doc fixes * Update docs/feature_pointing_device.md Co-authored-by: Drashna Jaelre <drashna@live.com> * performance tweak if side has usb * Don't run init funtions on wrong side * renamed some variables for consistency * fix pimoroni typos * Clamp instead of OR * Promote combined values to uint16_t * Update pointing_device.c Co-authored-by: Drashna Jaelre <drashna@live.com> Co-authored-by: Nick Brassel <nick@tzarc.org>
-rw-r--r--docs/ChangeLog/20220226/PR15304.md13
-rw-r--r--docs/feature_pointing_device.md116
-rw-r--r--docs/feature_split_keyboard.md8
-rw-r--r--drivers/sensors/pimoroni_trackball.c22
-rw-r--r--drivers/sensors/pimoroni_trackball.h9
-rw-r--r--quantum/pointing_device.c389
-rw-r--r--quantum/pointing_device.h13
-rw-r--r--quantum/pointing_device_drivers.c24
-rw-r--r--quantum/split_common/transaction_id_define.h6
-rw-r--r--quantum/split_common/transactions.c79
-rw-r--r--quantum/split_common/transport.h13
11 files changed, 626 insertions, 66 deletions
diff --git a/docs/ChangeLog/20220226/PR15304.md b/docs/ChangeLog/20220226/PR15304.md
new file mode 100644
index 0000000000..3cdb40db10
--- /dev/null
+++ b/docs/ChangeLog/20220226/PR15304.md
@@ -0,0 +1,13 @@
1### Split Common core now supports Pointing Devices ([#15304](https://github.com/qmk/qmk_firmware/pull/15304))
2
3Pointing devices can now be shared across a split keyboard with support for a single pointing device or a pointing device on each side.
4
5This feature can be enabled with `#define SPLIT_POINTING_ENABLE` and one of the following options:
6
7| Setting | Description |
8|---------------------------|------------------------------------|
9|`POINTING_DEVICE_LEFT` | Pointing device on the left side |
10|`POINTING_DEVICE_RIGHT` | Pointing device on the right side |
11|`POINTING_DEVICE_COMBINED` | Pointing device on both sides |
12
13See the [Pointing Device](../feature_pointing_device.md) documentation for further configuration options.
diff --git a/docs/feature_pointing_device.md b/docs/feature_pointing_device.md
index 5aef9bea27..f8de92f3b4 100644
--- a/docs/feature_pointing_device.md
+++ b/docs/feature_pointing_device.md
@@ -127,11 +127,10 @@ The Pimoroni Trackball module is a I2C based breakout board with an RGB enable t
127| Setting | Description | Default | 127| Setting | Description | Default |
128|-------------------------------------|------------------------------------------------------------------------------------|---------| 128|-------------------------------------|------------------------------------------------------------------------------------|---------|
129|`PIMORONI_TRACKBALL_ADDRESS` | (Required) Sets the I2C Address for the Pimoroni Trackball. | `0x0A` | 129|`PIMORONI_TRACKBALL_ADDRESS` | (Required) Sets the I2C Address for the Pimoroni Trackball. | `0x0A` |
130|`PIMORONI_TRACKBALL_TIMEOUT` | (Optional) The timeout for i2c communication with the trackpad in milliseconds. | `100` | 130|`PIMORONI_TRACKBALL_TIMEOUT` | (Optional) The timeout for i2c communication with the trackball in milliseconds. | `100` |
131|`PIMORONI_TRACKBALL_INTERVAL_MS` | (Optional) The update/read interval for the sensor in milliseconds. | `8` |
132|`PIMORONI_TRACKBALL_SCALE` | (Optional) The multiplier used to generate reports from the sensor. | `5` | 131|`PIMORONI_TRACKBALL_SCALE` | (Optional) The multiplier used to generate reports from the sensor. | `5` |
133|`PIMORONI_TRACKBALL_DEBOUNCE_CYCLES` | (Optional) The number of scan cycles used for debouncing on the ball press. | `20` | 132|`PIMORONI_TRACKBALL_DEBOUNCE_CYCLES` | (Optional) The number of scan cycles used for debouncing on the ball press. | `20` |
134|`PIMORONI_TRACKBALL_ERROR_COUNT` | (Optional) Specifies the number of read/write errors until the sensor is disabled. | `10` | 133|`PIMORONI_TRACKBALL_ERROR_COUNT` | (Optional) Specifies the number of read/write errors until the sensor is disabled. | `10` |
135 134
136### PMW 3360 Sensor 135### PMW 3360 Sensor
137 136
@@ -171,14 +170,35 @@ void pointing_device_driver_set_cpi(uint16_t cpi) {}
171 170
172## Common Configuration 171## Common Configuration
173 172
174| Setting | Description | Default | 173| Setting | Description | Default |
175|-------------------------------|-----------------------------------------------------------------------|---------------| 174|----------------------------------|-----------------------------------------------------------------------|-------------------|
176|`POINTING_DEVICE_ROTATION_90` | (Optional) Rotates the X and Y data by 90 degrees. | _not defined_ | 175|`POINTING_DEVICE_ROTATION_90` | (Optional) Rotates the X and Y data by 90 degrees. | _not defined_ |
177|`POINTING_DEVICE_ROTATION_180` | (Optional) Rotates the X and Y data by 180 degrees. | _not defined_ | 176|`POINTING_DEVICE_ROTATION_180` | (Optional) Rotates the X and Y data by 180 degrees. | _not defined_ |
178|`POINTING_DEVICE_ROTATION_270` | (Optional) Rotates the X and Y data by 270 degrees. | _not defined_ | 177|`POINTING_DEVICE_ROTATION_270` | (Optional) Rotates the X and Y data by 270 degrees. | _not defined_ |
179|`POINTING_DEVICE_INVERT_X` | (Optional) Inverts the X axis report. | _not defined_ | 178|`POINTING_DEVICE_INVERT_X` | (Optional) Inverts the X axis report. | _not defined_ |
180|`POINTING_DEVICE_INVERT_Y` | (Optional) Inverts the Y axis report. | _not defined_ | 179|`POINTING_DEVICE_INVERT_Y` | (Optional) Inverts the Y axis report. | _not defined_ |
181|`POINTING_DEVICE_MOTION_PIN` | (Optional) If supported, will only read from sensor if pin is active. | _not defined_ | 180|`POINTING_DEVICE_MOTION_PIN` | (Optional) If supported, will only read from sensor if pin is active. | _not defined_ |
181|`POINTING_DEVICE_TASK_THROTTLE_MS` | (Optional) Limits the frequency that the sensor is polled for motion. | _not defined_ |
182
183!> When using `SPLIT_POINTING_ENABLE` the `POINTING_DEVICE_MOTION_PIN` functionality is not supported and would recommend `POINTING_DEVICE_TASK_THROTTLE_MS` be set to `1`. Increasing this value will increase transport performance at the cost of possible mouse responsiveness.
184
185
186## Split Keyboard Configuration
187
188The following configuration options are only available when using `SPLIT_POINTING_ENABLE` see [data sync options](feature_split_keyboard.md?id=data-sync-options). The rotation and invert `*_RIGHT` options are only used with `POINTING_DEVICE_COMBINED`. If using `POINTING_DEVICE_LEFT` or `POINTING_DEVICE_RIGHT` use the common configuration above to configure your pointing device.
189
190| Setting | Description | Default |
191|----------------------------------------|-----------------------------------------------------------------------|---------------|
192|`POINTING_DEVICE_LEFT` | Pointing device on the left side (Required - pick one only) | _not defined_ |
193|`POINTING_DEVICE_RIGHT` | Pointing device on the right side (Required - pick one only) | _not defined_ |
194|`POINTING_DEVICE_COMBINED` | Pointing device on both sides (Required - pick one only) | _not defined_ |
195|`POINTING_DEVICE_ROTATION_90_RIGHT` | (Optional) Rotates the X and Y data by 90 degrees. | _not defined_ |
196|`POINTING_DEVICE_ROTATION_180_RIGHT` | (Optional) Rotates the X and Y data by 180 degrees. | _not defined_ |
197|`POINTING_DEVICE_ROTATION_270_RIGHT` | (Optional) Rotates the X and Y data by 270 degrees. | _not defined_ |
198|`POINTING_DEVICE_INVERT_X_RIGHT` | (Optional) Inverts the X axis report. | _not defined_ |
199|`POINTING_DEVICE_INVERT_Y_RIGHT` | (Optional) Inverts the Y axis report. | _not defined_ |
200
201!> If there is a `_RIGHT` configuration option or callback, the [common configuration](feature_pointing_device.md?id=common-configuration) option will work for the left. For correct left/right detection you should setup a [handedness option](feature_split_keyboard?id=setting-handedness), `EE_HANDS` is usually a good option for an existing board that doesn't do handedness by hardware.
182 202
183 203
184## Callbacks and Functions 204## Callbacks and Functions
@@ -196,6 +216,21 @@ void pointing_device_driver_set_cpi(uint16_t cpi) {}
196| `pointing_device_set_report(mouse_report)` | Sets the mouse report to the assigned `mouse_report_t` data structured passed to the function. | 216| `pointing_device_set_report(mouse_report)` | Sets the mouse report to the assigned `mouse_report_t` data structured passed to the function. |
197| `pointing_device_send(void)` | Sends the current mouse report to the host system. Function can be replaced. | 217| `pointing_device_send(void)` | Sends the current mouse report to the host system. Function can be replaced. |
198| `has_mouse_report_changed(old, new)` | Compares the old and new `mouse_report_t` data and returns true only if it has changed. | 218| `has_mouse_report_changed(old, new)` | Compares the old and new `mouse_report_t` data and returns true only if it has changed. |
219| `pointing_device_adjust_by_defines(mouse_report)` | Applies rotations and invert configurations to a raw mouse report. |
220
221
222## Split Keyboard Callbacks and Functions
223
224The combined functions below are only available when using `SPLIT_POINTING_ENABLE` and `POINTING_DEVICE_COMBINED`. The 2 callbacks `pointing_device_task_combined_*` replace the single sided equivalents above. See the [combined pointing devices example](feature_pointing_device.md?id=combined-pointing-devices)
225
226| Function | Description |
227|-----------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------|
228| `pointing_device_set_shared_report(mouse_report)` | Sets the shared mouse report to the assigned `mouse_report_t` data structured passed to the function. |
229| `pointing_device_set_cpi_on_side(bool, uint16_t)` | Sets the CPI/DPI of one side, if supported. Passing `true` will set the left and `false` the right` |
230| `pointing_device_combine_reports(left_report, right_report)` | Returns a combined mouse_report of left_report and right_report (as a `mouse_report_t` data structure) |
231| `pointing_device_task_combined_kb(left_report, right_report)` | Callback, so keyboard code can intercept and modify the data. Returns a combined mouse report. |
232| `pointing_device_task_combined_user(left_report, right_report)` | Callback, so user code can intercept and modify. Returns a combined mouse report using `pointing_device_combine_reports` |
233| `pointing_device_adjust_by_defines_right(mouse_report)` | Applies right side rotations and invert configurations to a raw mouse report. |
199 234
200 235
201# Manipulating Mouse Reports 236# Manipulating Mouse Reports
@@ -242,3 +277,62 @@ case MS_SPECIAL:
242``` 277```
243 278
244Recall that the mouse report is set to zero (except the buttons) whenever it is sent, so the scrolling would only occur once in each case. 279Recall that the mouse report is set to zero (except the buttons) whenever it is sent, so the scrolling would only occur once in each case.
280
281## Split Examples
282
283The following examples make use the `SPLIT_POINTING_ENABLE` functionality and show how to manipulate the mouse report for a scrolling mode.
284
285### Single Pointing Device
286
287The following example will work with either `POINTING_DEVICE_LEFT` or `POINTING_DEVICE_RIGHT` and enables scrolling mode while on a particular layer.
288
289```c
290
291static bool scrolling_mode = false;
292
293layer_state_t layer_state_set_user(layer_state_t state) {
294 switch (get_highest_layer(state)) {
295 case _RAISE: // If we're on the _RAISE layer enable scrolling mode
296 scrolling_mode = true;
297 pointing_device_set_cpi(2000);
298 break;
299 default:
300 if (scrolling_mode) { // check if we were scrolling before and set disable if so
301 scrolling_mode = false;
302 pointing_device_set_cpi(8000);
303 }
304 break;
305 }
306 return state;
307}
308
309report_mouse_t pointing_device_task_user(report_mouse_t mouse_report) {
310 if (scrolling_mode) {
311 mouse_report.h = mouse_report.x;
312 mouse_report.v = mouse_report.y;
313 mouse_report.x = 0;
314 mouse_report.y = 0;
315 }
316 return mouse_report;
317}
318
319```
320
321### Combined Pointing Devices
322
323The following example requires `POINTING_DEVICE_COMBINED` and sets the left side pointing device to scroll only.
324
325```c
326void keyboard_post_init_user(void) {
327 pointing_device_set_cpi_on_side(true, 1000); //Set cpi on left side to a low value for slower scrolling.
328 pointing_device_set_cpi_on_side(false, 8000); //Set cpi on right side to a reasonable value for mousing.
329}
330
331report_mouse_t pointing_device_task_combined_user(report_mouse_t left_report, report_mouse_t right_report) {
332 left_report.h = left_report.x;
333 left_report.v = left_report.y;
334 left_report.x = 0;
335 left_report.y = 0;
336 return pointing_device_combine_reports(left_report, right_report);
337}
338```
diff --git a/docs/feature_split_keyboard.md b/docs/feature_split_keyboard.md
index c8ba18beeb..b51593308e 100644
--- a/docs/feature_split_keyboard.md
+++ b/docs/feature_split_keyboard.md
@@ -266,6 +266,14 @@ This enables transmitting the current OLED on/off status to the slave side of th
266 266
267This enables transmitting the current ST7565 on/off status to the slave side of the split keyboard. The purpose of this feature is to support state (on/off state only) syncing. 267This enables transmitting the current ST7565 on/off status to the slave side of the split keyboard. The purpose of this feature is to support state (on/off state only) syncing.
268 268
269```c
270#define SPLIT_POINTING_ENABLE
271```
272
273This enables transmitting the pointing device status to the master side of the split keyboard. The purpose of this feature is to enable use pointing devices on the slave side.
274
275!> There is additional required configuration for `SPLIT_POINTING_ENABLE` outlined in the [pointing device documentation](feature_pointing_device.md?id=split-keyboard-configuration).
276
269### Custom data sync between sides :id=custom-data-sync 277### Custom data sync between sides :id=custom-data-sync
270 278
271QMK's split transport allows for arbitrary data transactions at both the keyboard and user levels. This is modelled on a remote procedure call, with the master invoking a function on the slave side, with the ability to send data from master to slave, process it slave side, and send data back from slave to master. 279QMK's split transport allows for arbitrary data transactions at both the keyboard and user levels. This is modelled on a remote procedure call, with the master invoking a function on the slave side, with the ability to send data from master to slave, process it slave side, and send data back from slave to master.
diff --git a/drivers/sensors/pimoroni_trackball.c b/drivers/sensors/pimoroni_trackball.c
index 7d390056ea..2867e763bc 100644
--- a/drivers/sensors/pimoroni_trackball.c
+++ b/drivers/sensors/pimoroni_trackball.c
@@ -33,8 +33,24 @@
33 33
34static uint16_t precision = 128; 34static uint16_t precision = 128;
35 35
36float pimoroni_trackball_get_precision(void) { return ((float)precision / 128); } 36uint16_t pimoroni_trackball_get_cpi(void) { return (precision * 125); }
37void pimoroni_trackball_set_precision(float floatprecision) { precision = (floatprecision * 128); } 37/**
38 * @brief Sets the scaling value for pimoroni trackball
39 *
40 * Sets a scaling value for pimoroni trackball to allow runtime adjustment. This isn't used by the sensor and is an
41 * approximation so the functions are consistent across drivers.
42 *
43 * NOTE: This rounds down to the nearest number divisable by 125 that's a positive integer, values below 125 are clamped to 125.
44 *
45 * @param cpi uint16_t
46 */
47void pimoroni_trackball_set_cpi(uint16_t cpi) {
48 if (cpi < 249) {
49 precision = 1;
50 } else {
51 precision = (cpi - (cpi % 125)) / 125;
52 }
53}
38 54
39void pimoroni_trackball_set_rgbw(uint8_t r, uint8_t g, uint8_t b, uint8_t w) { 55void pimoroni_trackball_set_rgbw(uint8_t r, uint8_t g, uint8_t b, uint8_t w) {
40 uint8_t data[4] = {r, g, b, w}; 56 uint8_t data[4] = {r, g, b, w};
@@ -60,7 +76,7 @@ i2c_status_t read_pimoroni_trackball(pimoroni_data_t* data) {
60 return status; 76 return status;
61} 77}
62 78
63__attribute__((weak)) void pimironi_trackball_device_init(void) { 79__attribute__((weak)) void pimoroni_trackball_device_init(void) {
64 i2c_init(); 80 i2c_init();
65 pimoroni_trackball_set_rgbw(0x00, 0x00, 0x00, 0x00); 81 pimoroni_trackball_set_rgbw(0x00, 0x00, 0x00, 0x00);
66} 82}
diff --git a/drivers/sensors/pimoroni_trackball.h b/drivers/sensors/pimoroni_trackball.h
index 59ee8724ba..e20ee748a7 100644
--- a/drivers/sensors/pimoroni_trackball.h
+++ b/drivers/sensors/pimoroni_trackball.h
@@ -23,9 +23,6 @@
23#ifndef PIMORONI_TRACKBALL_ADDRESS 23#ifndef PIMORONI_TRACKBALL_ADDRESS
24# define PIMORONI_TRACKBALL_ADDRESS 0x0A 24# define PIMORONI_TRACKBALL_ADDRESS 0x0A
25#endif 25#endif
26#ifndef PIMORONI_TRACKBALL_INTERVAL_MS
27# define PIMORONI_TRACKBALL_INTERVAL_MS 8
28#endif
29#ifndef PIMORONI_TRACKBALL_SCALE 26#ifndef PIMORONI_TRACKBALL_SCALE
30# define PIMORONI_TRACKBALL_SCALE 5 27# define PIMORONI_TRACKBALL_SCALE 5
31#endif 28#endif
@@ -52,10 +49,10 @@ typedef struct {
52 uint8_t click; 49 uint8_t click;
53} pimoroni_data_t; 50} pimoroni_data_t;
54 51
55void pimironi_trackball_device_init(void); 52void pimoroni_trackball_device_init(void);
56void pimoroni_trackball_set_rgbw(uint8_t red, uint8_t green, uint8_t blue, uint8_t white); 53void pimoroni_trackball_set_rgbw(uint8_t red, uint8_t green, uint8_t blue, uint8_t white);
57int16_t pimoroni_trackball_get_offsets(uint8_t negative_dir, uint8_t positive_dir, uint8_t scale); 54int16_t pimoroni_trackball_get_offsets(uint8_t negative_dir, uint8_t positive_dir, uint8_t scale);
58void pimoroni_trackball_adapt_values(int8_t* mouse, int16_t* offset); 55void pimoroni_trackball_adapt_values(int8_t* mouse, int16_t* offset);
59float pimoroni_trackball_get_precision(void); 56uint16_t pimoroni_trackball_get_cpi(void);
60void pimoroni_trackball_set_precision(float precision); 57void pimoroni_trackball_set_cpi(uint16_t cpi);
61i2c_status_t read_pimoroni_trackball(pimoroni_data_t* data); 58i2c_status_t read_pimoroni_trackball(pimoroni_data_t* data);
diff --git a/quantum/pointing_device.c b/quantum/pointing_device.c
index 2fefdb67b6..23d93fa15f 100644
--- a/quantum/pointing_device.c
+++ b/quantum/pointing_device.c
@@ -18,24 +18,105 @@
18 18
19#include "pointing_device.h" 19#include "pointing_device.h"
20#include <string.h> 20#include <string.h>
21#include "timer.h"
21#ifdef MOUSEKEY_ENABLE 22#ifdef MOUSEKEY_ENABLE
22# include "mousekey.h" 23# include "mousekey.h"
23#endif 24#endif
24#if (defined(POINTING_DEVICE_ROTATION_90) + defined(POINTING_DEVICE_ROTATION_180) + defined(POINTING_DEVICE_ROTATION_270)) > 1 25#if (defined(POINTING_DEVICE_ROTATION_90) + defined(POINTING_DEVICE_ROTATION_180) + defined(POINTING_DEVICE_ROTATION_270)) > 1
25# error More than one rotation selected. This is not supported. 26# error More than one rotation selected. This is not supported.
26#endif 27#endif
28#if defined(SPLIT_POINTING_ENABLE)
29# include "transactions.h"
30# include "keyboard.h"
27 31
28static report_mouse_t mouseReport = {}; 32report_mouse_t shared_mouse_report = {};
33uint16_t shared_cpi = 0;
34
35/**
36 * @brief Sets the shared mouse report used be pointing device task
37 *
38 * NOTE : Only available when using SPLIT_POINTING_ENABLE
39 *
40 * @param[in] new_mouse_report report_mouse_t
41 */
42void pointing_device_set_shared_report(report_mouse_t new_mouse_report) { shared_mouse_report = new_mouse_report; }
43
44/**
45 * @brief Gets current pointing device CPI if supported
46 *
47 * Gets current cpi of the shared report and returns it as uint16_t
48 *
49 * NOTE : Only available when using SPLIT_POINTING_ENABLE
50 *
51 * @return cpi value as uint16_t
52 */
53uint16_t pointing_device_get_shared_cpi(void) { return shared_cpi; }
54
55# if defined(POINTING_DEVICE_LEFT)
56# define POINTING_DEVICE_THIS_SIDE is_keyboard_left()
57# elif defined(POINTING_DEVICE_RIGHT)
58# define POINTING_DEVICE_THIS_SIDE !is_keyboard_left()
59# elif defined(POINTING_DEVICE_COMBINED)
60# define POINTING_DEVICE_THIS_SIDE true
61# endif
62
63#endif // defined(SPLIT_POINTING_ENABLE)
64
65static report_mouse_t local_mouse_report = {};
29 66
30extern const pointing_device_driver_t pointing_device_driver; 67extern const pointing_device_driver_t pointing_device_driver;
31 68
69/**
70 * @brief Compares 2 mouse reports for difference and returns result
71 *
72 * @param[in] new report_mouse_t
73 * @param[in] old report_mouse_t
74 * @return bool result
75 */
32__attribute__((weak)) bool has_mouse_report_changed(report_mouse_t new, report_mouse_t old) { return memcmp(&new, &old, sizeof(new)); } 76__attribute__((weak)) bool has_mouse_report_changed(report_mouse_t new, report_mouse_t old) { return memcmp(&new, &old, sizeof(new)); }
33 77
34__attribute__((weak)) void pointing_device_init_kb(void) {} 78/**
35__attribute__((weak)) void pointing_device_init_user(void) {} 79 * @brief Keyboard level code pointing device initialisation
80 *
81 */
82__attribute__((weak)) void pointing_device_init_kb(void) {}
83
84/**
85 * @brief User level code pointing device initialisation
86 *
87 */
88__attribute__((weak)) void pointing_device_init_user(void) {}
89
90/**
91 * @brief Weak function allowing for keyboard level mouse report modification
92 *
93 * Takes report_mouse_t struct allowing modification at keyboard level then returns report_mouse_t.
94 *
95 * @param[in] mouse_report report_mouse_t
96 * @return report_mouse_t
97 */
36__attribute__((weak)) report_mouse_t pointing_device_task_kb(report_mouse_t mouse_report) { return pointing_device_task_user(mouse_report); } 98__attribute__((weak)) report_mouse_t pointing_device_task_kb(report_mouse_t mouse_report) { return pointing_device_task_user(mouse_report); }
99
100/**
101 * @brief Weak function allowing for user level mouse report modification
102 *
103 * Takes report_mouse_t struct allowing modification at user level then returns report_mouse_t.
104 *
105 * @param[in] mouse_report report_mouse_t
106 * @return report_mouse_t
107 */
37__attribute__((weak)) report_mouse_t pointing_device_task_user(report_mouse_t mouse_report) { return mouse_report; } 108__attribute__((weak)) report_mouse_t pointing_device_task_user(report_mouse_t mouse_report) { return mouse_report; }
38 109
110/**
111 * @brief Handles pointing device buttons
112 *
113 * Returns modified button bitmask using bool pressed and selected pointing_device_buttons_t button in uint8_t buttons bitmask.
114 *
115 * @param buttons[in] uint8_t bitmask
116 * @param pressed[in] bool
117 * @param button[in] pointing_device_buttons_t value
118 * @return Modified uint8_t bitmask buttons
119 */
39__attribute__((weak)) uint8_t pointing_device_handle_buttons(uint8_t buttons, bool pressed, pointing_device_buttons_t button) { 120__attribute__((weak)) uint8_t pointing_device_handle_buttons(uint8_t buttons, bool pressed, pointing_device_buttons_t button) {
40 if (pressed) { 121 if (pressed) {
41 buttons |= 1 << (button); 122 buttons |= 1 << (button);
@@ -45,7 +126,17 @@ __attribute__((weak)) uint8_t pointing_device_handle_buttons(uint8_t buttons, bo
45 return buttons; 126 return buttons;
46} 127}
47 128
129/**
130 * @brief Initialises pointing device
131 *
132 * Initialises pointing device, perform driver init and optional keyboard/user level code.
133 */
48__attribute__((weak)) void pointing_device_init(void) { 134__attribute__((weak)) void pointing_device_init(void) {
135#if defined(SPLIT_POINTING_ENABLE)
136 if (!(POINTING_DEVICE_THIS_SIDE)) {
137 return;
138 }
139#endif
49 pointing_device_driver.init(); 140 pointing_device_driver.init();
50#ifdef POINTING_DEVICE_MOTION_PIN 141#ifdef POINTING_DEVICE_MOTION_PIN
51 setPinInputHigh(POINTING_DEVICE_MOTION_PIN); 142 setPinInputHigh(POINTING_DEVICE_MOTION_PIN);
@@ -54,67 +145,299 @@ __attribute__((weak)) void pointing_device_init(void) {
54 pointing_device_init_user(); 145 pointing_device_init_user();
55} 146}
56 147
148/**
149 * @brief Sends processed mouse report to host
150 *
151 * This sends the mouse report generated by pointing_device_task if changed since the last report. Once send zeros mouse report except buttons.
152 *
153 */
57__attribute__((weak)) void pointing_device_send(void) { 154__attribute__((weak)) void pointing_device_send(void) {
58 static report_mouse_t old_report = {}; 155 static report_mouse_t old_report = {};
59 156
60 // If you need to do other things, like debugging, this is the place to do it. 157 // If you need to do other things, like debugging, this is the place to do it.
61 if (has_mouse_report_changed(mouseReport, old_report)) { 158 if (has_mouse_report_changed(local_mouse_report, old_report)) {
62 host_mouse_send(&mouseReport); 159 host_mouse_send(&local_mouse_report);
63 } 160 }
64 // send it and 0 it out except for buttons, so those stay until they are explicity over-ridden using update_pointing_device 161 // send it and 0 it out except for buttons, so those stay until they are explicity over-ridden using update_pointing_device
65 mouseReport.x = 0; 162 local_mouse_report.x = 0;
66 mouseReport.y = 0; 163 local_mouse_report.y = 0;
67 mouseReport.v = 0; 164 local_mouse_report.v = 0;
68 mouseReport.h = 0; 165 local_mouse_report.h = 0;
69 166
70 memcpy(&old_report, &mouseReport, sizeof(mouseReport)); 167 memcpy(&old_report, &local_mouse_report, sizeof(local_mouse_report));
71} 168}
72 169
73__attribute__((weak)) void pointing_device_task(void) { 170/**
74 // Gather report info 171 * @brief Adjust mouse report by any optional common pointing configuration defines
75#ifdef POINTING_DEVICE_MOTION_PIN 172 *
76 if (!readPin(POINTING_DEVICE_MOTION_PIN)) 173 * This applies rotation or inversion to the mouse report as selected by the pointing device common configuration defines.
77#endif 174 *
78 mouseReport = pointing_device_driver.get_report(mouseReport); 175 * @param mouse_report[in] takes a report_mouse_t to be adjusted
79 176 * @return report_mouse_t with adjusted values
80 // Support rotation of the sensor data 177 */
178report_mouse_t pointing_device_adjust_by_defines(report_mouse_t mouse_report) {
179 // Support rotation of the sensor data
81#if defined(POINTING_DEVICE_ROTATION_90) || defined(POINTING_DEVICE_ROTATION_180) || defined(POINTING_DEVICE_ROTATION_270) 180#if defined(POINTING_DEVICE_ROTATION_90) || defined(POINTING_DEVICE_ROTATION_180) || defined(POINTING_DEVICE_ROTATION_270)
82 int8_t x = mouseReport.x, y = mouseReport.y; 181 int8_t x = mouse_report.x, y = mouse_report.y;
83# if defined(POINTING_DEVICE_ROTATION_90) 182# if defined(POINTING_DEVICE_ROTATION_90)
84 mouseReport.x = y; 183 mouse_report.x = y;
85 mouseReport.y = -x; 184 mouse_report.y = -x;
86# elif defined(POINTING_DEVICE_ROTATION_180) 185# elif defined(POINTING_DEVICE_ROTATION_180)
87 mouseReport.x = -x; 186 mouse_report.x = -x;
88 mouseReport.y = -y; 187 mouse_report.y = -y;
89# elif defined(POINTING_DEVICE_ROTATION_270) 188# elif defined(POINTING_DEVICE_ROTATION_270)
90 mouseReport.x = -y; 189 mouse_report.x = -y;
91 mouseReport.y = x; 190 mouse_report.y = x;
92# else 191# else
93# error "How the heck did you get here?!" 192# error "How the heck did you get here?!"
94# endif 193# endif
95#endif 194#endif
96 // Support Inverting the X and Y Axises 195 // Support Inverting the X and Y Axises
97#if defined(POINTING_DEVICE_INVERT_X) 196#if defined(POINTING_DEVICE_INVERT_X)
98 mouseReport.x = -mouseReport.x; 197 mouse_report.x = -mouse_report.x;
99#endif 198#endif
100#if defined(POINTING_DEVICE_INVERT_Y) 199#if defined(POINTING_DEVICE_INVERT_Y)
101 mouseReport.y = -mouseReport.y; 200 mouse_report.y = -mouse_report.y;
201#endif
202 return mouse_report;
203}
204
205/**
206 * @brief Retrieves and processes pointing device data.
207 *
208 * This function is part of the keyboard loop and retrieves the mouse report from the pointing device driver.
209 * It applies any optional configuration e.g. rotation or axis inversion and then initiates a send.
210 *
211 */
212__attribute__((weak)) void pointing_device_task(void) {
213#if defined(SPLIT_POINTING_ENABLE)
214 // Don't poll the target side pointing device.
215 if (!is_keyboard_master()) {
216 return;
217 };
218#endif
219
220#if defined(POINTING_DEVICE_TASK_THROTTLE_MS)
221 static uint32_t last_exec = 0;
222 if (timer_elapsed32(last_exec) < POINTING_DEVICE_TASK_THROTTLE_MS) {
223 return;
224 }
225 last_exec = timer_read32();
226#else
227# if defined(SPLIT_POINTING_ENABLE)
228# pragma message("It's recommended you enable a throttle when sharing pointing devices.")
229# endif
230#endif
231
232 // Gather report info
233#ifdef POINTING_DEVICE_MOTION_PIN
234# if defined(SPLIT_POINTING_ENABLE)
235# error POINTING_DEVICE_MOTION_PIN not supported when sharing the pointing device report between sides.
236# endif
237 if (!readPin(POINTING_DEVICE_MOTION_PIN))
102#endif 238#endif
103 239
240#if defined(SPLIT_POINTING_ENABLE)
241# if defined(POINTING_DEVICE_COMBINED)
242 static uint8_t old_buttons = 0;
243 local_mouse_report.buttons = old_buttons;
244 local_mouse_report = pointing_device_driver.get_report(local_mouse_report);
245 old_buttons = local_mouse_report.buttons;
246# elif defined(POINTING_DEVICE_LEFT) || defined(POINTING_DEVICE_RIGHT)
247 local_mouse_report = POINTING_DEVICE_THIS_SIDE ? pointing_device_driver.get_report(local_mouse_report) : shared_mouse_report;
248# else
249# error "You need to define the side(s) the pointing device is on. POINTING_DEVICE_COMBINED / POINTING_DEVICE_LEFT / POINTING_DEVICE_RIGHT"
250# endif
251#else
252 local_mouse_report = pointing_device_driver.get_report(local_mouse_report);
253#endif // defined(SPLIT_POINTING_ENABLE)
254
104 // allow kb to intercept and modify report 255 // allow kb to intercept and modify report
105 mouseReport = pointing_device_task_kb(mouseReport); 256#if defined(SPLIT_POINTING_ENABLE) && defined(POINTING_DEVICE_COMBINED)
257 if (is_keyboard_left()) {
258 local_mouse_report = pointing_device_adjust_by_defines(local_mouse_report);
259 shared_mouse_report = pointing_device_adjust_by_defines_right(shared_mouse_report);
260 } else {
261 local_mouse_report = pointing_device_adjust_by_defines_right(local_mouse_report);
262 shared_mouse_report = pointing_device_adjust_by_defines(shared_mouse_report);
263 }
264 local_mouse_report = is_keyboard_left() ? pointing_device_task_combined_kb(local_mouse_report, shared_mouse_report) : pointing_device_task_combined_kb(shared_mouse_report, local_mouse_report);
265#else
266 local_mouse_report = pointing_device_adjust_by_defines(local_mouse_report);
267 local_mouse_report = pointing_device_task_kb(local_mouse_report);
268#endif
106 // combine with mouse report to ensure that the combined is sent correctly 269 // combine with mouse report to ensure that the combined is sent correctly
107#ifdef MOUSEKEY_ENABLE 270#ifdef MOUSEKEY_ENABLE
108 report_mouse_t mousekey_report = mousekey_get_report(); 271 report_mouse_t mousekey_report = mousekey_get_report();
109 mouseReport.buttons = mouseReport.buttons | mousekey_report.buttons; 272 local_mouse_report.buttons = local_mouse_report.buttons | mousekey_report.buttons;
110#endif 273#endif
111 pointing_device_send(); 274 pointing_device_send();
112} 275}
113 276
114report_mouse_t pointing_device_get_report(void) { return mouseReport; } 277/**
278 * @brief Gets current mouse report used by pointing device task
279 *
280 * @return report_mouse_t
281 */
282report_mouse_t pointing_device_get_report(void) { return local_mouse_report; }
283
284/**
285 * @brief Sets mouse report used be pointing device task
286 *
287 * @param[in] new_mouse_report
288 */
289void pointing_device_set_report(report_mouse_t new_mouse_report) { local_mouse_report = new_mouse_report; }
290
291/**
292 * @brief Gets current pointing device CPI if supported
293 *
294 * Gets current cpi from pointing device driver if supported and returns it as uint16_t
295 *
296 * @return cpi value as uint16_t
297 */
298uint16_t pointing_device_get_cpi(void) {
299#if defined(SPLIT_POINTING_ENABLE)
300 return POINTING_DEVICE_THIS_SIDE ? pointing_device_driver.get_cpi() : shared_cpi;
301#else
302 return pointing_device_driver.get_cpi();
303#endif
304}
115 305
116void pointing_device_set_report(report_mouse_t newMouseReport) { mouseReport = newMouseReport; } 306/**
307 * @brief Set pointing device CPI if supported
308 *
309 * Takes a uint16_t value to set pointing device cpi if supported by driver.
310 *
311 * @param[in] cpi uint16_t value.
312 */
313void pointing_device_set_cpi(uint16_t cpi) {
314#if defined(SPLIT_POINTING_ENABLE)
315 if (POINTING_DEVICE_THIS_SIDE) {
316 pointing_device_driver.set_cpi(cpi);
317 } else {
318 shared_cpi = cpi;
319 }
320#else
321 pointing_device_driver.set_cpi(cpi);
322#endif
323}
117 324
118uint16_t pointing_device_get_cpi(void) { return pointing_device_driver.get_cpi(); } 325#if defined(SPLIT_POINTING_ENABLE) && defined(POINTING_DEVICE_COMBINED)
326/**
327 * @brief Set pointing device CPI if supported
328 *
329 * Takes a bool and uint16_t and allows setting cpi for a single side when using 2 pointing devices with a split keyboard.
330 *
331 * NOTE: Only available when using SPLIT_POINTING_ENABLE and POINTING_DEVICE_COMBINED
332 *
333 * @param[in] left true = left, false = right.
334 * @param[in] cpi uint16_t value.
335 */
336void pointing_device_set_cpi_on_side(bool left, uint16_t cpi) {
337 bool local = (is_keyboard_left() & left) ? true : false;
338 if (local) {
339 pointing_device_driver.set_cpi(cpi);
340 } else {
341 shared_cpi = cpi;
342 }
343}
119 344
120void pointing_device_set_cpi(uint16_t cpi) { pointing_device_driver.set_cpi(cpi); } 345/**
346 * @brief clamps int16_t to int8_t
347 *
348 * @param[in] int16_t value
349 * @return int8_t clamped value
350 */
351static inline int8_t pointing_device_movement_clamp(int16_t value) {
352 if (value < INT8_MIN) {
353 return INT8_MIN;
354 } else if (value > INT8_MAX) {
355 return INT8_MAX;
356 } else {
357 return value;
358 }
359}
360
361/**
362 * @brief combines 2 mouse reports and returns 2
363 *
364 * Combines 2 report_mouse_t structs, clamping movement values to int8_t and ignores report_id then returns the resulting report_mouse_t struct.
365 *
366 * NOTE: Only available when using SPLIT_POINTING_ENABLE and POINTING_DEVICE_COMBINED
367 *
368 * @param[in] left_report left report_mouse_t
369 * @param[in] right_report right report_mouse_t
370 * @return combined report_mouse_t of left_report and right_report
371 */
372report_mouse_t pointing_device_combine_reports(report_mouse_t left_report, report_mouse_t right_report) {
373 left_report.x = pointing_device_movement_clamp((int16_t)left_report.x + right_report.x);
374 left_report.y = pointing_device_movement_clamp((int16_t)left_report.y + right_report.y);
375 left_report.h = pointing_device_movement_clamp((int16_t)left_report.h + right_report.h);
376 left_report.v = pointing_device_movement_clamp((int16_t)left_report.v + right_report.v);
377 left_report.buttons |= right_report.buttons;
378 return left_report;
379}
380
381/**
382 * @brief Adjust mouse report by any optional right pointing configuration defines
383 *
384 * This applies rotation or inversion to the mouse report as selected by the pointing device common configuration defines.
385 *
386 * NOTE: Only available when using SPLIT_POINTING_ENABLE and POINTING_DEVICE_COMBINED
387 *
388 * @param[in] mouse_report report_mouse_t to be adjusted
389 * @return report_mouse_t with adjusted values
390 */
391report_mouse_t pointing_device_adjust_by_defines_right(report_mouse_t mouse_report) {
392 // Support rotation of the sensor data
393# if defined(POINTING_DEVICE_ROTATION_90_RIGHT) || defined(POINTING_DEVICE_ROTATION_RIGHT) || defined(POINTING_DEVICE_ROTATION_RIGHT)
394 int8_t x = mouse_report.x, y = mouse_report.y;
395# if defined(POINTING_DEVICE_ROTATION_90_RIGHT)
396 mouse_report.x = y;
397 mouse_report.y = -x;
398# elif defined(POINTING_DEVICE_ROTATION_180_RIGHT)
399 mouse_report.x = -x;
400 mouse_report.y = -y;
401# elif defined(POINTING_DEVICE_ROTATION_270_RIGHT)
402 mouse_report.x = -y;
403 mouse_report.y = x;
404# else
405# error "How the heck did you get here?!"
406# endif
407# endif
408 // Support Inverting the X and Y Axises
409# if defined(POINTING_DEVICE_INVERT_X_RIGHT)
410 mouse_report.x = -mouse_report.x;
411# endif
412# if defined(POINTING_DEVICE_INVERT_Y_RIGHT)
413 mouse_report.y = -mouse_report.y;
414# endif
415 return mouse_report;
416}
417
418/**
419 * @brief Weak function allowing for keyboard level mouse report modification
420 *
421 * Takes 2 report_mouse_t structs allowing individual modification of sides at keyboard level then returns pointing_device_task_combined_user.
422 *
423 * NOTE: Only available when using SPLIT_POINTING_ENABLE and POINTING_DEVICE_COMBINED
424 *
425 * @param[in] left_report report_mouse_t
426 * @param[in] right_report report_mouse_t
427 * @return pointing_device_task_combined_user(left_report, right_report) by default
428 */
429__attribute__((weak)) report_mouse_t pointing_device_task_combined_kb(report_mouse_t left_report, report_mouse_t right_report) { return pointing_device_task_combined_user(left_report, right_report); }
430
431/**
432 * @brief Weak function allowing for user level mouse report modification
433 *
434 * Takes 2 report_mouse_t structs allowing individual modification of sides at user level then returns pointing_device_combine_reports.
435 *
436 * NOTE: Only available when using SPLIT_POINTING_ENABLE and POINTING_DEVICE_COMBINED
437 *
438 * @param[in] left_report report_mouse_t
439 * @param[in] right_report report_mouse_t
440 * @return pointing_device_combine_reports(left_report, right_report) by default
441 */
442__attribute__((weak)) report_mouse_t pointing_device_task_combined_user(report_mouse_t left_report, report_mouse_t right_report) { return pointing_device_combine_reports(left_report, right_report); }
443#endif
diff --git a/quantum/pointing_device.h b/quantum/pointing_device.h
index 5106c26660..78398d8999 100644
--- a/quantum/pointing_device.h
+++ b/quantum/pointing_device.h
@@ -86,3 +86,16 @@ void pointing_device_init_user(void);
86report_mouse_t pointing_device_task_kb(report_mouse_t mouse_report); 86report_mouse_t pointing_device_task_kb(report_mouse_t mouse_report);
87report_mouse_t pointing_device_task_user(report_mouse_t mouse_report); 87report_mouse_t pointing_device_task_user(report_mouse_t mouse_report);
88uint8_t pointing_device_handle_buttons(uint8_t buttons, bool pressed, pointing_device_buttons_t button); 88uint8_t pointing_device_handle_buttons(uint8_t buttons, bool pressed, pointing_device_buttons_t button);
89report_mouse_t pointing_device_adjust_by_defines(report_mouse_t mouse_report);
90
91#if defined(SPLIT_POINTING_ENABLE)
92void pointing_device_set_shared_report(report_mouse_t report);
93uint16_t pointing_device_get_shared_cpi(void);
94# if defined(POINTING_DEVICE_COMBINED)
95void pointing_device_set_cpi_on_side(bool left, uint16_t cpi);
96report_mouse_t pointing_device_combine_reports(report_mouse_t left_report, report_mouse_t right_report);
97report_mouse_t pointing_device_task_combined_kb(report_mouse_t left_report, report_mouse_t right_report);
98report_mouse_t pointing_device_task_combined_user(report_mouse_t left_report, report_mouse_t right_report);
99report_mouse_t pointing_device_adjust_by_defines_right(report_mouse_t mouse_report);
100# endif //defined(POINTING_DEVICE_COMBINED)
101#endif //defined(SPLIT_POINTING_ENABLE)
diff --git a/quantum/pointing_device_drivers.c b/quantum/pointing_device_drivers.c
index 9ad5e76ba6..0852a0bea7 100644
--- a/quantum/pointing_device_drivers.c
+++ b/quantum/pointing_device_drivers.c
@@ -165,14 +165,13 @@ const pointing_device_driver_t pointing_device_driver = {
165// clang-format on 165// clang-format on
166 166
167#elif defined(POINTING_DEVICE_DRIVER_pimoroni_trackball) 167#elif defined(POINTING_DEVICE_DRIVER_pimoroni_trackball)
168report_mouse_t pimorono_trackball_get_report(report_mouse_t mouse_report) { 168report_mouse_t pimoroni_trackball_get_report(report_mouse_t mouse_report) {
169 static fast_timer_t throttle = 0; 169 static uint16_t debounce = 0;
170 static uint16_t debounce = 0; 170 static uint8_t error_count = 0;
171 static uint8_t error_count = 0; 171 pimoroni_data_t pimoroni_data = {0};
172 pimoroni_data_t pimoroni_data = {0}; 172 static int16_t x_offset = 0, y_offset = 0;
173 static int16_t x_offset = 0, y_offset = 0; 173
174 174 if (error_count < PIMORONI_TRACKBALL_ERROR_COUNT) {
175 if (error_count < PIMORONI_TRACKBALL_ERROR_COUNT && timer_elapsed_fast(throttle) >= PIMORONI_TRACKBALL_INTERVAL_MS) {
176 i2c_status_t status = read_pimoroni_trackball(&pimoroni_data); 175 i2c_status_t status = read_pimoroni_trackball(&pimoroni_data);
177 176
178 if (status == I2C_STATUS_SUCCESS) { 177 if (status == I2C_STATUS_SUCCESS) {
@@ -195,17 +194,16 @@ report_mouse_t pimorono_trackball_get_report(report_mouse_t mouse_report) {
195 } else { 194 } else {
196 error_count++; 195 error_count++;
197 } 196 }
198 throttle = timer_read_fast();
199 } 197 }
200 return mouse_report; 198 return mouse_report;
201} 199}
202 200
203// clang-format off 201// clang-format off
204const pointing_device_driver_t pointing_device_driver = { 202const pointing_device_driver_t pointing_device_driver = {
205 .init = pimironi_trackball_device_init, 203 .init = pimoroni_trackball_device_init,
206 .get_report = pimorono_trackball_get_report, 204 .get_report = pimoroni_trackball_get_report,
207 .set_cpi = NULL, 205 .set_cpi = pimoroni_trackball_set_cpi,
208 .get_cpi = NULL 206 .get_cpi = pimoroni_trackball_get_cpi
209}; 207};
210// clang-format on 208// clang-format on
211#elif defined(POINTING_DEVICE_DRIVER_pmw3360) 209#elif defined(POINTING_DEVICE_DRIVER_pmw3360)
diff --git a/quantum/split_common/transaction_id_define.h b/quantum/split_common/transaction_id_define.h
index 535bc21aea..aa71c3621e 100644
--- a/quantum/split_common/transaction_id_define.h
+++ b/quantum/split_common/transaction_id_define.h
@@ -78,6 +78,12 @@ enum serial_transaction_id {
78 PUT_ST7565, 78 PUT_ST7565,
79#endif // defined(ST7565_ENABLE) && defined(SPLIT_ST7565_ENABLE) 79#endif // defined(ST7565_ENABLE) && defined(SPLIT_ST7565_ENABLE)
80 80
81#if defined(POINTING_DEVICE_ENABLE) && defined(SPLIT_POINTING_ENABLE)
82 GET_POINTING_CHECKSUM,
83 GET_POINTING_DATA,
84 PUT_POINTING_CPI,
85#endif // defined(POINTING_DEVICE_ENABLE) && defined(SPLIT_POINTING_ENABLE)
86
81#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) 87#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
82 PUT_RPC_INFO, 88 PUT_RPC_INFO,
83 PUT_RPC_REQ_DATA, 89 PUT_RPC_REQ_DATA,
diff --git a/quantum/split_common/transactions.c b/quantum/split_common/transactions.c
index 3ff87710e7..9622acb377 100644
--- a/quantum/split_common/transactions.c
+++ b/quantum/split_common/transactions.c
@@ -579,6 +579,82 @@ static void st7565_handlers_slave(matrix_row_t master_matrix[], matrix_row_t sla
579#endif // defined(ST7565_ENABLE) && defined(SPLIT_ST7565_ENABLE) 579#endif // defined(ST7565_ENABLE) && defined(SPLIT_ST7565_ENABLE)
580 580
581//////////////////////////////////////////////////// 581////////////////////////////////////////////////////
582// POINTING
583
584#if defined(POINTING_DEVICE_ENABLE) && defined(SPLIT_POINTING_ENABLE)
585
586static bool pointing_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
587# if defined(POINTING_DEVICE_LEFT)
588 if (is_keyboard_left()) {
589 return true;
590 }
591# elif defined(POINTING_DEVICE_RIGHT)
592 if (!is_keyboard_left()) {
593 return true;
594 }
595# endif
596 static uint32_t last_update = 0;
597 static uint16_t last_cpi = 0;
598 report_mouse_t temp_state;
599 uint16_t temp_cpi;
600 bool okay = read_if_checksum_mismatch(GET_POINTING_CHECKSUM, GET_POINTING_DATA, &last_update, &temp_state, &split_shmem->pointing.report, sizeof(temp_state));
601 if (okay) pointing_device_set_shared_report(temp_state);
602 temp_cpi = pointing_device_get_shared_cpi();
603 if (temp_cpi && memcmp(&last_cpi, &temp_cpi, sizeof(temp_cpi)) != 0) {
604 memcpy(&split_shmem->pointing.cpi, &temp_cpi, sizeof(temp_cpi));
605 okay = transport_write(PUT_POINTING_CPI, &split_shmem->pointing.cpi, sizeof(split_shmem->pointing.cpi));
606 if (okay) {
607 last_cpi = temp_cpi;
608 }
609 }
610 return okay;
611}
612
613extern const pointing_device_driver_t pointing_device_driver;
614
615static void pointing_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
616# if defined(POINTING_DEVICE_LEFT)
617 if (!is_keyboard_left()) {
618 return;
619 }
620# elif defined(POINTING_DEVICE_RIGHT)
621 if (is_keyboard_left()) {
622 return;
623 }
624# endif
625 report_mouse_t temp_report;
626 uint16_t temp_cpi;
627# ifdef POINTING_DEVICE_TASK_THROTTLE_MS
628 static uint32_t last_exec = 0;
629 if (timer_elapsed32(last_exec) < POINTING_DEVICE_TASK_THROTTLE_MS) {
630 return;
631 }
632 last_exec = timer_read32();
633# endif
634 temp_cpi = pointing_device_driver.get_cpi();
635 if (split_shmem->pointing.cpi && memcmp(&split_shmem->pointing.cpi, &temp_cpi, sizeof(temp_cpi)) != 0) {
636 pointing_device_driver.set_cpi(split_shmem->pointing.cpi);
637 }
638 memset(&temp_report, 0, sizeof(temp_report));
639 temp_report = pointing_device_driver.get_report(temp_report);
640 memcpy(&split_shmem->pointing.report, &temp_report, sizeof(temp_report));
641 // Now update the checksum given that the pointing has been written to
642 split_shmem->pointing.checksum = crc8(&temp_report, sizeof(temp_report));
643}
644
645# define TRANSACTIONS_POINTING_MASTER() TRANSACTION_HANDLER_MASTER(pointing)
646# define TRANSACTIONS_POINTING_SLAVE() TRANSACTION_HANDLER_SLAVE(pointing)
647# define TRANSACTIONS_POINTING_REGISTRATIONS [GET_POINTING_CHECKSUM] = trans_target2initiator_initializer(pointing.checksum), [GET_POINTING_DATA] = trans_target2initiator_initializer(pointing.report), [PUT_POINTING_CPI] = trans_initiator2target_initializer(pointing.cpi),
648
649#else // defined(POINTING_DEVICE_ENABLE) && defined(SPLIT_POINTING_ENABLE)
650
651# define TRANSACTIONS_POINTING_MASTER()
652# define TRANSACTIONS_POINTING_SLAVE()
653# define TRANSACTIONS_POINTING_REGISTRATIONS
654
655#endif // defined(POINTING_DEVICE_ENABLE) && defined(SPLIT_POINTING_ENABLE)
656
657////////////////////////////////////////////////////
582 658
583uint8_t dummy; 659uint8_t dummy;
584split_transaction_desc_t split_transaction_table[NUM_TOTAL_TRANSACTIONS] = { 660split_transaction_desc_t split_transaction_table[NUM_TOTAL_TRANSACTIONS] = {
@@ -604,6 +680,7 @@ split_transaction_desc_t split_transaction_table[NUM_TOTAL_TRANSACTIONS] = {
604 TRANSACTIONS_WPM_REGISTRATIONS 680 TRANSACTIONS_WPM_REGISTRATIONS
605 TRANSACTIONS_OLED_REGISTRATIONS 681 TRANSACTIONS_OLED_REGISTRATIONS
606 TRANSACTIONS_ST7565_REGISTRATIONS 682 TRANSACTIONS_ST7565_REGISTRATIONS
683 TRANSACTIONS_POINTING_REGISTRATIONS
607// clang-format on 684// clang-format on
608 685
609#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) 686#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
@@ -629,6 +706,7 @@ bool transactions_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix
629 TRANSACTIONS_WPM_MASTER(); 706 TRANSACTIONS_WPM_MASTER();
630 TRANSACTIONS_OLED_MASTER(); 707 TRANSACTIONS_OLED_MASTER();
631 TRANSACTIONS_ST7565_MASTER(); 708 TRANSACTIONS_ST7565_MASTER();
709 TRANSACTIONS_POINTING_MASTER();
632 return true; 710 return true;
633} 711}
634 712
@@ -647,6 +725,7 @@ void transactions_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[
647 TRANSACTIONS_WPM_SLAVE(); 725 TRANSACTIONS_WPM_SLAVE();
648 TRANSACTIONS_OLED_SLAVE(); 726 TRANSACTIONS_OLED_SLAVE();
649 TRANSACTIONS_ST7565_SLAVE(); 727 TRANSACTIONS_ST7565_SLAVE();
728 TRANSACTIONS_POINTING_SLAVE();
650} 729}
651 730
652#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) 731#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
diff --git a/quantum/split_common/transport.h b/quantum/split_common/transport.h
index 1d4f6ed0cd..31b804908b 100644
--- a/quantum/split_common/transport.h
+++ b/quantum/split_common/transport.h
@@ -106,6 +106,15 @@ typedef struct _split_mods_sync_t {
106} split_mods_sync_t; 106} split_mods_sync_t;
107#endif // SPLIT_MODS_ENABLE 107#endif // SPLIT_MODS_ENABLE
108 108
109#if defined(POINTING_DEVICE_ENABLE) && defined(SPLIT_POINTING_ENABLE)
110# include "pointing_device.h"
111typedef struct _split_slave_pointing_sync_t {
112 uint8_t checksum;
113 report_mouse_t report;
114 uint16_t cpi;
115} split_slave_pointing_sync_t;
116#endif // defined(POINTING_DEVICE_ENABLE) && defined(SPLIT_POINTING_ENABLE)
117
109#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) 118#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
110typedef struct _rpc_sync_info_t { 119typedef struct _rpc_sync_info_t {
111 int8_t transaction_id; 120 int8_t transaction_id;
@@ -173,6 +182,10 @@ typedef struct _split_shared_memory_t {
173 uint8_t current_st7565_state; 182 uint8_t current_st7565_state;
174#endif // ST7565_ENABLE(OLED_ENABLE) && defined(SPLIT_ST7565_ENABLE) 183#endif // ST7565_ENABLE(OLED_ENABLE) && defined(SPLIT_ST7565_ENABLE)
175 184
185#if defined(POINTING_DEVICE_ENABLE) && defined(SPLIT_POINTING_ENABLE)
186 split_slave_pointing_sync_t pointing;
187#endif // defined(POINTING_DEVICE_ENABLE) && defined(SPLIT_POINTING_ENABLE)
188
176#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) 189#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
177 rpc_sync_info_t rpc_info; 190 rpc_sync_info_t rpc_info;
178 uint8_t rpc_m2s_buffer[RPC_M2S_BUFFER_SIZE]; 191 uint8_t rpc_m2s_buffer[RPC_M2S_BUFFER_SIZE];