forked from mirrors/qmk_userspace
[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>
This commit is contained in:
parent
76a673233c
commit
7f7364c559
11 changed files with 625 additions and 65 deletions
13
docs/ChangeLog/20220226/PR15304.md
Normal file
13
docs/ChangeLog/20220226/PR15304.md
Normal file
|
@ -0,0 +1,13 @@
|
|||
### Split Common core now supports Pointing Devices ([#15304](https://github.com/qmk/qmk_firmware/pull/15304))
|
||||
|
||||
Pointing devices can now be shared across a split keyboard with support for a single pointing device or a pointing device on each side.
|
||||
|
||||
This feature can be enabled with `#define SPLIT_POINTING_ENABLE` and one of the following options:
|
||||
|
||||
| Setting | Description |
|
||||
|---------------------------|------------------------------------|
|
||||
|`POINTING_DEVICE_LEFT` | Pointing device on the left side |
|
||||
|`POINTING_DEVICE_RIGHT` | Pointing device on the right side |
|
||||
|`POINTING_DEVICE_COMBINED` | Pointing device on both sides |
|
||||
|
||||
See the [Pointing Device](../feature_pointing_device.md) documentation for further configuration options.
|
|
@ -127,11 +127,10 @@ The Pimoroni Trackball module is a I2C based breakout board with an RGB enable t
|
|||
| Setting | Description | Default |
|
||||
|-------------------------------------|------------------------------------------------------------------------------------|---------|
|
||||
|`PIMORONI_TRACKBALL_ADDRESS` | (Required) Sets the I2C Address for the Pimoroni Trackball. | `0x0A` |
|
||||
|`PIMORONI_TRACKBALL_TIMEOUT` | (Optional) The timeout for i2c communication with the trackpad in milliseconds. | `100` |
|
||||
|`PIMORONI_TRACKBALL_INTERVAL_MS` | (Optional) The update/read interval for the sensor in milliseconds. | `8` |
|
||||
|`PIMORONI_TRACKBALL_TIMEOUT` | (Optional) The timeout for i2c communication with the trackball in milliseconds. | `100` |
|
||||
|`PIMORONI_TRACKBALL_SCALE` | (Optional) The multiplier used to generate reports from the sensor. | `5` |
|
||||
|`PIMORONI_TRACKBALL_DEBOUNCE_CYCLES` | (Optional) The number of scan cycles used for debouncing on the ball press. | `20` |
|
||||
|`PIMORONI_TRACKBALL_ERROR_COUNT` | (Optional) Specifies the number of read/write errors until the sensor is disabled. | `10` |
|
||||
|`PIMORONI_TRACKBALL_ERROR_COUNT` | (Optional) Specifies the number of read/write errors until the sensor is disabled. | `10` |
|
||||
|
||||
### PMW 3360 Sensor
|
||||
|
||||
|
@ -171,14 +170,35 @@ void pointing_device_driver_set_cpi(uint16_t cpi) {}
|
|||
|
||||
## Common Configuration
|
||||
|
||||
| Setting | Description | Default |
|
||||
|-------------------------------|-----------------------------------------------------------------------|---------------|
|
||||
|`POINTING_DEVICE_ROTATION_90` | (Optional) Rotates the X and Y data by 90 degrees. | _not defined_ |
|
||||
|`POINTING_DEVICE_ROTATION_180` | (Optional) Rotates the X and Y data by 180 degrees. | _not defined_ |
|
||||
|`POINTING_DEVICE_ROTATION_270` | (Optional) Rotates the X and Y data by 270 degrees. | _not defined_ |
|
||||
|`POINTING_DEVICE_INVERT_X` | (Optional) Inverts the X axis report. | _not defined_ |
|
||||
|`POINTING_DEVICE_INVERT_Y` | (Optional) Inverts the Y axis report. | _not defined_ |
|
||||
|`POINTING_DEVICE_MOTION_PIN` | (Optional) If supported, will only read from sensor if pin is active. | _not defined_ |
|
||||
| Setting | Description | Default |
|
||||
|----------------------------------|-----------------------------------------------------------------------|-------------------|
|
||||
|`POINTING_DEVICE_ROTATION_90` | (Optional) Rotates the X and Y data by 90 degrees. | _not defined_ |
|
||||
|`POINTING_DEVICE_ROTATION_180` | (Optional) Rotates the X and Y data by 180 degrees. | _not defined_ |
|
||||
|`POINTING_DEVICE_ROTATION_270` | (Optional) Rotates the X and Y data by 270 degrees. | _not defined_ |
|
||||
|`POINTING_DEVICE_INVERT_X` | (Optional) Inverts the X axis report. | _not defined_ |
|
||||
|`POINTING_DEVICE_INVERT_Y` | (Optional) Inverts the Y axis report. | _not defined_ |
|
||||
|`POINTING_DEVICE_MOTION_PIN` | (Optional) If supported, will only read from sensor if pin is active. | _not defined_ |
|
||||
|`POINTING_DEVICE_TASK_THROTTLE_MS` | (Optional) Limits the frequency that the sensor is polled for motion. | _not defined_ |
|
||||
|
||||
!> 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.
|
||||
|
||||
|
||||
## Split Keyboard Configuration
|
||||
|
||||
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.
|
||||
|
||||
| Setting | Description | Default |
|
||||
|----------------------------------------|-----------------------------------------------------------------------|---------------|
|
||||
|`POINTING_DEVICE_LEFT` | Pointing device on the left side (Required - pick one only) | _not defined_ |
|
||||
|`POINTING_DEVICE_RIGHT` | Pointing device on the right side (Required - pick one only) | _not defined_ |
|
||||
|`POINTING_DEVICE_COMBINED` | Pointing device on both sides (Required - pick one only) | _not defined_ |
|
||||
|`POINTING_DEVICE_ROTATION_90_RIGHT` | (Optional) Rotates the X and Y data by 90 degrees. | _not defined_ |
|
||||
|`POINTING_DEVICE_ROTATION_180_RIGHT` | (Optional) Rotates the X and Y data by 180 degrees. | _not defined_ |
|
||||
|`POINTING_DEVICE_ROTATION_270_RIGHT` | (Optional) Rotates the X and Y data by 270 degrees. | _not defined_ |
|
||||
|`POINTING_DEVICE_INVERT_X_RIGHT` | (Optional) Inverts the X axis report. | _not defined_ |
|
||||
|`POINTING_DEVICE_INVERT_Y_RIGHT` | (Optional) Inverts the Y axis report. | _not defined_ |
|
||||
|
||||
!> 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.
|
||||
|
||||
|
||||
## Callbacks and Functions
|
||||
|
@ -196,6 +216,21 @@ void pointing_device_driver_set_cpi(uint16_t cpi) {}
|
|||
| `pointing_device_set_report(mouse_report)` | Sets the mouse report to the assigned `mouse_report_t` data structured passed to the function. |
|
||||
| `pointing_device_send(void)` | Sends the current mouse report to the host system. Function can be replaced. |
|
||||
| `has_mouse_report_changed(old, new)` | Compares the old and new `mouse_report_t` data and returns true only if it has changed. |
|
||||
| `pointing_device_adjust_by_defines(mouse_report)` | Applies rotations and invert configurations to a raw mouse report. |
|
||||
|
||||
|
||||
## Split Keyboard Callbacks and Functions
|
||||
|
||||
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)
|
||||
|
||||
| Function | Description |
|
||||
|-----------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------|
|
||||
| `pointing_device_set_shared_report(mouse_report)` | Sets the shared mouse report to the assigned `mouse_report_t` data structured passed to the function. |
|
||||
| `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` |
|
||||
| `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) |
|
||||
| `pointing_device_task_combined_kb(left_report, right_report)` | Callback, so keyboard code can intercept and modify the data. Returns a combined mouse report. |
|
||||
| `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` |
|
||||
| `pointing_device_adjust_by_defines_right(mouse_report)` | Applies right side rotations and invert configurations to a raw mouse report. |
|
||||
|
||||
|
||||
# Manipulating Mouse Reports
|
||||
|
@ -242,3 +277,62 @@ case MS_SPECIAL:
|
|||
```
|
||||
|
||||
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.
|
||||
|
||||
## Split Examples
|
||||
|
||||
The following examples make use the `SPLIT_POINTING_ENABLE` functionality and show how to manipulate the mouse report for a scrolling mode.
|
||||
|
||||
### Single Pointing Device
|
||||
|
||||
The following example will work with either `POINTING_DEVICE_LEFT` or `POINTING_DEVICE_RIGHT` and enables scrolling mode while on a particular layer.
|
||||
|
||||
```c
|
||||
|
||||
static bool scrolling_mode = false;
|
||||
|
||||
layer_state_t layer_state_set_user(layer_state_t state) {
|
||||
switch (get_highest_layer(state)) {
|
||||
case _RAISE: // If we're on the _RAISE layer enable scrolling mode
|
||||
scrolling_mode = true;
|
||||
pointing_device_set_cpi(2000);
|
||||
break;
|
||||
default:
|
||||
if (scrolling_mode) { // check if we were scrolling before and set disable if so
|
||||
scrolling_mode = false;
|
||||
pointing_device_set_cpi(8000);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
report_mouse_t pointing_device_task_user(report_mouse_t mouse_report) {
|
||||
if (scrolling_mode) {
|
||||
mouse_report.h = mouse_report.x;
|
||||
mouse_report.v = mouse_report.y;
|
||||
mouse_report.x = 0;
|
||||
mouse_report.y = 0;
|
||||
}
|
||||
return mouse_report;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### Combined Pointing Devices
|
||||
|
||||
The following example requires `POINTING_DEVICE_COMBINED` and sets the left side pointing device to scroll only.
|
||||
|
||||
```c
|
||||
void keyboard_post_init_user(void) {
|
||||
pointing_device_set_cpi_on_side(true, 1000); //Set cpi on left side to a low value for slower scrolling.
|
||||
pointing_device_set_cpi_on_side(false, 8000); //Set cpi on right side to a reasonable value for mousing.
|
||||
}
|
||||
|
||||
report_mouse_t pointing_device_task_combined_user(report_mouse_t left_report, report_mouse_t right_report) {
|
||||
left_report.h = left_report.x;
|
||||
left_report.v = left_report.y;
|
||||
left_report.x = 0;
|
||||
left_report.y = 0;
|
||||
return pointing_device_combine_reports(left_report, right_report);
|
||||
}
|
||||
```
|
||||
|
|
|
@ -266,6 +266,14 @@ This enables transmitting the current OLED on/off status to the slave side of th
|
|||
|
||||
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.
|
||||
|
||||
```c
|
||||
#define SPLIT_POINTING_ENABLE
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
!> There is additional required configuration for `SPLIT_POINTING_ENABLE` outlined in the [pointing device documentation](feature_pointing_device.md?id=split-keyboard-configuration).
|
||||
|
||||
### Custom data sync between sides :id=custom-data-sync
|
||||
|
||||
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.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue