7.7 KiB
Joystick :id=joystick
This feature provides game controller input as a joystick device supporting up to 6 axes and 32 buttons. Axes can be read either from an ADC-capable input pin, or can be virtual, so that its value is provided by your code.
An analog device such as a 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.
Usage :id=usage
Add the following to your rules.mk
:
JOYSTICK_ENABLE = yes
By default the joystick driver is analog
, but you can change this with:
JOYSTICK_DRIVER = digital
Configuration :id=configuration
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
:
// Min 0, max 32
#define JOYSTICK_BUTTON_COUNT 16
// Min 0, max 6: X, Y, Z, Rx, Ry, Rz
#define JOYSTICK_AXIS_COUNT 3
// Min 8, max 16
#define JOYSTICK_AXIS_RESOLUTION 10
?> 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.
Axes :id=axes
When defining axes for your joystick, you must provide a definition array typically in your keymap.c
.
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.
joystick_config_t joystick_axes[JOYSTICK_AXES_COUNT] = {
JOYSTICK_AXIS_IN(A4, 900, 575, 285),
JOYSTICK_AXIS_VIRTUAL
};
Axes can be configured using one of the following macros:
JOYSTICK_AXIS_IN(input_pin, low, rest, high)
The ADC samples the provided pin.low
,high
andrest
correspond to the minimum, maximum, and resting (or centered) analog values of the axis, respectively.JOYSTICK_AXIS_IN_OUT(input_pin, output_pin, low, rest, high)
Same asJOYSTICK_AXIS_IN()
, but the providedoutput_pin
will be pulled high beforeinput_pin
is read.JOYSTICK_AXIS_IN_OUT_GROUND(input_pin, output_pin, ground_pin, low, rest, high)
Same asJOYSTICK_AXIS_IN_OUT()
, but the providedground_pin
will be pulled low before reading frominput_pin
.JOYSTICK_AXIS_VIRTUAL
No ADC reading is performed. The value should be provided by user code.
The low
and high
values can be swapped to effectively invert the axis.
Virtual Axes :id=virtual-axes
The following example adjusts two virtual axes (X and Y) based on keypad presses, with KC_P0
as a precision modifier:
joystick_config_t joystick_axes[JOYSTICK_AXES_COUNT] = {
JOYSTICK_AXIS_VIRTUAL, // x
JOYSTICK_AXIS_VIRTUAL // y
};
static bool precision = false;
static uint16_t precision_mod = 64;
static uint16_t axis_val = 127;
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
int16_t precision_val = axis_val;
if (precision) {
precision_val -= precision_mod;
}
switch (keycode) {
case KC_P8:
joystick_set_axis(1, record->event.pressed ? -precision_val : 0);
return false;
case KC_P2:
joystick_set_axis(1, record->event.pressed ? precision_val : 0);
return false;
case KC_P4:
joystick_set_axis(0, record->event.pressed ? -precision_val : 0);
return false;
case KC_P6:
joystick_set_axis(0, record->event.pressed ? precision_val : 0);
return false;
case KC_P0:
precision = record->event.pressed;
return false;
}
return true;
}
Keycodes :id=keycodes
Key | Aliases | Description |
---|---|---|
QK_JOYSTICK_BUTTON_0 |
JS_0 |
Button 0 |
QK_JOYSTICK_BUTTON_1 |
JS_1 |
Button 1 |
QK_JOYSTICK_BUTTON_2 |
JS_2 |
Button 2 |
QK_JOYSTICK_BUTTON_3 |
JS_3 |
Button 3 |
QK_JOYSTICK_BUTTON_4 |
JS_4 |
Button 4 |
QK_JOYSTICK_BUTTON_5 |
JS_5 |
Button 5 |
QK_JOYSTICK_BUTTON_6 |
JS_6 |
Button 6 |
QK_JOYSTICK_BUTTON_7 |
JS_7 |
Button 7 |
QK_JOYSTICK_BUTTON_8 |
JS_8 |
Button 8 |
QK_JOYSTICK_BUTTON_9 |
JS_9 |
Button 9 |
QK_JOYSTICK_BUTTON_10 |
JS_10 |
Button 10 |
QK_JOYSTICK_BUTTON_11 |
JS_11 |
Button 11 |
QK_JOYSTICK_BUTTON_12 |
JS_12 |
Button 12 |
QK_JOYSTICK_BUTTON_13 |
JS_13 |
Button 13 |
QK_JOYSTICK_BUTTON_14 |
JS_14 |
Button 14 |
QK_JOYSTICK_BUTTON_15 |
JS_15 |
Button 15 |
QK_JOYSTICK_BUTTON_16 |
JS_16 |
Button 16 |
QK_JOYSTICK_BUTTON_17 |
JS_17 |
Button 17 |
QK_JOYSTICK_BUTTON_18 |
JS_18 |
Button 18 |
QK_JOYSTICK_BUTTON_19 |
JS_19 |
Button 19 |
QK_JOYSTICK_BUTTON_20 |
JS_20 |
Button 20 |
QK_JOYSTICK_BUTTON_21 |
JS_21 |
Button 21 |
QK_JOYSTICK_BUTTON_22 |
JS_22 |
Button 22 |
QK_JOYSTICK_BUTTON_23 |
JS_23 |
Button 23 |
QK_JOYSTICK_BUTTON_24 |
JS_24 |
Button 24 |
QK_JOYSTICK_BUTTON_25 |
JS_25 |
Button 25 |
QK_JOYSTICK_BUTTON_26 |
JS_26 |
Button 26 |
QK_JOYSTICK_BUTTON_27 |
JS_27 |
Button 27 |
QK_JOYSTICK_BUTTON_28 |
JS_28 |
Button 28 |
QK_JOYSTICK_BUTTON_29 |
JS_29 |
Button 29 |
QK_JOYSTICK_BUTTON_30 |
JS_30 |
Button 30 |
QK_JOYSTICK_BUTTON_31 |
JS_31 |
Button 31 |
API :id=api
struct joystick_t
:id=api-joystick-t
Contains the state of the joystick.
Members :id=api-joystick-t-members
uint8_t buttons[]
A bit-packed array containing the joystick button states. The size is calculated as(JOYSTICK_BUTTON_COUNT - 1) / 8 + 1
.int16_t axes[]
An array of analog values for each defined axis.bool dirty
Whether the current state needs to be sent to the host.
struct joystick_config_t
:id=api-joystick-config-t
Describes a single axis.
Members :id=api-joystick-config-t-members
pin_t output_pin
A pin to set as output high when reading the analog value, orJS_VIRTUAL_AXIS
.pin_t input_pin
The pin to read the analog value from, orJS_VIRTUAL_AXIS
.pin_t ground_pin
A pin to set as output low when reading the analog value, orJS_VIRTUAL_AXIS
.uint16_t min_digit
The minimum analog value.uint16_t mid_digit
The resting or midpoint analog value.uint16_t max_digit
The maximum analog value.
void joystick_flush(void)
:id=api-joystick-flush
Send the joystick report to the host, if it has been marked as dirty.
void register_joystick_button(uint8_t button)
:id=api-register-joystick-button
Set the state of a button, and flush the report.
Arguments :id=api-register-joystick-button-arguments
uint8_t button
The index of the button to press, from 0 to 31.
void unregister_joystick_button(uint8_t button)
:id=api-unregister-joystick-button
Reset the state of a button, and flush the report.
Arguments :id=api-unregister-joystick-button-arguments
uint8_t button
The index of the button to release, from 0 to 31.
int16_t joystick_read_axis(uint8_t axis)
:id=api-joystick-read-axis
Sample and process the analog value of the given axis.
Arguments :id=api-joystick-read-axis-arguments
uint8_t axis
The axis to read.
Return Value :id=api-joystick-read-axis-return
A signed 16-bit integer, where 0 is the resting or mid point.
void joystick_set_axis(uint8_t axis, int16_t value)
:id=api-joystick-set-axis
Set the value of the given axis.
Arguments :id=api-joystick-set-axis-arguments
uint8_t axis
The axis to set the value of.int16_t value
The value to set.