qmk_firmware

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

joystick.md (8785B)


      1 # Joystick {#joystick}
      2 
      3 This feature provides game controller input as a joystick device supporting up to 6 axes, 32 buttons and a hat switch. Axes can be read either from an [ADC-capable input pin](../drivers/adc), or can be virtual, so that its value is provided by your code.
      4 
      5 An analog device such as a [potentiometer](https://en.wikipedia.org/wiki/Potentiometer) found on an analog joystick's axes is based on a voltage divider, where adjusting the movable wiper controls the output voltage which can then be read by the microcontroller's ADC.
      6 
      7 ## Usage {#usage}
      8 
      9 Add the following to your `rules.mk`:
     10 
     11 ```make
     12 JOYSTICK_ENABLE = yes
     13 ```
     14 
     15 By default the joystick driver is `analog`, but you can change this with:
     16 
     17 ```make
     18 JOYSTICK_DRIVER = digital
     19 ```
     20 
     21 When using `analog` with ARM, [you must use 3.3v with your Joystick](../drivers/adc). Although ARM boards such as the [Helios](https://keeb.supply/products/0xcb-helios) have 5v pin output, the ADC driver does not support it.
     22 
     23 ## Configuration {#configuration}
     24 
     25 By default, two axes and eight buttons are defined, with a reported resolution of 8 bits (-127 to +127). This can be changed in your `config.h`:
     26 
     27 ```c
     28 // Min 0, max 32
     29 #define JOYSTICK_BUTTON_COUNT 16
     30 // Min 0, max 6: X, Y, Z, Rx, Ry, Rz
     31 #define JOYSTICK_AXIS_COUNT 3
     32 // Min 8, max 16
     33 #define JOYSTICK_AXIS_RESOLUTION 10
     34 ```
     35 
     36 ::: tip
     37 You must define at least one button or axis. Also note that the maximum ADC resolution of the supported AVR MCUs is 10-bit, and 12-bit for most STM32 MCUs.
     38 :::
     39 
     40 ### Hat Switch {#hat-switch}
     41 
     42 To enable the 8-way hat switch, add the following to your `config.h`:
     43 
     44 ```c
     45 #define JOYSTICK_HAS_HAT
     46 ````
     47 
     48 The position can be set by calling `joystick_set_hat(value)`. The range of values moves clockwise from the top (ie. north), with the default "center" position represented by a value of `-1`:
     49 
     50 ```
     51          0
     52  7       N       1
     53    NW .--'--. NE
     54      /       \
     55 6 W |   -1    | E 2
     56      \       /
     57    SW '--.--' SE
     58  5       S       3
     59          4
     60 ```
     61 
     62 Alternatively you can use these predefined names:
     63 
     64 |Define                  |Value|Angle|
     65 |------------------------|-----|-----|
     66 |`JOYSTICK_HAT_CENTER`   |`-1` |     |
     67 |`JOYSTICK_HAT_NORTH`    |`0`  |0°   |
     68 |`JOYSTICK_HAT_NORTHEAST`|`1`  |45°  |
     69 |`JOYSTICK_HAT_EAST`     |`2`  |90°  |
     70 |`JOYSTICK_HAT_SOUTHEAST`|`3`  |135° |
     71 |`JOYSTICK_HAT_SOUTH`    |`4`  |180° |
     72 |`JOYSTICK_HAT_SOUTHWEST`|`5`  |225° |
     73 |`JOYSTICK_HAT_WEST`     |`6`  |270° |
     74 |`JOYSTICK_HAT_NORTHWEST`|`7`  |315° |
     75 
     76 ### Axes {#axes}
     77 
     78 When defining axes for your joystick, you must provide a definition array typically in your `keymap.c`.
     79 
     80 For instance, the below example configures two axes. The X axis is read from the `A4` pin. With the default axis resolution of 8 bits, the range of values between 900 and 575 are scaled to -127 through 0, and values 575 to 285 are scaled to 0 through 127. The Y axis is configured as a virtual axis, and its value is not read from any pin. Instead, the user must update the axis value programmatically.
     81 
     82 ```c
     83 joystick_config_t joystick_axes[JOYSTICK_AXIS_COUNT] = {
     84     JOYSTICK_AXIS_IN(A4, 900, 575, 285),
     85     JOYSTICK_AXIS_VIRTUAL
     86 };
     87 ```
     88 
     89 Axes can be configured using one of the following macros:
     90 
     91  * `JOYSTICK_AXIS_IN(input_pin, low, rest, high)`  
     92    The ADC samples the provided pin. `low`, `high` and `rest` correspond to the minimum, maximum, and resting (or centered) analog values of the axis, respectively.
     93  * `JOYSTICK_AXIS_VIRTUAL`  
     94    No ADC reading is performed. The value should be provided by user code.
     95 
     96 The `low` and `high` values can be swapped to effectively invert the axis.
     97 
     98 #### Virtual Axes {#virtual-axes}
     99 
    100 The following example adjusts two virtual axes (X and Y) based on keypad presses, with `KC_P0` as a precision modifier:
    101 
    102 ```c
    103 joystick_config_t joystick_axes[JOYSTICK_AXIS_COUNT] = {
    104     JOYSTICK_AXIS_VIRTUAL, // x
    105     JOYSTICK_AXIS_VIRTUAL  // y
    106 };
    107 
    108 static bool precision = false;
    109 static uint16_t precision_mod = 64;
    110 static uint16_t axis_val = 127;
    111 
    112 bool process_record_user(uint16_t keycode, keyrecord_t *record) {
    113     int16_t precision_val = axis_val;
    114     if (precision) {
    115         precision_val -= precision_mod;
    116     }
    117 
    118     switch (keycode) {
    119         case KC_P8:
    120             joystick_set_axis(1, record->event.pressed ? -precision_val : 0);
    121             return false;
    122         case KC_P2:
    123             joystick_set_axis(1, record->event.pressed ? precision_val : 0);
    124             return false;
    125         case KC_P4:
    126             joystick_set_axis(0, record->event.pressed ? -precision_val : 0);
    127             return false;
    128         case KC_P6:
    129             joystick_set_axis(0, record->event.pressed ? precision_val : 0);
    130             return false;
    131         case KC_P0:
    132             precision = record->event.pressed;
    133             return false;
    134     }
    135     return true;
    136 }
    137 ```
    138 
    139 ## Keycodes {#keycodes}
    140 
    141 |Key                    |Aliases|Description|
    142 |-----------------------|-------|-----------|
    143 |`QK_JOYSTICK_BUTTON_0` |`JS_0` |Button 0   |
    144 |`QK_JOYSTICK_BUTTON_1` |`JS_1` |Button 1   |
    145 |`QK_JOYSTICK_BUTTON_2` |`JS_2` |Button 2   |
    146 |`QK_JOYSTICK_BUTTON_3` |`JS_3` |Button 3   |
    147 |`QK_JOYSTICK_BUTTON_4` |`JS_4` |Button 4   |
    148 |`QK_JOYSTICK_BUTTON_5` |`JS_5` |Button 5   |
    149 |`QK_JOYSTICK_BUTTON_6` |`JS_6` |Button 6   |
    150 |`QK_JOYSTICK_BUTTON_7` |`JS_7` |Button 7   |
    151 |`QK_JOYSTICK_BUTTON_8` |`JS_8` |Button 8   |
    152 |`QK_JOYSTICK_BUTTON_9` |`JS_9` |Button 9   |
    153 |`QK_JOYSTICK_BUTTON_10`|`JS_10`|Button 10  |
    154 |`QK_JOYSTICK_BUTTON_11`|`JS_11`|Button 11  |
    155 |`QK_JOYSTICK_BUTTON_12`|`JS_12`|Button 12  |
    156 |`QK_JOYSTICK_BUTTON_13`|`JS_13`|Button 13  |
    157 |`QK_JOYSTICK_BUTTON_14`|`JS_14`|Button 14  |
    158 |`QK_JOYSTICK_BUTTON_15`|`JS_15`|Button 15  |
    159 |`QK_JOYSTICK_BUTTON_16`|`JS_16`|Button 16  |
    160 |`QK_JOYSTICK_BUTTON_17`|`JS_17`|Button 17  |
    161 |`QK_JOYSTICK_BUTTON_18`|`JS_18`|Button 18  |
    162 |`QK_JOYSTICK_BUTTON_19`|`JS_19`|Button 19  |
    163 |`QK_JOYSTICK_BUTTON_20`|`JS_20`|Button 20  |
    164 |`QK_JOYSTICK_BUTTON_21`|`JS_21`|Button 21  |
    165 |`QK_JOYSTICK_BUTTON_22`|`JS_22`|Button 22  |
    166 |`QK_JOYSTICK_BUTTON_23`|`JS_23`|Button 23  |
    167 |`QK_JOYSTICK_BUTTON_24`|`JS_24`|Button 24  |
    168 |`QK_JOYSTICK_BUTTON_25`|`JS_25`|Button 25  |
    169 |`QK_JOYSTICK_BUTTON_26`|`JS_26`|Button 26  |
    170 |`QK_JOYSTICK_BUTTON_27`|`JS_27`|Button 27  |
    171 |`QK_JOYSTICK_BUTTON_28`|`JS_28`|Button 28  |
    172 |`QK_JOYSTICK_BUTTON_29`|`JS_29`|Button 29  |
    173 |`QK_JOYSTICK_BUTTON_30`|`JS_30`|Button 30  |
    174 |`QK_JOYSTICK_BUTTON_31`|`JS_31`|Button 31  |
    175 
    176 ## API {#api}
    177 
    178 ### `struct joystick_t` {#api-joystick-t}
    179 
    180 Contains the state of the joystick.
    181 
    182 #### Members {#api-joystick-t-members}
    183 
    184  - `uint8_t buttons[]`  
    185    A bit-packed array containing the joystick button states. The size is calculated as `(JOYSTICK_BUTTON_COUNT - 1) / 8 + 1`.
    186  - `int16_t axes[]`  
    187    An array of analog values for each defined axis.
    188  - `int8_t hat`  
    189    The hat switch position.
    190  - `bool dirty`  
    191    Whether the current state needs to be sent to the host.
    192 
    193 ---
    194 
    195 ### `struct joystick_config_t` {#api-joystick-config-t}
    196 
    197 Describes a single axis.
    198 
    199 #### Members {#api-joystick-config-t-members}
    200 
    201  - `pin_t input_pin`  
    202    The pin to read the analog value from, or `JS_VIRTUAL_AXIS`.
    203  - `uint16_t min_digit`  
    204    The minimum analog value.
    205  - `uint16_t mid_digit`  
    206    The resting or midpoint analog value.
    207  - `uint16_t max_digit`  
    208    The maximum analog value.
    209 
    210 ---
    211 
    212 ### `void joystick_flush(void)` {#api-joystick-flush}
    213 
    214 Send the joystick report to the host, if it has been marked as dirty.
    215 
    216 ---
    217 
    218 ### `void register_joystick_button(uint8_t button)` {#api-register-joystick-button}
    219 
    220 Set the state of a button, and flush the report.
    221 
    222 #### Arguments {#api-register-joystick-button-arguments}
    223 
    224  - `uint8_t button`  
    225    The index of the button to press, from 0 to 31.
    226 
    227 ---
    228 
    229 ### `void unregister_joystick_button(uint8_t button)` {#api-unregister-joystick-button}
    230 
    231 Reset the state of a button, and flush the report.
    232 
    233 #### Arguments {#api-unregister-joystick-button-arguments}
    234 
    235  - `uint8_t button`  
    236    The index of the button to release, from 0 to 31.
    237 
    238 ---
    239 
    240 ### `int16_t joystick_read_axis(uint8_t axis)` {#api-joystick-read-axis}
    241 
    242 Sample and process the analog value of the given axis.
    243 
    244 #### Arguments {#api-joystick-read-axis-arguments}
    245 
    246  - `uint8_t axis`  
    247    The axis to read.
    248 
    249 #### Return Value {#api-joystick-read-axis-return}
    250 
    251 A signed 16-bit integer, where 0 is the resting or mid point.
    252 
    253 ### `void joystick_set_axis(uint8_t axis, int16_t value)` {#api-joystick-set-axis}
    254 
    255 Set the value of the given axis.
    256 
    257 #### Arguments {#api-joystick-set-axis-arguments}
    258 
    259  - `uint8_t axis`  
    260    The axis to set the value of.
    261  - `int16_t value`  
    262    The value to set.
    263 
    264 ---
    265 
    266 ### `void joystick_set_hat(int8_t value)` {#api-joystick-set-hat}
    267 
    268 Set the position of the hat switch.
    269 
    270 #### Arguments {#api-joystick-set-hat-arguments}
    271 
    272  - `int8_t value`  
    273    The hat switch position to set.