diff options
| author | Dasky <32983009+daskygit@users.noreply.github.com> | 2021-12-27 01:05:51 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-12-27 12:05:51 +1100 |
| commit | 7f7364c55912879baaff8fafca550d02f17b4d44 (patch) | |
| tree | 8afd414f6b202a126632a8c047dcf200312c78ff /docs | |
| parent | 76a673233c8cb3d97130a6dece364c24b29f5fd7 (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>
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/ChangeLog/20220226/PR15304.md | 13 | ||||
| -rw-r--r-- | docs/feature_pointing_device.md | 116 | ||||
| -rw-r--r-- | docs/feature_split_keyboard.md | 8 |
3 files changed, 126 insertions, 11 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 | |||
| 3 | Pointing devices can now be shared across a split keyboard with support for a single pointing device or a pointing device on each side. | ||
| 4 | |||
| 5 | This 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 | |||
| 13 | See 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 | |||
| 188 | The 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 | |||
| 224 | The 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 | ||
| 244 | Recall 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. | 279 | Recall 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 | |||
| 283 | The 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 | |||
| 287 | The 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 | |||
| 291 | static bool scrolling_mode = false; | ||
| 292 | |||
| 293 | layer_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 | |||
| 309 | report_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 | |||
| 323 | The following example requires `POINTING_DEVICE_COMBINED` and sets the left side pointing device to scroll only. | ||
| 324 | |||
| 325 | ```c | ||
| 326 | void 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 | |||
| 331 | report_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 | ||
| 267 | This 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. | 267 | This 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 | |||
| 273 | This 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 | ||
| 271 | QMK'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. | 279 | QMK'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. |
