logo

qmk_firmware

custom branch of QMK firmware git clone https://anongit.hacktivis.me/git/qmk_firmware.git

joystick.md (8785B)


  1. # Joystick {#joystick}
  2. 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.
  3. 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.
  4. ## Usage {#usage}
  5. Add the following to your `rules.mk`:
  6. ```make
  7. JOYSTICK_ENABLE = yes
  8. ```
  9. By default the joystick driver is `analog`, but you can change this with:
  10. ```make
  11. JOYSTICK_DRIVER = digital
  12. ```
  13. 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.
  14. ## Configuration {#configuration}
  15. 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`:
  16. ```c
  17. // Min 0, max 32
  18. #define JOYSTICK_BUTTON_COUNT 16
  19. // Min 0, max 6: X, Y, Z, Rx, Ry, Rz
  20. #define JOYSTICK_AXIS_COUNT 3
  21. // Min 8, max 16
  22. #define JOYSTICK_AXIS_RESOLUTION 10
  23. ```
  24. ::: tip
  25. 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.
  26. :::
  27. ### Hat Switch {#hat-switch}
  28. To enable the 8-way hat switch, add the following to your `config.h`:
  29. ```c
  30. #define JOYSTICK_HAS_HAT
  31. ````
  32. 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`:
  33. ```
  34. 0
  35. 7 N 1
  36. NW .--'--. NE
  37. / \
  38. 6 W | -1 | E 2
  39. \ /
  40. SW '--.--' SE
  41. 5 S 3
  42. 4
  43. ```
  44. Alternatively you can use these predefined names:
  45. |Define |Value|Angle|
  46. |------------------------|-----|-----|
  47. |`JOYSTICK_HAT_CENTER` |`-1` | |
  48. |`JOYSTICK_HAT_NORTH` |`0` |0° |
  49. |`JOYSTICK_HAT_NORTHEAST`|`1` |45° |
  50. |`JOYSTICK_HAT_EAST` |`2` |90° |
  51. |`JOYSTICK_HAT_SOUTHEAST`|`3` |135° |
  52. |`JOYSTICK_HAT_SOUTH` |`4` |180° |
  53. |`JOYSTICK_HAT_SOUTHWEST`|`5` |225° |
  54. |`JOYSTICK_HAT_WEST` |`6` |270° |
  55. |`JOYSTICK_HAT_NORTHWEST`|`7` |315° |
  56. ### Axes {#axes}
  57. When defining axes for your joystick, you must provide a definition array typically in your `keymap.c`.
  58. 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.
  59. ```c
  60. joystick_config_t joystick_axes[JOYSTICK_AXIS_COUNT] = {
  61. JOYSTICK_AXIS_IN(A4, 900, 575, 285),
  62. JOYSTICK_AXIS_VIRTUAL
  63. };
  64. ```
  65. Axes can be configured using one of the following macros:
  66. * `JOYSTICK_AXIS_IN(input_pin, low, rest, high)`
  67. 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.
  68. * `JOYSTICK_AXIS_VIRTUAL`
  69. No ADC reading is performed. The value should be provided by user code.
  70. The `low` and `high` values can be swapped to effectively invert the axis.
  71. #### Virtual Axes {#virtual-axes}
  72. The following example adjusts two virtual axes (X and Y) based on keypad presses, with `KC_P0` as a precision modifier:
  73. ```c
  74. joystick_config_t joystick_axes[JOYSTICK_AXIS_COUNT] = {
  75. JOYSTICK_AXIS_VIRTUAL, // x
  76. JOYSTICK_AXIS_VIRTUAL // y
  77. };
  78. static bool precision = false;
  79. static uint16_t precision_mod = 64;
  80. static uint16_t axis_val = 127;
  81. bool process_record_user(uint16_t keycode, keyrecord_t *record) {
  82. int16_t precision_val = axis_val;
  83. if (precision) {
  84. precision_val -= precision_mod;
  85. }
  86. switch (keycode) {
  87. case KC_P8:
  88. joystick_set_axis(1, record->event.pressed ? -precision_val : 0);
  89. return false;
  90. case KC_P2:
  91. joystick_set_axis(1, record->event.pressed ? precision_val : 0);
  92. return false;
  93. case KC_P4:
  94. joystick_set_axis(0, record->event.pressed ? -precision_val : 0);
  95. return false;
  96. case KC_P6:
  97. joystick_set_axis(0, record->event.pressed ? precision_val : 0);
  98. return false;
  99. case KC_P0:
  100. precision = record->event.pressed;
  101. return false;
  102. }
  103. return true;
  104. }
  105. ```
  106. ## Keycodes {#keycodes}
  107. |Key |Aliases|Description|
  108. |-----------------------|-------|-----------|
  109. |`QK_JOYSTICK_BUTTON_0` |`JS_0` |Button 0 |
  110. |`QK_JOYSTICK_BUTTON_1` |`JS_1` |Button 1 |
  111. |`QK_JOYSTICK_BUTTON_2` |`JS_2` |Button 2 |
  112. |`QK_JOYSTICK_BUTTON_3` |`JS_3` |Button 3 |
  113. |`QK_JOYSTICK_BUTTON_4` |`JS_4` |Button 4 |
  114. |`QK_JOYSTICK_BUTTON_5` |`JS_5` |Button 5 |
  115. |`QK_JOYSTICK_BUTTON_6` |`JS_6` |Button 6 |
  116. |`QK_JOYSTICK_BUTTON_7` |`JS_7` |Button 7 |
  117. |`QK_JOYSTICK_BUTTON_8` |`JS_8` |Button 8 |
  118. |`QK_JOYSTICK_BUTTON_9` |`JS_9` |Button 9 |
  119. |`QK_JOYSTICK_BUTTON_10`|`JS_10`|Button 10 |
  120. |`QK_JOYSTICK_BUTTON_11`|`JS_11`|Button 11 |
  121. |`QK_JOYSTICK_BUTTON_12`|`JS_12`|Button 12 |
  122. |`QK_JOYSTICK_BUTTON_13`|`JS_13`|Button 13 |
  123. |`QK_JOYSTICK_BUTTON_14`|`JS_14`|Button 14 |
  124. |`QK_JOYSTICK_BUTTON_15`|`JS_15`|Button 15 |
  125. |`QK_JOYSTICK_BUTTON_16`|`JS_16`|Button 16 |
  126. |`QK_JOYSTICK_BUTTON_17`|`JS_17`|Button 17 |
  127. |`QK_JOYSTICK_BUTTON_18`|`JS_18`|Button 18 |
  128. |`QK_JOYSTICK_BUTTON_19`|`JS_19`|Button 19 |
  129. |`QK_JOYSTICK_BUTTON_20`|`JS_20`|Button 20 |
  130. |`QK_JOYSTICK_BUTTON_21`|`JS_21`|Button 21 |
  131. |`QK_JOYSTICK_BUTTON_22`|`JS_22`|Button 22 |
  132. |`QK_JOYSTICK_BUTTON_23`|`JS_23`|Button 23 |
  133. |`QK_JOYSTICK_BUTTON_24`|`JS_24`|Button 24 |
  134. |`QK_JOYSTICK_BUTTON_25`|`JS_25`|Button 25 |
  135. |`QK_JOYSTICK_BUTTON_26`|`JS_26`|Button 26 |
  136. |`QK_JOYSTICK_BUTTON_27`|`JS_27`|Button 27 |
  137. |`QK_JOYSTICK_BUTTON_28`|`JS_28`|Button 28 |
  138. |`QK_JOYSTICK_BUTTON_29`|`JS_29`|Button 29 |
  139. |`QK_JOYSTICK_BUTTON_30`|`JS_30`|Button 30 |
  140. |`QK_JOYSTICK_BUTTON_31`|`JS_31`|Button 31 |
  141. ## API {#api}
  142. ### `struct joystick_t` {#api-joystick-t}
  143. Contains the state of the joystick.
  144. #### Members {#api-joystick-t-members}
  145. - `uint8_t buttons[]`
  146. A bit-packed array containing the joystick button states. The size is calculated as `(JOYSTICK_BUTTON_COUNT - 1) / 8 + 1`.
  147. - `int16_t axes[]`
  148. An array of analog values for each defined axis.
  149. - `int8_t hat`
  150. The hat switch position.
  151. - `bool dirty`
  152. Whether the current state needs to be sent to the host.
  153. ---
  154. ### `struct joystick_config_t` {#api-joystick-config-t}
  155. Describes a single axis.
  156. #### Members {#api-joystick-config-t-members}
  157. - `pin_t input_pin`
  158. The pin to read the analog value from, or `JS_VIRTUAL_AXIS`.
  159. - `uint16_t min_digit`
  160. The minimum analog value.
  161. - `uint16_t mid_digit`
  162. The resting or midpoint analog value.
  163. - `uint16_t max_digit`
  164. The maximum analog value.
  165. ---
  166. ### `void joystick_flush(void)` {#api-joystick-flush}
  167. Send the joystick report to the host, if it has been marked as dirty.
  168. ---
  169. ### `void register_joystick_button(uint8_t button)` {#api-register-joystick-button}
  170. Set the state of a button, and flush the report.
  171. #### Arguments {#api-register-joystick-button-arguments}
  172. - `uint8_t button`
  173. The index of the button to press, from 0 to 31.
  174. ---
  175. ### `void unregister_joystick_button(uint8_t button)` {#api-unregister-joystick-button}
  176. Reset the state of a button, and flush the report.
  177. #### Arguments {#api-unregister-joystick-button-arguments}
  178. - `uint8_t button`
  179. The index of the button to release, from 0 to 31.
  180. ---
  181. ### `int16_t joystick_read_axis(uint8_t axis)` {#api-joystick-read-axis}
  182. Sample and process the analog value of the given axis.
  183. #### Arguments {#api-joystick-read-axis-arguments}
  184. - `uint8_t axis`
  185. The axis to read.
  186. #### Return Value {#api-joystick-read-axis-return}
  187. A signed 16-bit integer, where 0 is the resting or mid point.
  188. ### `void joystick_set_axis(uint8_t axis, int16_t value)` {#api-joystick-set-axis}
  189. Set the value of the given axis.
  190. #### Arguments {#api-joystick-set-axis-arguments}
  191. - `uint8_t axis`
  192. The axis to set the value of.
  193. - `int16_t value`
  194. The value to set.
  195. ---
  196. ### `void joystick_set_hat(int8_t value)` {#api-joystick-set-hat}
  197. Set the position of the hat switch.
  198. #### Arguments {#api-joystick-set-hat-arguments}
  199. - `int8_t value`
  200. The hat switch position to set.