qmk_firmware

QMK firmware for my keyboards (Corne, Sweep Ferris) and trackball (Ploopy Adept)
Log | Files | Refs | Submodules | LICENSE

pointing_device.md (69251B)


      1 # Pointing Device {#pointing-device}
      2 
      3 Pointing Device is a generic name for a feature intended to be generic: moving the system pointer around.  There are certainly other options for it - like mousekeys - but this aims to be easily modifiable and hardware driven.  You can implement custom keys to control functionality, or you can gather information from other peripherals and insert it directly here - let QMK handle the processing for you.
      4 
      5 To enable Pointing Device, add the following line in your rules.mk and specify one of the driver options below.
      6 
      7 ```make
      8 POINTING_DEVICE_ENABLE = yes
      9 ```
     10 
     11 ## Sensor Drivers
     12 
     13 There are a number of sensors that are supported by default. Note that only one sensor can be enabled by `POINTING_DEVICE_DRIVER` at a time.  If you need to enable more than one sensor, then you need to implement it manually, using the `custom` driver.
     14 
     15 ### ADNS 5050 Sensor
     16 
     17 To use the ADNS 5050 sensor, add this to your `rules.mk`
     18 
     19 ```make
     20 POINTING_DEVICE_DRIVER = adns5050
     21 ```
     22 
     23 The ADNS 5050 sensor uses a serial type protocol for communication, and requires an additional light source.
     24 
     25 | Setting (`config.h`) | Description                                                        | Default                    |
     26 | -------------------- | ------------------------------------------------------------------ | -------------------------- |
     27 | `ADNS5050_SCLK_PIN`  | (Required) The pin connected to the clock pin of the sensor.       | `POINTING_DEVICE_SCLK_PIN` |
     28 | `ADNS5050_SDIO_PIN`  | (Required) The pin connected to the data pin of the sensor.        | `POINTING_DEVICE_SDIO_PIN` |
     29 | `ADNS5050_CS_PIN`    | (Required) The pin connected to the Chip Select pin of the sensor. | `POINTING_DEVICE_CS_PIN`   |
     30 
     31 
     32 
     33 The CPI range is 125-1375, in increments of 125. Defaults to 500 CPI.
     34 
     35 ### ADNS 9800 Sensor
     36 
     37 To use the ADNS 9800 sensor, add this to your `rules.mk`
     38 
     39 ```make
     40 POINTING_DEVICE_DRIVER = adns9800
     41 ```
     42 
     43 The ADNS 9800 is an SPI driven optical sensor, that uses laser output for surface tracking.
     44 
     45 | Setting (`config.h`)    | Description                                                            | Default                  |
     46 | ----------------------- | ---------------------------------------------------------------------- | ------------------------ |
     47 | `ADNS9800_CLOCK_SPEED`  | (Optional) Sets the clock speed that the sensor runs at.               | `2000000`                |
     48 | `ADNS9800_SPI_LSBFIRST` | (Optional) Sets the Least/Most Significant Byte First setting for SPI. | `false`                  |
     49 | `ADNS9800_SPI_MODE`     | (Optional) Sets the SPI Mode for the sensor.                           | `3`                      |
     50 | `ADNS9800_SPI_DIVISOR`  | (Optional) Sets the SPI Divisor used for SPI communication.            | _varies_                 |
     51 | `ADNS9800_CS_PIN`       | (Required) Sets the Chip Select pin connected to the sensor.           | `POINTING_DEVICE_CS_PIN` |
     52 
     53 
     54 The CPI range is 800-8200, in increments of 200. Defaults to 1800 CPI.
     55 
     56 ### Analog Joystick
     57 
     58 To use an analog joystick to control the pointer, add this to your `rules.mk`
     59 
     60 ```make
     61 POINTING_DEVICE_DRIVER = analog_joystick
     62 ```
     63 
     64 The Analog Joystick is an analog (ADC) driven sensor.  There are a variety of joysticks that you can use for this.
     65 
     66 | Setting (`config.h`)              | Description                                                                | Default       |
     67 | --------------------------------- | -------------------------------------------------------------------------- | ------------- |
     68 | `ANALOG_JOYSTICK_X_AXIS_PIN`      | (Required) The pin used for the vertical/X axis.                           | _not defined_ |
     69 | `ANALOG_JOYSTICK_Y_AXIS_PIN`      | (Required) The pin used for the horizontal/Y axis.                         | _not defined_ |
     70 | `ANALOG_JOYSTICK_AXIS_MIN`        | (Optional) Sets the lower range to be considered movement.                 | `0`           |
     71 | `ANALOG_JOYSTICK_AXIS_MAX`        | (Optional) Sets the upper range to be considered movement.                 | `1023`        |
     72 | `ANALOG_JOYSTICK_AUTO_AXIS`       | (Optional) Sets ranges to be considered movement automatically.            | _not defined_ |
     73 | `ANALOG_JOYSTICK_SPEED_REGULATOR` | (Optional) The divisor used to slow down movement. (lower makes it faster) | `20`          |
     74 | `ANALOG_JOYSTICK_READ_INTERVAL`   | (Optional) The interval in milliseconds between reads.                     | `10`          |
     75 | `ANALOG_JOYSTICK_SPEED_MAX`       | (Optional) The maximum value used for motion.                              | `2`           |
     76 | `ANALOG_JOYSTICK_CLICK_PIN`       | (Optional) The pin wired up to the press switch of the analog stick.       | _not defined_ |
     77 | `ANALOG_JOYSTICK_WEIGHTS`         | (Optional) Use custom weights for lever positions.                         | _not defined_ |
     78 | `ANALOG_JOYSTICK_CUTOFF`          | (Optional) Cut off movement when joystick returns to start position.       | _not defined_ |
     79 
     80 If `ANALOG_JOYSTICK_AUTO_AXIS` is used, then `ANALOG_JOYSTICK_AXIS_MIN` and `ANALOG_JOYSTICK_AXIS_MAX` are ignored.
     81 
     82 By default analog joystick implementation uses `x^2` weighting for lever positions. `ANALOG_JOYSTICK_WEIGHTS` allows to experiment with different configurations that might feel better.
     83 
     84 E.g. This is weights for `((x-0.4)^3+0.064)/0.282`:
     85 
     86 ```c
     87 #define ANALOG_JOYSTICK_WEIGHTS {0,2,4,5,7,8,9,10,12,13,14,15,15,16,17,18,18,19,19,20,20,21,21,21,22,22,22,22,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,24,24,24,24,24,24,25,25,25,26,26,26,27,28,28,29,29,30,31,32,33,34,35,36,37,38,40,41,43,44,46,48,49,51,53,56,58,60,62,65,68,70,73,76,79,82,85,89,92,96,100}
     88 ```
     89 
     90 You can use following JS code to generate weights for different formulas:
     91 
     92 ```js
     93 JSON.stringify(Array.from(Array(101).keys()).map(x => Math.ceil((((x/100-0.4)**3+0.064)/0.282*100))))
     94 ```
     95 
     96 ### Azoteq IQS5XX Trackpad
     97 
     98 To use a Azoteq IQS5XX trackpad, add this to your `rules.mk`:
     99 
    100 ```make
    101 POINTING_DEVICE_DRIVER = azoteq_iqs5xx
    102 ```
    103 
    104 This supports the  IQS525, IQS550 and IQS572 controllers, with the latter two being used in the TPS43 and TPS65 trackpads.
    105 
    106 #### Device settings
    107 
    108 Specific device profiles are provided which set the required values for dimensions and resolution.
    109 
    110 | Setting                          | Description                                                |
    111 | -------------------------------- | ---------------------------------------------------------- |
    112 | `AZOTEQ_IQS5XX_TPS43`            | (Pick One) Sets resolution/mm to TPS43 specifications.     |
    113 | `AZOTEQ_IQS5XX_TPS65`            | (Pick One) Sets resolution/mm to TPS65 specifications.     |
    114 
    115 ::: tip
    116 If using one of the above defines you can skip to gesture settings.
    117 :::
    118 
    119 | Setting                          | Description                                                | Default       |
    120 | -------------------------------- | ---------------------------------------------------------- | ------------- |
    121 | `AZOTEQ_IQS5XX_WIDTH_MM`         | (Required) Width of the trackpad sensor in millimeters.    | _not defined_ |
    122 | `AZOTEQ_IQS5XX_HEIGHT_MM`        | (Required) Height of the trackpad sensor in millimeters.   | _not defined_ |
    123 | `AZOTEQ_IQS5XX_RESOLUTION_X`     | (Optional) Specify X resolution for CPI calculation.       | _not defined_ |
    124 | `AZOTEQ_IQS5XX_RESOLUTION_Y`     | (Optional) Specify Y resolution for CPI calculation.       | _not defined_ |
    125 
    126 **`AZOTEQ_IQS5XX_RESOLUTION_X/Y`** fall back resolutions are provided within the driver based on controller model.
    127 
    128 | I2C Setting               | Description                                                                     | Default |
    129 | ------------------------- | ------------------------------------------------------------------------------- | ------- |
    130 | `AZOTEQ_IQS5XX_ADDRESS`   | (Optional) Sets the I2C Address for the Azoteq trackpad                         | `0xE8`  |
    131 | `AZOTEQ_IQS5XX_TIMEOUT_MS`| (Optional) The timeout for i2c communication with in milliseconds.              | `10`    |
    132 
    133 #### Gesture settings
    134 
    135 | Setting                                   | Description                                                                          | Default     |
    136 | ----------------------------------------- | ------------------------------------------------------------------------------------ | ----------- |
    137 | `AZOTEQ_IQS5XX_TAP_ENABLE`                | (Optional) Enable single finger tap. (Left click)                                    | `true`      |
    138 | `AZOTEQ_IQS5XX_TWO_FINGER_TAP_ENABLE`     | (Optional) Enable two finger tap. (Right click)                                      | `true`      |
    139 | `AZOTEQ_IQS5XX_PRESS_AND_HOLD_ENABLE`     | (Optional) Emulates holding left click to select text.                               | `false`     |
    140 | `AZOTEQ_IQS5XX_SWIPE_X_ENABLE`            | (Optional) Enable swipe gestures X+ (Mouse Button 5) / X- (Mouse Button 4)           | `false`     |
    141 | `AZOTEQ_IQS5XX_SWIPE_Y_ENABLE`            | (Optional) Enable swipe gestures Y+ (Mouse Button 3) / Y- (Mouse Button 6)           | `false`     |
    142 | `AZOTEQ_IQS5XX_ZOOM_ENABLE`               | (Optional) Enable zoom gestures Zoom Out (Mouse Button 7) / Zoom In (Mouse Button 8) | `false`     |
    143 | `AZOTEQ_IQS5XX_SCROLL_ENABLE`             | (Optional) Enable scrolling using two fingers.                                       | `true`      |
    144 | `AZOTEQ_IQS5XX_TAP_TIME`                  | (Optional) Maximum time in ms for tap to be registered.                              | `150`       |
    145 | `AZOTEQ_IQS5XX_TAP_DISTANCE`              | (Optional) Maximum deviation in pixels before single tap is no longer valid.         | `25`        |
    146 | `AZOTEQ_IQS5XX_HOLD_TIME`                 | (Optional) Minimum time in ms for press and hold.                                    | `300`       |
    147 | `AZOTEQ_IQS5XX_SWIPE_INITIAL_TIME`        | (Optional) Maximum time to travel initial distance before swipe is registered.       | `150`       |
    148 | `AZOTEQ_IQS5XX_SWIPE_INITIAL_DISTANCE`    | (Optional) Minimum travel in pixels before swipe is registered.                      | `300`       |
    149 | `AZOTEQ_IQS5XX_SWIPE_CONSECUTIVE_TIME`    | (Optional) Maximum time to travel consecutive distance before swipe is registered.   | `0`         |
    150 | `AZOTEQ_IQS5XX_SWIPE_CONSECUTIVE_DISTANCE`| (Optional) Minimum travel in pixels before a consecutive swipe is registered.        | `2000`      |
    151 | `AZOTEQ_IQS5XX_SCROLL_INITIAL_DISTANCE`   | (Optional) Minimum travel in pixels before scroll is registered.                     | `50`        |
    152 | `AZOTEQ_IQS5XX_ZOOM_INITIAL_DISTANCE`     | (Optional) Minimum travel in pixels before zoom is registered.                       | `50`        |
    153 | `AZOTEQ_IQS5XX_ZOOM_CONSECUTIVE_DISTANCE` | (Optional) Maximum time to travel zoom distance before zoom is registered.           | `25`        |
    154 
    155 #### Rotation settings
    156 
    157 | Setting                      | Description                                                | Default       |
    158 | ---------------------------- | ---------------------------------------------------------- | ------------- |
    159 | `AZOTEQ_IQS5XX_ROTATION_90`  | (Optional) Configures hardware for 90 degree rotation.     | _not defined_ |
    160 | `AZOTEQ_IQS5XX_ROTATION_180` | (Optional) Configures hardware for 180 degree rotation.    | _not defined_ |
    161 | `AZOTEQ_IQS5XX_ROTATION_270` | (Optional) Configures hardware for 270 degree rotation.    | _not defined_ |
    162 
    163 ### Cirque Trackpad
    164 
    165 To use the Cirque Trackpad sensor, add this to your `rules.mk`:
    166 
    167 ```make
    168 POINTING_DEVICE_DRIVER = cirque_pinnacle_i2c
    169 ```
    170 
    171 or
    172 
    173 ```make
    174 POINTING_DEVICE_DRIVER = cirque_pinnacle_spi
    175 ```
    176 
    177 
    178 This supports the Cirque Pinnacle 1CA027 Touch Controller, which is used in the TM040040, TM035035 and the TM023023 trackpads. These are I2C or SPI compatible, and both configurations are supported.
    179 
    180 #### Common settings
    181 
    182 | Setting                              | Description                                                | Default                                     |
    183 | ------------------------------------ | ---------------------------------------------------------- | ------------------------------------------- |
    184 | `CIRQUE_PINNACLE_DIAMETER_MM`        | (Optional) Diameter of the trackpad sensor in millimeters. | `40`                                        |
    185 | `CIRQUE_PINNACLE_ATTENUATION`        | (Optional) Sets the attenuation of the sensor data.        | `EXTREG__TRACK_ADCCONFIG__ADC_ATTENUATE_4X` |
    186 | `CIRQUE_PINNACLE_CURVED_OVERLAY`     | (Optional) Applies settings tuned for curved overlay.      | _not defined_                               |
    187 | `CIRQUE_PINNACLE_POSITION_MODE`      | (Optional) Mode of operation.                              | _not defined_                               |
    188 | `CIRQUE_PINNACLE_SKIP_SENSOR_CHECK`  | (Optional) Skips sensor presence check                     | _not defined_                               |
    189 
    190 **`CIRQUE_PINNACLE_ATTENUATION`** is a measure of how much data is suppressed in regards to sensitivity. The higher the attenuation, the less sensitive the touchpad will be.
    191 
    192 Default attenuation is set to 4X, although if you are using a thicker overlay (such as the curved overlay) you will want a lower attenuation such as 2X. The possible values are:
    193 * `EXTREG__TRACK_ADCCONFIG__ADC_ATTENUATE_4X`: Least sensitive
    194 * `EXTREG__TRACK_ADCCONFIG__ADC_ATTENUATE_3X`
    195 * `EXTREG__TRACK_ADCCONFIG__ADC_ATTENUATE_2X`
    196 * `EXTREG__TRACK_ADCCONFIG__ADC_ATTENUATE_1X`: Most sensitive
    197 
    198 **`CIRQUE_PINNACLE_POSITION_MODE`** can be `CIRQUE_PINNACLE_ABSOLUTE_MODE` or `CIRQUE_PINNACLE_RELATIVE_MODE`. Modes differ in supported features/gestures.
    199 
    200 * `CIRQUE_PINNACLE_ABSOLUTE_MODE`: Reports absolute x, y, z (touch pressure) coordinates and up to 5 hw buttons connected to the trackpad
    201 * `CIRQUE_PINNACLE_RELATIVE_MODE`: Reports x/y deltas, scroll and up to 3 buttons (2 of them can be from taps, see gestures) connected to trackpad. Supports taps on secondary side of split. Saves about 2k of flash compared to absolute mode with all features.
    202 
    203 | I2C Setting               | Description                                                                     | Default |
    204 | ------------------------- | ------------------------------------------------------------------------------- | ------- |
    205 | `CIRQUE_PINNACLE_ADDR`    | (Required) Sets the I2C Address for the Cirque Trackpad                         | `0x2A`  |
    206 | `CIRQUE_PINNACLE_TIMEOUT` | (Optional) The timeout for i2c communication with the trackpad in milliseconds. | `20`    |
    207 
    208 | SPI Setting                    | Description                                                            | Default                  |
    209 | ------------------------------ | ---------------------------------------------------------------------- | ------------------------ |
    210 | `CIRQUE_PINNACLE_CLOCK_SPEED`  | (Optional) Sets the clock speed that the sensor runs at.               | `1000000`                |
    211 | `CIRQUE_PINNACLE_SPI_LSBFIRST` | (Optional) Sets the Least/Most Significant Byte First setting for SPI. | `false`                  |
    212 | `CIRQUE_PINNACLE_SPI_MODE`     | (Optional) Sets the SPI Mode for the sensor.                           | `1`                      |
    213 | `CIRQUE_PINNACLE_SPI_DIVISOR`  | (Optional) Sets the SPI Divisor used for SPI communication.            | _varies_                 |
    214 | `CIRQUE_PINNACLE_SPI_CS_PIN`   | (Required) Sets the Chip Select pin connected to the sensor.           | `POINTING_DEVICE_CS_PIN` |
    215 
    216 Default Scaling is 1024. Actual CPI depends on trackpad diameter.
    217 
    218 Also see the `POINTING_DEVICE_TASK_THROTTLE_MS`, which defaults to 10ms when using Cirque Pinnacle, which matches the internal update rate of the position registers (in standard configuration). Advanced configuration for pen/stylus usage might require lower values.
    219 
    220 #### Absolute mode settings
    221 
    222 | Setting                                 | Description                                                             | Default     |
    223 |-----------------------------------------|-------------------------------------------------------------------------|-------------|
    224 | `CIRQUE_PINNACLE_X_LOWER`               | (Optional) The minimum reachable X value on the sensor.                 | `127`       |
    225 | `CIRQUE_PINNACLE_X_UPPER`               | (Optional) The maximum reachable X value on the sensor.                 | `1919`      |
    226 | `CIRQUE_PINNACLE_Y_LOWER`               | (Optional) The minimum reachable Y value on the sensor.                 | `63`        |
    227 | `CIRQUE_PINNACLE_Y_UPPER`               | (Optional) The maximum reachable Y value on the sensor.                 | `1471`      |
    228 | `CIRQUE_PINNACLE_REACHABLE_CALIBRATION` | (Optional) Enable console messages to aide in calibrating above values. | not defined |
    229 
    230 #### Absolute mode gestures
    231 
    232 | Gesture Setting                                | Description                                                                    | Default              |
    233 | ---------------------------------------------- | ------------------------------------------------------------------------------ | -------------------- |
    234 | `CIRQUE_PINNACLE_TAP_ENABLE`                   | (Optional) Enable tap to click. This currently only works on the master side.  | _not defined_        |
    235 | `CIRQUE_PINNACLE_TAPPING_TERM`                 | (Optional) Length of time that a touch can be to be considered a tap.          | `TAPPING_TERM`/`200` |
    236 | `CIRQUE_PINNACLE_TOUCH_DEBOUNCE`               | (Optional) Length of time that a touch can be to be considered a tap.          | `TAPPING_TERM`/`200` |
    237 
    238 `POINTING_DEVICE_GESTURES_SCROLL_ENABLE` in this mode enables circular scroll. Touch originating in outer ring can trigger scroll by moving along the perimeter. Near side triggers vertical scroll and far side triggers horizontal scroll.
    239 
    240 Additionally, `POINTING_DEVICE_GESTURES_CURSOR_GLIDE_ENABLE` is supported in this mode.
    241 
    242 #### Relative mode gestures
    243 
    244 | Gesture Setting (`config.h`)           | Description                                                                                                                                                                               | Default       |
    245 | -------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- |
    246 | `CIRQUE_PINNACLE_TAP_ENABLE`           | (Optional) Enable tap to "left click". Works on both sides of a split keyboard.                                                                                                           | _not defined_ |
    247 | `CIRQUE_PINNACLE_SECONDARY_TAP_ENABLE` | (Optional) Tap in upper right corner (half of the finger needs to be outside of the trackpad) of the trackpad will result in "right click". `CIRQUE_PINNACLE_TAP_ENABLE` must be enabled. | _not defined_ |
    248 
    249 Tapping term and debounce are not configurable in this mode since it's handled by trackpad internally.
    250 
    251 `POINTING_DEVICE_GESTURES_SCROLL_ENABLE` in this mode enables side scroll. Touch originating on the right side can trigger vertical scroll (IntelliSense trackpad style).
    252 
    253 ### PAW 3204 Sensor
    254 
    255 To use the paw 3204 sensor, add this to your `rules.mk`
    256 
    257 ```make
    258 POINTING_DEVICE_DRIVER = paw3204
    259 ```
    260 
    261 The paw 3204 sensor uses a serial type protocol for communication, and requires an additional light source.
    262 
    263 | Setting (`config.h`) | Description                                                    | Default                    |
    264 | -------------------- |--------------------------------------------------------------- | -------------------------- |
    265 | `PAW3204_SCLK_PIN`   | (Required) The pin connected to the clock pin of the sensor.   | `POINTING_DEVICE_SCLK_PIN` |
    266 | `PAW3204_SDIO_PIN`   | (Required) The pin connected to the data pin of the sensor.    | `POINTING_DEVICE_SDIO_PIN` |
    267 
    268 The CPI range is 400-1600, with supported values of (400, 500, 600, 800, 1000, 1200 and 1600).  Defaults to 1000 CPI.
    269 
    270 ### PAW-3222 Sensor
    271 
    272 To use the PAW-3222 sensor, add this to your `rules.mk`:
    273 
    274 ```make
    275 POINTING_DEVICE_DRIVER = paw3222
    276 ```
    277 
    278 The following pins must be defined in `config.h`:
    279 
    280 | Setting (`config.h`)  | Description                                                        | Default                      |
    281 | --------------------- | ------------------------------------------------------------------ | ---------------------------- |
    282 | `PAW3222_CS_PIN`      | (Required) The pin connected to the chip select pin of the sensor. | `POINTING_DEVICE_CS_PIN`     |
    283 | `PAW3222_SPI_DIVISOR` | (Required) The SPI clock divisor. This is dependent on your MCU.   | _not defined_                |
    284 
    285 The CPI range is up to 4,000. Defaults to 1,000 CPI.
    286 
    287 ### Pimoroni Trackball
    288 
    289 To use the Pimoroni Trackball module, add this to your `rules.mk`:
    290 
    291 ```make
    292 POINTING_DEVICE_DRIVER = pimoroni_trackball
    293 ```
    294 
    295 The Pimoroni Trackball module is a I2C based breakout board with an RGB enable trackball.
    296 
    297 | Setting (`config.h`)                 | Description                                                                        | Default |
    298 | ------------------------------------ | ---------------------------------------------------------------------------------- | ------- |
    299 | `PIMORONI_TRACKBALL_ADDRESS`         | (Required) Sets the I2C Address for the Pimoroni Trackball.                        | `0x0A`  |
    300 | `PIMORONI_TRACKBALL_TIMEOUT`         | (Optional) The timeout for i2c communication with the trackball in milliseconds.   | `100`   |
    301 | `PIMORONI_TRACKBALL_SCALE`           | (Optional) The multiplier used to generate reports from the sensor.                | `5`     |
    302 | `PIMORONI_TRACKBALL_DEBOUNCE_CYCLES` | (Optional) The number of scan cycles used for debouncing on the ball press.        | `20`    |
    303 | `PIMORONI_TRACKBALL_ERROR_COUNT`     | (Optional) Specifies the number of read/write errors until the sensor is disabled. | `10`    |
    304 
    305 ### PMW3320 Sensor
    306 
    307 To use the PMW3320 sensor, add this to your `rules.mk`
    308 
    309 ```make
    310 POINTING_DEVICE_DRIVER = pmw3320
    311 ```
    312 
    313 The PMW3320 sensor uses a serial type protocol for communication, and requires an additional light source (it could work without one, but expect it to be out of service early).
    314 
    315 | Setting             | Description                                                         | Default                    |
    316 | ------------------- | ------------------------------------------------------------------- | -------------------------- |
    317 | `PMW3320_SCLK_PIN` | (Required) The pin connected to the clock pin of the sensor.        | `POINTING_DEVICE_SCLK_PIN` |
    318 | `PMW3320_SDIO_PIN` | (Required) The pin connected to the data pin of the sensor.         | `POINTING_DEVICE_SDIO_PIN` |
    319 | `PMW3320_CS_PIN`   | (Required) The pin connected to the cable select pin of the sensor. | `POINTING_DEVICE_CS_PIN`   |
    320 
    321 The CPI range is 500-3500, in increments of 250. Defaults to 1000 CPI.
    322 
    323 ### PMW 3360 and PMW 3389 Sensor
    324 
    325 This drivers supports both the PMW 3360 and PMW 3389 sensor as well as multiple sensors of the same type _per_ controller, so 2 can be attached at the same side for split keyboards (or unsplit keyboards).
    326 
    327 To use the **PMW 3360** sensor, add this to your `rules.mk`
    328 
    329 ```make
    330 POINTING_DEVICE_DRIVER = pmw3360
    331 ```
    332 
    333 The CPI range is 100-12000, in increments of 100. Defaults to 1600 CPI.
    334 
    335 To use the **PMW 3389** sensor, add this to your `rules.mk`
    336 
    337 ```make
    338 POINTING_DEVICE_DRIVER = pmw3389
    339 ```
    340 
    341 The CPI range is 50-16000, in increments of 50. Defaults to 2000 CPI.
    342 
    343 Both PMW 3360 and PMW 3389 are SPI driven optical sensors, that use a built in IR LED for surface tracking.
    344 If you have different CS wiring on each half you can use `PMW33XX_CS_PIN_RIGHT` or `PMW33XX_CS_PINS_RIGHT` in combination with `PMW33XX_CS_PIN` or `PMW33XX_CS_PINS` to configure both sides independently. If `_RIGHT` values aren't provided, they default to be the same as the left ones.
    345 
    346 | Setting (`config.h`)         | Description                                                                                 | Default                  |
    347 | ---------------------------- | ------------------------------------------------------------------------------------------- | ------------------------ |
    348 | `PMW33XX_CS_PIN`             | (Required) Sets the Chip Select pin connected to the sensor.                                | `POINTING_DEVICE_CS_PIN` |
    349 | `PMW33XX_CS_PINS`            | (Alternative) Sets the Chip Select pins connected to multiple sensors.                      | `{PMW33XX_CS_PIN}`       |
    350 | `PMW33XX_CS_PIN_RIGHT`       | (Optional) Sets the Chip Select pin connected to the sensor on the right half.              | `PMW33XX_CS_PIN`         |
    351 | `PMW33XX_CS_PINS_RIGHT`      | (Optional) Sets the Chip Select pins connected to multiple sensors on the right half.       | `{PMW33XX_CS_PIN_RIGHT}` |
    352 | `PMW33XX_CPI`                | (Optional) Sets counts per inch sensitivity of the sensor.                                  | _varies_                 |
    353 | `PMW33XX_CLOCK_SPEED`        | (Optional) Sets the clock speed that the sensor runs at.                                    | `2000000`                |
    354 | `PMW33XX_SPI_DIVISOR`        | (Optional) Sets the SPI Divisor used for SPI communication.                                 | _varies_                 |
    355 | `PMW33XX_LIFTOFF_DISTANCE`   | (Optional) Sets the lift off distance at run time                                           | `0x02`                   |
    356 | `ROTATIONAL_TRANSFORM_ANGLE` | (Optional) Allows for the sensor data to be rotated +/- 127 degrees directly in the sensor. | `0`                      |
    357 
    358 To use multiple sensors, instead of setting `PMW33XX_CS_PIN` you need to set `PMW33XX_CS_PINS` and also handle and merge the read from this sensor in user code.
    359 Note that different (per sensor) values of CPI, speed liftoff, rotational angle or flipping of X/Y is not currently supported.
    360 
    361 ```c
    362 // in config.h:
    363 #define PMW33XX_CS_PINS { B5, B6 }
    364 // in keyboard.c:
    365 #ifdef POINTING_DEVICE_ENABLE
    366 void pointing_device_init_kb(void) {
    367     pmw33xx_init(1);         // index 1 is the second device.
    368     pmw33xx_set_cpi(0, 800); // applies to first sensor
    369     pmw33xx_set_cpi(1, 800); // applies to second sensor
    370     pointing_device_init_user();
    371 }
    372 
    373 // Contains report from sensor #0 already, need to merge in from sensor #1
    374 report_mouse_t pointing_device_task_kb(report_mouse_t mouse_report) {
    375     pmw33xx_report_t report = pmw33xx_read_burst(1);
    376     if (!report.motion.b.is_lifted && report.motion.b.is_motion) {
    377 // From quantum/pointing_device_drivers.c
    378 #define constrain_hid(amt) ((amt) < -127 ? -127 : ((amt) > 127 ? 127 : (amt)))
    379         mouse_report.x = constrain_hid(mouse_report.x + report.delta_x);
    380         mouse_report.y = constrain_hid(mouse_report.y + report.delta_y);
    381     }
    382     return pointing_device_task_user(mouse_report);
    383 }
    384 #endif
    385 
    386 ```
    387 
    388 ### Custom Driver
    389 
    390 If you have a sensor type that isn't supported above, a custom option is available by adding the following to your `rules.mk`
    391 
    392 ```make
    393 POINTING_DEVICE_DRIVER = custom
    394 ```
    395 
    396 Using the custom driver will require implementing the following functions:
    397 
    398 ```c
    399 bool           pointing_device_driver_init(void) { return true; }
    400 report_mouse_t pointing_device_driver_get_report(report_mouse_t mouse_report) { return mouse_report; }
    401 uint16_t       pointing_device_driver_get_cpi(void) { return 0; }
    402 void           pointing_device_driver_set_cpi(uint16_t cpi) {}
    403 ```
    404 
    405 ::: warning
    406 Ideally, new sensor hardware should be added to `drivers/sensors/` and `quantum/pointing_device_drivers.c`, but there may be cases where it's very specific to the hardware.  So these functions are provided, just in case.
    407 :::
    408 
    409 ## Common Configuration
    410 
    411 | Setting                                        | Description                                                                                                                      | Default       |
    412 | ---------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | ------------- |
    413 | `MOUSE_EXTENDED_REPORT`                        | (Optional) Enables support for extended mouse reports. (-32767 to 32767, instead of just -127 to 127).                           | _not defined_ |
    414 | `WHEEL_EXTENDED_REPORT`                        | (Optional) Enables support for extended wheel reports. (-32767 to 32767, instead of just -127 to 127).                           | _not defined_ |
    415 | `POINTING_DEVICE_ROTATION_90`                  | (Optional) Rotates the X and Y data by  90 degrees.                                                                              | _not defined_ |
    416 | `POINTING_DEVICE_ROTATION_180`                 | (Optional) Rotates the X and Y data by 180 degrees.                                                                              | _not defined_ |
    417 | `POINTING_DEVICE_ROTATION_270`                 | (Optional) Rotates the X and Y data by 270 degrees.                                                                              | _not defined_ |
    418 | `POINTING_DEVICE_INVERT_X`                     | (Optional) Inverts the X axis report.                                                                                            | _not defined_ |
    419 | `POINTING_DEVICE_INVERT_Y`                     | (Optional) Inverts the Y axis report.                                                                                            | _not defined_ |
    420 | `POINTING_DEVICE_MOTION_PIN`                   | (Optional) If supported, will only read from sensor if pin is active.                                                            | _not defined_ |
    421 | `POINTING_DEVICE_MOTION_PIN_ACTIVE_LOW`        | (Optional) If defined then the motion pin is active-low.                                                                         | _varies_      |
    422 | `POINTING_DEVICE_TASK_THROTTLE_MS`             | (Optional) Limits the frequency that the sensor is polled for motion.                                                            | _not defined_ |
    423 | `POINTING_DEVICE_GESTURES_CURSOR_GLIDE_ENABLE` | (Optional) Enable inertial cursor. Cursor continues moving after a flick gesture and slows down by kinetic friction.             | _not defined_ |
    424 | `POINTING_DEVICE_GESTURES_SCROLL_ENABLE`       | (Optional) Enable scroll gesture. The gesture that activates the scroll is device dependent.                                     | _not defined_ |
    425 | `POINTING_DEVICE_CS_PIN`                       | (Optional) Provides a default CS pin, useful for supporting multiple sensor configs.                                             | _not defined_ |
    426 | `POINTING_DEVICE_SDIO_PIN`                     | (Optional) Provides a default SDIO pin, useful for supporting multiple sensor configs.                                           | _not defined_ |
    427 | `POINTING_DEVICE_SCLK_PIN`                     | (Optional) Provides a default SCLK pin, useful for supporting multiple sensor configs.                                           | _not defined_ |
    428 
    429 ::: warning
    430 When using `SPLIT_POINTING_ENABLE` the `POINTING_DEVICE_MOTION_PIN` functionality is not supported and `POINTING_DEVICE_TASK_THROTTLE_MS` will default to `1`. Increasing this value will increase transport performance at the cost of possible mouse responsiveness.
    431 :::
    432 
    433 The `POINTING_DEVICE_CS_PIN`, `POINTING_DEVICE_SDIO_PIN`, and `POINTING_DEVICE_SCLK_PIN` provide a convenient way to define a single pin that can be used for an interchangeable sensor config.  This allows you to have a single config, without defining each device.  Each sensor allows for this to be overridden with their own defines.
    434 
    435 ::: warning
    436 Any pointing device with a lift/contact status can integrate inertial cursor feature into its driver, controlled by `POINTING_DEVICE_GESTURES_CURSOR_GLIDE_ENABLE`. e.g. PMW3360 can use Lift_Stat from Motion register. Note that `POINTING_DEVICE_MOTION_PIN` cannot be used with this feature; continuous polling of `get_report()` is needed to generate glide reports.
    437 :::
    438 
    439 ## High Resolution Scrolling
    440 
    441 | Setting                                  | Description                                                                                                               | Default       |
    442 | ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | ------------- |
    443 | `POINTING_DEVICE_HIRES_SCROLL_ENABLE`    | (Optional) Enables high resolution scrolling.                                                                             | _not defined_ |
    444 | `POINTING_DEVICE_HIRES_SCROLL_MULTIPLIER`| (Optional) Resolution multiplier value used by high resolution scrolling. Must be between 1 and 127, inclusive.           | `120`         |
    445 | `POINTING_DEVICE_HIRES_SCROLL_EXPONENT`  | (Optional) Resolution exponent value used by high resolution scrolling. Must be between 0 and 127, inclusive.             | `0`           |
    446 
    447 The `POINTING_DEVICE_HIRES_SCROLL_ENABLE` setting enables smooth and continuous scrolling when using trackballs or high-end encoders as mouse wheels (as opposed to the typical stepped behavior of most mouse wheels).
    448 This works by adding a resolution multiplier to the HID descriptor for mouse wheel reports, causing the host computer to interpret each wheel tick sent by the keyboard as a fraction of a normal wheel tick.
    449 The resolution multiplier is set to `1 / (POINTING_DEVICE_HIRES_SCROLL_MULTIPLIER * (10 ^ POINTING_DEVICE_HIRES_SCROLL_EXPONENT))`, which is `1 / 120` by default.
    450 If even smoother scrolling than provided by this default value is desired, first try using `#define POINTING_DEVICE_HIRES_SCROLL_EXPONENT 1` which will result in a multiplier of `1 / 1200`.
    451 
    452 The function `pointing_device_get_hires_scroll_resolution()` can be called to get the pre-computed resolution multiplier value as a `uint16_t`.
    453 
    454 ::: warning
    455 High resolution scrolling usually results in larger and/or more frequent mouse reports. This can result in overflow errors and overloading of the host computer's input buffer.
    456 To deal with these issues, define `WHEEL_EXTENDED_REPORT` and throttle the rate at which mouse reports are sent.
    457 :::
    458 
    459 ::: warning
    460 Many programs, especially those that implement their own smoothing for scrolling, don't work well when they receive simultaneous vertical and horizontal wheel inputs (e.g. from high resolution drag-scroll using a trackball).
    461 These programs typically implement their smoothing in a way that assumes the user will only scroll in one axis at a time, resulting in slow or jittery motion when trying to scroll at an angle.
    462 This can be addressed by snapping scrolling to one axis at a time.
    463 :::
    464 
    465 ## Split Keyboard Configuration
    466 
    467 The following configuration options are only available when using `SPLIT_POINTING_ENABLE` see [data sync options](split_keyboard#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.
    468 
    469 | Setting                              | Description                                                                                           | Default       |
    470 | ------------------------------------ | ----------------------------------------------------------------------------------------------------- | ------------- |
    471 | `POINTING_DEVICE_LEFT`               | Pointing device on the left side (Required - pick one only)                                           | _not defined_ |
    472 | `POINTING_DEVICE_RIGHT`              | Pointing device on the right side (Required - pick one only)                                          | _not defined_ |
    473 | `POINTING_DEVICE_COMBINED`           | Pointing device on both sides (Required - pick one only)                                              | _not defined_ |
    474 | `POINTING_DEVICE_ROTATION_90_RIGHT`  | (Optional) Rotates the X and Y data by  90 degrees.                                                   | _not defined_ |
    475 | `POINTING_DEVICE_ROTATION_180_RIGHT` | (Optional) Rotates the X and Y data by 180 degrees.                                                   | _not defined_ |
    476 | `POINTING_DEVICE_ROTATION_270_RIGHT` | (Optional) Rotates the X and Y data by 270 degrees.                                                   | _not defined_ |
    477 | `POINTING_DEVICE_INVERT_X_RIGHT`     | (Optional) Inverts the X axis report.                                                                 | _not defined_ |
    478 | `POINTING_DEVICE_INVERT_Y_RIGHT`     | (Optional) Inverts the Y axis report.                                                                 | _not defined_ |
    479 
    480 ::: warning
    481 If there is a `_RIGHT` configuration option or callback, the [common configuration](pointing_device#common-configuration) option will work for the left. For correct left/right detection you should setup a [handedness option](split_keyboard#setting-handedness), `EE_HANDS` is usually a good option for an existing board that doesn't do handedness by hardware.
    482 :::
    483 
    484 
    485 ## Callbacks and Functions
    486 
    487 | Function                                                      | Description                                                                                                   |
    488 | ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
    489 | `pointing_device_init_kb(void)`                               | Callback to allow for keyboard level initialization. Useful for additional hardware sensors.                  |
    490 | `pointing_device_init_user(void)`                             | Callback to allow for user level initialization. Useful for additional hardware sensors.                      |
    491 | `pointing_device_task_kb(mouse_report)`                       | Callback that sends sensor data, so keyboard code can intercept and modify the data.  Returns a mouse report. |
    492 | `pointing_device_task_user(mouse_report)`                     | Callback that sends sensor data, so user code can intercept and modify the data.  Returns a mouse report.     |
    493 | `pointing_device_handle_buttons(buttons, pressed, button)`    | Callback to handle hardware button presses. Returns a `uint8_t`.                                              |
    494 | `pointing_device_get_cpi(void)`                               | Gets the current CPI/DPI setting from the sensor, if supported.                                               |
    495 | `pointing_device_set_cpi(uint16_t)`                           | Sets the CPI/DPI, if supported.                                                                               |
    496 | `pointing_device_get_report(void)`                            | Returns the current mouse report (as a `report_mouse_t` data structure).                                      |
    497 | `pointing_device_set_report(mouse_report)`                    | Sets the mouse report to the assigned `report_mouse_t` data structured passed to the function.                |
    498 | `pointing_device_send(void)`                                  | Sends the current mouse report to the host system.  Function can be replaced.                                 |
    499 | `has_mouse_report_changed(new_report, old_report)`            | Compares the old and new `report_mouse_t` data and returns true only if it has changed.                       |
    500 | `pointing_device_adjust_by_defines(mouse_report)`             | Applies rotations and invert configurations to a raw mouse report.                                            |
    501 | `pointing_device_get_status(void)`                            | Returns device status as `pointing_device_status_t` a good return is `POINTING_DEVICE_STATUS_SUCCESS`.        |
    502 | `pointing_device_set_status(pointing_device_status_t status)` | Sets device status, anything other than `POINTING_DEVICE_STATUS_SUCCESS` will disable reports from the device.|
    503 
    504 
    505 ## Split Keyboard Callbacks and Functions
    506 
    507 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](pointing_device#combined-pointing-devices)
    508 
    509 | Function                                                        | Description                                                                                                              |
    510 | --------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
    511 | `pointing_device_set_shared_report(mouse_report)`               | Sets the shared mouse report to the assigned `report_mouse_t` data structured passed to the function.                    |
    512 | `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                       |
    513 | `pointing_device_combine_reports(left_report, right_report)`    | Returns a combined mouse_report of left_report and right_report (as a `report_mouse_t` data structure)                   |
    514 | `pointing_device_task_combined_kb(left_report, right_report)`   | Callback, so keyboard code can intercept and modify the data. Returns a combined mouse report.                           |
    515 | `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` |
    516 | `pointing_device_adjust_by_defines_right(mouse_report)`         | Applies right side rotations and invert configurations to a raw mouse report.                                            |
    517 
    518 
    519 # Manipulating Mouse Reports
    520 
    521 The report_mouse_t (here "mouseReport") has the following properties:
    522 
    523 * `mouseReport.x` - this is a signed int from -127 to 127 (not 128, this is defined in USB HID spec) representing movement (+ to the right, - to the left) on the x axis.
    524 * `mouseReport.y` - this is a signed int from -127 to 127 (not 128, this is defined in USB HID spec) representing movement (+ upward, - downward) on the y axis.
    525 * `mouseReport.v` - this is a signed int from -127 to 127 (not 128, this is defined in USB HID spec) representing vertical scrolling (+ upward, - downward).
    526 * `mouseReport.h` - this is a signed int from -127 to 127 (not 128, this is defined in USB HID spec) representing horizontal scrolling (+ right, - left).
    527 * `mouseReport.buttons` - this is a uint8_t in which all 8 bits are used.  These bits represent the mouse button state - bit 0 is mouse button 1, and bit 7 is mouse button 8.
    528 
    529 To manually manipulate the mouse reports outside of the `pointing_device_task_*` functions, you can use:
    530 
    531 * `pointing_device_get_report()` - Returns the current report_mouse_t that represents the information sent to the host computer
    532 * `pointing_device_set_report(report_mouse_t mouse_report)` - Overrides and saves the report_mouse_t to be sent to the host computer
    533 * `pointing_device_send()` - Sends the mouse report to the host and zeroes out the report.
    534 
    535 When the mouse report is sent, the x, y, v, and h values are set to 0 (this is done in `pointing_device_send()`, which can be overridden to avoid this behavior).  This way, button states persist, but movement will only occur once.  For further customization, both `pointing_device_init` and `pointing_device_task` can be overridden.
    536 
    537 Additionally, by default, `pointing_device_send()` will only send a report when the report has actually changed.  This prevents it from continuously sending mouse reports, which will keep the host system awake.  This behavior can be changed by creating your own `pointing_device_send()` function.
    538 
    539 Also, you use the `has_mouse_report_changed(new_report, old_report)` function to check to see if the report has changed.
    540 
    541 ## Examples
    542 
    543 ### Custom Mouse Keycode
    544 
    545 In this example, a custom key is used to click the mouse and scroll 127 units vertically and horizontally, then undo all of that when released - because that's a totally useful function.
    546 
    547 ```c
    548 case MS_SPECIAL:
    549     report_mouse_t currentReport = pointing_device_get_report();
    550     if (record->event.pressed) {
    551         currentReport.v = 127;
    552         currentReport.h = 127;
    553         currentReport.buttons |= MOUSE_BTN1;  // this is defined in report.h
    554     } else {
    555         currentReport.v = -127;
    556         currentReport.h = -127;
    557         currentReport.buttons &= ~MOUSE_BTN1;
    558     }
    559     pointing_device_set_report(currentReport);
    560     pointing_device_send();
    561     break;
    562 ```
    563 
    564 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.
    565 
    566 ### Drag Scroll or Mouse Scroll
    567 
    568 A very common implementation is to use the mouse movement to scroll instead of moving the cursor on the system.  This uses the `pointing_device_task_user` callback to intercept and modify the mouse report before it's sent to the host system.
    569 
    570 ```c
    571 enum custom_keycodes {
    572     DRAG_SCROLL = SAFE_RANGE,
    573 };
    574 
    575 bool set_scrolling = false;
    576 
    577 report_mouse_t pointing_device_task_user(report_mouse_t mouse_report) {
    578     if (set_scrolling) {
    579         mouse_report.h = mouse_report.x;
    580         mouse_report.v = mouse_report.y;
    581         mouse_report.x = 0;
    582         mouse_report.y = 0;
    583     }
    584     return mouse_report;
    585 }
    586 
    587 bool process_record_user(uint16_t keycode, keyrecord_t *record) {
    588     if (keycode == DRAG_SCROLL && record->event.pressed) {
    589         set_scrolling = !set_scrolling;
    590     }
    591     return true;
    592 }
    593 ```
    594 
    595 This allows you to toggle between scrolling and cursor movement by pressing the DRAG_SCROLL key.
    596 
    597 ### Advanced Drag Scroll
    598 
    599 Sometimes, like with the Cirque trackpad, you will run into issues where the scrolling may be too fast.
    600 
    601 Here is a slightly more advanced example of drag scrolling. You will be able to change the scroll speed based on the values in set in `SCROLL_DIVISOR_H` and `SCROLL_DIVISOR_V`. This bit of code is also set up so that instead of toggling the scrolling state with set_scrolling = !set_scrolling, the set_scrolling variable is set directly to record->event.pressed. This way, the drag scrolling will only be active while the DRAG_SCROLL button is held down.
    602 
    603 ```c
    604 enum custom_keycodes {
    605     DRAG_SCROLL = SAFE_RANGE,
    606 };
    607 
    608 bool set_scrolling = false;
    609 
    610 // Modify these values to adjust the scrolling speed
    611 #define SCROLL_DIVISOR_H 8.0
    612 #define SCROLL_DIVISOR_V 8.0
    613 
    614 // Variables to store accumulated scroll values
    615 float scroll_accumulated_h = 0;
    616 float scroll_accumulated_v = 0;
    617 
    618 // Function to handle mouse reports and perform drag scrolling
    619 report_mouse_t pointing_device_task_user(report_mouse_t mouse_report) {
    620     // Check if drag scrolling is active
    621     if (set_scrolling) {
    622         // Calculate and accumulate scroll values based on mouse movement and divisors
    623         scroll_accumulated_h += (float)mouse_report.x / SCROLL_DIVISOR_H;
    624         scroll_accumulated_v += (float)mouse_report.y / SCROLL_DIVISOR_V;
    625 
    626         // Assign integer parts of accumulated scroll values to the mouse report
    627         mouse_report.h = (int8_t)scroll_accumulated_h;
    628         mouse_report.v = (int8_t)scroll_accumulated_v;
    629 
    630         // Update accumulated scroll values by subtracting the integer parts
    631         scroll_accumulated_h -= (int8_t)scroll_accumulated_h;
    632         scroll_accumulated_v -= (int8_t)scroll_accumulated_v;
    633 
    634         // Clear the X and Y values of the mouse report
    635         mouse_report.x = 0;
    636         mouse_report.y = 0;
    637     }
    638     return mouse_report;
    639 }
    640 
    641 // Function to handle key events and enable/disable drag scrolling
    642 bool process_record_user(uint16_t keycode, keyrecord_t *record) {
    643     switch (keycode) {
    644         case DRAG_SCROLL:
    645             // Toggle set_scrolling when DRAG_SCROLL key is pressed or released
    646             set_scrolling = record->event.pressed;
    647             break;
    648         default:
    649             break;
    650     }
    651     return true;
    652 }
    653 
    654 // Function to handle layer changes and disable drag scrolling when not in AUTO_MOUSE_DEFAULT_LAYER
    655 layer_state_t layer_state_set_user(layer_state_t state) {
    656     // Disable set_scrolling if the current layer is not the AUTO_MOUSE_DEFAULT_LAYER
    657     if (get_highest_layer(state) != AUTO_MOUSE_DEFAULT_LAYER) {
    658         set_scrolling = false;
    659     }
    660     return state;
    661 }
    662 
    663 ```
    664 
    665 
    666 ## Split Examples
    667 
    668 The following examples make use the `SPLIT_POINTING_ENABLE` functionality and show how to manipulate the mouse report for a scrolling mode.
    669 
    670 ### Single Pointing Device
    671 
    672 The following example will work with either `POINTING_DEVICE_LEFT` or `POINTING_DEVICE_RIGHT` and enables scrolling mode while on a particular layer.
    673 
    674 ```c
    675 
    676 static bool scrolling_mode = false;
    677 
    678 layer_state_t layer_state_set_user(layer_state_t state) {
    679     switch (get_highest_layer(state)) {
    680         case _RAISE:  // If we're on the _RAISE layer enable scrolling mode
    681             scrolling_mode = true;
    682             pointing_device_set_cpi(2000);
    683             break;
    684         default:
    685             if (scrolling_mode) {  // check if we were scrolling before and set disable if so
    686                 scrolling_mode = false;
    687                 pointing_device_set_cpi(8000);
    688             }
    689             break;
    690     }
    691     return state;
    692 }
    693 
    694 report_mouse_t pointing_device_task_user(report_mouse_t mouse_report) {
    695     if (scrolling_mode) {
    696         mouse_report.h = mouse_report.x;
    697         mouse_report.v = mouse_report.y;
    698         mouse_report.x = 0;
    699         mouse_report.y = 0;
    700     }
    701     return mouse_report;
    702 }
    703 ```
    704 
    705 ### Combined Pointing Devices
    706 
    707 The following example requires `POINTING_DEVICE_COMBINED` and sets the left side pointing device to scroll only.
    708 
    709 ```c
    710 void keyboard_post_init_user(void) {
    711     pointing_device_set_cpi_on_side(true, 1000); //Set cpi on left side to a low value for slower scrolling.
    712     pointing_device_set_cpi_on_side(false, 8000); //Set cpi on right side to a reasonable value for mousing.
    713 }
    714 
    715 report_mouse_t pointing_device_task_combined_user(report_mouse_t left_report, report_mouse_t right_report) {
    716     left_report.h = left_report.x;
    717     left_report.v = left_report.y;
    718     left_report.x = 0;
    719     left_report.y = 0;
    720     return pointing_device_combine_reports(left_report, right_report);
    721 }
    722 ```
    723 
    724 # Troubleshooting
    725 
    726 If you are having issues with pointing device drivers debug messages can be enabled that will give you insights in the inner workings. To enable these add to your keyboards `config.h` file:
    727 
    728 ```c
    729 #define POINTING_DEVICE_DEBUG
    730 ```
    731 
    732 ::: tip
    733 The messages will be printed out to the `CONSOLE` output. For additional information, refer to [Debugging/Troubleshooting QMK](../faq_debug).
    734 :::
    735 
    736 
    737 ---
    738 # Automatic Mouse Layer {#pointing-device-auto-mouse}
    739 
    740 When using a pointing device combined with a keyboard the mouse buttons are often kept on a separate layer from the default keyboard layer, which requires pressing or holding a key to change layers before using the mouse. To make this easier and more efficient an additional pointing device feature may be enabled that will automatically activate a target layer as soon as the pointing device is active _(in motion, mouse button pressed etc.)_ and deactivate the target layer after a set time.
    741 
    742 Additionally if any key that is defined as a mouse key is pressed then the layer will be held as long as the key is pressed and the timer will be reset on key release. When a non-mouse key is pressed then the layer is deactivated early _(with some exceptions see below)_.  Mod, mod tap, and one shot mod keys are ignored _(i.e. don't hold or activate layer but do not deactivate the layer either)_ when sending a modifier keycode _(e.g. hold for mod tap)_ allowing for mod keys to be used with the mouse without activating the target layer when typing.
    743 
    744 All of the standard layer keys (tap toggling, toggle, toggle on, one_shot, layer tap, layer mod) that activate the current target layer are uniquely handled to ensure they behave as expected _(see layer key table below)_. The target layer that can be changed at any point during by calling the `set_auto_mouse_layer(<new_target_layer>);` function.
    745 
    746 ### Behaviour of Layer keys that activate the target layer
    747 | Layer key as in `keymap.c` | Auto Mouse specific behaviour                                                                                         |
    748 | -------------------------- | --------------------------------------------------------------------------------------------------------------------- |
    749 | `MO(<target_layer>)`       | Treated as a mouse key holding the layer while pressed                                                                |
    750 | `LT(<target_layer>)`       | When tapped will be treated as non mouse key and mouse key when held                                                  |
    751 | `LM(<target_layer>)`       | Treated as a mouse key                                                                                                |
    752 | `TG(<target_layer>)`       | Will set flag preventing target layer deactivation or removal until pressed again                                     |
    753 | `TO(<target_layer>)`       | Same as `TG(<target_layer>)`                                                                                          |
    754 | `TT(<target_layer>)`       | Treated as a mouse key when `tap.count < TAPPING_TOGGLE` and as `TG` when `tap.count == TAPPING_TOGGLE`               |
    755 | `DF(<target_layer>)`       | Skips auto mouse key processing similar to mod keys                                                                   |
    756 | `OSL(<target_layer>)`      | Skips, but if current one shot layer is the target layer then it will prevent target layer deactivation or removal    |
    757 
    758 
    759 ## How to enable:
    760 
    761 ```c
    762 // in config.h:
    763 #define POINTING_DEVICE_AUTO_MOUSE_ENABLE
    764 // only required if not setting mouse layer elsewhere
    765 #define AUTO_MOUSE_DEFAULT_LAYER <index of your mouse layer>
    766 
    767 // in keymap.c:
    768 void pointing_device_init_user(void) {
    769     set_auto_mouse_layer(<mouse_layer>); // only required if AUTO_MOUSE_DEFAULT_LAYER is not set to index of <mouse_layer>
    770     set_auto_mouse_enable(true);         // always required before the auto mouse feature will work
    771 }
    772 ```
    773 
    774 Because the auto mouse feature can be disabled/enabled during runtime and starts as disabled by default it must be enabled by calling `set_auto_mouse_enable(true);` somewhere in firmware before the feature will work.
    775 
    776 _Note: for setting the target layer during initialization either setting `AUTO_MOUSE_DEFAULT_LAYER` in `config.h` or calling `set_auto_mouse_layer(<mouse_layer>)` can be used._
    777 
    778 
    779 ## How to Customize:
    780 
    781 There are a few ways to control the auto mouse feature with both `config.h` options and functions for controlling it during runtime.
    782 
    783 ### `config.h` Options:
    784 | Define                              | Description                                                           |         Range        |    Units    |                    Default |
    785 | ----------------------------------- | --------------------------------------------------------------------- | :------------------: | :---------: | -------------------------: |
    786 | `POINTING_DEVICE_AUTO_MOUSE_ENABLE` | (Required) Enables auto mouse layer feature                           |                      |   _None_    |              _Not defined_ |
    787 | `AUTO_MOUSE_DEFAULT_LAYER`          | (Optional) Index of layer to use as default target layer              |    0 - `LAYER_MAX`   | _`uint8_t`_ |                        `1` |
    788 | `AUTO_MOUSE_TIME`                   | (Optional) Time layer remains active after activation                 | _ideally_ (250-1000) |     _ms_    |                   `650 ms` |
    789 | `AUTO_MOUSE_DELAY`                  | (Optional) Lockout time after non-mouse key is pressed                | _ideally_ (100-1000) |     _ms_    | `TAPPING_TERM` or `200 ms` |
    790 | `AUTO_MOUSE_DEBOUNCE`               | (Optional) Time delay from last activation to next update             | _ideally_ (10 - 100) |     _ms_    |                    `25 ms` |
    791 | `AUTO_MOUSE_THRESHOLD`              | (Optional) Amount of mouse movement required to switch layers         | 0 -                  |   _units_   |                 `10 units` |
    792 
    793 ### Adding mouse keys
    794 
    795 While all default mouse keys and layer keys(for current mouse layer) are treated as mouse keys, additional Keyrecords can be added to mouse keys by adding them to the is_mouse_record_* stack.
    796 
    797 #### Callbacks for setting up additional key codes as mouse keys:
    798 | Callback                                                             | Description                                        |
    799 | -------------------------------------------------------------------- | -------------------------------------------------- |
    800 | `bool is_mouse_record_kb(uint16_t keycode, keyrecord_t* record)`     |  keyboard level callback for adding mouse keys     |
    801 | `bool is_mouse_record_user(uint16_t keycode, keyrecord_t* record)`   |  user/keymap level callback for adding mouse keys  |
    802 
    803 ##### To use the callback function to add mouse keys:
    804 
    805 The following code will cause the enter key and all of the arrow keys to be treated as mouse keys (hold target layer while they are pressed and reset active layer timer).
    806 ```c
    807 
    808 // in <keyboard>.c:
    809 bool is_mouse_record_kb(uint16_t keycode, keyrecord_t* record) {
    810     switch(keycode) {
    811         case KC_ENT:
    812             return true;
    813         case KC_RIGHT ... KC_UP:
    814             return true;
    815         default:
    816             return false;
    817     }
    818     return  is_mouse_record_user(keycode, record);
    819 }
    820 ```
    821 
    822 
    823 ## Advanced control
    824 
    825 There are several functions that allow for more advanced interaction with the auto mouse feature allowing for greater control.
    826 
    827 ### Functions to control auto mouse enable and target layer:
    828 | Function                                                   | Description                                                                          | Aliases                   |     Return type |
    829 | :--------------------------------------------------------- | ------------------------------------------------------------------------------------ | ------------------------- | --------------: |
    830 | `set_auto_mouse_enable(bool enable)`                       | Enable or disable auto mouse (true:enable, false:disable)                            |                           |    `void`(None) |
    831 | `get_auto_mouse_enable(void)`                              | Return auto mouse enable state (true:enabled, false:disabled)                        | `AUTO_MOUSE_ENABLED`      |          `bool` |
    832 | `set_auto_mouse_layer(uint8_t LAYER)`                      | Change/set the target layer for auto mouse                                           |                           |    `void`(None) |
    833 | `get_auto_mouse_layer(void)`                               | Return auto mouse target layer index                                                 | `AUTO_MOUSE_TARGET_LAYER` |       `uint8_t` |
    834 | `remove_auto_mouse_layer(layer_state_t state, bool force)` | Return `state` with target layer removed if appropriate (ignore criteria if `force`) |                           | `layer_state_t` |
    835 | `auto_mouse_layer_off(void)`                               | Disable target layer if appropriate will call (makes call to `layer_state_set`)      |                           |   `void`(None)  |
    836 | `auto_mouse_toggle(void)`                                  | Toggle on/off target toggle state (disables layer deactivation when true)            |                           |    `void`(None) |
    837 | `get_auto_mouse_toggle(void)`                              | Return value of toggling state variable                                              |                           |          `bool` |
    838 | `set_auto_mouse_timeout(uint16_t timeout)`                 | Change/set the timeout for turing off the layer                                      |                           |    `void`(None) |
    839 | `get_auto_mouse_timeout(void)`                             | Return the current timeout for turing off the layer                                  |                           |      `uint16_t` |
    840 | `set_auto_mouse_debounce(uint16_t timeout)`                | Change/set the debounce for preventing layer activation                              |                           |    `void`(None) |
    841 | `get_auto_mouse_debounce(void)`                            | Return the current debounce for preventing layer activation                          |                           |       `uint8_t` |
    842 | `is_auto_mouse_active(void)`                               | Returns the active state of the auto mouse layer (eg if the layer has been triggered)|                           |          `bool` |
    843 | `get_auto_mouse_key_tracker(void)`                         | Gets the current count for the auto mouse key tracker.                               |                           |        `int8_t` |
    844 | `set_auto_mouse_key_tracker(int8_t key_tracker)`           | Sets/Overrides the current count for the auto mouse key tracker.                     |                           |    `void`(None) |
    845 
    846 _NOTES:_
    847 
    848 - _Due to the nature of how some functions work, the `auto_mouse_trigger_reset`, and `auto_mouse_layer_off` functions should never be called in the `layer_state_set_*` stack as this can cause indefinite loops._
    849 - _It is recommended that `remove_auto_mouse_layer` is used in the `layer_state_set_*` stack of functions and `auto_mouse_layer_off` is used everywhere else_
    850 - _`remove_auto_mouse_layer(state, false)` or `auto_mouse_layer_off()` should be called before any instance of `set_auto_mouse_enabled(false)` or `set_auto_mouse_layer(layer)` to ensure that the target layer will be removed appropriately before disabling auto mouse or changing target to avoid a stuck layer_
    851 
    852 ### Functions for handling custom key events:
    853 | Function                                                   | Description                                                                      |     Return type |
    854 | :--------------------------------------------------------- | -------------------------------------------------------------------------------- | --------------: |
    855 | `auto_mouse_keyevent(bool pressed)`                        | Auto mouse mouse key event (true: key down, false: key up)                       |    `void`(None) |
    856 | `auto_mouse_trigger_reset(bool pressed)`                   | Reset auto mouse status on key down and start delay timer (non-mouse key event)  |    `void`(None) |
    857 | `auto_mouse_toggle(void)`                                  | Toggle on/off target toggle state (disables layer deactivation when true)        |    `void`(None) |
    858 | `get_auto_mouse_toggle(void)`                              | Return value of toggling state variable                                          |          `bool` |
    859 
    860 _NOTE: Generally it would be preferable to use the `is_mouse_record_*` functions to add any additional keys that should act as mouse keys rather than adding `auto_mouse_keyevent(record.event->pressed)` to `process_records_*`_
    861 
    862 ### Advanced control examples
    863 
    864 #### Disable auto mouse on certain layers:
    865 
    866 The auto mouse feature can be disabled any time and this can be helpful if you want to disable the auto mouse feature under certain circumstances such as when particular layers are active. One issue however is the handling of the target layer, it needs to be removed appropriately **before** disabling auto mouse _(see notes under control functions above)_. The following function would disable the auto_mouse feature whenever the layers `_LAYER5` through `_LAYER7` are active as the top most layer _(ignoring target layer)_.
    867 
    868 ```c
    869 // in keymap.c:
    870 layer_state_t layer_state_set_user(layer_state_t state) {
    871     // checks highest layer other than target layer
    872     switch(get_highest_layer(remove_auto_mouse_layer(state, true))) {
    873         case _LAYER5 ... _LAYER7:
    874             // remove_auto_mouse_target must be called to adjust state *before* setting enable
    875             state = remove_auto_mouse_layer(state, false);
    876             set_auto_mouse_enable(false);
    877             break;
    878         default:
    879             set_auto_mouse_enable(true);
    880             break;
    881     }
    882     // recommend that any code that makes adjustment based on auto mouse layer state would go here
    883     return state;
    884 }
    885 ```
    886 
    887 #### Set different target layer when a particular layer is active:
    888 
    889 The below code will change the auto mouse layer target to `_MOUSE_LAYER_2` when `_DEFAULT_LAYER_2` is highest default layer state.
    890 
    891 *NOTE: that `auto_mouse_layer_off` is used here instead of `remove_auto_mouse_layer` as `default_layer_state_set_*` stack is separate from the `layer_state_set_*` stack*, if something similar was to be done in `layer_state_set_user`, `state = remove_auto_mouse_layer(state, false)` should be used instead.
    892 
    893 *ADDITIONAL NOTE: `AUTO_MOUSE_TARGET_LAYER` is checked if already set to avoid deactivating the target layer unless needed*.
    894 
    895 ```c
    896 // in keymap.c
    897 layer_state_t default_layer_state_set_user(layer_state_t state) {
    898     // switch on change in default layer need to check if target layer already set to avoid turning off layer needlessly
    899     switch(get_highest_layer(state)) {
    900         case _DEFAULT_LAYER_2:
    901             if ((AUTO_MOUSE_TARGET_LAYER) == _MOUSE_LAYER_2) break;
    902             auto_mouse_layer_off();
    903             set_auto_mouse_layer(_MOUSE_LAYER_2);
    904             break;
    905 
    906         default:
    907             if((AUTO_MOUSE_TARGET_LAYER) == _MOUSE_LAYER_1) break;
    908             auto_mouse_layer_off();
    909             set_auto_mouse_layer(_MOUSE_LAYER_1);
    910     }
    911     return state;
    912 }
    913 ```
    914 
    915 ### Use custom keys to control auto mouse:
    916 
    917 Custom key records could also be created that control the auto mouse feature.
    918 
    919 The code example below would create a custom key that would toggle the auto mouse feature on and off when pressed while also setting a bool that could be used to disable other code that may turn it on such as the layer code above.
    920 
    921 ```c
    922 // in config.h:
    923 enum user_custom_keycodes {
    924     AM_Toggle = SAFE_RANGE
    925 };
    926 
    927 // in keymap.c:
    928 // set up global bool to adjust other user code
    929 bool auto_mouse_tg_off = !AUTO_MOUSE_ENABLED;
    930 
    931 bool process_record_user(uint16_t keycode, keyrecord_t* record) {
    932     switch (keycode) {
    933         // toggle auto mouse enable key
    934         case AM_Toggle:
    935             if(record->event.pressed) { // key down
    936                 auto_mouse_layer_off(); // disable target layer if needed
    937                 set_auto_mouse_enabled((AUTO_MOUSE_ENABLED) ^ 1);
    938                 auto_mouse_tg_off = !get_auto_mouse_enabled();
    939             } // do nothing on key up
    940             return false; // prevent further processing of keycode
    941     }
    942 }
    943 ```
    944 
    945 
    946 ## Customize Target Layer Activation
    947 
    948 Layer activation can be customized by overwriting the `auto_mouse_activation` function. This function is checked every time `pointing_device_task` is called when inactive and every `AUTO_MOUSE_DEBOUNCE` ms when active, and will evaluate pointing device level conditions that trigger target layer activation. When it returns true, the target layer will be activated barring the usual exceptions _(e.g. delay time has not expired)_.
    949 
    950 By default it will return true if any of the `mouse_report` axes `x`,`y`,`h`,`v` are non zero, or if there is any mouse buttons active in `mouse_report`.
    951 _Note: The Cirque pinnacle track pad already implements a custom activation function that will activate on touchdown as well as movement all of the default conditions, currently this only works for the master side of split keyboards._
    952 
    953 | Function                                                   | Description                                                                      |     Return type |
    954 | :--------------------------------------------------------- | -------------------------------------------------------------------------------- | --------------: |
    955 | `auto_mouse_activation(report_mouse_t mouse_report)`       | Overwritable function that controls target layer activation (when true)          |          `bool` |
    956 
    957 ## Auto Mouse for Custom Pointing Device Task
    958 
    959 When using a custom pointing device (overwriting `pointing_device_task`) the following code should be somewhere in the `pointing_device_task_*` stack:
    960 
    961 ```c
    962 bool pointing_device_task(void) {
    963     //...Custom pointing device task code
    964 
    965     // handle automatic mouse layer (needs report_mouse_t as input)
    966     pointing_device_task_auto_mouse(local_mouse_report);
    967 
    968     //...More custom pointing device task code
    969 
    970     return pointing_device_send();
    971 }
    972 ```
    973 
    974 In general the following two functions must be implemented in appropriate locations for auto mouse to function:
    975 
    976 | Function                                                       | Description                                                  |           Suggested location |
    977 | -------------------------------------------------------------- | ------------------------------------------------------------ | ---------------------------: |
    978 | `pointing_device_task_auto_mouse(report_mouse_t mouse_report)` | handles target layer activation and is_active status updates | `pointing_device_task` stack |
    979 | `process_auto_mouse(uint16_t keycode, keyrecord_t* record)`    | Keycode processing for auto mouse                            |       `process_record` stack |