diff --git a/docs/feature_joystick.md b/docs/feature_joystick.md index be3c781f6cd4..12bbf5b35eff 100644 --- a/docs/feature_joystick.md +++ b/docs/feature_joystick.md @@ -141,6 +141,12 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) { } ``` +### Axis Resolution + +By default, the resolution of each axis is 8 bit, giving a range of -127 to +127. If you need higher precision, you can increase it by defining eg. `JOYSTICK_AXES_RESOLUTION 12` in your `config.h`. The resolution must be between 8 and 16. + +Note that the supported AVR MCUs have a 10-bit ADC, and 12-bit for most STM32 MCUs. + ### Triggering Joystick Buttons Joystick buttons are normal Quantum keycodes, defined as `JS_BUTTON0` to `JS_BUTTON31`, depending on the number of buttons you have configured. diff --git a/quantum/joystick.h b/quantum/joystick.h index a95472b9fd44..87dbc24aff81 100644 --- a/quantum/joystick.h +++ b/quantum/joystick.h @@ -1,5 +1,9 @@ #pragma once +#include "quantum.h" + +#include + #ifndef JOYSTICK_BUTTON_COUNT # define JOYSTICK_BUTTON_COUNT 8 #endif @@ -8,9 +12,13 @@ # define JOYSTICK_AXES_COUNT 4 #endif -#include "quantum.h" +#ifndef JOYSTICK_AXES_RESOLUTION +# define JOYSTICK_AXES_RESOLUTION 8 +#elif JOYSTICK_AXES_RESOLUTION < 8 || JOYSTICK_AXES_RESOLUTION > 16 +# error JOYSTICK_AXES_RESOLUTION must be between 8 and 16 +#endif -#include +#define JOYSTICK_RESOLUTION ((1L << (JOYSTICK_AXES_RESOLUTION - 1)) - 1) // configure on input_pin of the joystick_axes array entry to JS_VIRTUAL_AXIS // to prevent it from being read from the ADC. This allows outputing forged axis value. diff --git a/quantum/process_keycode/process_joystick.c b/quantum/process_keycode/process_joystick.c index 5778a7434c1c..3ffaf42bf847 100644 --- a/quantum/process_keycode/process_joystick.c +++ b/quantum/process_keycode/process_joystick.c @@ -129,17 +129,17 @@ bool process_joystick_analogread_quantum() { // test the converted value against the lower range int32_t ref = joystick_axes[axis_index].mid_digit; int32_t range = joystick_axes[axis_index].min_digit; - int32_t ranged_val = ((axis_val - ref) * -127) / (range - ref); + int32_t ranged_val = ((axis_val - ref) * -JOYSTICK_RESOLUTION) / (range - ref); if (ranged_val > 0) { // the value is in the higher range range = joystick_axes[axis_index].max_digit; - ranged_val = ((axis_val - ref) * 127) / (range - ref); + ranged_val = ((axis_val - ref) * JOYSTICK_RESOLUTION) / (range - ref); } // clamp the result in the valid range - ranged_val = ranged_val < -127 ? -127 : ranged_val; - ranged_val = ranged_val > 127 ? 127 : ranged_val; + ranged_val = ranged_val < -JOYSTICK_RESOLUTION ? -JOYSTICK_RESOLUTION : ranged_val; + ranged_val = ranged_val > JOYSTICK_RESOLUTION ? JOYSTICK_RESOLUTION : ranged_val; if (ranged_val != joystick_status.axes[axis_index]) { joystick_status.axes[axis_index] = ranged_val; diff --git a/tmk_core/common/report.h b/tmk_core/common/report.h index 1aa33c998d1e..2a0549ab8967 100644 --- a/tmk_core/common/report.h +++ b/tmk_core/common/report.h @@ -192,7 +192,11 @@ typedef struct { typedef struct { #if JOYSTICK_AXES_COUNT > 0 - int8_t axes[JOYSTICK_AXES_COUNT]; +# if JOYSTICK_AXES_RESOLUTION > 8 + int16_t axes[JOYSTICK_AXES_COUNT]; +# else + int8_t axes[JOYSTICK_AXES_COUNT]; +# endif #endif #if JOYSTICK_BUTTON_COUNT > 0 diff --git a/tmk_core/protocol/usb_descriptor.c b/tmk_core/protocol/usb_descriptor.c index f5d32445de50..a0c0d4cdc80f 100644 --- a/tmk_core/protocol/usb_descriptor.c +++ b/tmk_core/protocol/usb_descriptor.c @@ -41,6 +41,10 @@ #include "usb_descriptor.h" #include "usb_descriptor_common.h" +#ifdef JOYSTICK_ENABLE +# include "joystick.h" +#endif + // clang-format off /* @@ -308,10 +312,17 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM JoystickReport[] = { HID_RI_USAGE(8, 0x35), // Rz # endif # if JOYSTICK_AXES_COUNT >= 1 - HID_RI_LOGICAL_MINIMUM(8, -127), - HID_RI_LOGICAL_MAXIMUM(8, 127), + # if JOYSTICK_AXES_RESOLUTION == 8 + HID_RI_LOGICAL_MINIMUM(8, -JOYSTICK_RESOLUTION), + HID_RI_LOGICAL_MAXIMUM(8, JOYSTICK_RESOLUTION), HID_RI_REPORT_COUNT(8, JOYSTICK_AXES_COUNT), HID_RI_REPORT_SIZE(8, 0x08), + # else + HID_RI_LOGICAL_MINIMUM(16, -JOYSTICK_RESOLUTION), + HID_RI_LOGICAL_MAXIMUM(16, JOYSTICK_RESOLUTION), + HID_RI_REPORT_COUNT(8, JOYSTICK_AXES_COUNT), + HID_RI_REPORT_SIZE(8, 0x10), + # endif HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), # endif