summaryrefslogtreecommitdiffstats
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/ChangeLog/20220226/PR15304.md13
-rw-r--r--docs/compatible_microcontrollers.md15
-rw-r--r--docs/feature_combo.md42
-rw-r--r--docs/feature_debounce_type.md1
-rw-r--r--docs/feature_grave_esc.md10
-rw-r--r--docs/feature_haptic_feedback.md4
-rw-r--r--docs/feature_key_lock.md3
-rw-r--r--docs/feature_mouse_keys.md18
-rw-r--r--docs/feature_pointing_device.md172
-rw-r--r--docs/feature_split_keyboard.md8
-rw-r--r--docs/feature_wpm.md2
-rw-r--r--docs/internals_gpio_control.md24
-rw-r--r--docs/keycodes.md17
-rw-r--r--docs/keycodes_magic.md1
-rw-r--r--docs/platformdev_chibios_earlyinit.md1
-rw-r--r--docs/quantum_keycodes.md10
-rw-r--r--docs/reference_info_json.md6
17 files changed, 270 insertions, 77 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 @@
+### 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.
diff --git a/docs/compatible_microcontrollers.md b/docs/compatible_microcontrollers.md
index 1f46a1c634..b74d49d0e3 100644
--- a/docs/compatible_microcontrollers.md
+++ b/docs/compatible_microcontrollers.md
@@ -1,6 +1,6 @@
# Compatible Microcontrollers
-QMK runs on any USB-capable AVR or ARM microcontroller with enough flash space - generally 32kB or more, though it will *just* squeeze into 16kB with most features disabled.
+QMK runs on any USB-capable AVR or ARM microcontroller with enough flash space - generally 32kB+ for AVR, and 64kB+ for ARM. With significant disabling of features, QMK may *just* squeeze into 16kB AVR MCUs.
## Atmel AVR
@@ -8,7 +8,11 @@ The following use [LUFA](https://www.fourwalledcubicle.com/LUFA.php) as the USB
* [ATmega16U2](https://www.microchip.com/wwwproducts/en/ATmega16U2) / [ATmega32U2](https://www.microchip.com/wwwproducts/en/ATmega32U2)
* [ATmega16U4](https://www.microchip.com/wwwproducts/en/ATmega16U4) / [ATmega32U4](https://www.microchip.com/wwwproducts/en/ATmega32U4)
+ * SparkFun Pro Micro (and clones)
+ * PJRC Teensy 2.0
+ * Adafruit Feather 32U4
* [AT90USB64](https://www.microchip.com/wwwproducts/en/AT90USB646) / [AT90USB128](https://www.microchip.com/wwwproducts/en/AT90USB1286)
+ * PJRC Teensy++ 2.0
* [AT90USB162](https://www.microchip.com/wwwproducts/en/AT90USB162)
Certain MCUs which do not have native USB will use [V-USB](https://www.obdev.at/products/vusb/index.html) instead:
@@ -25,11 +29,15 @@ You can also use any ARM chip with USB that [ChibiOS](https://www.chibios.org) s
* [STM32F0x2](https://www.st.com/en/microcontrollers-microprocessors/stm32f0x2.html)
* [STM32F103](https://www.st.com/en/microcontrollers-microprocessors/stm32f103.html)
+ * Bluepill (with STM32duino bootloader)
* [STM32F303](https://www.st.com/en/microcontrollers-microprocessors/stm32f303.html)
+ * QMK Proton-C
* [STM32F401](https://www.st.com/en/microcontrollers-microprocessors/stm32f401.html)
+ * WeAct Blackpill
* [STM32F405](https://www.st.com/en/microcontrollers-microprocessors/stm32f405-415.html)
* [STM32F407](https://www.st.com/en/microcontrollers-microprocessors/stm32f407-417.html)
* [STM32F411](https://www.st.com/en/microcontrollers-microprocessors/stm32f411.html)
+ * WeAct Blackpill
* [STM32F446](https://www.st.com/en/microcontrollers-microprocessors/stm32f446.html)
* [STM32G431](https://www.st.com/en/microcontrollers-microprocessors/stm32g4x1.html)
* [STM32G474](https://www.st.com/en/microcontrollers-microprocessors/stm32g4x4.html)
@@ -45,13 +53,16 @@ You can also use any ARM chip with USB that [ChibiOS](https://www.chibios.org) s
### NXP (Kinetis)
* [MKL26Z64](https://www.nxp.com/products/processors-and-microcontrollers/arm-microcontrollers/general-purpose-mcus/kl-series-cortex-m0-plus/kinetis-kl2x-72-96-mhz-usb-ultra-low-power-microcontrollers-mcus-based-on-arm-cortex-m0-plus-core:KL2x)
+ * PJRC Teensy LC
* [MK20DX128](https://www.nxp.com/products/processors-and-microcontrollers/arm-microcontrollers/general-purpose-mcus/k-series-cortex-m4/k2x-usb/kinetis-k20-50-mhz-full-speed-usb-mixed-signal-integration-microcontrollers-based-on-arm-cortex-m4-core:K20_50)
* [MK20DX256](https://www.nxp.com/products/processors-and-microcontrollers/arm-microcontrollers/general-purpose-mcus/k-series-cortex-m4/k2x-usb/kinetis-k20-72-mhz-full-speed-usb-mixed-signal-integration-microcontrollers-mcus-based-on-arm-cortex-m4-core:K20_72)
+ * PJRC Teensy 3.2
* [MK66FX1M0](https://www.nxp.com/products/processors-and-microcontrollers/arm-microcontrollers/general-purpose-mcus/k-series-cortex-m4/k6x-ethernet/kinetis-k66-180-mhz-dual-high-speed-full-speed-usbs-2mb-flash-microcontrollers-mcus-based-on-arm-cortex-m4-core:K66_180)
+ * PJRC Teensy 3.6
## Atmel ATSAM
-There is limited support for one of Atmel's ATSAM microcontrollers, that being the [ATSAMD51J18A](https://www.microchip.com/wwwproducts/en/ATSAMD51J18A) used by the [Massdrop keyboards](https://github.com/qmk/qmk_firmware/tree/master/keyboards/massdrop).
+There is limited support for one of Atmel's ATSAM microcontrollers, that being the [ATSAMD51J18A](https://www.microchip.com/wwwproducts/en/ATSAMD51J18A) used by the [Massdrop keyboards](https://github.com/qmk/qmk_firmware/tree/master/keyboards/massdrop). However, it is not recommended to design a board with this microcontroller as the support is quite specialized to Massdrop hardware.
## RISC-V
diff --git a/docs/feature_combo.md b/docs/feature_combo.md
index 47128c431b..c0e10f09d5 100644
--- a/docs/feature_combo.md
+++ b/docs/feature_combo.md
@@ -141,10 +141,13 @@ Processing combos has two buffers, one for the key presses, another for the comb
## Modifier Combos
If a combo resolves to a Modifier, the window for processing the combo can be extended independently from normal combos. By default, this is disabled but can be enabled with `#define COMBO_MUST_HOLD_MODS`, and the time window can be configured with `#define COMBO_HOLD_TERM 150` (default: `TAPPING_TERM`). With `COMBO_MUST_HOLD_MODS`, you cannot tap the combo any more which makes the combo less prone to misfires.
-## Per Combo Timing, Holding and Tapping
-For each combo, it is possible to configure the time window it has to pressed in, if it needs to be held down, or if it needs to be tapped.
+## Strict key press order
+By defining `COMBO_MUST_PRESS_IN_ORDER` combos only activate when the keys are pressed in the same order as they are defined in the key array.
-For example, tap-only combos are useful if any (or all) of the underlying keys is a Mod-Tap or a Layer-Tap key. When you tap the combo, you get the combo result. When you press the combo and hold it down, the combo doesn't actually activate. Instead the keys are processed separately as if the combo wasn't even there.
+## Per Combo Timing, Holding, Tapping and Key Press Order
+For each combo, it is possible to configure the time window it has to pressed in, if it needs to be held down, if it needs to be tapped, or if its keys need to be pressed in order.
+
+For example, tap-only combos are useful if any (or all) of the underlying keys are mod-tap or layer-tap keys. When you tap the combo, you get the combo result. When you press the combo and hold it down, the combo doesn't activate. Instead the keys are processed separately as if the combo wasn't even there.
In order to use these features, the following configuration options and functions need to be defined. Coming up with useful timings and configuration is left as an exercise for the reader.
@@ -153,6 +156,7 @@ In order to use these features, the following configuration options and function
| `COMBO_TERM_PER_COMBO` | uint16_t get_combo_term(uint16_t index, combo_t \*combo) | Optional per-combo timeout window. (default: `COMBO_TERM`) |
| `COMBO_MUST_HOLD_PER_COMBO` | bool get_combo_must_hold(uint16_t index, combo_t \*combo) | Controls if a given combo should fire immediately on tap or if it needs to be held. (default: `false`) |
| `COMBO_MUST_TAP_PER_COMBO` | bool get_combo_must_tap(uint16_t index, combo_t \*combo) | Controls if a given combo should fire only if tapped within `COMBO_HOLD_TERM`. (default: `false`) |
+| `COMBO_MUST_PRESS_IN_ORDER_PER_COMBO` | bool get_combo_must_press_in_order(uint16_t index, combo_t \*combo) | Controls if a given combo should fire only if its keys are pressed in order. (default: `true`) |
Examples:
```c
@@ -216,6 +220,38 @@ bool get_combo_must_tap(uint16_t index, combo_t *combo) {
return false;
}
+
+bool get_combo_must_press_in_order(uint16_t combo_index, combo_t *combo) {
+ switch (combo_index) {
+ /* List combos here that you want to only activate if their keys
+ * are pressed in the same order as they are defined in the combo's key
+ * array. */
+ case COMBO_NAME_HERE:
+ return true;
+ default:
+ return false;
+ }
+}
+```
+
+## Generic hook to (dis)allow a combo activation
+
+By defining `COMBO_SHOULD_TRIGGER` and its companying function `bool combo_should_trigger(uint16_t combo_index, combo_t *combo, uint16_t keycode, keyrecord_t *record)` you can block or allow combos to activate on the conditions of your choice.
+For example, you could disallow some combos on the base layer and allow them on another. Or disable combos on the home row when a timer is running.
+
+Examples:
+```c
+bool combo_should_trigger(uint16_t combo_index, combo_t *combo, uint16_t keycode, keyrecord_t *record) {
+ /* Disable combo `SOME_COMBO` on layer `_LAYER_A` */
+ switch (combo_index) {
+ case SOME_COMBO:
+ if (layer_state_is(_LAYER_A)) {
+ return false;
+ }
+ }
+
+ return true;
+}
```
## Variable Length Combos
diff --git a/docs/feature_debounce_type.md b/docs/feature_debounce_type.md
index f37a785b1e..9cd736a24a 100644
--- a/docs/feature_debounce_type.md
+++ b/docs/feature_debounce_type.md
@@ -116,6 +116,7 @@ Where name of algorithm is one of:
For use in keyboards where refreshing ```NUM_KEYS``` 8-bit counters is computationally expensive / low scan rate, and fingers usually only hit one row at a time. This could be
appropriate for the ErgoDox models; the matrix is rotated 90°, and hence its "rows" are really columns, and each finger only hits a single "row" at a time in normal use.
* ```sym_eager_pk``` - debouncing per key. On any state change, response is immediate, followed by ```DEBOUNCE``` milliseconds of no further input for that key
+* ```sym_defer_pr``` - debouncing per row. On any state change, a per-row timer is set. When ```DEBOUNCE``` milliseconds of no changes have occurred on that row, the entire row is pushed. Can improve responsiveness over `sym_defer_g` while being less susceptible than per-key debouncers to noise.
* ```sym_defer_pk``` - debouncing per key. On any state change, a per-key timer is set. When ```DEBOUNCE``` milliseconds of no changes have occurred on that key, the key status change is pushed.
* ```asym_eager_defer_pk``` - debouncing per key. On a key-down state change, response is immediate, followed by ```DEBOUNCE``` milliseconds of no further input for that key. On a key-up state change, a per-key timer is set. When ```DEBOUNCE``` milliseconds of no changes have occurred on that key, the key-up status change is pushed.
diff --git a/docs/feature_grave_esc.md b/docs/feature_grave_esc.md
index f135b1dede..09d098ee4e 100644
--- a/docs/feature_grave_esc.md
+++ b/docs/feature_grave_esc.md
@@ -4,17 +4,17 @@ If you're using a 60% keyboard, or any other layout with no F-row, you will have
## Usage
-Replace the `KC_GRV` key in your keymap (usually to the left of the `1` key) with `KC_GESC`. Most of the time this key will output `KC_ESC` when pressed. However, when Shift or GUI are held down it will output `KC_GRV` instead.
+Replace the `KC_GRV` key in your keymap (usually to the left of the `1` key) with `QK_GESC`. Most of the time this key will output `KC_ESC` when pressed. However, when Shift or GUI are held down it will output `KC_GRV` instead.
## What Your OS Sees
-If Mary presses GESC on her keyboard, the OS will see an KC_ESC character. Now if Mary holds Shift down and presses GESC it will output `~`, or a shifted backtick. Now if she holds GUI/CMD/WIN, it will output a simple <code>&#96;</code> character.
+If Mary presses `QK_GESC` on her keyboard, the OS will see an KC_ESC character. Now if Mary holds Shift down and presses `QK_GESC` it will output `~`, or a shifted backtick. Now if she holds GUI/CMD/WIN, it will output a simple <code>&#96;</code> character.
## Keycodes
-|Key |Aliases |Description |
-|---------|-----------|------------------------------------------------------------------|
-|`KC_GESC`|`GRAVE_ESC`|Escape when pressed, <code>&#96;</code> when Shift or GUI are held|
+|Key |Aliases |Description |
+|-----------------|---------|------------------------------------------------------------------|
+|`QK_GRAVE_ESCAPE`|`QK_GESC`|Escape when pressed, <code>&#96;</code> when Shift or GUI are held|
### Caveats
diff --git a/docs/feature_haptic_feedback.md b/docs/feature_haptic_feedback.md
index c8c74cb8f0..bbdf7e122c 100644
--- a/docs/feature_haptic_feedback.md
+++ b/docs/feature_haptic_feedback.md
@@ -167,7 +167,7 @@ List of waveform sequences from the datasheet:
```
#define DRV_GREETING *sequence name or number*
```
-If haptic feedback is enabled, the keyboard will vibrate to a specific sqeuence during startup. That can be selected using the following define:
+If haptic feedback is enabled, the keyboard will vibrate to a specific sequence during startup. That can be selected using the following define:
```
#define DRV_MODE_DEFAULT *sequence name or number*
@@ -207,4 +207,4 @@ With the entry of `#define NO_HAPTIC_LOCKKEYS` in config.h, none of the followin
With the entry of `#define NO_HAPTIC_NAV` in config.h, none of the following keys will trigger a feedback: Print Screen, Pause, Insert, Delete, Page Down, Page Up, Left Arrow, Up Arrow, Right Arrow, Down Arrow, End, Home.
### NO_HAPTIC_NUMERIC
-With the entry of `#define NO_HAPTIC_NUMERIC` in config.h, none of the following keys between 0 and 9 (KC_1 ... KC_0) will trigger a feedback. \ No newline at end of file
+With the entry of `#define NO_HAPTIC_NUMERIC` in config.h, none of the following keys between 0 and 9 (KC_1 ... KC_0) will trigger a feedback.
diff --git a/docs/feature_key_lock.md b/docs/feature_key_lock.md
index 8e6e29f0e6..7681394229 100644
--- a/docs/feature_key_lock.md
+++ b/docs/feature_key_lock.md
@@ -19,4 +19,5 @@ First, enable Key Lock by setting `KEY_LOCK_ENABLE = yes` in your `rules.mk`. Th
Key Lock is only able to hold standard action keys and [One Shot modifier](one_shot_keys.md) keys (for example, if you have your Shift defined as `OSM(KC_LSFT)`).
This does not include any of the QMK special functions (except One Shot modifiers), or shifted versions of keys such as `KC_LPRN`. If it's in the [Basic Keycodes](keycodes_basic.md) list, it can be held.
-Switching layers will not cancel the Key Lock.
+Switching layers will not cancel the Key Lock. The Key Lock can be cancelled by calling the `cancel_key_lock()` function.
+
diff --git a/docs/feature_mouse_keys.md b/docs/feature_mouse_keys.md
index 8e2a3a4cd1..a9fa71abdc 100644
--- a/docs/feature_mouse_keys.md
+++ b/docs/feature_mouse_keys.md
@@ -59,13 +59,13 @@ This is the default mode. You can adjust the cursor and scrolling acceleration u
|Define |Default|Description |
|----------------------------|-------|---------------------------------------------------------|
-|`MOUSEKEY_DELAY` |300 |Delay between pressing a movement key and cursor movement|
-|`MOUSEKEY_INTERVAL` |50 |Time between cursor movements in milliseconds |
-|`MOUSEKEY_MOVE_DELTA` |5 |Step size |
+|`MOUSEKEY_DELAY` |10 |Delay between pressing a movement key and cursor movement|
+|`MOUSEKEY_INTERVAL` |20 |Time between cursor movements in milliseconds |
+|`MOUSEKEY_MOVE_DELTA` |8 |Step size |
|`MOUSEKEY_MAX_SPEED` |10 |Maximum cursor speed at which acceleration stops |
-|`MOUSEKEY_TIME_TO_MAX` |20 |Time until maximum cursor speed is reached |
-|`MOUSEKEY_WHEEL_DELAY` |300 |Delay between pressing a wheel key and wheel movement |
-|`MOUSEKEY_WHEEL_INTERVAL` |100 |Time between wheel movements |
+|`MOUSEKEY_TIME_TO_MAX` |30 |Time until maximum cursor speed is reached |
+|`MOUSEKEY_WHEEL_DELAY` |10 |Delay between pressing a wheel key and wheel movement |
+|`MOUSEKEY_WHEEL_INTERVAL` |80 |Time between wheel movements |
|`MOUSEKEY_WHEEL_MAX_SPEED` |8 |Maximum number of scroll steps per scroll action |
|`MOUSEKEY_WHEEL_TIME_TO_MAX`|40 |Time until maximum scroll speed is reached |
@@ -85,9 +85,9 @@ This is an extension of the accelerated mode. The kinetic mode uses a quadratic
|Define |Default |Description |
|--------------------------------------|---------|---------------------------------------------------------------|
|`MK_KINETIC_SPEED` |undefined|Enable kinetic mode |
-|`MOUSEKEY_DELAY` |8 |Delay between pressing a movement key and cursor movement |
-|`MOUSEKEY_INTERVAL` |8 |Time between cursor movements in milliseconds |
-|`MOUSEKEY_MOVE_DELTA` |25 |Step size for accelerating from initial to base speed |
+|`MOUSEKEY_DELAY` |5 |Delay between pressing a movement key and cursor movement |
+|`MOUSEKEY_INTERVAL` |10 |Time between cursor movements in milliseconds |
+|`MOUSEKEY_MOVE_DELTA` |5 |Step size for accelerating from initial to base speed |
|`MOUSEKEY_INITIAL_SPEED` |100 |Initial speed of the cursor in pixel per second |
|`MOUSEKEY_BASE_SPEED` |1000 |Maximum cursor speed at which acceleration stops |
|`MOUSEKEY_DECELERATED_SPEED` |400 |Decelerated cursor speed |
diff --git a/docs/feature_pointing_device.md b/docs/feature_pointing_device.md
index fb6936620c..84ab885738 100644
--- a/docs/feature_pointing_device.md
+++ b/docs/feature_pointing_device.md
@@ -40,13 +40,13 @@ POINTING_DEVICE_DRIVER = adns9800
The ADNS 9800 is an SPI driven optical sensor, that uses laser output for surface tracking.
-| Setting | Description | Default |
-|------------------------|------------------------------------------------------------------------|---------------|
-|`ADNS9800_CLOCK_SPEED` | (Optional) Sets the clock speed that the sensor runs at. | `2000000` |
-|`ADNS9800_SPI_LSBFIRST` | (Optional) Sets the Least/Most Significant Byte First setting for SPI. | `false` |
-|`ADNS9800_SPI_MODE` | (Optional) Sets the SPI Mode for the sensor. | `3` |
-|`ADNS9800_SPI_DIVISOR` | (Optional) Sets the SPI Divisor used for SPI communication. | _varies_ |
-|`ADNS9800_CS_PIN` | (Required) Sets the Cable Select pin connected to the sensor. | _not defined_ |
+| Setting | Description | Default |
+|--------------------------------|------------------------------------------------------------------------|---------------|
+|`ADNS9800_CLOCK_SPEED` | (Optional) Sets the clock speed that the sensor runs at. | `2000000` |
+|`ADNS9800_SPI_LSBFIRST` | (Optional) Sets the Least/Most Significant Byte First setting for SPI. | `false` |
+|`ADNS9800_SPI_MODE` | (Optional) Sets the SPI Mode for the sensor. | `3` |
+|`ADNS9800_SPI_DIVISOR` | (Optional) Sets the SPI Divisor used for SPI communication. | _varies_ |
+|`ADNS9800_CS_PIN` | (Required) Sets the Cable Select pin connected to the sensor. | _not defined_ |
The CPI range is 800-8200, in increments of 200. Defaults to 1800 CPI.
@@ -69,7 +69,7 @@ The Analog Joystick is an analog (ADC) driven sensor. There are a variety of jo
|`ANALOG_JOYSTICK_AXIS_MAX` | (Optional) Sets the upper range to be considered movement. | `1023` |
|`ANALOG_JOYSTICK_SPEED_REGULATOR` | (Optional) The divisor used to slow down movement. (lower makes it faster) | `20` |
|`ANALOG_JOYSTICK_READ_INTERVAL` | (Optional) The interval in milliseconds between reads. | `10` |
-|`ANALOG_JOYSTICK_SPEED_MAX` | (Optional) The maxiumum value used for motion. | `2` |
+|`ANALOG_JOYSTICK_SPEED_MAX` | (Optional) The maximum value used for motion. | `2` |
|`ANALOG_JOYSTICK_CLICK_PIN` | (Optional) The pin wired up to the press switch of the analog stick. | _not defined_ |
@@ -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
@@ -145,16 +144,40 @@ The PMW 3360 is an SPI driven optical sensor, that uses a built in IR LED for su
| Setting | Description | Default |
|-----------------------------|--------------------------------------------------------------------------------------------|---------------|
-|`PMW3360_CS_PIN` | (Required) Sets the Cable Select pin connected to the sensor. | _not defined_ |
-|`PMW3360_CLOCK_SPEED` | (Optional) Sets the clock speed that the sensor runs at. | `2000000` |
-|`PMW3360_SPI_LSBFIRST` | (Optional) Sets the Least/Most Significant Byte First setting for SPI. | `false` |
-|`PMW3360_SPI_MODE` | (Optional) Sets the SPI Mode for the sensor. | `3` |
-|`PMW3360_SPI_DIVISOR` | (Optional) Sets the SPI Divisor used for SPI communication. | _varies_ |
-|`PMW3360_LIFTOFF_DISTANCE` | (Optional) Sets the lift off distance at run time | `0x02` |
-|`ROTATIONAL_TRANSFORM_ANGLE` | (Optional) Allows for the sensor data to be rotated +/- 30 degrees directly in the sensor. | `0` |
+|`PMW3360_CS_PIN` | (Required) Sets the Cable Select pin connected to the sensor. | _not defined_ |
+|`PMW3360_CLOCK_SPEED` | (Optional) Sets the clock speed that the sensor runs at. | `2000000` |
+|`PMW3360_SPI_LSBFIRST` | (Optional) Sets the Least/Most Significant Byte First setting for SPI. | `false` |
+|`PMW3360_SPI_MODE` | (Optional) Sets the SPI Mode for the sensor. | `3` |
+|`PMW3360_SPI_DIVISOR` | (Optional) Sets the SPI Divisor used for SPI communication. | _varies_ |
+|`PMW3360_LIFTOFF_DISTANCE` | (Optional) Sets the lift off distance at run time | `0x02` |
+|`ROTATIONAL_TRANSFORM_ANGLE` | (Optional) Allows for the sensor data to be rotated +/- 127 degrees directly in the sensor.| `0` |
+|`PMW3360_FIRMWARE_UPLOAD_FAST` | (Optional) Skips the 15us wait between firmware blocks. | _not defined_ |
The CPI range is 100-12000, in increments of 100. Defaults to 1600 CPI.
+### PMW 3389 Sensor
+
+To use the PMW 3389 sensor, add this to your `rules.mk`
+
+```make
+POINTING_DEVICE_DRIVER = pmw3389
+```
+
+The PMW 3389 is an SPI driven optical sensor, that uses a built in IR LED for surface tracking.
+
+| Setting | Description | Default |
+|---------------------------------|--------------------------------------------------------------------------------------------|---------------|
+|`PMW3389_CS_PIN` | (Required) Sets the Cable Select pin connected to the sensor. | _not defined_ |
+|`PMW3389_CLOCK_SPEED` | (Optional) Sets the clock speed that the sensor runs at. | `2000000` |
+|`PMW3389_SPI_LSBFIRST` | (Optional) Sets the Least/Most Significant Byte First setting for SPI. | `false` |
+|`PMW3389_SPI_MODE` | (Optional) Sets the SPI Mode for the sensor. | `3` |
+|`PMW3389_SPI_DIVISOR` | (Optional) Sets the SPI Divisor used for SPI communication. | _varies_ |
+|`PMW3389_LIFTOFF_DISTANCE` | (Optional) Sets the lift off distance at run time | `0x02` |
+|`ROTATIONAL_TRANSFORM_ANGLE` | (Optional) Allows for the sensor data to be rotated +/- 30 degrees directly in the sensor. | `0` |
+|`PMW3389_FIRMWARE_UPLOAD_FAST` | (Optional) Skips the 15us wait between firmware blocks. | _not defined_ |
+
+The CPI range is 50-16000, in increments of 50. Defaults to 2000 CPI.
+
### Custom Driver
@@ -171,14 +194,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
@@ -188,7 +232,7 @@ void pointing_device_driver_set_cpi(uint16_t cpi) {}
| `pointing_device_init_kb(void)` | Callback to allow for keyboard level initialization. Useful for additional hardware sensors. |
| `pointing_device_init_user(void)` | Callback to allow for user level initialization. Useful for additional hardware sensors. |
| `pointing_device_task_kb(mouse_report)` | Callback that sends sensor data, so keyboard code can intercept and modify the data. Returns a mouse report. |
-| `pointing_device_task_user(mouse_report)` | Callback that sends sensor data, so user coe can intercept and modify the data. Returns a mouse report. |
+| `pointing_device_task_user(mouse_report)` | Callback that sends sensor data, so user code can intercept and modify the data. Returns a mouse report. |
| `pointing_device_handle_buttons(buttons, pressed, button)` | Callback to handle hardware button presses. Returns a `uint8_t`. |
| `pointing_device_get_cpi(void)` | Gets the current CPI/DPI setting from the sensor, if supported. |
| `pointing_device_set_cpi(uint16_t)` | Sets the CPI/DPI, if supported. |
@@ -196,6 +240,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
@@ -274,3 +333,62 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
```
This allows you to toggle between scrolling and cursor movement by pressing the DRAG_SCROLL key.
+
+## 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);
+}
+```
+=======
diff --git a/docs/feature_split_keyboard.md b/docs/feature_split_keyboard.md
index dbc7740f98..6ef70bf788 100644
--- a/docs/feature_split_keyboard.md
+++ b/docs/feature_split_keyboard.md
@@ -273,6 +273,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.
diff --git a/docs/feature_wpm.md b/docs/feature_wpm.md
index 87145c97e3..9f98ef8336 100644
--- a/