From 3cf76111398d7df38f5840ce98cd585376cc6245 Mon Sep 17 00:00:00 2001 From: achol Date: Wed, 17 Oct 2018 11:23:20 +0200 Subject: [PATCH 01/22] add support for hid gamepad interface add documentation for HID joystick Add joystick_task to read analog axes values even when no key is pressed or release. update doc Update docs/feature_joystick.md Manage pin setup and read to maintain matrix scan after analog read --- common_features.mk | 9 ++ docs/_summary.md | 1 + docs/feature_joystick.md | 85 ++++++++++++++++ quantum/joystick.c | 11 +++ quantum/joystick.h | 48 +++++++++ quantum/process_keycode/process_joystick.c | 79 +++++++++++++++ quantum/process_keycode/process_joystick.h | 13 +++ quantum/quantum.c | 7 ++ quantum/quantum_keycodes.h | 35 +++++++ tmk_core/common/keyboard.c | 7 ++ tmk_core/protocol/chibios/usb_main.c | 73 ++++++++++++++ tmk_core/protocol/lufa/lufa.c | 83 ++++++++++++++++ tmk_core/protocol/usb_descriptor.c | 103 +++++++++++++++++++- tmk_core/protocol/usb_descriptor.h | 15 +++ tmk_core/protocol/vusb/vusb.c | 108 ++++++++++++++++++++- 15 files changed, 675 insertions(+), 2 deletions(-) create mode 100644 docs/feature_joystick.md create mode 100644 quantum/joystick.c create mode 100644 quantum/joystick.h create mode 100644 quantum/process_keycode/process_joystick.c create mode 100644 quantum/process_keycode/process_joystick.h diff --git a/common_features.mk b/common_features.mk index 269ca2b137d1..9180b4f7cb3a 100644 --- a/common_features.mk +++ b/common_features.mk @@ -511,3 +511,12 @@ ifeq ($(strip $(AUTO_SHIFT_ENABLE)), yes) OPT_DEFS += -DAUTO_SHIFT_MODIFIERS endif endif + +ifeq ($(strip $(JOYSTICK_ENABLE)), yes) + OPT_DEFS += -DJOYSTICK_ENABLE + SRC += $(QUANTUM_DIR)/process_keycode/process_joystick.c + SRC += $(QUANTUM_DIR)/joystick.c + ifeq ($(PLATFORM),AVR) + SRC += drivers/avr/analog.c + endif +endif diff --git a/docs/_summary.md b/docs/_summary.md index d6186bbf997f..336def3dc702 100644 --- a/docs/_summary.md +++ b/docs/_summary.md @@ -97,6 +97,7 @@ * [DIP Switch](feature_dip_switch.md) * [Encoders](feature_encoders.md) * [Haptic Feedback](feature_haptic_feedback.md) + * [Joystick](feature_joystick.md) * [Proton C Conversion](proton_c_conversion.md) * [PS/2 Mouse](feature_ps2_mouse.md) * [Split Keyboard](feature_split_keyboard.md) diff --git a/docs/feature_joystick.md b/docs/feature_joystick.md new file mode 100644 index 000000000000..43a4f228355d --- /dev/null +++ b/docs/feature_joystick.md @@ -0,0 +1,85 @@ +## Joystick HID Device + +The keyboard can be made to be recognized as a joystick HID device by the Operating System. + +This is enabled by adding the following to `rules.mk` + +``` +JOYSTICK_ENABLE = yes +``` + +### Configuring the joystick + +The default joystick has 2 axes and and 8 buttons. This can be changed from the config.h file : + +``` +//max 32 for JOYSTICK_BUTTON_COUNT +#define JOYSTICK_BUTTON_COUNT 16 +//max 6 for JOYSTICK_AXES_COUNT +#define JOYSTICK_AXES_COUNT 3 +``` + +When defining axes for your joystick, you have to provide a definition array for it. You can do this from your keymap.c file. +A joystick will either be read from an input pin that allows the use of an ADC, or can be virtual, so that its value is provided by your code. +You have to define an array of type ''joystick_config_t'' and of proper size, in the following way : + +``` +//joystick config +joystick_config_t joystick_axes[JOYSTICK_AXES_COUNT] = { + [0] = {A1, D7, 65280, 65472}, + [1] = {JS_VIRTUAL_AXIS, JS_VIRTUAL_AXIS, 65280, 65472} +}; +``` + +In this example, the first axis will be read from the D7 pin while A1 is set high, using an analogRead, whereas the second axis will not be read. +If you connected the your analog component to Vcc instead of an output pin, you can set the output setting to JS_VIRTUAL_AXIS. +In order to give a value to the second axis, you can do so in any customizable entry point of quantum : as an action, in process_record_user or in matrix_scan_user, or even in joystick_task(void) which is called even when no key has been pressed. +You assign a value by writing to joystick_status.axes[axis_index] a signed 8bit value (-127 to 127). Then it is necessary to assign the flag JS_UPDATED to joystick_status.status in order for the change to be taken into account. + +The following example writes two axes based on keypad presses, with KP_5 as a precision modifier : + +``` +#ifdef JOYSTICK_ENABLE +static bool precision_on; +#endif + +bool process_record_user(uint16_t keycode, keyrecord_t *record) { + switch(keycode){ +#ifdef JOYSTICK_ENABLE + // virtual joystick + case KC_P8: + joystick_status.axes[1] -= (record->event.pressed ? 1 : -1) * (precision_on ?70 : 127); + joystick_status.status |= JS_UPDATED; + break; + case KC_P2: + joystick_status.axes[1] += (record->event.pressed ? 1 : -1) * (precision_on ?70 : 127); + joystick_status.status |= JS_UPDATED; + break; + case KC_P4: + joystick_status.axes[0] -= (record->event.pressed ? 1 : -1) * (precision_on ?70 : 127); + joystick_status.status |= JS_UPDATED; + break; + case KC_P6: + joystick_status.axes[0] += (record->event.pressed ? 1 : -1) * (precision_on ?70 : 127); + joystick_status.status |= JS_UPDATED; + break; + case KC_P5: + precision_on = record->event.pressed; + joystick_status.axes[0] *= record->event.pressed ? 70/127.f : 127/70.f; + joystick_status.axes[1] *= record->event.pressed ? 70/127.f : 127/70.f; + joystick_status.status |= JS_UPDATED; + break; +#endif + } + + return true; +} +``` + +### Triggering joystick buttons + +Joystick buttons are normal quantum keycode, defined as JS_BUTTON0 to JS_BUTTON_MAX, which depends on the number of buttons you have configured. +To trigger a joystick button, just add the corresponding keycode to your keymap. + + + diff --git a/quantum/joystick.c b/quantum/joystick.c new file mode 100644 index 000000000000..e6906913db79 --- /dev/null +++ b/quantum/joystick.c @@ -0,0 +1,11 @@ +#include "joystick.h" + +joystick_t joystick_status = { + .buttons = {0}, + .axes = {0}, + .status = 0 +}; + +//array defining the reading of analog values for each axis +__attribute__ ((weak)) +joystick_config_t joystick_axes[JOYSTICK_AXES_COUNT] = {}; diff --git a/quantum/joystick.h b/quantum/joystick.h new file mode 100644 index 000000000000..6ca9ab887854 --- /dev/null +++ b/quantum/joystick.h @@ -0,0 +1,48 @@ +#ifndef JOYSTICK_H +#define JOYSTICK_H + +#ifndef JOYSTICK_BUTTON_COUNT +#define JOYSTICK_BUTTON_COUNT 8 +#endif + +#ifndef JOYSTICK_AXES_COUNT +#define JOYSTICK_AXES_COUNT 4 +#endif + +#include + +//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. +// +#define JS_VIRTUAL_AXIS 0xFF + +typedef struct { + uint8_t output_pin; + uint8_t input_pin; + + //the AVR ADC offers 10 bit precision, with significant bits on the higher part + uint16_t min_digit; + uint16_t max_digit; +} joystick_config_t; + +extern joystick_config_t joystick_axes[JOYSTICK_AXES_COUNT]; + +enum joystick_status{ + JS_INITIALIZED = 1, + JS_UPDATED = 2 +}; + +typedef struct { + + uint8_t buttons[JOYSTICK_BUTTON_COUNT/8+1]; + + int8_t axes[JOYSTICK_AXES_COUNT]; + uint8_t status:2; +} joystick_t; + +extern joystick_t joystick_status; + +//to be implemented in the hid protocol library +void send_joystick_packet(joystick_t* joystick); + +#endif //JOYSTICK_H \ No newline at end of file diff --git a/quantum/process_keycode/process_joystick.c b/quantum/process_keycode/process_joystick.c new file mode 100644 index 000000000000..f90fd2393769 --- /dev/null +++ b/quantum/process_keycode/process_joystick.c @@ -0,0 +1,79 @@ +#include "process_joystick.h" + +#include +#include + +#ifdef __AVR__ +# include +#endif + +#include + +bool process_joystick_buttons(uint16_t keycode, keyrecord_t *record); + +bool process_joystick(uint16_t keycode, keyrecord_t *record){ + + if (process_joystick_buttons(keycode, record) + && (joystick_status.status & JS_UPDATED)>0){ + send_joystick_packet(&joystick_status); + joystick_status.status &= ~JS_UPDATED; + } + + return true; +} + +__attribute__ ((weak)) +void joystick_task(void){ + if (process_joystick_analog() && (joystick_status.status & JS_UPDATED)){ + send_joystick_packet(&joystick_status); + joystick_status.status &= ~JS_UPDATED; + } +} + +bool process_joystick_buttons(uint16_t keycode, keyrecord_t *record){ + + if (keycode < JS_BUTTON0 || keycode > JS_BUTTON_MAX){ + return true; + } else { + if (record->event.pressed){ + joystick_status.buttons[(keycode-JS_BUTTON0)/8] |= 1<<(keycode%8); + } else { + joystick_status.buttons[(keycode-JS_BUTTON0)/8] &= ~(1<<(keycode%8)); + } + + joystick_status.status |= JS_UPDATED; + } + + return true; +} + +__attribute__ ((weak)) +bool process_joystick_analog(){ +#if JOYSTICK_AXES_COUNT > 0 + for (int axis_index=0 ; axis_index +#include "quantum.h" + +bool process_joystick(uint16_t keycode, keyrecord_t *record); + +void joystick_task(void); + +bool process_joystick_analog(void); + +#endif //PROCESS_JOYSTICK_H \ No newline at end of file diff --git a/quantum/quantum.c b/quantum/quantum.c index 749a08eea9e9..c8e062f8ff51 100644 --- a/quantum/quantum.c +++ b/quantum/quantum.c @@ -63,6 +63,10 @@ float bell_song[][2] = SONG(TERMINAL_SOUND); # endif #endif +#ifdef JOYSTICK_ENABLE +#include +#endif //JOYSTICK_ENABLE + static void do_code16(uint16_t code, void (*f)(uint8_t)) { switch (code) { case QK_MODS ... QK_MODS_MAX: @@ -265,6 +269,9 @@ bool process_record_quantum(keyrecord_t *record) { #endif #if defined(RGBLIGHT_ENABLE) || defined(RGB_MATRIX_ENABLE) process_rgb(keycode, record) && +#endif +#ifdef JOYSTICK_ENABLE + process_joystick(keycode, record) && #endif true)) { return false; diff --git a/quantum/quantum_keycodes.h b/quantum/quantum_keycodes.h index 54428fe1f24d..e8b010d76c2f 100644 --- a/quantum/quantum_keycodes.h +++ b/quantum/quantum_keycodes.h @@ -512,6 +512,41 @@ enum quantum_keycodes { DYN_MACRO_PLAY1, DYN_MACRO_PLAY2, + JS_BUTTON0, + JS_BUTTON_MIN = JS_BUTTON0, + JS_BUTTON1, + JS_BUTTON2, + JS_BUTTON3, + JS_BUTTON4, + JS_BUTTON5, + JS_BUTTON6, + JS_BUTTON7, + JS_BUTTON8, + JS_BUTTON9, + JS_BUTTON10, + JS_BUTTON11, + JS_BUTTON12, + JS_BUTTON13, + JS_BUTTON14, + JS_BUTTON15, + JS_BUTTON16, + JS_BUTTON17, + JS_BUTTON18, + JS_BUTTON19, + JS_BUTTON20, + JS_BUTTON21, + JS_BUTTON22, + JS_BUTTON23, + JS_BUTTON24, + JS_BUTTON25, + JS_BUTTON26, + JS_BUTTON27, + JS_BUTTON28, + JS_BUTTON29, + JS_BUTTON30, + JS_BUTTON31, + JS_BUTTON_MAX = JS_BUTTON31, + // always leave at the end SAFE_RANGE }; diff --git a/tmk_core/common/keyboard.c b/tmk_core/common/keyboard.c index a767d9c8773e..ae50a6e5e96a 100644 --- a/tmk_core/common/keyboard.c +++ b/tmk_core/common/keyboard.c @@ -71,6 +71,9 @@ along with this program. If not, see . #ifdef MIDI_ENABLE # include "process_midi.h" #endif +#ifdef JOYSTICK_ENABLE +# include "process_joystick.h" +#endif #ifdef HD44780_ENABLE # include "hd44780.h" #endif @@ -396,6 +399,10 @@ void keyboard_task(void) { } #endif +#ifdef JOYSTICK_ENABLE + joystick_task(); +#endif + // update LED if (led_status != host_keyboard_leds()) { led_status = host_keyboard_leds(); diff --git a/tmk_core/protocol/chibios/usb_main.c b/tmk_core/protocol/chibios/usb_main.c index ecc83d9ecc94..3c7c7ea8bde7 100644 --- a/tmk_core/protocol/chibios/usb_main.c +++ b/tmk_core/protocol/chibios/usb_main.c @@ -47,6 +47,10 @@ extern keymap_config_t keymap_config; #endif +#ifdef JOYSTICK_ENABLE +# include +#endif + /* --------------------------------------------------------- * Global interface variables and declarations * --------------------------------------------------------- @@ -246,6 +250,9 @@ typedef struct { #endif #ifdef VIRTSER_ENABLE usb_driver_config_t serial_driver; +#endif +#ifdef JOYSTICK_ENABLE + usb_driver_config_t joystick_driver; #endif }; usb_driver_config_t array[0]; @@ -283,6 +290,14 @@ static usb_driver_configs_t drivers = { # define CDC_OUT_MODE USB_EP_MODE_TYPE_BULK .serial_driver = QMK_USB_DRIVER_CONFIG(CDC, CDC_NOTIFICATION_EPNUM, false), #endif + +#ifdef JOYSTICK_ENABLE + #define JOYSTICK_IN_CAPACITY 4 + #define JOYSTICK_OUT_CAPACITY 4 + #define JOYSTICK_IN_MODE USB_EP_MODE_TYPE_BULK + #define JOYSTICK_OUT_MODE USB_EP_MODE_TYPE_BULK + .joystick_driver = QMK_USB_DRIVER_CONFIG(JOYSTICK, 0, false), +#endif }; #define NUM_USB_DRIVERS (sizeof(drivers) / sizeof(usb_driver_config_t)) @@ -870,3 +885,61 @@ void virtser_task(void) { } #endif + +#ifdef JOYSTICK_ENABLE + +typedef struct { + #if JOYSTICK_AXES_COUNT>0 + int8_t axes[JOYSTICK_AXES_COUNT]; + #endif + + #if JOYSTICK_BUTTON_COUNT>0 + uint8_t buttons[(JOYSTICK_BUTTON_COUNT-1)/8+1]; + #endif +} __attribute__ ((packed)) joystick_report_t; + +void send_joystick_packet(joystick_t* joystick) { + joystick_report_t rep = { + #if JOYSTICK_AXES_COUNT>0 + .axes = { + joystick->axes[0] + + #if JOYSTICK_AXES_COUNT >= 2 + ,joystick->axes[1] + #endif + #if JOYSTICK_AXES_COUNT >= 3 + ,joystick->axes[2] + #endif + #if JOYSTICK_AXES_COUNT >= 4 + ,joystick->axes[3] + #endif + #if JOYSTICK_AXES_COUNT >= 5 + ,joystick->axes[4] + #endif + #if JOYSTICK_AXES_COUNT >= 6 + ,joystick->axes[5] + #endif + }, + #endif //JOYSTICK_AXES_COUNT>0 + + #if JOYSTICK_BUTTON_COUNT>0 + .buttons = { + joystick->buttons[0] + + #if JOYSTICK_BUTTON_COUNT>8 + ,joystick->buttons[1] + #endif + #if JOYSTICK_BUTTON_COUNT>16 + ,joystick->buttons[2] + #endif + #if JOYSTICK_BUTTON_COUNT>24 + ,joystick->buttons[3] + #endif + } + #endif //JOYSTICK_BUTTON_COUNT>0 + }; + + chnWrite(&drivers.joystick_driver.driver, (uint8_t*)&rep, sizeof(rep)); +} + +#endif diff --git a/tmk_core/protocol/lufa/lufa.c b/tmk_core/protocol/lufa/lufa.c index d673841fd55c..a4c617622bd4 100644 --- a/tmk_core/protocol/lufa/lufa.c +++ b/tmk_core/protocol/lufa/lufa.c @@ -85,6 +85,10 @@ extern keymap_config_t keymap_config; # include "raw_hid.h" #endif +#ifdef JOYSTICK_ENABLE + #include "joystick.h" +#endif + uint8_t keyboard_idle = 0; /* 0: Boot Protocol, 1: Report Protocol(default) */ uint8_t keyboard_protocol = 1; @@ -263,6 +267,85 @@ static void Console_Task(void) { } #endif +/******************************************************************************* + * Joystick + ******************************************************************************/ +#ifdef JOYSTICK_ENABLE + +typedef struct { + #if JOYSTICK_AXES_COUNT>0 + int8_t axes[JOYSTICK_AXES_COUNT]; + #endif + + #if JOYSTICK_BUTTON_COUNT>0 + uint8_t buttons[(JOYSTICK_BUTTON_COUNT-1)/8+1]; + #endif +} __attribute__ ((packed)) joystick_report_t; + +void send_joystick_packet(joystick_t* joystick){ + + uint8_t timeout = 255; + uint8_t where = where_to_send(); + + if (where != OUTPUT_USB && where != OUTPUT_USB_AND_BT) { + return; + } + + joystick_report_t r = { + #if JOYSTICK_AXES_COUNT>0 + .axes = { + joystick->axes[0] + + #if JOYSTICK_AXES_COUNT >= 2 + ,joystick->axes[1] + #endif + #if JOYSTICK_AXES_COUNT >= 3 + ,joystick->axes[2] + #endif + #if JOYSTICK_AXES_COUNT >= 4 + ,joystick->axes[3] + #endif + #if JOYSTICK_AXES_COUNT >= 5 + ,joystick->axes[4] + #endif + #if JOYSTICK_AXES_COUNT >= 6 + ,joystick->axes[5] + #endif + }, + #endif //JOYSTICK_AXES_COUNT>0 + + #if JOYSTICK_BUTTON_COUNT>0 + .buttons = { + joystick->buttons[0] + + #if JOYSTICK_BUTTON_COUNT>8 + ,joystick->buttons[1] + #endif + #if JOYSTICK_BUTTON_COUNT>16 + ,joystick->buttons[2] + #endif + #if JOYSTICK_BUTTON_COUNT>24 + ,joystick->buttons[3] + #endif + } + #endif //JOYSTICK_BUTTON_COUNT>0 + }; + + /* Select the Joystick Report Endpoint */ + Endpoint_SelectEndpoint(JOYSTICK_IN_EPNUM); + + /* Check if write ready for a polling interval around 10ms */ + while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40); + if (!Endpoint_IsReadWriteAllowed()) return; + + /* Write Joystick Report Data */ + Endpoint_Write_Stream_LE(&r, sizeof(joystick_report_t), NULL); + + /* Finalize the stream transfer to send the last packet */ + Endpoint_ClearIN(); +} +#endif + /******************************************************************************* * USB Events ******************************************************************************/ diff --git a/tmk_core/protocol/usb_descriptor.c b/tmk_core/protocol/usb_descriptor.c index f2b91b099e35..718035158c1d 100644 --- a/tmk_core/protocol/usb_descriptor.c +++ b/tmk_core/protocol/usb_descriptor.c @@ -278,6 +278,53 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM ConsoleReport[] = { }; #endif +#ifdef JOYSTICK_ENABLE +const USB_Descriptor_HIDReport_Datatype_t PROGMEM JoystickReport[] = +{ + HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */ + HID_RI_USAGE(8, 0x04), /* Joystick */ + HID_RI_COLLECTION(8, 0x01), /* Application */ + HID_RI_USAGE(8, 0x01), /* Pointer */ + HID_RI_COLLECTION(8, 0x00), /* Physical */ + + #if JOYSTICK_AXES_COUNT >= 1 + HID_RI_USAGE(8, 0x30), // USAGE (X) + #endif + #if JOYSTICK_AXES_COUNT >= 2 + HID_RI_USAGE(8, 0x31), // USAGE (Y) + #endif + #if JOYSTICK_AXES_COUNT >= 3 + HID_RI_USAGE(8, 0x32), // USAGE (Z) + #endif + #if JOYSTICK_AXES_COUNT >= 4 + HID_RI_USAGE(8, 0x33), // USAGE (RX) + #endif + #if JOYSTICK_AXES_COUNT >= 5 + HID_RI_USAGE(8, 0x34), // USAGE (RY) + #endif + #if JOYSTICK_AXES_COUNT >= 6 + HID_RI_USAGE(8, 0x35), // USAGE (RZ) + #endif + HID_RI_LOGICAL_MINIMUM(8, -127), + HID_RI_LOGICAL_MAXIMUM(8, 127), + HID_RI_REPORT_COUNT(8, JOYSTICK_AXES_COUNT), + HID_RI_REPORT_SIZE(8, 0x08), + HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE), + + HID_RI_USAGE_PAGE(8, 0x09), /* Button */ + HID_RI_USAGE_MINIMUM(8, 0x01), /* Button 1 */ + HID_RI_USAGE_MAXIMUM(8, JOYSTICK_BUTTON_COUNT), /* Button 5 */ + HID_RI_LOGICAL_MINIMUM(8, 0x00), + HID_RI_LOGICAL_MAXIMUM(8, 0x01), + HID_RI_REPORT_COUNT(8, JOYSTICK_BUTTON_COUNT), + HID_RI_REPORT_SIZE(8, 0x01), + HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), + + HID_RI_END_COLLECTION(0), + HID_RI_END_COLLECTION(0), +}; +#endif + /* * Device descriptor */ @@ -287,7 +334,6 @@ const USB_Descriptor_Device_t PROGMEM DeviceDescriptor = { .Type = DTYPE_Device }, .USBSpecification = VERSION_BCD(1, 1, 0), - #if VIRTSER_ENABLE .Class = USB_CSCP_IADDeviceClass, .SubClass = USB_CSCP_IADDeviceSubclass, @@ -812,6 +858,49 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor = { .PollingIntervalMS = 0x05 }, #endif + + + /* + * Joystick + */ +#ifdef JOYSTICK_ENABLE + .Joystick_Interface = + { + .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface}, + + .InterfaceNumber = JOYSTICK_INTERFACE, + .AlternateSetting = 0x00, + + .TotalEndpoints = 1, + + .Class = HID_CSCP_HIDClass, + .SubClass = HID_CSCP_NonBootSubclass, + .Protocol = HID_CSCP_NonBootProtocol, + + .InterfaceStrIndex = NO_DESCRIPTOR + }, + + .Joystick_HID = + { + .Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID}, + + .HIDSpec = VERSION_BCD(1,1,1), + .CountryCode = 0x00, + .TotalReportDescriptors = 1, + .HIDReportType = HID_DTYPE_Report, + .HIDReportLength = sizeof(JoystickReport) + }, + + .Joystick_INEndpoint = + { + .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, + + .EndpointAddress = (ENDPOINT_DIR_IN | JOYSTICK_IN_EPNUM), + .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), + .EndpointSize = JOYSTICK_EPSIZE, + .PollingIntervalMS = 0x0A + }, +#endif }; /* @@ -943,6 +1032,12 @@ uint16_t get_usb_descriptor(const uint16_t wValue, const uint16_t wIndex, const Size = sizeof(USB_HID_Descriptor_HID_t); break; +#endif +#ifdef JOYSTICK_ENABLE + case JOYSTICK_INTERFACE: + Address = &ConfigurationDescriptor.Joystick_HID; + Size = sizeof(USB_HID_Descriptor_HID_t); + break; #endif } @@ -987,6 +1082,12 @@ uint16_t get_usb_descriptor(const uint16_t wValue, const uint16_t wIndex, const Size = sizeof(ConsoleReport); break; +#endif +#ifdef JOYSTICK_ENABLE + case JOYSTICK_INTERFACE: + Address = &JoystickReport; + Size = sizeof(JoystickReport); + break; #endif } diff --git a/tmk_core/protocol/usb_descriptor.h b/tmk_core/protocol/usb_descriptor.h index b2423fa7e662..bcc9cab4bbb1 100644 --- a/tmk_core/protocol/usb_descriptor.h +++ b/tmk_core/protocol/usb_descriptor.h @@ -123,6 +123,13 @@ typedef struct { USB_Descriptor_Endpoint_t CDC_DataOutEndpoint; USB_Descriptor_Endpoint_t CDC_DataInEndpoint; #endif + +#ifdef JOYSTICK_ENABLE + // Joystick HID Interface + USB_Descriptor_Interface_t Joystick_Interface; + USB_HID_Descriptor_HID_t Joystick_HID; + USB_Descriptor_Endpoint_t Joystick_INEndpoint; +#endif } USB_Descriptor_Configuration_t; /* @@ -164,6 +171,9 @@ enum usb_interfaces { CDI_INTERFACE, #endif +#if defined(JOYSTICK_ENABLE) + JOYSTICK_INTERFACE, +#endif TOTAL_INTERFACES }; @@ -224,6 +234,10 @@ enum usb_endpoints { # define CDC_IN_EPADDR (ENDPOINT_DIR_IN | CDC_IN_EPNUM) # define CDC_OUT_EPADDR (ENDPOINT_DIR_OUT | CDC_OUT_EPNUM) #endif +#ifdef JOYSTICK_ENABLE + JOYSTICK_IN_EPNUM = NEXT_EPNUM, + JOYSTICK_OUT_EPNUM = NEXT_EPNUM, +#endif }; #ifdef PROTOCOL_LUFA @@ -248,6 +262,7 @@ enum usb_endpoints { #define MIDI_STREAM_EPSIZE 64 #define CDC_NOTIFICATION_EPSIZE 8 #define CDC_EPSIZE 16 +#define JOYSTICK_EPSIZE 8 uint16_t get_usb_descriptor(const uint16_t wValue, const uint16_t wIndex, const void** const DescriptorAddress); #endif diff --git a/tmk_core/protocol/vusb/vusb.c b/tmk_core/protocol/vusb/vusb.c index abf723952e4a..61d1ba53e752 100644 --- a/tmk_core/protocol/vusb/vusb.c +++ b/tmk_core/protocol/vusb/vusb.c @@ -26,6 +26,8 @@ along with this program. If not, see . #include "debug.h" #include "host_driver.h" #include "vusb.h" +#include "joystick.h" +#include "joystick.h" #include static uint8_t vusb_keyboard_leds = 0; @@ -79,6 +81,7 @@ static void send_keyboard(report_keyboard_t *report); static void send_mouse(report_mouse_t *report); static void send_system(uint16_t data); static void send_consumer(uint16_t data); +static void send_joystick(void); static host_driver_t driver = {keyboard_leds, send_keyboard, send_mouse, send_system, send_consumer}; @@ -139,6 +142,68 @@ static void send_consumer(uint16_t data) { #endif } +typedef struct { + uint8_t report_id; + + #if JOYSTICK_AXES_COUNT>0 + int8_t axes[JOYSTICK_AXES_COUNT]; + #endif + + #if JOYSTICK_BUTTON_COUNT>0 + uint8_t buttons[(JOYSTICK_BUTTON_COUNT-1)/8+1]; + #endif +} __attribute__ ((packed)) vusb_joystick_report_t; + +void send_joystick_packet(joystick_t* status) +{ + vusb_joystick_report_t r = { + .report_id = 0x4, + + #if JOYSTICK_AXES_COUNT>0 + .axes = { + status->axes[0] + + #if JOYSTICK_AXES_COUNT >= 2 + ,status->axes[1] + #endif + #if JOYSTICK_AXES_COUNT >= 3 + ,status->axes[2] + #endif + #if JOYSTICK_AXES_COUNT >= 4 + ,status->axes[3] + #endif + #if JOYSTICK_AXES_COUNT >= 5 + ,status->axes[4] + #endif + #if JOYSTICK_AXES_COUNT >= 6 + ,status->axes[5] + #endif + }, + #endif //JOYSTICK_AXES_COUNT>0 + + #if JOYSTICK_BUTTON_COUNT>0 + .buttons = { + status->buttons[0] + + #if JOYSTICK_BUTTON_COUNT>8 + ,status->buttons[1] + #endif + #if JOYSTICK_BUTTON_COUNT>16 + ,status->buttons[2] + #endif + #if JOYSTICK_BUTTON_COUNT>24 + ,status->buttons[3] + #endif + } + #endif //JOYSTICK_BUTTON_COUNT>0 + }; + if (usbInterruptIsReady3()) { + usbSetInterrupt3((void *)&r, sizeof(vusb_joystick_report_t)); + } +} + + + /*------------------------------------------------------------------* * Request from host * *------------------------------------------------------------------*/ @@ -251,7 +316,7 @@ const PROGMEM uchar keyboard_hid_report[] = { 0xC0 // End Collection }; -#if defined(MOUSE_ENABLE) || defined(EXTRAKEY_ENABLE) +#if defined(MOUSE_ENABLE) || defined(EXTRAKEY_ENABLE) || defined(JOYSTICK_ENABLE) const PROGMEM uchar mouse_extra_hid_report[] = { # ifdef MOUSE_ENABLE // Mouse report descriptor @@ -332,6 +397,47 @@ const PROGMEM uchar mouse_extra_hid_report[] = { 0x81, 0x00, // Input (Data, Array, Absolute) 0xC0 // End Collection # endif +#if JOYSTICK_ENABLE + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) + 0x09, 0x04, // USAGE (Joystick) + 0xa1, 0x01, // COLLECTION (Application) + 0x85, 0x4, // REPORT_ID (4) + 0x09, 0x01, // USAGE (Pointer) + 0xa1, 0x00, // COLLECTION (Physical) + #if JOYSTICK_AXES_COUNT >= 1 + 0x09, 0x30, // USAGE (X) + #endif + #if JOYSTICK_AXES_COUNT >= 2 + 0x09, 0x31, // USAGE (Y) + #endif + #if JOYSTICK_AXES_COUNT >= 3 + 0x09, 0x32, // USAGE (Z) + #endif + #if JOYSTICK_AXES_COUNT >= 4 + 0x09, 0x33, // USAGE (RX) + #endif + #if JOYSTICK_AXES_COUNT >= 5 + 0x09, 0x34, // USAGE (RY) + #endif + #if JOYSTICK_AXES_COUNT >= 6 + 0x09, 0x35, // USAGE (RZ) + #endif + 0x15, 0x81, // LOGICAL_MINIMUM (-127) + 0x25, 0x7f, // LOGICAL_MAXIMUM (127) + 0x75, 0x08, // REPORT_SIZE (8) + 0x95, JOYSTICK_AXES_COUNT, // REPORT_COUNT (JOYSTICK_AXES_COUNT) + 0x81, 0x02, // INPUT (Data,Var,Abs) + 0xc0, // END_COLLECTION + 0x05, 0x09, // USAGE_PAGE (Button) + 0x19, 0x01, // USAGE_MINIMUM (Button 1) + 0x29, JOYSTICK_BUTTON_COUNT, // USAGE_MAXIMUM + 0x15, 0x00, // LOGICAL_MINIMUM (0) + 0x25, 0x01, // LOGICAL_MAXIMUM (1) + 0x75, 0x01, // REPORT_SIZE (1) + 0x95, JOYSTICK_BUTTON_COUNT, // REPORT_COUNT + 0x81, 0x02, // INPUT (Data,Var,Abs) + 0xc0 // END_COLLECTION +#endif //GAMEPAD_ENABLE }; #endif From ee43b338eafee909453863cfeb5a6d989eb4c1e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20J=C3=BAnior?= Date: Fri, 7 Dec 2018 04:00:55 -0500 Subject: [PATCH 02/22] Incorporates patches and changes to HID reporting There are some patches provided by @a-chol incorporated on this commit, and also some changes I made to the HID Report structure. The most interesting is the one dealing with number of buttons: Linux doesn't seem to care, but Windows requires the HID structure to be byte aligned (that's in the spec). So if one declares 8/16/32... buttons they should not have any issues, but this is what happens when you have 9 buttons: ``` bits |0|1|2|3|4|5|6|7| |*|*|*|*|*|*|*|*| axis 0 (report size 8) |*|*|*|*|*|*|*|*| ... |*|*|*|*|*|*|*|*| |*|*|*|*|*|*|*|*| |*|*|*|*|*|*|*|*| |*|*|*|*|*|*|*|*| |*|*|*|*|*|*|*|*| axis 6 |*|*|*|*|*|*|*|*| first 8 buttons (report size 1) |*| | | | | | | | last of 9 buttons, not aligned ``` So for that I added a conditonal that will add a number of reports with size 1 to make sure it aligns to the next multiple of 8. Those reports send dummy inputs that don't do anything aside from aligning the data. Tested on Linux, Windows 10 and Street Fighter (where the joystick is recognized as direct-input) --- tmk_core/protocol/lufa/lufa.c | 4 ++++ tmk_core/protocol/usb_descriptor.c | 14 +++++++++----- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/tmk_core/protocol/lufa/lufa.c b/tmk_core/protocol/lufa/lufa.c index a4c617622bd4..8b2a5b476755 100644 --- a/tmk_core/protocol/lufa/lufa.c +++ b/tmk_core/protocol/lufa/lufa.c @@ -493,6 +493,10 @@ void EVENT_USB_Device_ConfigurationChanged(void) { ConfigSuccess &= Endpoint_ConfigureEndpoint(CDC_OUT_EPADDR, EP_TYPE_BULK, CDC_EPSIZE, ENDPOINT_BANK_SINGLE); ConfigSuccess &= Endpoint_ConfigureEndpoint(CDC_IN_EPADDR, EP_TYPE_BULK, CDC_EPSIZE, ENDPOINT_BANK_SINGLE); #endif +#ifdef JOYSTICK_ENABLE + ConfigSuccess &= ENDPOINT_CONFIG(JOYSTICK_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN, + JOYSTICK_EPSIZE, ENDPOINT_BANK_SINGLE); +#endif } /* FIXME: Expose this table in the docs somehow diff --git a/tmk_core/protocol/usb_descriptor.c b/tmk_core/protocol/usb_descriptor.c index 718035158c1d..5f96df0760f7 100644 --- a/tmk_core/protocol/usb_descriptor.c +++ b/tmk_core/protocol/usb_descriptor.c @@ -284,9 +284,8 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM JoystickReport[] = HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */ HID_RI_USAGE(8, 0x04), /* Joystick */ HID_RI_COLLECTION(8, 0x01), /* Application */ - HID_RI_USAGE(8, 0x01), /* Pointer */ HID_RI_COLLECTION(8, 0x00), /* Physical */ - + HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */ #if JOYSTICK_AXES_COUNT >= 1 HID_RI_USAGE(8, 0x30), // USAGE (X) #endif @@ -309,8 +308,8 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM JoystickReport[] = HID_RI_LOGICAL_MAXIMUM(8, 127), HID_RI_REPORT_COUNT(8, JOYSTICK_AXES_COUNT), HID_RI_REPORT_SIZE(8, 0x08), - HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE), - + HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), + HID_RI_USAGE_PAGE(8, 0x09), /* Button */ HID_RI_USAGE_MINIMUM(8, 0x01), /* Button 1 */ HID_RI_USAGE_MAXIMUM(8, JOYSTICK_BUTTON_COUNT), /* Button 5 */ @@ -319,7 +318,12 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM JoystickReport[] = HID_RI_REPORT_COUNT(8, JOYSTICK_BUTTON_COUNT), HID_RI_REPORT_SIZE(8, 0x01), HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), - + + #if (JOYSTICK_BUTTON_COUNT % 8) != 0 + HID_RI_REPORT_SIZE(8, 0x01), + HID_RI_REPORT_COUNT(8, 8 - (JOYSTICK_BUTTON_COUNT % 8)), + HID_RI_INPUT(8, HID_IOF_CONSTANT), + #endif HID_RI_END_COLLECTION(0), HID_RI_END_COLLECTION(0), }; From b030c45705685063aa6df3c8558076a57e1faae5 Mon Sep 17 00:00:00 2001 From: achol Date: Fri, 7 Dec 2018 00:27:49 +0100 Subject: [PATCH 03/22] Add save and restore of each pin used in reading joystick (AVR). Allow output pin to be JS_VIRTUAL_AXIS if the axis is connected to Vcc instead of an output pin from the MCU. Fix joystick report id Fix broken v-usb hid joystick interface. Make it more resilient to unusual settings (none multiple of eight button count, 0 buttons or 0 axes) Correct adc reading for multiple axes. Piecewise range conversion for uncentered raw value range. Input, output and ground pin configuration per axis. Documentation fixes --- docs/feature_joystick.md | 96 ++++++++++++++++---- drivers/avr/analog.c | 24 +++++ quantum/joystick.c | 6 +- quantum/joystick.h | 9 +- quantum/process_keycode/process_joystick.c | 101 ++++++++++++++++++--- quantum/process_keycode/process_joystick.h | 3 +- tmk_core/common/report.h | 3 +- tmk_core/protocol/vusb/vusb.c | 19 +++- 8 files changed, 223 insertions(+), 38 deletions(-) diff --git a/docs/feature_joystick.md b/docs/feature_joystick.md index 43a4f228355d..1d1d08ed0491 100644 --- a/docs/feature_joystick.md +++ b/docs/feature_joystick.md @@ -8,6 +8,21 @@ This is enabled by adding the following to `rules.mk` JOYSTICK_ENABLE = yes ``` +The joystick feature provides two services : + * reading an analog input device + * sending gamepad HID reports + +Both services can be used without the other, depending on wether you just want to read a device but not send gamepad reports (for volume control for instance) +or send gamepad reports based on values computed by the keyboard. + +### Analog circuit + +An analog device such as a potentiometer found on a gamepad's analog axes is based on a [voltage divider](https://en.wikipedia.org/wiki/Voltage_divider). +It is composed of three connectors linked to the ground, the power input and power output (usually the middle one). The power output holds the voltage that varies based on the position of the cursor, +which value will be read using your MCU's [ADC](https://en.wikipedia.org/wiki/Analog-to-digital_converter). +Depending on what pins are already used by your keyboard's matrix, the rest of the circuit can get a little bit more complicated, +feeding the power input and ground connection through pins and using diodes to avoid bad interactions with the matrix scanning procedures. + ### Configuring the joystick The default joystick has 2 axes and and 8 buttons. This can be changed from the config.h file : @@ -19,54 +34,101 @@ The default joystick has 2 axes and and 8 buttons. This can be changed from the #define JOYSTICK_AXES_COUNT 3 ``` -When defining axes for your joystick, you have to provide a definition array for it. You can do this from your keymap.c file. -A joystick will either be read from an input pin that allows the use of an ADC, or can be virtual, so that its value is provided by your code. -You have to define an array of type ''joystick_config_t'' and of proper size, in the following way : +When defining axes for your joystick, you have to provide a definition array. You can do this from your keymap.c file. +A joystick will either be read from an input pin that allows the use of the ADC, or can be virtual, so that its value is provided by your code. +You have to define an array of type ''joystick_config_t'' and of proper size. + +There are three ways for your circuit to work with the ADC, that relies on the use of 1, 2 or 3 pins of the MCU: + * 1 pin : your analog device is directly connected to your device Ground and Vcc. The only pin used is the ADC pin of your choice. + * 2 pins : your analog device is powered through a pin that allows toggling it on or off. The other pin is used to read the input value through the ADC + * 3 pins : both the power input and ground are connected to pins that must be set to a proper state before reading and restored afterwards. + +The configuration of each axis is performed using one of four macros: + * JOYSTICK_AXIS_VIRTUAL : no ADC reading must be performed, that value will be provided by keyboard/keymap-level code + * JOYSTICK_AXIS_IN (INPUT_PIN, LOW, REST, HIGH) : a voltage will be read on the provided pin, which must be an ADC-capable pin. + * JOYSTICK_AXIS_IN_OUT (INPUT_PIN, OUTPUT_PIN, LOW, REST, HIGH) : the provided OUTPUT_PIN will be set high before INPUT_PIN is read. + * JOYSTICK_AXIS_IN_OUT_GROUND(INPUT_PIN, OUTPUT_PIN, GROUND_PIN, LOW, REST, HIGH) : the OUTPUT_PIN will be set high and GROUND_PIN will be set low before reading from INPUT_PIN + +In any case where an ADC reading takes place (when INPUT_PIN is provided), additional LOW, REST and HIGH parameters are used. +They implement the calibration of the analog device by defining the range of read values that will be mapped to the lowest, resting position and highest possible value for the axis (-127 to 127). +In practice, you have to provide the lowest/highest raw adc reading, and the raw reading at resting position, when no deflection is applied. You can provide inverted LOW and HIGH to invert the axis. + +For instance, an axes configuration can be defined in the following way : ``` //joystick config joystick_config_t joystick_axes[JOYSTICK_AXES_COUNT] = { - [0] = {A1, D7, 65280, 65472}, - [1] = {JS_VIRTUAL_AXIS, JS_VIRTUAL_AXIS, 65280, 65472} + [0] = JOYSTICK_AXIS_IN_OUT_GROUND(A4, B0, A7, 900, 575, 285) +, [1] = JOYSTICK_AXIS_VIRTUAL }; ``` -In this example, the first axis will be read from the D7 pin while A1 is set high, using an analogRead, whereas the second axis will not be read. -If you connected the your analog component to Vcc instead of an output pin, you can set the output setting to JS_VIRTUAL_AXIS. +When the ADC reads 900 or higher, the returned axis value will be -127, whereas it will be 127 when the ADC reads 285 or lower. Zero is returned when 575 is read. + +In this example, the first axis will be read from the A4 pin while B0 is set high and A7 is set low, using an analogRead, whereas the second axis will not be read. + In order to give a value to the second axis, you can do so in any customizable entry point of quantum : as an action, in process_record_user or in matrix_scan_user, or even in joystick_task(void) which is called even when no key has been pressed. -You assign a value by writing to joystick_status.axes[axis_index] a signed 8bit value (-127 to 127). Then it is necessary to assign the flag JS_UPDATED to joystick_status.status in order for the change to be taken into account. +You assign a value by writing to joystick_status.axes[axis_index] a signed 8bit value (ranging from -127 to 127). Then it is necessary to assign the flag JS_UPDATED to joystick_status.status in order for an updated HID report to be sent. The following example writes two axes based on keypad presses, with KP_5 as a precision modifier : ``` #ifdef JOYSTICK_ENABLE -static bool precision_on; +static uint8_t precision_val = 70; +static uint8_t axesFlags = 0; +enum Axes{ + Precision = 1, + Axis1High = 2, + Axis1Low = 4, + Axis2High = 8, + Axis2Low = 16 +}; #endif bool process_record_user(uint16_t keycode, keyrecord_t *record) { switch(keycode){ #ifdef JOYSTICK_ENABLE // virtual joystick + #if JOYSTICK_AXES_COUNT>1 case KC_P8: - joystick_status.axes[1] -= (record->event.pressed ? 1 : -1) * (precision_on ?70 : 127); + if (record->event.pressed){ + axesFlags |= Axis2Low; + } else { + axesFlags &= ~Axis2Low; + } joystick_status.status |= JS_UPDATED; break; case KC_P2: - joystick_status.axes[1] += (record->event.pressed ? 1 : -1) * (precision_on ?70 : 127); + if (record->event.pressed){ + axesFlags |= Axis2High; + } else { + axesFlags &= ~Axis2High; + } joystick_status.status |= JS_UPDATED; break; + #endif case KC_P4: - joystick_status.axes[0] -= (record->event.pressed ? 1 : -1) * (precision_on ?70 : 127); + if (record->event.pressed){ + axesFlags |= Axis1Low; + } else { + axesFlags &= ~Axis1Low; + } joystick_status.status |= JS_UPDATED; break; case KC_P6: - joystick_status.axes[0] += (record->event.pressed ? 1 : -1) * (precision_on ?70 : 127); + if (record->event.pressed){ + axesFlags |= Axis1High; + } else { + axesFlags &= ~Axis1High; + } joystick_status.status |= JS_UPDATED; break; case KC_P5: - precision_on = record->event.pressed; - joystick_status.axes[0] *= record->event.pressed ? 70/127.f : 127/70.f; - joystick_status.axes[1] *= record->event.pressed ? 70/127.f : 127/70.f; + if (record->event.pressed){ + axesFlags |= Precision; + } else { + axesFlags &= ~Precision; + } joystick_status.status |= JS_UPDATED; break; #endif @@ -81,5 +143,3 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) { Joystick buttons are normal quantum keycode, defined as JS_BUTTON0 to JS_BUTTON_MAX, which depends on the number of buttons you have configured. To trigger a joystick button, just add the corresponding keycode to your keymap. - - diff --git a/drivers/avr/analog.c b/drivers/avr/analog.c index abe478b7129d..e79e49b04a3a 100644 --- a/drivers/avr/analog.c +++ b/drivers/avr/analog.c @@ -46,6 +46,7 @@ int16_t analogRead(uint8_t pin) { #endif } +<<<<<<< HEAD int16_t analogReadPin(pin_t pin) { return adc_read(pinToMux(pin)); } uint8_t pinToMux(pin_t pin) { @@ -94,6 +95,29 @@ uint8_t pinToMux(pin_t pin) { case C5: return _BV(MUX2) | _BV(MUX0); // ADC5 // ADC7:6 not present in DIP package and not shared by GPIO pins default: return _BV(MUX3) | _BV(MUX2) | _BV(MUX1) | _BV(MUX0); // 0V +======= +// Mux input +int16_t adc_read(uint8_t mux) +{ +#if defined(__AVR_AT90USB162__) + return 0; +#else + uint16_t res = 0; + + ADCSRA = (1<>>>>>> 5939a4430... Add save and restore of each pin used in reading joystick (AVR). #endif // clang-format on } diff --git a/quantum/joystick.c b/quantum/joystick.c index e6906913db79..ebad4ec3df3d 100644 --- a/quantum/joystick.c +++ b/quantum/joystick.c @@ -2,7 +2,11 @@ joystick_t joystick_status = { .buttons = {0}, - .axes = {0}, + .axes = { +#if JOYSTICK_AXES_COUNT>0 + 0 +#endif + }, .status = 0 }; diff --git a/quantum/joystick.h b/quantum/joystick.h index 6ca9ab887854..a1d2c7c8312c 100644 --- a/quantum/joystick.h +++ b/quantum/joystick.h @@ -16,12 +16,19 @@ // #define JS_VIRTUAL_AXIS 0xFF +#define JOYSTICK_AXIS_VIRTUAL {JS_VIRTUAL_AXIS,JS_VIRTUAL_AXIS,JS_VIRTUAL_AXIS,0 ,1023} +#define JOYSTICK_AXIS_IN(INPUT_PIN, LOW, REST, HIGH) {JS_VIRTUAL_AXIS,INPUT_PIN ,JS_VIRTUAL_AXIS,LOW,REST,HIGH} +#define JOYSTICK_AXIS_IN_OUT(INPUT_PIN, OUTPUT_PIN, LOW, REST, HIGH) {OUTPUT_PIN ,INPUT_PIN ,JS_VIRTUAL_AXIS,LOW,REST,HIGH} +#define JOYSTICK_AXIS_IN_OUT_GROUND(INPUT_PIN, OUTPUT_PIN, GROUND_PIN, LOW, REST, HIGH) {OUTPUT_PIN ,INPUT_PIN ,GROUND_PIN ,LOW,REST,HIGH} + typedef struct { uint8_t output_pin; uint8_t input_pin; + uint8_t ground_pin; //the AVR ADC offers 10 bit precision, with significant bits on the higher part uint16_t min_digit; + uint16_t mid_digit; uint16_t max_digit; } joystick_config_t; @@ -36,7 +43,7 @@ typedef struct { uint8_t buttons[JOYSTICK_BUTTON_COUNT/8+1]; - int8_t axes[JOYSTICK_AXES_COUNT]; + int16_t axes[JOYSTICK_AXES_COUNT]; uint8_t status:2; } joystick_t; diff --git a/quantum/process_keycode/process_joystick.c b/quantum/process_keycode/process_joystick.c index f90fd2393769..11cfd5e1d76d 100644 --- a/quantum/process_keycode/process_joystick.c +++ b/quantum/process_keycode/process_joystick.c @@ -24,12 +24,14 @@ bool process_joystick(uint16_t keycode, keyrecord_t *record){ __attribute__ ((weak)) void joystick_task(void){ - if (process_joystick_analog() && (joystick_status.status & JS_UPDATED)){ + if (process_joystick_analogread() && (joystick_status.status & JS_UPDATED)){ send_joystick_packet(&joystick_status); joystick_status.status &= ~JS_UPDATED; } } + + bool process_joystick_buttons(uint16_t keycode, keyrecord_t *record){ if (keycode < JS_BUTTON0 || keycode > JS_BUTTON_MAX){ @@ -47,33 +49,110 @@ bool process_joystick_buttons(uint16_t keycode, keyrecord_t *record){ return true; } +uint8_t savePinState(uint8_t pin){ +#ifdef __AVR__ + uint8_t pinNumber = pin & 0xF; + return ((PIN_ADDRESS(pin, 2) >> pinNumber) & 0x1) << 1 + | ((PIN_ADDRESS(pin, 1) >> pinNumber) & 0x1) ; +#else + return 0; +#endif +} + +void restorePinState(uint8_t pin, uint8_t restoreState){ +#ifdef __AVR__ + uint8_t pinNumber = pin & 0xF; + PIN_ADDRESS(pin, 2) = (PIN_ADDRESS(pin, 2) & ~_BV(pinNumber)) | (((restoreState >> 1) & 0x1) << pinNumber); + PIN_ADDRESS(pin, 1) = (PIN_ADDRESS(pin, 1) & ~_BV(pinNumber)) | ((restoreState & 0x1) << pinNumber); +#else + return; +#endif +} + __attribute__ ((weak)) -bool process_joystick_analog(){ +bool process_joystick_analogread(){ + return process_joystick_analogread_quantum(); +} + +bool process_joystick_analogread_quantum(){ + #if JOYSTICK_AXES_COUNT > 0 for (int axis_index=0 ; axis_index 0){ + //the value is in the higher range + range = joystick_axes[axis_index].max_digit; + ranged_val = 127*fminf(1.f, (axis_val - (float)(ref)) /(range - (float)ref)); + } + + if (ranged_val!=joystick_status.axes[axis_index]){ + joystick_status.axes[axis_index] = ranged_val; joystick_status.status |= JS_UPDATED; } - writePinLow(joystick_axes[axis_index].output_pin); + //restore output, ground and input status + if (joystick_axes[axis_index].output_pin!=JS_VIRTUAL_AXIS) { + restorePinState(joystick_axes[axis_index].output_pin, outputSavedState); + } + if (joystick_axes[axis_index].ground_pin!=JS_VIRTUAL_AXIS) { + restorePinState(joystick_axes[axis_index].ground_pin, groundSavedState); + } + + restorePinState(joystick_axes[axis_index].input_pin, inputSavedState); + } + #endif return true; } diff --git a/quantum/process_keycode/process_joystick.h b/quantum/process_keycode/process_joystick.h index f19a9221c20f..28562d259509 100644 --- a/quantum/process_keycode/process_joystick.h +++ b/quantum/process_keycode/process_joystick.h @@ -8,6 +8,7 @@ bool process_joystick(uint16_t keycode, keyrecord_t *record); void joystick_task(void); -bool process_joystick_analog(void); +bool process_joystick_analogread(void); +bool process_joystick_analogread_quantum(void); #endif //PROCESS_JOYSTICK_H \ No newline at end of file diff --git a/tmk_core/common/report.h b/tmk_core/common/report.h index 61ef6ea66cf8..82f150f26a2a 100644 --- a/tmk_core/common/report.h +++ b/tmk_core/common/report.h @@ -29,7 +29,8 @@ enum hid_report_ids { REPORT_ID_MOUSE, REPORT_ID_SYSTEM, REPORT_ID_CONSUMER, - REPORT_ID_NKRO + REPORT_ID_NKRO, + REPORT_ID_JOYSTICK }; /* Mouse buttons */ diff --git a/tmk_core/protocol/vusb/vusb.c b/tmk_core/protocol/vusb/vusb.c index 61d1ba53e752..571ca3389023 100644 --- a/tmk_core/protocol/vusb/vusb.c +++ b/tmk_core/protocol/vusb/vusb.c @@ -157,8 +157,7 @@ typedef struct { void send_joystick_packet(joystick_t* status) { vusb_joystick_report_t r = { - .report_id = 0x4, - + .report_id = REPORT_ID_JOYSTICK, #if JOYSTICK_AXES_COUNT>0 .axes = { status->axes[0] @@ -401,9 +400,10 @@ const PROGMEM uchar mouse_extra_hid_report[] = { 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 0x09, 0x04, // USAGE (Joystick) 0xa1, 0x01, // COLLECTION (Application) - 0x85, 0x4, // REPORT_ID (4) + 0x85, REPORT_ID_JOYSTICK, // REPORT_ID (6) 0x09, 0x01, // USAGE (Pointer) 0xa1, 0x00, // COLLECTION (Physical) +#if JOYSTICK_AXES_COUNT > 0 #if JOYSTICK_AXES_COUNT >= 1 0x09, 0x30, // USAGE (X) #endif @@ -427,7 +427,8 @@ const PROGMEM uchar mouse_extra_hid_report[] = { 0x75, 0x08, // REPORT_SIZE (8) 0x95, JOYSTICK_AXES_COUNT, // REPORT_COUNT (JOYSTICK_AXES_COUNT) 0x81, 0x02, // INPUT (Data,Var,Abs) - 0xc0, // END_COLLECTION +#endif +#if JOYSTICK_BUTTON_COUNT> 0 0x05, 0x09, // USAGE_PAGE (Button) 0x19, 0x01, // USAGE_MINIMUM (Button 1) 0x29, JOYSTICK_BUTTON_COUNT, // USAGE_MAXIMUM @@ -436,8 +437,16 @@ const PROGMEM uchar mouse_extra_hid_report[] = { 0x75, 0x01, // REPORT_SIZE (1) 0x95, JOYSTICK_BUTTON_COUNT, // REPORT_COUNT 0x81, 0x02, // INPUT (Data,Var,Abs) + //fill up report to get it byte-aligned +#if (JOYSTICK_BUTTON_COUNT % 8) != 0 + 0x75, 0x01, // REPORT_SIZE (1) + 0x95, 8 - (JOYSTICK_BUTTON_COUNT % 8), // REPORT_COUNT + 0x81, 0x01, // INPUT (Data,Var,Abs) + #endif +#endif + 0xc0, // END_COLLECTION 0xc0 // END_COLLECTION -#endif //GAMEPAD_ENABLE +#endif //JOYSTICK_ENABLE }; #endif From d88bdc6a1bb1f1e425726345279046f76b09b0cb Mon Sep 17 00:00:00 2001 From: a-chol Date: Sun, 29 Dec 2019 18:04:50 +0100 Subject: [PATCH 04/22] Fix port addressing for joystick analog read --- drivers/avr/analog.c | 33 +++++----------------- quantum/process_keycode/process_joystick.c | 9 +++--- tmk_core/protocol/vusb/vusb.c | 1 - 3 files changed, 12 insertions(+), 31 deletions(-) diff --git a/drivers/avr/analog.c b/drivers/avr/analog.c index e79e49b04a3a..a20f0ba68aff 100644 --- a/drivers/avr/analog.c +++ b/drivers/avr/analog.c @@ -46,7 +46,6 @@ int16_t analogRead(uint8_t pin) { #endif } -<<<<<<< HEAD int16_t analogReadPin(pin_t pin) { return adc_read(pinToMux(pin)); } uint8_t pinToMux(pin_t pin) { @@ -95,36 +94,13 @@ uint8_t pinToMux(pin_t pin) { case C5: return _BV(MUX2) | _BV(MUX0); // ADC5 // ADC7:6 not present in DIP package and not shared by GPIO pins default: return _BV(MUX3) | _BV(MUX2) | _BV(MUX1) | _BV(MUX0); // 0V -======= -// Mux input -int16_t adc_read(uint8_t mux) -{ -#if defined(__AVR_AT90USB162__) - return 0; -#else - uint16_t res = 0; - - ADCSRA = (1<>>>>>> 5939a4430... Add save and restore of each pin used in reading joystick (AVR). #endif // clang-format on } } int16_t adc_read(uint8_t mux) { - uint8_t low; + uint16_t low; // Enable ADC and configure prescaler ADCSRA = _BV(ADEN) | ADC_PRESCALER; @@ -152,5 +128,10 @@ int16_t adc_read(uint8_t mux) { // Must read LSB first low = ADCL; // Must read MSB only once! - return (ADCH << 8) | low; + low |= (ADCH << 8); + + //turn off the ADC + ADCSRA &= ~(1< #include +#include #ifdef __AVR__ # include @@ -52,8 +53,8 @@ bool process_joystick_buttons(uint16_t keycode, keyrecord_t *record){ uint8_t savePinState(uint8_t pin){ #ifdef __AVR__ uint8_t pinNumber = pin & 0xF; - return ((PIN_ADDRESS(pin, 2) >> pinNumber) & 0x1) << 1 - | ((PIN_ADDRESS(pin, 1) >> pinNumber) & 0x1) ; + return ((PORTx_ADDRESS(pin) >> pinNumber) & 0x1) << 1 + | ((DDRx_ADDRESS(pin) >> pinNumber) & 0x1) ; #else return 0; #endif @@ -62,8 +63,8 @@ uint8_t savePinState(uint8_t pin){ void restorePinState(uint8_t pin, uint8_t restoreState){ #ifdef __AVR__ uint8_t pinNumber = pin & 0xF; - PIN_ADDRESS(pin, 2) = (PIN_ADDRESS(pin, 2) & ~_BV(pinNumber)) | (((restoreState >> 1) & 0x1) << pinNumber); - PIN_ADDRESS(pin, 1) = (PIN_ADDRESS(pin, 1) & ~_BV(pinNumber)) | ((restoreState & 0x1) << pinNumber); + PORTx_ADDRESS(pin) = (PORTx_ADDRESS(pin) & ~_BV(pinNumber)) | (((restoreState >> 1) & 0x1) << pinNumber); + DDRx_ADDRESS(pin) = (DDRx_ADDRESS(pin) & ~_BV(pinNumber)) | ((restoreState & 0x1) << pinNumber); #else return; #endif diff --git a/tmk_core/protocol/vusb/vusb.c b/tmk_core/protocol/vusb/vusb.c index 571ca3389023..7c9f1bca6b6a 100644 --- a/tmk_core/protocol/vusb/vusb.c +++ b/tmk_core/protocol/vusb/vusb.c @@ -81,7 +81,6 @@ static void send_keyboard(report_keyboard_t *report); static void send_mouse(report_mouse_t *report); static void send_system(uint16_t data); static void send_consumer(uint16_t data); -static void send_joystick(void); static host_driver_t driver = {keyboard_leds, send_keyboard, send_mouse, send_system, send_consumer}; From 801be6047343322f2b98c010c828d28f830e2d9b Mon Sep 17 00:00:00 2001 From: Nick Brassel Date: Fri, 10 Jan 2020 06:29:34 +1100 Subject: [PATCH 05/22] The other required set of changes As per the PR, the changes still holding it up. Add onekey for testing. Fix ARM builds. Fix device descriptor when either axes or buttons is zero. Add compile-time check for at least one axis or button. Move definition to try to fix conflict. PR review comments. qmk cformat --- docs/feature_joystick.md | 32 +-- drivers/avr/analog.c | 8 +- .../onekey/keymaps/joystick/config.h | 3 + .../onekey/keymaps/joystick/keymap.c | 5 + .../onekey/keymaps/joystick/rules.mk | 1 + quantum/joystick.c | 20 +- quantum/joystick.h | 55 ++-- quantum/process_keycode/process_joystick.c | 238 +++++++++--------- quantum/process_keycode/process_joystick.h | 5 +- quantum/quantum.c | 4 - quantum/quantum.h | 4 + tmk_core/common/keyboard.c | 2 +- tmk_core/common/report.h | 10 + tmk_core/protocol/chibios/usb_main.c | 110 ++++---- tmk_core/protocol/lufa/lufa.c | 103 ++++---- tmk_core/protocol/usb_descriptor.c | 78 +++--- tmk_core/protocol/usb_descriptor.h | 8 +- tmk_core/protocol/vusb/vusb.c | 227 ++++++++--------- 18 files changed, 455 insertions(+), 458 deletions(-) create mode 100644 keyboards/handwired/onekey/keymaps/joystick/config.h create mode 100644 keyboards/handwired/onekey/keymaps/joystick/keymap.c create mode 100644 keyboards/handwired/onekey/keymaps/joystick/rules.mk diff --git a/docs/feature_joystick.md b/docs/feature_joystick.md index 1d1d08ed0491..2cf2c5737821 100644 --- a/docs/feature_joystick.md +++ b/docs/feature_joystick.md @@ -1,6 +1,6 @@ ## Joystick HID Device -The keyboard can be made to be recognized as a joystick HID device by the Operating System. +The keyboard can be made to be recognized as a joystick HID device by the Operating System. This is enabled by adding the following to `rules.mk` @@ -8,24 +8,26 @@ This is enabled by adding the following to `rules.mk` JOYSTICK_ENABLE = yes ``` -The joystick feature provides two services : +The joystick feature provides two services : * reading an analog input device * sending gamepad HID reports -Both services can be used without the other, depending on wether you just want to read a device but not send gamepad reports (for volume control for instance) +Both services can be used without the other, depending on whether you just want to read a device but not send gamepad reports (for volume control for instance) or send gamepad reports based on values computed by the keyboard. +!> Reading analog axes is not currently functional on ARM MCUs. + ### Analog circuit An analog device such as a potentiometer found on a gamepad's analog axes is based on a [voltage divider](https://en.wikipedia.org/wiki/Voltage_divider). -It is composed of three connectors linked to the ground, the power input and power output (usually the middle one). The power output holds the voltage that varies based on the position of the cursor, -which value will be read using your MCU's [ADC](https://en.wikipedia.org/wiki/Analog-to-digital_converter). -Depending on what pins are already used by your keyboard's matrix, the rest of the circuit can get a little bit more complicated, +It is composed of three connectors linked to the ground, the power input and power output (usually the middle one). The power output holds the voltage that varies based on the position of the cursor, +which value will be read using your MCU's [ADC](https://en.wikipedia.org/wiki/Analog-to-digital_converter). +Depending on what pins are already used by your keyboard's matrix, the rest of the circuit can get a little bit more complicated, feeding the power input and ground connection through pins and using diodes to avoid bad interactions with the matrix scanning procedures. ### Configuring the joystick -The default joystick has 2 axes and and 8 buttons. This can be changed from the config.h file : +The default joystick has 2 axes and and 8 buttons. This can be changed from the config.h file : ``` //max 32 for JOYSTICK_BUTTON_COUNT @@ -38,22 +40,22 @@ When defining axes for your joystick, you have to provide a definition array. Yo A joystick will either be read from an input pin that allows the use of the ADC, or can be virtual, so that its value is provided by your code. You have to define an array of type ''joystick_config_t'' and of proper size. -There are three ways for your circuit to work with the ADC, that relies on the use of 1, 2 or 3 pins of the MCU: +There are three ways for your circuit to work with the ADC, that relies on the use of 1, 2 or 3 pins of the MCU: * 1 pin : your analog device is directly connected to your device Ground and Vcc. The only pin used is the ADC pin of your choice. * 2 pins : your analog device is powered through a pin that allows toggling it on or off. The other pin is used to read the input value through the ADC * 3 pins : both the power input and ground are connected to pins that must be set to a proper state before reading and restored afterwards. - + The configuration of each axis is performed using one of four macros: * JOYSTICK_AXIS_VIRTUAL : no ADC reading must be performed, that value will be provided by keyboard/keymap-level code * JOYSTICK_AXIS_IN (INPUT_PIN, LOW, REST, HIGH) : a voltage will be read on the provided pin, which must be an ADC-capable pin. * JOYSTICK_AXIS_IN_OUT (INPUT_PIN, OUTPUT_PIN, LOW, REST, HIGH) : the provided OUTPUT_PIN will be set high before INPUT_PIN is read. * JOYSTICK_AXIS_IN_OUT_GROUND(INPUT_PIN, OUTPUT_PIN, GROUND_PIN, LOW, REST, HIGH) : the OUTPUT_PIN will be set high and GROUND_PIN will be set low before reading from INPUT_PIN - -In any case where an ADC reading takes place (when INPUT_PIN is provided), additional LOW, REST and HIGH parameters are used. + +In any case where an ADC reading takes place (when INPUT_PIN is provided), additional LOW, REST and HIGH parameters are used. They implement the calibration of the analog device by defining the range of read values that will be mapped to the lowest, resting position and highest possible value for the axis (-127 to 127). In practice, you have to provide the lowest/highest raw adc reading, and the raw reading at resting position, when no deflection is applied. You can provide inverted LOW and HIGH to invert the axis. -For instance, an axes configuration can be defined in the following way : +For instance, an axes configuration can be defined in the following way : ``` //joystick config @@ -65,12 +67,12 @@ joystick_config_t joystick_axes[JOYSTICK_AXES_COUNT] = { When the ADC reads 900 or higher, the returned axis value will be -127, whereas it will be 127 when the ADC reads 285 or lower. Zero is returned when 575 is read. -In this example, the first axis will be read from the A4 pin while B0 is set high and A7 is set low, using an analogRead, whereas the second axis will not be read. +In this example, the first axis will be read from the A4 pin while B0 is set high and A7 is set low, using an analogRead, whereas the second axis will not be read. In order to give a value to the second axis, you can do so in any customizable entry point of quantum : as an action, in process_record_user or in matrix_scan_user, or even in joystick_task(void) which is called even when no key has been pressed. You assign a value by writing to joystick_status.axes[axis_index] a signed 8bit value (ranging from -127 to 127). Then it is necessary to assign the flag JS_UPDATED to joystick_status.status in order for an updated HID report to be sent. -The following example writes two axes based on keypad presses, with KP_5 as a precision modifier : +The following example writes two axes based on keypad presses, with KP_5 as a precision modifier : ``` #ifdef JOYSTICK_ENABLE @@ -133,7 +135,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) { break; #endif } - + return true; } ``` diff --git a/drivers/avr/analog.c b/drivers/avr/analog.c index a20f0ba68aff..5430602f1e7d 100644 --- a/drivers/avr/analog.c +++ b/drivers/avr/analog.c @@ -129,9 +129,9 @@ int16_t adc_read(uint8_t mux) { low = ADCL; // Must read MSB only once! low |= (ADCH << 8); - - //turn off the ADC - ADCSRA &= ~(1<0 - 0 +joystick_t joystick_status = {.buttons = {0}, + .axes = + { +#if JOYSTICK_AXES_COUNT > 0 + 0 #endif - }, - .status = 0 -}; + }, + .status = 0}; -//array defining the reading of analog values for each axis -__attribute__ ((weak)) -joystick_config_t joystick_axes[JOYSTICK_AXES_COUNT] = {}; +// array defining the reading of analog values for each axis +__attribute__((weak)) joystick_config_t joystick_axes[JOYSTICK_AXES_COUNT] = {}; diff --git a/quantum/joystick.h b/quantum/joystick.h index a1d2c7c8312c..26d159aa1246 100644 --- a/quantum/joystick.h +++ b/quantum/joystick.h @@ -1,55 +1,52 @@ -#ifndef JOYSTICK_H -#define JOYSTICK_H +#pragma once #ifndef JOYSTICK_BUTTON_COUNT -#define JOYSTICK_BUTTON_COUNT 8 +# define JOYSTICK_BUTTON_COUNT 8 #endif #ifndef JOYSTICK_AXES_COUNT -#define JOYSTICK_AXES_COUNT 4 +# define JOYSTICK_AXES_COUNT 4 #endif #include -//configure on input_pin of the joystick_axes array entry to JS_VIRTUAL_AXIS +// 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. // #define JS_VIRTUAL_AXIS 0xFF -#define JOYSTICK_AXIS_VIRTUAL {JS_VIRTUAL_AXIS,JS_VIRTUAL_AXIS,JS_VIRTUAL_AXIS,0 ,1023} -#define JOYSTICK_AXIS_IN(INPUT_PIN, LOW, REST, HIGH) {JS_VIRTUAL_AXIS,INPUT_PIN ,JS_VIRTUAL_AXIS,LOW,REST,HIGH} -#define JOYSTICK_AXIS_IN_OUT(INPUT_PIN, OUTPUT_PIN, LOW, REST, HIGH) {OUTPUT_PIN ,INPUT_PIN ,JS_VIRTUAL_AXIS,LOW,REST,HIGH} -#define JOYSTICK_AXIS_IN_OUT_GROUND(INPUT_PIN, OUTPUT_PIN, GROUND_PIN, LOW, REST, HIGH) {OUTPUT_PIN ,INPUT_PIN ,GROUND_PIN ,LOW,REST,HIGH} +#define JOYSTICK_AXIS_VIRTUAL \ + { JS_VIRTUAL_AXIS, JS_VIRTUAL_AXIS, JS_VIRTUAL_AXIS, 0, 1023 } +#define JOYSTICK_AXIS_IN(INPUT_PIN, LOW, REST, HIGH) \ + { JS_VIRTUAL_AXIS, INPUT_PIN, JS_VIRTUAL_AXIS, LOW, REST, HIGH } +#define JOYSTICK_AXIS_IN_OUT(INPUT_PIN, OUTPUT_PIN, LOW, REST, HIGH) \ + { OUTPUT_PIN, INPUT_PIN, JS_VIRTUAL_AXIS, LOW, REST, HIGH } +#define JOYSTICK_AXIS_IN_OUT_GROUND(INPUT_PIN, OUTPUT_PIN, GROUND_PIN, LOW, REST, HIGH) \ + { OUTPUT_PIN, INPUT_PIN, GROUND_PIN, LOW, REST, HIGH } typedef struct { - uint8_t output_pin; - uint8_t input_pin; - uint8_t ground_pin; - - //the AVR ADC offers 10 bit precision, with significant bits on the higher part - uint16_t min_digit; - uint16_t mid_digit; - uint16_t max_digit; + uint8_t output_pin; + uint8_t input_pin; + uint8_t ground_pin; + + // the AVR ADC offers 10 bit precision, with significant bits on the higher part + uint16_t min_digit; + uint16_t mid_digit; + uint16_t max_digit; } joystick_config_t; extern joystick_config_t joystick_axes[JOYSTICK_AXES_COUNT]; -enum joystick_status{ - JS_INITIALIZED = 1, - JS_UPDATED = 2 -}; +enum joystick_status { JS_INITIALIZED = 1, JS_UPDATED = 2 }; typedef struct { - - uint8_t buttons[JOYSTICK_BUTTON_COUNT/8+1]; - - int16_t axes[JOYSTICK_AXES_COUNT]; - uint8_t status:2; + uint8_t buttons[JOYSTICK_BUTTON_COUNT / 8 + 1]; + + int16_t axes[JOYSTICK_AXES_COUNT]; + uint8_t status : 2; } joystick_t; extern joystick_t joystick_status; -//to be implemented in the hid protocol library +// to be implemented in the hid protocol library void send_joystick_packet(joystick_t* joystick); - -#endif //JOYSTICK_H \ No newline at end of file diff --git a/quantum/process_keycode/process_joystick.c b/quantum/process_keycode/process_joystick.c index 59dddddf0dd9..c0c58015cc93 100644 --- a/quantum/process_keycode/process_joystick.c +++ b/quantum/process_keycode/process_joystick.c @@ -1,159 +1,145 @@ +#include "joystick.h" #include "process_joystick.h" -#include -#include -#include - #ifdef __AVR__ -# include +# include "analog.h" #endif #include +#include bool process_joystick_buttons(uint16_t keycode, keyrecord_t *record); -bool process_joystick(uint16_t keycode, keyrecord_t *record){ - - if (process_joystick_buttons(keycode, record) - && (joystick_status.status & JS_UPDATED)>0){ - send_joystick_packet(&joystick_status); - joystick_status.status &= ~JS_UPDATED; - } - - return true; +bool process_joystick(uint16_t keycode, keyrecord_t *record) { + if (process_joystick_buttons(keycode, record) && (joystick_status.status & JS_UPDATED) > 0) { + send_joystick_packet(&joystick_status); + joystick_status.status &= ~JS_UPDATED; + } + + return true; } -__attribute__ ((weak)) -void joystick_task(void){ - if (process_joystick_analogread() && (joystick_status.status & JS_UPDATED)){ - send_joystick_packet(&joystick_status); - joystick_status.status &= ~JS_UPDATED; - } +void joystick_task(void) { + if (process_joystick_analogread() && (joystick_status.status & JS_UPDATED)) { + send_joystick_packet(&joystick_status); + joystick_status.status &= ~JS_UPDATED; + } } +bool process_joystick_buttons(uint16_t keycode, keyrecord_t *record) { + if (keycode < JS_BUTTON0 || keycode > JS_BUTTON_MAX) { + return true; + } else { + if (record->event.pressed) { + joystick_status.buttons[(keycode - JS_BUTTON0) / 8] |= 1 << (keycode % 8); + } else { + joystick_status.buttons[(keycode - JS_BUTTON0) / 8] &= ~(1 << (keycode % 8)); + } + joystick_status.status |= JS_UPDATED; + } -bool process_joystick_buttons(uint16_t keycode, keyrecord_t *record){ - - if (keycode < JS_BUTTON0 || keycode > JS_BUTTON_MAX){ return true; - } else { - if (record->event.pressed){ - joystick_status.buttons[(keycode-JS_BUTTON0)/8] |= 1<<(keycode%8); - } else { - joystick_status.buttons[(keycode-JS_BUTTON0)/8] &= ~(1<<(keycode%8)); - } - - joystick_status.status |= JS_UPDATED; - } - - return true; } -uint8_t savePinState(uint8_t pin){ +uint8_t savePinState(uint8_t pin) { #ifdef __AVR__ - uint8_t pinNumber = pin & 0xF; - return ((PORTx_ADDRESS(pin) >> pinNumber) & 0x1) << 1 - | ((DDRx_ADDRESS(pin) >> pinNumber) & 0x1) ; + uint8_t pinNumber = pin & 0xF; + return ((PORTx_ADDRESS(pin) >> pinNumber) & 0x1) << 1 | ((DDRx_ADDRESS(pin) >> pinNumber) & 0x1); #else - return 0; + return 0; #endif } -void restorePinState(uint8_t pin, uint8_t restoreState){ +void restorePinState(uint8_t pin, uint8_t restoreState) { #ifdef __AVR__ - uint8_t pinNumber = pin & 0xF; - PORTx_ADDRESS(pin) = (PORTx_ADDRESS(pin) & ~_BV(pinNumber)) | (((restoreState >> 1) & 0x1) << pinNumber); - DDRx_ADDRESS(pin) = (DDRx_ADDRESS(pin) & ~_BV(pinNumber)) | ((restoreState & 0x1) << pinNumber); + uint8_t pinNumber = pin & 0xF; + PORTx_ADDRESS(pin) = (PORTx_ADDRESS(pin) & ~_BV(pinNumber)) | (((restoreState >> 1) & 0x1) << pinNumber); + DDRx_ADDRESS(pin) = (DDRx_ADDRESS(pin) & ~_BV(pinNumber)) | ((restoreState & 0x1) << pinNumber); #else - return; + return; #endif } -__attribute__ ((weak)) -bool process_joystick_analogread(){ - return process_joystick_analogread_quantum(); -} - -bool process_joystick_analogread_quantum(){ +__attribute__((weak)) bool process_joystick_analogread() { return process_joystick_analogread_quantum(); } +bool process_joystick_analogread_quantum() { #if JOYSTICK_AXES_COUNT > 0 - for (int axis_index=0 ; axis_index 0){ - //the value is in the higher range - range = joystick_axes[axis_index].max_digit; - ranged_val = 127*fminf(1.f, (axis_val - (float)(ref)) /(range - (float)ref)); - } - - if (ranged_val!=joystick_status.axes[axis_index]){ - joystick_status.axes[axis_index] = ranged_val; - joystick_status.status |= JS_UPDATED; - } - - //restore output, ground and input status - if (joystick_axes[axis_index].output_pin!=JS_VIRTUAL_AXIS) { - restorePinState(joystick_axes[axis_index].output_pin, outputSavedState); - } - if (joystick_axes[axis_index].ground_pin!=JS_VIRTUAL_AXIS) { - restorePinState(joystick_axes[axis_index].ground_pin, groundSavedState); + for (int axis_index = 0; axis_index < JOYSTICK_AXES_COUNT; ++axis_index) { + if (joystick_axes[axis_index].input_pin == JS_VIRTUAL_AXIS) { + continue; + } + + // save previous input pin status as well + uint8_t inputSavedState = savePinState(joystick_axes[axis_index].input_pin); + + // disable pull-up resistor + writePinLow(joystick_axes[axis_index].input_pin); + + // if pin was a pull-up input, we need to uncharge it by turning it low + // before making it a low input + setPinOutput(joystick_axes[axis_index].input_pin); + + wait_us(10); + + // save and apply output pin status + uint8_t outputSavedState = 0; + if (joystick_axes[axis_index].output_pin != JS_VIRTUAL_AXIS) { + // save previous output pin status + outputSavedState = savePinState(joystick_axes[axis_index].output_pin); + + setPinOutput(joystick_axes[axis_index].output_pin); + writePinHigh(joystick_axes[axis_index].output_pin); + } + + uint8_t groundSavedState = 0; + if (joystick_axes[axis_index].ground_pin != JS_VIRTUAL_AXIS) { + // save previous output pin status + groundSavedState = savePinState(joystick_axes[axis_index].ground_pin); + + setPinOutput(joystick_axes[axis_index].ground_pin); + writePinLow(joystick_axes[axis_index].ground_pin); + } + + wait_us(10); + + setPinInput(joystick_axes[axis_index].input_pin); + + wait_us(10); + +# ifdef __AVR__ + int16_t axis_val = analogReadPin(joystick_axes[axis_index].input_pin); +# else + // default to resting position + int16_t axis_val = joystick_axes[axis_index].mid_digit; +# endif + + // test the converted value against the lower range + uint16_t ref = joystick_axes[axis_index].mid_digit; + uint16_t range = joystick_axes[axis_index].min_digit; + int16_t ranged_val = -127 * fminf(1.f, (axis_val - (float)(ref)) / (range - (float)ref)); + if (ranged_val > 0) { + // the value is in the higher range + range = joystick_axes[axis_index].max_digit; + ranged_val = 127 * fminf(1.f, (axis_val - (float)(ref)) / (range - (float)ref)); + } + + if (ranged_val != joystick_status.axes[axis_index]) { + joystick_status.axes[axis_index] = ranged_val; + joystick_status.status |= JS_UPDATED; + } + + // restore output, ground and input status + if (joystick_axes[axis_index].output_pin != JS_VIRTUAL_AXIS) { + restorePinState(joystick_axes[axis_index].output_pin, outputSavedState); + } + if (joystick_axes[axis_index].ground_pin != JS_VIRTUAL_AXIS) { + restorePinState(joystick_axes[axis_index].ground_pin, groundSavedState); + } + + restorePinState(joystick_axes[axis_index].input_pin, inputSavedState); } - - restorePinState(joystick_axes[axis_index].input_pin, inputSavedState); - - } - + #endif - return true; + return true; } diff --git a/quantum/process_keycode/process_joystick.h b/quantum/process_keycode/process_joystick.h index 28562d259509..7a8b82913aa1 100644 --- a/quantum/process_keycode/process_joystick.h +++ b/quantum/process_keycode/process_joystick.h @@ -1,5 +1,4 @@ -#ifndef PROCESS_JOYSTICK_H -#define PROCESS_JOYSTICK_H +#pragma once #include #include "quantum.h" @@ -10,5 +9,3 @@ void joystick_task(void); bool process_joystick_analogread(void); bool process_joystick_analogread_quantum(void); - -#endif //PROCESS_JOYSTICK_H \ No newline at end of file diff --git a/quantum/quantum.c b/quantum/quantum.c index c8e062f8ff51..4f940a061585 100644 --- a/quantum/quantum.c +++ b/quantum/quantum.c @@ -63,10 +63,6 @@ float bell_song[][2] = SONG(TERMINAL_SOUND); # endif #endif -#ifdef JOYSTICK_ENABLE -#include -#endif //JOYSTICK_ENABLE - static void do_code16(uint16_t code, void (*f)(uint8_t)) { switch (code) { case QK_MODS ... QK_MODS_MAX: diff --git a/quantum/quantum.h b/quantum/quantum.h index d03ba5942a04..5d347dd95380 100644 --- a/quantum/quantum.h +++ b/quantum/quantum.h @@ -142,6 +142,10 @@ extern layer_state_t layer_state; # include "process_magic.h" #endif +#ifdef JOYSTICK_ENABLE +# include "process_joystick.h" +#endif + #ifdef GRAVE_ESC_ENABLE # include "process_grave_esc.h" #endif diff --git a/tmk_core/common/keyboard.c b/tmk_core/common/keyboard.c index ae50a6e5e96a..44de86c77766 100644 --- a/tmk_core/common/keyboard.c +++ b/tmk_core/common/keyboard.c @@ -72,7 +72,7 @@ along with this program. If not, see . # include "process_midi.h" #endif #ifdef JOYSTICK_ENABLE -# include "process_joystick.h" +# include "process_joystick.h" #endif #ifdef HD44780_ENABLE # include "hd44780.h" diff --git a/tmk_core/common/report.h b/tmk_core/common/report.h index 82f150f26a2a..4c0e6ecb0a30 100644 --- a/tmk_core/common/report.h +++ b/tmk_core/common/report.h @@ -185,6 +185,16 @@ typedef struct { int8_t h; } __attribute__((packed)) report_mouse_t; +typedef struct { +#if JOYSTICK_AXES_COUNT > 0 + int8_t axes[JOYSTICK_AXES_COUNT]; +#endif + +#if JOYSTICK_BUTTON_COUNT > 0 + uint8_t buttons[(JOYSTICK_BUTTON_COUNT - 1) / 8 + 1]; +#endif +} __attribute__((packed)) joystick_report_t; + /* keycode to system usage */ static inline uint16_t KEYCODE2SYSTEM(uint8_t key) { switch (key) { diff --git a/tmk_core/protocol/chibios/usb_main.c b/tmk_core/protocol/chibios/usb_main.c index 3c7c7ea8bde7..7d4cf82ac0ca 100644 --- a/tmk_core/protocol/chibios/usb_main.c +++ b/tmk_core/protocol/chibios/usb_main.c @@ -48,7 +48,7 @@ extern keymap_config_t keymap_config; #endif #ifdef JOYSTICK_ENABLE -# include +# include "joystick.h" #endif /* --------------------------------------------------------- @@ -292,11 +292,11 @@ static usb_driver_configs_t drivers = { #endif #ifdef JOYSTICK_ENABLE - #define JOYSTICK_IN_CAPACITY 4 - #define JOYSTICK_OUT_CAPACITY 4 - #define JOYSTICK_IN_MODE USB_EP_MODE_TYPE_BULK - #define JOYSTICK_OUT_MODE USB_EP_MODE_TYPE_BULK - .joystick_driver = QMK_USB_DRIVER_CONFIG(JOYSTICK, 0, false), +# define JOYSTICK_IN_CAPACITY 4 +# define JOYSTICK_OUT_CAPACITY 4 +# define JOYSTICK_IN_MODE USB_EP_MODE_TYPE_BULK +# define JOYSTICK_OUT_MODE USB_EP_MODE_TYPE_BULK + .joystick_driver = QMK_USB_DRIVER_CONFIG(JOYSTICK, 0, false), #endif }; @@ -888,58 +888,54 @@ void virtser_task(void) { #ifdef JOYSTICK_ENABLE -typedef struct { - #if JOYSTICK_AXES_COUNT>0 - int8_t axes[JOYSTICK_AXES_COUNT]; - #endif - - #if JOYSTICK_BUTTON_COUNT>0 - uint8_t buttons[(JOYSTICK_BUTTON_COUNT-1)/8+1]; - #endif -} __attribute__ ((packed)) joystick_report_t; - -void send_joystick_packet(joystick_t* joystick) { +void send_joystick_packet(joystick_t *joystick) { joystick_report_t rep = { - #if JOYSTICK_AXES_COUNT>0 - .axes = { - joystick->axes[0] - - #if JOYSTICK_AXES_COUNT >= 2 - ,joystick->axes[1] - #endif - #if JOYSTICK_AXES_COUNT >= 3 - ,joystick->axes[2] - #endif - #if JOYSTICK_AXES_COUNT >= 4 - ,joystick->axes[3] - #endif - #if JOYSTICK_AXES_COUNT >= 5 - ,joystick->axes[4] - #endif - #if JOYSTICK_AXES_COUNT >= 6 - ,joystick->axes[5] - #endif - }, - #endif //JOYSTICK_AXES_COUNT>0 - - #if JOYSTICK_BUTTON_COUNT>0 - .buttons = { - joystick->buttons[0] - - #if JOYSTICK_BUTTON_COUNT>8 - ,joystick->buttons[1] - #endif - #if JOYSTICK_BUTTON_COUNT>16 - ,joystick->buttons[2] - #endif - #if JOYSTICK_BUTTON_COUNT>24 - ,joystick->buttons[3] - #endif - } - #endif //JOYSTICK_BUTTON_COUNT>0 - }; - - chnWrite(&drivers.joystick_driver.driver, (uint8_t*)&rep, sizeof(rep)); +# if JOYSTICK_AXES_COUNT > 0 + .axes = {joystick->axes[0] + +# if JOYSTICK_AXES_COUNT >= 2 + , + joystick->axes[1] +# endif +# if JOYSTICK_AXES_COUNT >= 3 + , + joystick->axes[2] +# endif +# if JOYSTICK_AXES_COUNT >= 4 + , + joystick->axes[3] +# endif +# if JOYSTICK_AXES_COUNT >= 5 + , + joystick->axes[4] +# endif +# if JOYSTICK_AXES_COUNT >= 6 + , + joystick->axes[5] +# endif + }, +# endif // JOYSTICK_AXES_COUNT>0 + +# if JOYSTICK_BUTTON_COUNT > 0 + .buttons = {joystick->buttons[0] + +# if JOYSTICK_BUTTON_COUNT > 8 + , + joystick->buttons[1] +# endif +# if JOYSTICK_BUTTON_COUNT > 16 + , + joystick->buttons[2] +# endif +# if JOYSTICK_BUTTON_COUNT > 24 + , + joystick->buttons[3] +# endif + } +# endif // JOYSTICK_BUTTON_COUNT>0 + }; + + chnWrite(&drivers.joystick_driver.driver, (uint8_t *)&rep, sizeof(rep)); } #endif diff --git a/tmk_core/protocol/lufa/lufa.c b/tmk_core/protocol/lufa/lufa.c index 8b2a5b476755..5250e08c2f4d 100644 --- a/tmk_core/protocol/lufa/lufa.c +++ b/tmk_core/protocol/lufa/lufa.c @@ -86,7 +86,7 @@ extern keymap_config_t keymap_config; #endif #ifdef JOYSTICK_ENABLE - #include "joystick.h" +# include "joystick.h" #endif uint8_t keyboard_idle = 0; @@ -271,64 +271,58 @@ static void Console_Task(void) { * Joystick ******************************************************************************/ #ifdef JOYSTICK_ENABLE - -typedef struct { - #if JOYSTICK_AXES_COUNT>0 - int8_t axes[JOYSTICK_AXES_COUNT]; - #endif - - #if JOYSTICK_BUTTON_COUNT>0 - uint8_t buttons[(JOYSTICK_BUTTON_COUNT-1)/8+1]; - #endif -} __attribute__ ((packed)) joystick_report_t; - -void send_joystick_packet(joystick_t* joystick){ - +void send_joystick_packet(joystick_t *joystick) { uint8_t timeout = 255; - uint8_t where = where_to_send(); - + uint8_t where = where_to_send(); + if (where != OUTPUT_USB && where != OUTPUT_USB_AND_BT) { - return; + return; } - + joystick_report_t r = { - #if JOYSTICK_AXES_COUNT>0 - .axes = { - joystick->axes[0] - - #if JOYSTICK_AXES_COUNT >= 2 - ,joystick->axes[1] - #endif - #if JOYSTICK_AXES_COUNT >= 3 - ,joystick->axes[2] - #endif - #if JOYSTICK_AXES_COUNT >= 4 - ,joystick->axes[3] - #endif - #if JOYSTICK_AXES_COUNT >= 5 - ,joystick->axes[4] - #endif - #if JOYSTICK_AXES_COUNT >= 6 - ,joystick->axes[5] - #endif +# if JOYSTICK_AXES_COUNT > 0 + .axes = {joystick->axes[0] + +# if JOYSTICK_AXES_COUNT >= 2 + , + joystick->axes[1] +# endif +# if JOYSTICK_AXES_COUNT >= 3 + , + joystick->axes[2] +# endif +# if JOYSTICK_AXES_COUNT >= 4 + , + joystick->axes[3] +# endif +# if JOYSTICK_AXES_COUNT >= 5 + , + joystick->axes[4] +# endif +# if JOYSTICK_AXES_COUNT >= 6 + , + joystick->axes[5] +# endif }, - #endif //JOYSTICK_AXES_COUNT>0 - - #if JOYSTICK_BUTTON_COUNT>0 - .buttons = { - joystick->buttons[0] - - #if JOYSTICK_BUTTON_COUNT>8 - ,joystick->buttons[1] - #endif - #if JOYSTICK_BUTTON_COUNT>16 - ,joystick->buttons[2] - #endif - #if JOYSTICK_BUTTON_COUNT>24 - ,joystick->buttons[3] - #endif +# endif // JOYSTICK_AXES_COUNT>0 + +# if JOYSTICK_BUTTON_COUNT > 0 + .buttons = {joystick->buttons[0] + +# if JOYSTICK_BUTTON_COUNT > 8 + , + joystick->buttons[1] +# endif +# if JOYSTICK_BUTTON_COUNT > 16 + , + joystick->buttons[2] +# endif +# if JOYSTICK_BUTTON_COUNT > 24 + , + joystick->buttons[3] +# endif } - #endif //JOYSTICK_BUTTON_COUNT>0 +# endif // JOYSTICK_BUTTON_COUNT>0 }; /* Select the Joystick Report Endpoint */ @@ -494,8 +488,7 @@ void EVENT_USB_Device_ConfigurationChanged(void) { ConfigSuccess &= Endpoint_ConfigureEndpoint(CDC_IN_EPADDR, EP_TYPE_BULK, CDC_EPSIZE, ENDPOINT_BANK_SINGLE); #endif #ifdef JOYSTICK_ENABLE - ConfigSuccess &= ENDPOINT_CONFIG(JOYSTICK_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN, - JOYSTICK_EPSIZE, ENDPOINT_BANK_SINGLE); + ConfigSuccess &= ENDPOINT_CONFIG(JOYSTICK_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN, JOYSTICK_EPSIZE, ENDPOINT_BANK_SINGLE); #endif } diff --git a/tmk_core/protocol/usb_descriptor.c b/tmk_core/protocol/usb_descriptor.c index 5f96df0760f7..0ef6a1986701 100644 --- a/tmk_core/protocol/usb_descriptor.c +++ b/tmk_core/protocol/usb_descriptor.c @@ -279,51 +279,58 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM ConsoleReport[] = { #endif #ifdef JOYSTICK_ENABLE +#if JOYSTICK_AXES_COUNT == 0 && JOYSTICK_BUTTON_COUNT == 0 + #error Need at least one axis or button for joystick +#endif const USB_Descriptor_HIDReport_Datatype_t PROGMEM JoystickReport[] = { HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */ HID_RI_USAGE(8, 0x04), /* Joystick */ HID_RI_COLLECTION(8, 0x01), /* Application */ HID_RI_COLLECTION(8, 0x00), /* Physical */ - HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */ - #if JOYSTICK_AXES_COUNT >= 1 + HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */ + #if JOYSTICK_AXES_COUNT >= 1 HID_RI_USAGE(8, 0x30), // USAGE (X) #endif - #if JOYSTICK_AXES_COUNT >= 2 + #if JOYSTICK_AXES_COUNT >= 2 HID_RI_USAGE(8, 0x31), // USAGE (Y) #endif - #if JOYSTICK_AXES_COUNT >= 3 + #if JOYSTICK_AXES_COUNT >= 3 HID_RI_USAGE(8, 0x32), // USAGE (Z) #endif - #if JOYSTICK_AXES_COUNT >= 4 + #if JOYSTICK_AXES_COUNT >= 4 HID_RI_USAGE(8, 0x33), // USAGE (RX) #endif - #if JOYSTICK_AXES_COUNT >= 5 + #if JOYSTICK_AXES_COUNT >= 5 HID_RI_USAGE(8, 0x34), // USAGE (RY) #endif - #if JOYSTICK_AXES_COUNT >= 6 + #if JOYSTICK_AXES_COUNT >= 6 HID_RI_USAGE(8, 0x35), // USAGE (RZ) #endif - HID_RI_LOGICAL_MINIMUM(8, -127), - HID_RI_LOGICAL_MAXIMUM(8, 127), - HID_RI_REPORT_COUNT(8, JOYSTICK_AXES_COUNT), - HID_RI_REPORT_SIZE(8, 0x08), - HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), - - HID_RI_USAGE_PAGE(8, 0x09), /* Button */ - HID_RI_USAGE_MINIMUM(8, 0x01), /* Button 1 */ - HID_RI_USAGE_MAXIMUM(8, JOYSTICK_BUTTON_COUNT), /* Button 5 */ - HID_RI_LOGICAL_MINIMUM(8, 0x00), - HID_RI_LOGICAL_MAXIMUM(8, 0x01), - HID_RI_REPORT_COUNT(8, JOYSTICK_BUTTON_COUNT), - HID_RI_REPORT_SIZE(8, 0x01), - HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), + #if JOYSTICK_AXES_COUNT >= 1 + HID_RI_LOGICAL_MINIMUM(8, -127), + HID_RI_LOGICAL_MAXIMUM(8, 127), + HID_RI_REPORT_COUNT(8, JOYSTICK_AXES_COUNT), + HID_RI_REPORT_SIZE(8, 0x08), + HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), + #endif - #if (JOYSTICK_BUTTON_COUNT % 8) != 0 - HID_RI_REPORT_SIZE(8, 0x01), - HID_RI_REPORT_COUNT(8, 8 - (JOYSTICK_BUTTON_COUNT % 8)), - HID_RI_INPUT(8, HID_IOF_CONSTANT), - #endif + #if JOYSTICK_BUTTON_COUNT >= 1 + HID_RI_USAGE_PAGE(8, 0x09), /* Button */ + HID_RI_USAGE_MINIMUM(8, 0x01), /* Button 1 */ + HID_RI_USAGE_MAXIMUM(8, JOYSTICK_BUTTON_COUNT), /* Button max */ + HID_RI_LOGICAL_MINIMUM(8, 0x00), + HID_RI_LOGICAL_MAXIMUM(8, 0x01), + HID_RI_REPORT_COUNT(8, JOYSTICK_BUTTON_COUNT), + HID_RI_REPORT_SIZE(8, 0x01), + HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), + + #if (JOYSTICK_BUTTON_COUNT % 8) != 0 + HID_RI_REPORT_SIZE(8, 0x01), + HID_RI_REPORT_COUNT(8, 8 - (JOYSTICK_BUTTON_COUNT % 8)), + HID_RI_INPUT(8, HID_IOF_CONSTANT), + #endif + #endif HID_RI_END_COLLECTION(0), HID_RI_END_COLLECTION(0), }; @@ -863,7 +870,6 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor = { }, #endif - /* * Joystick */ @@ -902,7 +908,7 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor = { .EndpointAddress = (ENDPOINT_DIR_IN | JOYSTICK_IN_EPNUM), .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), .EndpointSize = JOYSTICK_EPSIZE, - .PollingIntervalMS = 0x0A + .PollingIntervalMS = USB_POLLING_INTERVAL_MS }, #endif }; @@ -1038,10 +1044,10 @@ uint16_t get_usb_descriptor(const uint16_t wValue, const uint16_t wIndex, const break; #endif #ifdef JOYSTICK_ENABLE - case JOYSTICK_INTERFACE: - Address = &ConfigurationDescriptor.Joystick_HID; - Size = sizeof(USB_HID_Descriptor_HID_t); - break; + case JOYSTICK_INTERFACE: + Address = &ConfigurationDescriptor.Joystick_HID; + Size = sizeof(USB_HID_Descriptor_HID_t); + break; #endif } @@ -1088,10 +1094,10 @@ uint16_t get_usb_descriptor(const uint16_t wValue, const uint16_t wIndex, const break; #endif #ifdef JOYSTICK_ENABLE - case JOYSTICK_INTERFACE: - Address = &JoystickReport; - Size = sizeof(JoystickReport); - break; + case JOYSTICK_INTERFACE: + Address = &JoystickReport; + Size = sizeof(JoystickReport); + break; #endif } diff --git a/tmk_core/protocol/usb_descriptor.h b/tmk_core/protocol/usb_descriptor.h index bcc9cab4bbb1..17ed7517c1c6 100644 --- a/tmk_core/protocol/usb_descriptor.h +++ b/tmk_core/protocol/usb_descriptor.h @@ -126,9 +126,9 @@ typedef struct { #ifdef JOYSTICK_ENABLE // Joystick HID Interface - USB_Descriptor_Interface_t Joystick_Interface; - USB_HID_Descriptor_HID_t Joystick_HID; - USB_Descriptor_Endpoint_t Joystick_INEndpoint; + USB_Descriptor_Interface_t Joystick_Interface; + USB_HID_Descriptor_HID_t Joystick_HID; + USB_Descriptor_Endpoint_t Joystick_INEndpoint; #endif } USB_Descriptor_Configuration_t; @@ -235,7 +235,7 @@ enum usb_endpoints { # define CDC_OUT_EPADDR (ENDPOINT_DIR_OUT | CDC_OUT_EPNUM) #endif #ifdef JOYSTICK_ENABLE - JOYSTICK_IN_EPNUM = NEXT_EPNUM, + JOYSTICK_IN_EPNUM = NEXT_EPNUM, JOYSTICK_OUT_EPNUM = NEXT_EPNUM, #endif }; diff --git a/tmk_core/protocol/vusb/vusb.c b/tmk_core/protocol/vusb/vusb.c index 7c9f1bca6b6a..049664c993e2 100644 --- a/tmk_core/protocol/vusb/vusb.c +++ b/tmk_core/protocol/vusb/vusb.c @@ -27,7 +27,6 @@ along with this program. If not, see . #include "host_driver.h" #include "vusb.h" #include "joystick.h" -#include "joystick.h" #include static uint8_t vusb_keyboard_leds = 0; @@ -144,64 +143,67 @@ static void send_consumer(uint16_t data) { typedef struct { uint8_t report_id; - #if JOYSTICK_AXES_COUNT>0 - int8_t axes[JOYSTICK_AXES_COUNT]; - #endif +#if JOYSTICK_AXES_COUNT > 0 + int8_t axes[JOYSTICK_AXES_COUNT]; +#endif - #if JOYSTICK_BUTTON_COUNT>0 - uint8_t buttons[(JOYSTICK_BUTTON_COUNT-1)/8+1]; - #endif -} __attribute__ ((packed)) vusb_joystick_report_t; +#if JOYSTICK_BUTTON_COUNT > 0 + uint8_t buttons[(JOYSTICK_BUTTON_COUNT - 1) / 8 + 1]; +#endif +} __attribute__((packed)) vusb_joystick_report_t; -void send_joystick_packet(joystick_t* status) -{ +void send_joystick_packet(joystick_t *status) { vusb_joystick_report_t r = { .report_id = REPORT_ID_JOYSTICK, - #if JOYSTICK_AXES_COUNT>0 - .axes = { - status->axes[0] - - #if JOYSTICK_AXES_COUNT >= 2 - ,status->axes[1] - #endif - #if JOYSTICK_AXES_COUNT >= 3 - ,status->axes[2] - #endif - #if JOYSTICK_AXES_COUNT >= 4 - ,status->axes[3] - #endif - #if JOYSTICK_AXES_COUNT >= 5 - ,status->axes[4] - #endif - #if JOYSTICK_AXES_COUNT >= 6 - ,status->axes[5] - #endif +#if JOYSTICK_AXES_COUNT > 0 + .axes = {status->axes[0] + +# if JOYSTICK_AXES_COUNT >= 2 + , + status->axes[1] +# endif +# if JOYSTICK_AXES_COUNT >= 3 + , + status->axes[2] +# endif +# if JOYSTICK_AXES_COUNT >= 4 + , + status->axes[3] +# endif +# if JOYSTICK_AXES_COUNT >= 5 + , + status->axes[4] +# endif +# if JOYSTICK_AXES_COUNT >= 6 + , + status->axes[5] +# endif }, - #endif //JOYSTICK_AXES_COUNT>0 - - #if JOYSTICK_BUTTON_COUNT>0 - .buttons = { - status->buttons[0] - - #if JOYSTICK_BUTTON_COUNT>8 - ,status->buttons[1] - #endif - #if JOYSTICK_BUTTON_COUNT>16 - ,status->buttons[2] - #endif - #if JOYSTICK_BUTTON_COUNT>24 - ,status->buttons[3] - #endif +#endif // JOYSTICK_AXES_COUNT>0 + +#if JOYSTICK_BUTTON_COUNT > 0 + .buttons = {status->buttons[0] + +# if JOYSTICK_BUTTON_COUNT > 8 + , + status->buttons[1] +# endif +# if JOYSTICK_BUTTON_COUNT > 16 + , + status->buttons[2] +# endif +# if JOYSTICK_BUTTON_COUNT > 24 + , + status->buttons[3] +# endif } - #endif //JOYSTICK_BUTTON_COUNT>0 +#endif // JOYSTICK_BUTTON_COUNT>0 }; if (usbInterruptIsReady3()) { usbSetInterrupt3((void *)&r, sizeof(vusb_joystick_report_t)); } } - - /*------------------------------------------------------------------* * Request from host * *------------------------------------------------------------------*/ @@ -395,57 +397,58 @@ const PROGMEM uchar mouse_extra_hid_report[] = { 0x81, 0x00, // Input (Data, Array, Absolute) 0xC0 // End Collection # endif -#if JOYSTICK_ENABLE - 0x05, 0x01, // USAGE_PAGE (Generic Desktop) - 0x09, 0x04, // USAGE (Joystick) - 0xa1, 0x01, // COLLECTION (Application) - 0x85, REPORT_ID_JOYSTICK, // REPORT_ID (6) - 0x09, 0x01, // USAGE (Pointer) - 0xa1, 0x00, // COLLECTION (Physical) -#if JOYSTICK_AXES_COUNT > 0 - #if JOYSTICK_AXES_COUNT >= 1 - 0x09, 0x30, // USAGE (X) - #endif - #if JOYSTICK_AXES_COUNT >= 2 - 0x09, 0x31, // USAGE (Y) - #endif - #if JOYSTICK_AXES_COUNT >= 3 - 0x09, 0x32, // USAGE (Z) - #endif - #if JOYSTICK_AXES_COUNT >= 4 - 0x09, 0x33, // USAGE (RX) - #endif - #if JOYSTICK_AXES_COUNT >= 5 - 0x09, 0x34, // USAGE (RY) - #endif - #if JOYSTICK_AXES_COUNT >= 6 - 0x09, 0x35, // USAGE (RZ) - #endif - 0x15, 0x81, // LOGICAL_MINIMUM (-127) - 0x25, 0x7f, // LOGICAL_MAXIMUM (127) - 0x75, 0x08, // REPORT_SIZE (8) - 0x95, JOYSTICK_AXES_COUNT, // REPORT_COUNT (JOYSTICK_AXES_COUNT) - 0x81, 0x02, // INPUT (Data,Var,Abs) -#endif -#if JOYSTICK_BUTTON_COUNT> 0 - 0x05, 0x09, // USAGE_PAGE (Button) - 0x19, 0x01, // USAGE_MINIMUM (Button 1) - 0x29, JOYSTICK_BUTTON_COUNT, // USAGE_MAXIMUM - 0x15, 0x00, // LOGICAL_MINIMUM (0) - 0x25, 0x01, // LOGICAL_MAXIMUM (1) - 0x75, 0x01, // REPORT_SIZE (1) - 0x95, JOYSTICK_BUTTON_COUNT, // REPORT_COUNT - 0x81, 0x02, // INPUT (Data,Var,Abs) - //fill up report to get it byte-aligned -#if (JOYSTICK_BUTTON_COUNT % 8) != 0 - 0x75, 0x01, // REPORT_SIZE (1) - 0x95, 8 - (JOYSTICK_BUTTON_COUNT % 8), // REPORT_COUNT - 0x81, 0x01, // INPUT (Data,Var,Abs) - #endif -#endif - 0xc0, // END_COLLECTION - 0xc0 // END_COLLECTION -#endif //JOYSTICK_ENABLE +# if JOYSTICK_ENABLE + 0x05, + 0x01, // USAGE_PAGE (Generic Desktop) + 0x09, 0x04, // USAGE (Joystick) + 0xa1, 0x01, // COLLECTION (Application) + 0x85, REPORT_ID_JOYSTICK, // REPORT_ID (6) + 0x09, 0x01, // USAGE (Pointer) + 0xa1, 0x00, // COLLECTION (Physical) +# if JOYSTICK_AXES_COUNT > 0 +# if JOYSTICK_AXES_COUNT >= 1 + 0x09, 0x30, // USAGE (X) +# endif +# if JOYSTICK_AXES_COUNT >= 2 + 0x09, 0x31, // USAGE (Y) +# endif +# if JOYSTICK_AXES_COUNT >= 3 + 0x09, 0x32, // USAGE (Z) +# endif +# if JOYSTICK_AXES_COUNT >= 4 + 0x09, 0x33, // USAGE (RX) +# endif +# if JOYSTICK_AXES_COUNT >= 5 + 0x09, 0x34, // USAGE (RY) +# endif +# if JOYSTICK_AXES_COUNT >= 6 + 0x09, 0x35, // USAGE (RZ) +# endif + 0x15, 0x81, // LOGICAL_MINIMUM (-127) + 0x25, 0x7f, // LOGICAL_MAXIMUM (127) + 0x75, 0x08, // REPORT_SIZE (8) + 0x95, JOYSTICK_AXES_COUNT, // REPORT_COUNT (JOYSTICK_AXES_COUNT) + 0x81, 0x02, // INPUT (Data,Var,Abs) +# endif +# if JOYSTICK_BUTTON_COUNT > 0 + 0x05, 0x09, // USAGE_PAGE (Button) + 0x19, 0x01, // USAGE_MINIMUM (Button 1) + 0x29, JOYSTICK_BUTTON_COUNT, // USAGE_MAXIMUM + 0x15, 0x00, // LOGICAL_MINIMUM (0) + 0x25, 0x01, // LOGICAL_MAXIMUM (1) + 0x75, 0x01, // REPORT_SIZE (1) + 0x95, JOYSTICK_BUTTON_COUNT, // REPORT_COUNT + 0x81, 0x02, // INPUT (Data,Var,Abs) +// fill up report to get it byte-aligned +# if (JOYSTICK_BUTTON_COUNT % 8) != 0 + 0x75, 0x01, // REPORT_SIZE (1) + 0x95, 8 - (JOYSTICK_BUTTON_COUNT % 8), // REPORT_COUNT + 0x81, 0x01, // INPUT (Data,Var,Abs) +# endif +# endif + 0xc0, // END_COLLECTION + 0xc0 // END_COLLECTION +# endif // JOYSTICK_ENABLE }; #endif @@ -468,19 +471,19 @@ const PROGMEM char usbDescriptorConfiguration[] = { /* USB configuration descriptor */ 9, /* sizeof(usbDescriptorConfiguration): length of descriptor in bytes */ USBDESCR_CONFIG, /* descriptor type */ -# if defined (MOUSE_ENABLE) || defined(EXTRAKEY_ENABLE) - 59, // 9 + (9 + 9 + 7) + (9 + 9 + 7) -#else - 34, // 9 + (9 + 9 + 7) +# if defined(MOUSE_ENABLE) || defined(EXTRAKEY_ENABLE) + 59, // 9 + (9 + 9 + 7) + (9 + 9 + 7) +# else + 34, // 9 + (9 + 9 + 7) # endif 0, - // 18 + 7 * USB_CFG_HAVE_INTRIN_ENDPOINT + 7 * USB_CFG_HAVE_INTRIN_ENDPOINT3 + 9, 0, - /* total length of data returned (including inlined descriptors) */ +// 18 + 7 * USB_CFG_HAVE_INTRIN_ENDPOINT + 7 * USB_CFG_HAVE_INTRIN_ENDPOINT3 + 9, 0, +/* total length of data returned (including inlined descriptors) */ # if defined(MOUSE_ENABLE) || defined(EXTRAKEY_ENABLE) 2, /* number of interfaces in this configuration */ # else 1, -#endif +# endif 1, /* index of this configuration */ 0, /* configuration name string index */ # if USB_CFG_IS_SELF_POWERED @@ -533,13 +536,13 @@ const PROGMEM char usbDescriptorConfiguration[] = { 0, /* PROTOCOL: none */ 0, /* string index for interface */ /* HID descriptor */ - 9, /* sizeof(usbDescrHID): length of descriptor in bytes */ - USBDESCR_HID, /* descriptor type: HID */ - 0x01, 0x01, /* BCD representation of HID version */ - 0x00, /* target country code */ - 0x01, /* number of HID Report (or other HID class) Descriptor infos to follow */ - 0x22, /* descriptor type: report */ - sizeof(mouse_extra_hid_report), 0, /* total length of report descriptor */ + 9, /* sizeof(usbDescrHID): length of descriptor in bytes */ + USBDESCR_HID, /* descriptor type: HID */ + 0x01, 0x01, /* BCD representation of HID version */ + 0x00, /* target country code */ + 0x01, /* number of HID Report (or other HID class) Descriptor infos to follow */ + 0x22, /* descriptor type: report */ + sizeof(mouse_extra_hid_report), 0, /* total length of report descriptor */ # if USB_CFG_HAVE_INTRIN_ENDPOINT3 /* endpoint descriptor for endpoint 3 */ /* Endpoint descriptor */ 7, /* sizeof(usbDescrEndpoint) */ From 6fd7f9d12f19e9662f5cbbe6f373b1059f43967b Mon Sep 17 00:00:00 2001 From: a-chol Date: Fri, 20 Mar 2020 19:59:23 +0100 Subject: [PATCH 06/22] avoid float functions to compute range mapping for axis adc reading --- quantum/process_keycode/process_joystick.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/quantum/process_keycode/process_joystick.c b/quantum/process_keycode/process_joystick.c index c0c58015cc93..f26b6c6f3f9c 100644 --- a/quantum/process_keycode/process_joystick.c +++ b/quantum/process_keycode/process_joystick.c @@ -114,15 +114,20 @@ bool process_joystick_analogread_quantum() { int16_t axis_val = joystick_axes[axis_index].mid_digit; # endif - // test the converted value against the lower range - uint16_t ref = joystick_axes[axis_index].mid_digit; - uint16_t range = joystick_axes[axis_index].min_digit; - int16_t ranged_val = -127 * fminf(1.f, (axis_val - (float)(ref)) / (range - (float)ref)); - if (ranged_val > 0) { - // the value is in the higher range - range = joystick_axes[axis_index].max_digit; - ranged_val = 127 * fminf(1.f, (axis_val - (float)(ref)) / (range - (float)ref)); + //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) ; + + 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); } + + //clamp the result in the valid range + ranged_val = ranged_val<-127 ? -127 : ranged_val; + ranged_val = ranged_val>127 ? 127 : ranged_val; if (ranged_val != joystick_status.axes[axis_index]) { joystick_status.axes[axis_index] = ranged_val; From 38cd264dd8a97501d805ef40816c43573c936f35 Mon Sep 17 00:00:00 2001 From: Nick Brassel Date: Tue, 10 Mar 2020 18:50:44 +1100 Subject: [PATCH 07/22] Remove V-USB support for now. Updated docs accordingly. --- docs/feature_joystick.md | 10 ++- drivers/avr/analog.c | 1 + tmk_core/protocol/vusb/vusb.c | 147 ++++------------------------------ 3 files changed, 22 insertions(+), 136 deletions(-) diff --git a/docs/feature_joystick.md b/docs/feature_joystick.md index 2cf2c5737821..8aed87b1163c 100644 --- a/docs/feature_joystick.md +++ b/docs/feature_joystick.md @@ -4,10 +4,12 @@ The keyboard can be made to be recognized as a joystick HID device by the Operat This is enabled by adding the following to `rules.mk` -``` +```makefile JOYSTICK_ENABLE = yes ``` +!> Joystick support is not currently available on V-USB devices. + The joystick feature provides two services : * reading an analog input device * sending gamepad HID reports @@ -29,7 +31,7 @@ feeding the power input and ground connection through pins and using diodes to a The default joystick has 2 axes and and 8 buttons. This can be changed from the config.h file : -``` +```c //max 32 for JOYSTICK_BUTTON_COUNT #define JOYSTICK_BUTTON_COUNT 16 //max 6 for JOYSTICK_AXES_COUNT @@ -57,7 +59,7 @@ In practice, you have to provide the lowest/highest raw adc reading, and the raw For instance, an axes configuration can be defined in the following way : -``` +```c //joystick config joystick_config_t joystick_axes[JOYSTICK_AXES_COUNT] = { [0] = JOYSTICK_AXIS_IN_OUT_GROUND(A4, B0, A7, 900, 575, 285) @@ -74,7 +76,7 @@ You assign a value by writing to joystick_status.axes[axis_index] a signed 8bit The following example writes two axes based on keypad presses, with KP_5 as a precision modifier : -``` +```c #ifdef JOYSTICK_ENABLE static uint8_t precision_val = 70; static uint8_t axesFlags = 0; diff --git a/drivers/avr/analog.c b/drivers/avr/analog.c index 5430602f1e7d..f67aec2ed093 100644 --- a/drivers/avr/analog.c +++ b/drivers/avr/analog.c @@ -97,6 +97,7 @@ uint8_t pinToMux(pin_t pin) { #endif // clang-format on } + return 0; } int16_t adc_read(uint8_t mux) { diff --git a/tmk_core/protocol/vusb/vusb.c b/tmk_core/protocol/vusb/vusb.c index 049664c993e2..abf723952e4a 100644 --- a/tmk_core/protocol/vusb/vusb.c +++ b/tmk_core/protocol/vusb/vusb.c @@ -26,7 +26,6 @@ along with this program. If not, see . #include "debug.h" #include "host_driver.h" #include "vusb.h" -#include "joystick.h" #include static uint8_t vusb_keyboard_leds = 0; @@ -140,70 +139,6 @@ static void send_consumer(uint16_t data) { #endif } -typedef struct { - uint8_t report_id; - -#if JOYSTICK_AXES_COUNT > 0 - int8_t axes[JOYSTICK_AXES_COUNT]; -#endif - -#if JOYSTICK_BUTTON_COUNT > 0 - uint8_t buttons[(JOYSTICK_BUTTON_COUNT - 1) / 8 + 1]; -#endif -} __attribute__((packed)) vusb_joystick_report_t; - -void send_joystick_packet(joystick_t *status) { - vusb_joystick_report_t r = { - .report_id = REPORT_ID_JOYSTICK, -#if JOYSTICK_AXES_COUNT > 0 - .axes = {status->axes[0] - -# if JOYSTICK_AXES_COUNT >= 2 - , - status->axes[1] -# endif -# if JOYSTICK_AXES_COUNT >= 3 - , - status->axes[2] -# endif -# if JOYSTICK_AXES_COUNT >= 4 - , - status->axes[3] -# endif -# if JOYSTICK_AXES_COUNT >= 5 - , - status->axes[4] -# endif -# if JOYSTICK_AXES_COUNT >= 6 - , - status->axes[5] -# endif - }, -#endif // JOYSTICK_AXES_COUNT>0 - -#if JOYSTICK_BUTTON_COUNT > 0 - .buttons = {status->buttons[0] - -# if JOYSTICK_BUTTON_COUNT > 8 - , - status->buttons[1] -# endif -# if JOYSTICK_BUTTON_COUNT > 16 - , - status->buttons[2] -# endif -# if JOYSTICK_BUTTON_COUNT > 24 - , - status->buttons[3] -# endif - } -#endif // JOYSTICK_BUTTON_COUNT>0 - }; - if (usbInterruptIsReady3()) { - usbSetInterrupt3((void *)&r, sizeof(vusb_joystick_report_t)); - } -} - /*------------------------------------------------------------------* * Request from host * *------------------------------------------------------------------*/ @@ -316,7 +251,7 @@ const PROGMEM uchar keyboard_hid_report[] = { 0xC0 // End Collection }; -#if defined(MOUSE_ENABLE) || defined(EXTRAKEY_ENABLE) || defined(JOYSTICK_ENABLE) +#if defined(MOUSE_ENABLE) || defined(EXTRAKEY_ENABLE) const PROGMEM uchar mouse_extra_hid_report[] = { # ifdef MOUSE_ENABLE // Mouse report descriptor @@ -397,58 +332,6 @@ const PROGMEM uchar mouse_extra_hid_report[] = { 0x81, 0x00, // Input (Data, Array, Absolute) 0xC0 // End Collection # endif -# if JOYSTICK_ENABLE - 0x05, - 0x01, // USAGE_PAGE (Generic Desktop) - 0x09, 0x04, // USAGE (Joystick) - 0xa1, 0x01, // COLLECTION (Application) - 0x85, REPORT_ID_JOYSTICK, // REPORT_ID (6) - 0x09, 0x01, // USAGE (Pointer) - 0xa1, 0x00, // COLLECTION (Physical) -# if JOYSTICK_AXES_COUNT > 0 -# if JOYSTICK_AXES_COUNT >= 1 - 0x09, 0x30, // USAGE (X) -# endif -# if JOYSTICK_AXES_COUNT >= 2 - 0x09, 0x31, // USAGE (Y) -# endif -# if JOYSTICK_AXES_COUNT >= 3 - 0x09, 0x32, // USAGE (Z) -# endif -# if JOYSTICK_AXES_COUNT >= 4 - 0x09, 0x33, // USAGE (RX) -# endif -# if JOYSTICK_AXES_COUNT >= 5 - 0x09, 0x34, // USAGE (RY) -# endif -# if JOYSTICK_AXES_COUNT >= 6 - 0x09, 0x35, // USAGE (RZ) -# endif - 0x15, 0x81, // LOGICAL_MINIMUM (-127) - 0x25, 0x7f, // LOGICAL_MAXIMUM (127) - 0x75, 0x08, // REPORT_SIZE (8) - 0x95, JOYSTICK_AXES_COUNT, // REPORT_COUNT (JOYSTICK_AXES_COUNT) - 0x81, 0x02, // INPUT (Data,Var,Abs) -# endif -# if JOYSTICK_BUTTON_COUNT > 0 - 0x05, 0x09, // USAGE_PAGE (Button) - 0x19, 0x01, // USAGE_MINIMUM (Button 1) - 0x29, JOYSTICK_BUTTON_COUNT, // USAGE_MAXIMUM - 0x15, 0x00, // LOGICAL_MINIMUM (0) - 0x25, 0x01, // LOGICAL_MAXIMUM (1) - 0x75, 0x01, // REPORT_SIZE (1) - 0x95, JOYSTICK_BUTTON_COUNT, // REPORT_COUNT - 0x81, 0x02, // INPUT (Data,Var,Abs) -// fill up report to get it byte-aligned -# if (JOYSTICK_BUTTON_COUNT % 8) != 0 - 0x75, 0x01, // REPORT_SIZE (1) - 0x95, 8 - (JOYSTICK_BUTTON_COUNT % 8), // REPORT_COUNT - 0x81, 0x01, // INPUT (Data,Var,Abs) -# endif -# endif - 0xc0, // END_COLLECTION - 0xc0 // END_COLLECTION -# endif // JOYSTICK_ENABLE }; #endif @@ -471,19 +354,19 @@ const PROGMEM char usbDescriptorConfiguration[] = { /* USB configuration descriptor */ 9, /* sizeof(usbDescriptorConfiguration): length of descriptor in bytes */ USBDESCR_CONFIG, /* descriptor type */ -# if defined(MOUSE_ENABLE) || defined(EXTRAKEY_ENABLE) - 59, // 9 + (9 + 9 + 7) + (9 + 9 + 7) -# else - 34, // 9 + (9 + 9 + 7) +# if defined (MOUSE_ENABLE) || defined(EXTRAKEY_ENABLE) + 59, // 9 + (9 + 9 + 7) + (9 + 9 + 7) +#else + 34, // 9 + (9 + 9 + 7) # endif 0, -// 18 + 7 * USB_CFG_HAVE_INTRIN_ENDPOINT + 7 * USB_CFG_HAVE_INTRIN_ENDPOINT3 + 9, 0, -/* total length of data returned (including inlined descriptors) */ + // 18 + 7 * USB_CFG_HAVE_INTRIN_ENDPOINT + 7 * USB_CFG_HAVE_INTRIN_ENDPOINT3 + 9, 0, + /* total length of data returned (including inlined descriptors) */ # if defined(MOUSE_ENABLE) || defined(EXTRAKEY_ENABLE) 2, /* number of interfaces in this configuration */ # else 1, -# endif +#endif 1, /* index of this configuration */ 0, /* configuration name string index */ # if USB_CFG_IS_SELF_POWERED @@ -536,13 +419,13 @@ const PROGMEM char usbDescriptorConfiguration[] = { 0, /* PROTOCOL: none */ 0, /* string index for interface */ /* HID descriptor */ - 9, /* sizeof(usbDescrHID): length of descriptor in bytes */ - USBDESCR_HID, /* descriptor type: HID */ - 0x01, 0x01, /* BCD representation of HID version */ - 0x00, /* target country code */ - 0x01, /* number of HID Report (or other HID class) Descriptor infos to follow */ - 0x22, /* descriptor type: report */ - sizeof(mouse_extra_hid_report), 0, /* total length of report descriptor */ + 9, /* sizeof(usbDescrHID): length of descriptor in bytes */ + USBDESCR_HID, /* descriptor type: HID */ + 0x01, 0x01, /* BCD representation of HID version */ + 0x00, /* target country code */ + 0x01, /* number of HID Report (or other HID class) Descriptor infos to follow */ + 0x22, /* descriptor type: report */ + sizeof(mouse_extra_hid_report), 0, /* total length of report descriptor */ # if USB_CFG_HAVE_INTRIN_ENDPOINT3 /* endpoint descriptor for endpoint 3 */ /* Endpoint descriptor */ 7, /* sizeof(usbDescrEndpoint) */ From a8a2825bd481dcd96d2311c80fb9867c72e48048 Mon Sep 17 00:00:00 2001 From: a-chol Date: Sun, 22 Mar 2020 11:09:11 +0100 Subject: [PATCH 08/22] Update tmk_core/protocol/lufa/lufa.c Co-Authored-By: Ryan --- tmk_core/protocol/lufa/lufa.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tmk_core/protocol/lufa/lufa.c b/tmk_core/protocol/lufa/lufa.c index 5250e08c2f4d..c11eb3173896 100644 --- a/tmk_core/protocol/lufa/lufa.c +++ b/tmk_core/protocol/lufa/lufa.c @@ -273,11 +273,6 @@ static void Console_Task(void) { #ifdef JOYSTICK_ENABLE void send_joystick_packet(joystick_t *joystick) { uint8_t timeout = 255; - uint8_t where = where_to_send(); - - if (where != OUTPUT_USB && where != OUTPUT_USB_AND_BT) { - return; - } joystick_report_t r = { # if JOYSTICK_AXES_COUNT > 0 From 86853a4110142cd0aafc3e6eb510fa103bfeee12 Mon Sep 17 00:00:00 2001 From: a-chol Date: Sun, 22 Mar 2020 11:09:21 +0100 Subject: [PATCH 09/22] Update tmk_core/protocol/usb_descriptor.c Co-Authored-By: Ryan --- tmk_core/protocol/usb_descriptor.c | 64 +++++++++++++++--------------- 1 file changed, 31 insertions(+), 33 deletions(-) diff --git a/tmk_core/protocol/usb_descriptor.c b/tmk_core/protocol/usb_descriptor.c index 0ef6a1986701..2f33e8db5c52 100644 --- a/tmk_core/protocol/usb_descriptor.c +++ b/tmk_core/protocol/usb_descriptor.c @@ -874,42 +874,40 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor = { * Joystick */ #ifdef JOYSTICK_ENABLE - .Joystick_Interface = - { - .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface}, - - .InterfaceNumber = JOYSTICK_INTERFACE, - .AlternateSetting = 0x00, - - .TotalEndpoints = 1, - - .Class = HID_CSCP_HIDClass, - .SubClass = HID_CSCP_NonBootSubclass, - .Protocol = HID_CSCP_NonBootProtocol, - - .InterfaceStrIndex = NO_DESCRIPTOR + .Joystick_Interface = { + .Header = { + .Size = sizeof(USB_Descriptor_Interface_t), + .Type = DTYPE_Interface }, - - .Joystick_HID = - { - .Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID}, - - .HIDSpec = VERSION_BCD(1,1,1), - .CountryCode = 0x00, - .TotalReportDescriptors = 1, - .HIDReportType = HID_DTYPE_Report, - .HIDReportLength = sizeof(JoystickReport) + .InterfaceNumber = JOYSTICK_INTERFACE, + .AlternateSetting = 0x00, + .TotalEndpoints = 1, + .Class = HID_CSCP_HIDClass, + .SubClass = HID_CSCP_NonBootSubclass, + .Protocol = HID_CSCP_NonBootProtocol, + .InterfaceStrIndex = NO_DESCRIPTOR + }, + .Joystick_HID = { + .Header = { + .Size = sizeof(USB_HID_Descriptor_HID_t), + .Type = HID_DTYPE_HID }, - - .Joystick_INEndpoint = - { - .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, - - .EndpointAddress = (ENDPOINT_DIR_IN | JOYSTICK_IN_EPNUM), - .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), - .EndpointSize = JOYSTICK_EPSIZE, - .PollingIntervalMS = USB_POLLING_INTERVAL_MS + .HIDSpec = VERSION_BCD(1, 1, 1), + .CountryCode = 0x00, + .TotalReportDescriptors = 1, + .HIDReportType = HID_DTYPE_Report, + .HIDReportLength = sizeof(JoystickReport) + }, + .Joystick_INEndpoint = { + .Header = { + .Size = sizeof(USB_Descriptor_Endpoint_t), + .Type = DTYPE_Endpoint }, + .EndpointAddress = (ENDPOINT_DIR_IN | JOYSTICK_IN_EPNUM), + .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), + .EndpointSize = JOYSTICK_EPSIZE, + .PollingIntervalMS = USB_POLLING_INTERVAL_MS + } #endif }; From c6c01f9eff86d11ce966b240844ec53fd96db3d3 Mon Sep 17 00:00:00 2001 From: a-chol Date: Sun, 22 Mar 2020 11:09:30 +0100 Subject: [PATCH 10/22] Update tmk_core/protocol/usb_descriptor.c Co-Authored-By: Ryan --- tmk_core/protocol/usb_descriptor.c | 99 +++++++++++++++--------------- 1 file changed, 49 insertions(+), 50 deletions(-) diff --git a/tmk_core/protocol/usb_descriptor.c b/tmk_core/protocol/usb_descriptor.c index 2f33e8db5c52..1dbe1c024166 100644 --- a/tmk_core/protocol/usb_descriptor.c +++ b/tmk_core/protocol/usb_descriptor.c @@ -282,57 +282,56 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM ConsoleReport[] = { #if JOYSTICK_AXES_COUNT == 0 && JOYSTICK_BUTTON_COUNT == 0 #error Need at least one axis or button for joystick #endif -const USB_Descriptor_HIDReport_Datatype_t PROGMEM JoystickReport[] = -{ - HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */ - HID_RI_USAGE(8, 0x04), /* Joystick */ - HID_RI_COLLECTION(8, 0x01), /* Application */ - HID_RI_COLLECTION(8, 0x00), /* Physical */ - HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */ - #if JOYSTICK_AXES_COUNT >= 1 - HID_RI_USAGE(8, 0x30), // USAGE (X) - #endif - #if JOYSTICK_AXES_COUNT >= 2 - HID_RI_USAGE(8, 0x31), // USAGE (Y) - #endif - #if JOYSTICK_AXES_COUNT >= 3 - HID_RI_USAGE(8, 0x32), // USAGE (Z) - #endif - #if JOYSTICK_AXES_COUNT >= 4 - HID_RI_USAGE(8, 0x33), // USAGE (RX) - #endif - #if JOYSTICK_AXES_COUNT >= 5 - HID_RI_USAGE(8, 0x34), // USAGE (RY) - #endif - #if JOYSTICK_AXES_COUNT >= 6 - HID_RI_USAGE(8, 0x35), // USAGE (RZ) - #endif - #if JOYSTICK_AXES_COUNT >= 1 - HID_RI_LOGICAL_MINIMUM(8, -127), - HID_RI_LOGICAL_MAXIMUM(8, 127), - HID_RI_REPORT_COUNT(8, JOYSTICK_AXES_COUNT), - HID_RI_REPORT_SIZE(8, 0x08), - HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), - #endif - - #if JOYSTICK_BUTTON_COUNT >= 1 - HID_RI_USAGE_PAGE(8, 0x09), /* Button */ - HID_RI_USAGE_MINIMUM(8, 0x01), /* Button 1 */ - HID_RI_USAGE_MAXIMUM(8, JOYSTICK_BUTTON_COUNT), /* Button max */ - HID_RI_LOGICAL_MINIMUM(8, 0x00), - HID_RI_LOGICAL_MAXIMUM(8, 0x01), - HID_RI_REPORT_COUNT(8, JOYSTICK_BUTTON_COUNT), - HID_RI_REPORT_SIZE(8, 0x01), - HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), - - #if (JOYSTICK_BUTTON_COUNT % 8) != 0 - HID_RI_REPORT_SIZE(8, 0x01), - HID_RI_REPORT_COUNT(8, 8 - (JOYSTICK_BUTTON_COUNT % 8)), - HID_RI_INPUT(8, HID_IOF_CONSTANT), - #endif - #endif +const USB_Descriptor_HIDReport_Datatype_t PROGMEM JoystickReport[] = { + HID_RI_USAGE_PAGE(8, 0x01), // Generic Desktop + HID_RI_USAGE(8, 0x04), // Joystick + HID_RI_COLLECTION(8, 0x01), // Application + HID_RI_COLLECTION(8, 0x00), // Physical + HID_RI_USAGE_PAGE(8, 0x01), // Generic Desktop +# if JOYSTICK_AXES_COUNT >= 1 + HID_RI_USAGE(8, 0x30), // X +# endif +# if JOYSTICK_AXES_COUNT >= 2 + HID_RI_USAGE(8, 0x31), // Y +# endif +# if JOYSTICK_AXES_COUNT >= 3 + HID_RI_USAGE(8, 0x32), // Z +# endif +# if JOYSTICK_AXES_COUNT >= 4 + HID_RI_USAGE(8, 0x33), // Rx +# endif +# if JOYSTICK_AXES_COUNT >= 5 + HID_RI_USAGE(8, 0x34), // Ry +# endif +# if JOYSTICK_AXES_COUNT >= 6 + HID_RI_USAGE(8, 0x35), // Rz +# endif +# if JOYSTICK_AXES_COUNT >= 1 + HID_RI_LOGICAL_MINIMUM(8, -127), + HID_RI_LOGICAL_MAXIMUM(8, 127), + HID_RI_REPORT_COUNT(8, JOYSTICK_AXES_COUNT), + HID_RI_REPORT_SIZE(8, 0x08), + HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), +# endif + +# if JOYSTICK_BUTTON_COUNT >= 1 + HID_RI_USAGE_PAGE(8, 0x09), // Button + HID_RI_USAGE_MINIMUM(8, 0x01), + HID_RI_USAGE_MAXIMUM(8, JOYSTICK_BUTTON_COUNT), + HID_RI_LOGICAL_MINIMUM(8, 0x00), + HID_RI_LOGICAL_MAXIMUM(8, 0x01), + HID_RI_REPORT_COUNT(8, JOYSTICK_BUTTON_COUNT), + HID_RI_REPORT_SIZE(8, 0x01), + HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), + +# if (JOYSTICK_BUTTON_COUNT % 8) != 0 + HID_RI_REPORT_COUNT(8, 8 - (JOYSTICK_BUTTON_COUNT % 8)), + HID_RI_REPORT_SIZE(8, 0x01), + HID_RI_INPUT(8, HID_IOF_CONSTANT), +# endif +# endif HID_RI_END_COLLECTION(0), - HID_RI_END_COLLECTION(0), + HID_RI_END_COLLECTION(0) }; #endif From 34bedc3787b7d9a929f9a65511f1405f884a23a6 Mon Sep 17 00:00:00 2001 From: a-chol Date: Sun, 22 Mar 2020 11:09:41 +0100 Subject: [PATCH 11/22] Update tmk_core/protocol/usb_descriptor.c Co-Authored-By: Ryan --- tmk_core/protocol/usb_descriptor.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tmk_core/protocol/usb_descriptor.c b/tmk_core/protocol/usb_descriptor.c index 1dbe1c024166..207a8ced61c5 100644 --- a/tmk_core/protocol/usb_descriptor.c +++ b/tmk_core/protocol/usb_descriptor.c @@ -279,9 +279,9 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM ConsoleReport[] = { #endif #ifdef JOYSTICK_ENABLE -#if JOYSTICK_AXES_COUNT == 0 && JOYSTICK_BUTTON_COUNT == 0 - #error Need at least one axis or button for joystick -#endif +# if JOYSTICK_AXES_COUNT == 0 && JOYSTICK_BUTTON_COUNT == 0 +# error Need at least one axis or button for joystick +# endif const USB_Descriptor_HIDReport_Datatype_t PROGMEM JoystickReport[] = { HID_RI_USAGE_PAGE(8, 0x01), // Generic Desktop HID_RI_USAGE(8, 0x04), // Joystick From def06b49762e45423e2ccb1c109879324139c337 Mon Sep 17 00:00:00 2001 From: a-chol Date: Sun, 29 Mar 2020 15:43:19 +0200 Subject: [PATCH 12/22] Add support for joystick adc reading for stm32 MCUs. Fix joystick hid report sending for chibios --- common_features.mk | 4 +--- quantum/joystick.h | 6 +++--- quantum/process_keycode/process_joystick.c | 6 ++---- tmk_core/protocol/chibios/usb_main.c | 10 +++++++++- 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/common_features.mk b/common_features.mk index 9180b4f7cb3a..461b9effd67a 100644 --- a/common_features.mk +++ b/common_features.mk @@ -516,7 +516,5 @@ ifeq ($(strip $(JOYSTICK_ENABLE)), yes) OPT_DEFS += -DJOYSTICK_ENABLE SRC += $(QUANTUM_DIR)/process_keycode/process_joystick.c SRC += $(QUANTUM_DIR)/joystick.c - ifeq ($(PLATFORM),AVR) - SRC += drivers/avr/analog.c - endif + SRC += analog.c endif diff --git a/quantum/joystick.h b/quantum/joystick.h index 26d159aa1246..37a18df570cc 100644 --- a/quantum/joystick.h +++ b/quantum/joystick.h @@ -25,9 +25,9 @@ { OUTPUT_PIN, INPUT_PIN, GROUND_PIN, LOW, REST, HIGH } typedef struct { - uint8_t output_pin; - uint8_t input_pin; - uint8_t ground_pin; + uint32_t output_pin; + uint32_t input_pin; + uint32_t ground_pin; // the AVR ADC offers 10 bit precision, with significant bits on the higher part uint16_t min_digit; diff --git a/quantum/process_keycode/process_joystick.c b/quantum/process_keycode/process_joystick.c index f26b6c6f3f9c..6cd289c18e5d 100644 --- a/quantum/process_keycode/process_joystick.c +++ b/quantum/process_keycode/process_joystick.c @@ -1,9 +1,7 @@ #include "joystick.h" #include "process_joystick.h" -#ifdef __AVR__ -# include "analog.h" -#endif +#include "analog.h" #include #include @@ -107,7 +105,7 @@ bool process_joystick_analogread_quantum() { wait_us(10); -# ifdef __AVR__ +# if defined(__AVR__) || defined(PROTOCOL_CHIBIOS) int16_t axis_val = analogReadPin(joystick_axes[axis_index].input_pin); # else // default to resting position diff --git a/tmk_core/protocol/chibios/usb_main.c b/tmk_core/protocol/chibios/usb_main.c index 7d4cf82ac0ca..ea25ce0a8cd6 100644 --- a/tmk_core/protocol/chibios/usb_main.c +++ b/tmk_core/protocol/chibios/usb_main.c @@ -935,7 +935,15 @@ void send_joystick_packet(joystick_t *joystick) { # endif // JOYSTICK_BUTTON_COUNT>0 }; - chnWrite(&drivers.joystick_driver.driver, (uint8_t *)&rep, sizeof(rep)); + // chnWrite(&drivers.joystick_driver.driver, (uint8_t *)&rep, sizeof(rep)); + osalSysLock(); + if (usbGetDriverStateI(&USB_DRIVER) != USB_ACTIVE) { + osalSysUnlock(); + return; + } + + usbStartTransmitI(&USB_DRIVER, JOYSTICK_IN_EPNUM, (uint8_t *)&rep, sizeof(joystick_report_t)); + osalSysUnlock(); } #endif From 887e96cbb214eb04240f8abc59481a79e63c6c32 Mon Sep 17 00:00:00 2001 From: a-chol Date: Mon, 30 Mar 2020 00:51:43 +0200 Subject: [PATCH 13/22] Fix HID joystick report sending for ChibiOS. Add one analog axis to the onekey:joystick keymap. Fix pin state save and restore during joystick analog read for STM32 MCUs. --- .../onekey/keymaps/joystick/config.h | 2 +- .../onekey/keymaps/joystick/keymap.c | 6 ++++ quantum/process_keycode/process_joystick.c | 32 +++++++++++++++---- 3 files changed, 33 insertions(+), 7 deletions(-) diff --git a/keyboards/handwired/onekey/keymaps/joystick/config.h b/keyboards/handwired/onekey/keymaps/joystick/config.h index 2e2aa9433d0c..c43f204802b8 100644 --- a/keyboards/handwired/onekey/keymaps/joystick/config.h +++ b/keyboards/handwired/onekey/keymaps/joystick/config.h @@ -1,3 +1,3 @@ #pragma once -#define JOYSTICK_AXES_COUNT 0 +#define JOYSTICK_AXES_COUNT 1 #define JOYSTICK_BUTTON_COUNT 1 diff --git a/keyboards/handwired/onekey/keymaps/joystick/keymap.c b/keyboards/handwired/onekey/keymaps/joystick/keymap.c index 95acf7c85081..353d31e2835e 100644 --- a/keyboards/handwired/onekey/keymaps/joystick/keymap.c +++ b/keyboards/handwired/onekey/keymaps/joystick/keymap.c @@ -1,5 +1,11 @@ #include QMK_KEYBOARD_H +#include "joystick.h" + const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { LAYOUT( JS_BUTTON0 ) }; +//joystick config +joystick_config_t joystick_axes[JOYSTICK_AXES_COUNT] = { + [0] = JOYSTICK_AXIS_IN(A0, 0, 512, 1024) +}; \ No newline at end of file diff --git a/quantum/process_keycode/process_joystick.c b/quantum/process_keycode/process_joystick.c index 6cd289c18e5d..ef9d43aa4128 100644 --- a/quantum/process_keycode/process_joystick.c +++ b/quantum/process_keycode/process_joystick.c @@ -17,6 +17,7 @@ bool process_joystick(uint16_t keycode, keyrecord_t *record) { return true; } +__attribute__((weak)) void joystick_task(void) { if (process_joystick_analogread() && (joystick_status.status & JS_UPDATED)) { send_joystick_packet(&joystick_status); @@ -40,20 +41,39 @@ bool process_joystick_buttons(uint16_t keycode, keyrecord_t *record) { return true; } -uint8_t savePinState(uint8_t pin) { +uint16_t savePinState(uint32_t pin) { #ifdef __AVR__ uint8_t pinNumber = pin & 0xF; return ((PORTx_ADDRESS(pin) >> pinNumber) & 0x1) << 1 | ((DDRx_ADDRESS(pin) >> pinNumber) & 0x1); +#elif defined(PROTOCOL_CHIBIOS) + /* + The pin configuration is backed up in the following format : + bit 15 9 8 7 6 5 4 3 2 1 0 + |unused|ODR|IDR|PUPDR|OSPEEDR|OTYPER|MODER| + */ + return (( PAL_PORT(pin)->MODER >> (2*PAL_PAD(pin))) & 0x3) + | (((PAL_PORT(pin)->OTYPER >> (1*PAL_PAD(pin))) & 0x1) << 2) + | (((PAL_PORT(pin)->OSPEEDR >> (2*PAL_PAD(pin))) & 0x3) << 3) + | (((PAL_PORT(pin)->PUPDR >> (2*PAL_PAD(pin))) & 0x3) << 5) + | (((PAL_PORT(pin)->IDR >> (1*PAL_PAD(pin))) & 0x1) << 7) + | (((PAL_PORT(pin)->ODR >> (1*PAL_PAD(pin))) & 0x1) << 8); #else return 0; #endif } -void restorePinState(uint8_t pin, uint8_t restoreState) { +void restorePinState(uint32_t pin, uint16_t restoreState) { #ifdef __AVR__ uint8_t pinNumber = pin & 0xF; PORTx_ADDRESS(pin) = (PORTx_ADDRESS(pin) & ~_BV(pinNumber)) | (((restoreState >> 1) & 0x1) << pinNumber); DDRx_ADDRESS(pin) = (DDRx_ADDRESS(pin) & ~_BV(pinNumber)) | ((restoreState & 0x1) << pinNumber); +#elif defined(PROTOCOL_CHIBIOS) + PAL_PORT(pin)->MODER = (PAL_PORT(pin)->MODER & ~(0x3<< (2*PAL_PAD(pin)))) | (restoreState & 0x3) << (2*PAL_PAD(pin)); + PAL_PORT(pin)->OTYPER = (PAL_PORT(pin)->OTYPER & ~(0x1<< (1*PAL_PAD(pin)))) | ((restoreState>>2) & 0x1) << (1*PAL_PAD(pin)); + PAL_PORT(pin)->OSPEEDR= (PAL_PORT(pin)->OSPEEDR & ~(0x3<< (2*PAL_PAD(pin)))) | ((restoreState>>3) & 0x3) << (2*PAL_PAD(pin)); + PAL_PORT(pin)->PUPDR = (PAL_PORT(pin)->PUPDR & ~(0x3<< (2*PAL_PAD(pin)))) | ((restoreState>>5) & 0x3) << (2*PAL_PAD(pin)); + PAL_PORT(pin)->IDR = (PAL_PORT(pin)->IDR & ~(0x1<< (1*PAL_PAD(pin)))) | ((restoreState>>7) & 0x1) << (1*PAL_PAD(pin)); + PAL_PORT(pin)->ODR = (PAL_PORT(pin)->ODR & ~(0x1<< (1*PAL_PAD(pin)))) | ((restoreState>>8) & 0x1) << (1*PAL_PAD(pin)); #else return; #endif @@ -69,7 +89,7 @@ bool process_joystick_analogread_quantum() { } // save previous input pin status as well - uint8_t inputSavedState = savePinState(joystick_axes[axis_index].input_pin); + uint16_t inputSavedState = savePinState(joystick_axes[axis_index].input_pin); // disable pull-up resistor writePinLow(joystick_axes[axis_index].input_pin); @@ -81,7 +101,7 @@ bool process_joystick_analogread_quantum() { wait_us(10); // save and apply output pin status - uint8_t outputSavedState = 0; + uint16_t outputSavedState = 0; if (joystick_axes[axis_index].output_pin != JS_VIRTUAL_AXIS) { // save previous output pin status outputSavedState = savePinState(joystick_axes[axis_index].output_pin); @@ -90,7 +110,7 @@ bool process_joystick_analogread_quantum() { writePinHigh(joystick_axes[axis_index].output_pin); } - uint8_t groundSavedState = 0; + uint16_t groundSavedState = 0; if (joystick_axes[axis_index].ground_pin != JS_VIRTUAL_AXIS) { // save previous output pin status groundSavedState = savePinState(joystick_axes[axis_index].ground_pin); @@ -126,7 +146,7 @@ bool process_joystick_analogread_quantum() { //clamp the result in the valid range ranged_val = ranged_val<-127 ? -127 : ranged_val; ranged_val = ranged_val>127 ? 127 : ranged_val; - + if (ranged_val != joystick_status.axes[axis_index]) { joystick_status.axes[axis_index] = ranged_val; joystick_status.status |= JS_UPDATED; From c447c4ffd5301793c91ac717d3f6318f7a17d8cf Mon Sep 17 00:00:00 2001 From: a-chol Date: Mon, 30 Mar 2020 11:17:14 +0200 Subject: [PATCH 14/22] Update tmk_core/protocol/chibios/usb_main.c Co-Authored-By: Ryan --- tmk_core/protocol/chibios/usb_main.c | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/tmk_core/protocol/chibios/usb_main.c b/tmk_core/protocol/chibios/usb_main.c index ea25ce0a8cd6..cd34fd289100 100644 --- a/tmk_core/protocol/chibios/usb_main.c +++ b/tmk_core/protocol/chibios/usb_main.c @@ -891,45 +891,37 @@ void virtser_task(void) { void send_joystick_packet(joystick_t *joystick) { joystick_report_t rep = { # if JOYSTICK_AXES_COUNT > 0 - .axes = {joystick->axes[0] + .axes = {joystick->axes[0], # if JOYSTICK_AXES_COUNT >= 2 - , - joystick->axes[1] + joystick->axes[1], # endif # if JOYSTICK_AXES_COUNT >= 3 - , - joystick->axes[2] + joystick->axes[2], # endif # if JOYSTICK_AXES_COUNT >= 4 - , - joystick->axes[3] + joystick->axes[3], # endif # if JOYSTICK_AXES_COUNT >= 5 - , - joystick->axes[4] + joystick->axes[4], # endif # if JOYSTICK_AXES_COUNT >= 6 - , - joystick->axes[5] + joystick->axes[5], # endif }, # endif // JOYSTICK_AXES_COUNT>0 # if JOYSTICK_BUTTON_COUNT > 0 - .buttons = {joystick->buttons[0] + .buttons = {joystick->buttons[0], # if JOYSTICK_BUTTON_COUNT > 8 - , - joystick->buttons[1] + joystick->buttons[1], # endif # if JOYSTICK_BUTTON_COUNT > 16 - , - joystick->buttons[2] + joystick->buttons[2], # endif # if JOYSTICK_BUTTON_COUNT > 24 - , - joystick->buttons[3] + joystick->buttons[3], # endif } # endif // JOYSTICK_BUTTON_COUNT>0 From 0ce015d0c963d825ab6f613a7c18fe687cbeeece Mon Sep 17 00:00:00 2001 From: a-chol Date: Mon, 30 Mar 2020 11:17:26 +0200 Subject: [PATCH 15/22] Update tmk_core/protocol/lufa/lufa.c Co-Authored-By: Ryan --- tmk_core/protocol/lufa/lufa.c | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/tmk_core/protocol/lufa/lufa.c b/tmk_core/protocol/lufa/lufa.c index c11eb3173896..3660aaee396c 100644 --- a/tmk_core/protocol/lufa/lufa.c +++ b/tmk_core/protocol/lufa/lufa.c @@ -276,45 +276,37 @@ void send_joystick_packet(joystick_t *joystick) { joystick_report_t r = { # if JOYSTICK_AXES_COUNT > 0 - .axes = {joystick->axes[0] + .axes = {joystick->axes[0], # if JOYSTICK_AXES_COUNT >= 2 - , - joystick->axes[1] + joystick->axes[1], # endif # if JOYSTICK_AXES_COUNT >= 3 - , - joystick->axes[2] + joystick->axes[2], # endif # if JOYSTICK_AXES_COUNT >= 4 - , - joystick->axes[3] + joystick->axes[3], # endif # if JOYSTICK_AXES_COUNT >= 5 - , - joystick->axes[4] + joystick->axes[4], # endif # if JOYSTICK_AXES_COUNT >= 6 - , - joystick->axes[5] + joystick->axes[5], # endif }, # endif // JOYSTICK_AXES_COUNT>0 # if JOYSTICK_BUTTON_COUNT > 0 - .buttons = {joystick->buttons[0] + .buttons = {joystick->buttons[0], # if JOYSTICK_BUTTON_COUNT > 8 - , - joystick->buttons[1] + joystick->buttons[1], # endif # if JOYSTICK_BUTTON_COUNT > 16 - , - joystick->buttons[2] + joystick->buttons[2], # endif # if JOYSTICK_BUTTON_COUNT > 24 - , - joystick->buttons[3] + joystick->buttons[3], # endif } # endif // JOYSTICK_BUTTON_COUNT>0 From 476fce8a32b4e87bb8b327ef82c7bb4b6e58465c Mon Sep 17 00:00:00 2001 From: a-chol Date: Mon, 30 Mar 2020 11:19:23 +0200 Subject: [PATCH 16/22] Add missing mcuconf.h and halconf.h to onekey:joystick keymap. Add suggested fixes from PR. --- docs/feature_joystick.md | 8 +- .../onekey/keymaps/joystick/halconf.h | 524 ++++++++++++++++++ .../onekey/keymaps/joystick/mcuconf.h | 273 +++++++++ quantum/joystick.h | 6 +- quantum/process_keycode/process_joystick.c | 16 +- tmk_core/protocol/usb_descriptor.c | 1 + 6 files changed, 813 insertions(+), 15 deletions(-) create mode 100644 keyboards/handwired/onekey/keymaps/joystick/halconf.h create mode 100644 keyboards/handwired/onekey/keymaps/joystick/mcuconf.h diff --git a/docs/feature_joystick.md b/docs/feature_joystick.md index 8aed87b1163c..70c2338d5a13 100644 --- a/docs/feature_joystick.md +++ b/docs/feature_joystick.md @@ -1,8 +1,8 @@ -## Joystick HID Device +## Joystick -The keyboard can be made to be recognized as a joystick HID device by the Operating System. +The keyboard can be made to be recognized as a joystick HID device by the operating system. -This is enabled by adding the following to `rules.mk` +This is enabled by adding the following to `rules.mk`: ```makefile JOYSTICK_ENABLE = yes @@ -10,7 +10,7 @@ JOYSTICK_ENABLE = yes !> Joystick support is not currently available on V-USB devices. -The joystick feature provides two services : +The joystick feature provides two services: * reading an analog input device * sending gamepad HID reports diff --git a/keyboards/handwired/onekey/keymaps/joystick/halconf.h b/keyboards/handwired/onekey/keymaps/joystick/halconf.h new file mode 100644 index 000000000000..0a8c978676a1 --- /dev/null +++ b/keyboards/handwired/onekey/keymaps/joystick/halconf.h @@ -0,0 +1,524 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file templates/halconf.h + * @brief HAL configuration header. + * @details HAL configuration file, this file allows to enable or disable the + * various device drivers from your application. You may also use + * this file in order to override the device drivers default settings. + * + * @addtogroup HAL_CONF + * @{ + */ + +#ifndef HALCONF_H +# define HALCONF_H + +# define _CHIBIOS_HAL_CONF_ +# define _CHIBIOS_HAL_CONF_VER_7_0_ + +# include "mcuconf.h" + +/** + * @brief Enables the PAL subsystem. + */ +# if !defined(HAL_USE_PAL) || defined(__DOXYGEN__) +# define HAL_USE_PAL TRUE +# endif + +/** + * @brief Enables the ADC subsystem. + */ +# if !defined(HAL_USE_ADC) || defined(__DOXYGEN__) +# define HAL_USE_ADC TRUE +# endif + +/** + * @brief Enables the CAN subsystem. + */ +# if !defined(HAL_USE_CAN) || defined(__DOXYGEN__) +# define HAL_USE_CAN FALSE +# endif + +/** + * @brief Enables the cryptographic subsystem. + */ +# if !defined(HAL_USE_CRY) || defined(__DOXYGEN__) +# define HAL_USE_CRY FALSE +# endif + +/** + * @brief Enables the DAC subsystem. + */ +# if !defined(HAL_USE_DAC) || defined(__DOXYGEN__) +# define HAL_USE_DAC TRUE +# endif + +/** + * @brief Enables the GPT subsystem. + */ +# if !defined(HAL_USE_GPT) || defined(__DOXYGEN__) +# define HAL_USE_GPT TRUE +# endif + +/** + * @brief Enables the I2C subsystem. + */ +# if !defined(HAL_USE_I2C) || defined(__DOXYGEN__) +# define HAL_USE_I2C TRUE +# endif + +/** + * @brief Enables the I2S subsystem. + */ +# if !defined(HAL_USE_I2S) || defined(__DOXYGEN__) +# define HAL_USE_I2S FALSE +# endif + +/** + * @brief Enables the ICU subsystem. + */ +# if !defined(HAL_USE_ICU) || defined(__DOXYGEN__) +# define HAL_USE_ICU FALSE +# endif + +/** + * @brief Enables the MAC subsystem. + */ +# if !defined(HAL_USE_MAC) || defined(__DOXYGEN__) +# define HAL_USE_MAC FALSE +# endif + +/** + * @brief Enables the MMC_SPI subsystem. + */ +# if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__) +# define HAL_USE_MMC_SPI FALSE +# endif + +/** + * @brief Enables the PWM subsystem. + */ +# if !defined(HAL_USE_PWM) || defined(__DOXYGEN__) +# define HAL_USE_PWM TRUE +# endif + +/** + * @brief Enables the RTC subsystem. + */ +# if !defined(HAL_USE_RTC) || defined(__DOXYGEN__) +# define HAL_USE_RTC FALSE +# endif + +/** + * @brief Enables the SDC subsystem. + */ +# if !defined(HAL_USE_SDC) || defined(__DOXYGEN__) +# define HAL_USE_SDC FALSE +# endif + +/** + * @brief Enables the SERIAL subsystem. + */ +# if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__) +# define HAL_USE_SERIAL FALSE +# endif + +/** + * @brief Enables the SERIAL over USB subsystem. + */ +# if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__) +# define HAL_USE_SERIAL_USB TRUE +# endif + +/** + * @brief Enables the SIO subsystem. + */ +# if !defined(HAL_USE_SIO) || defined(__DOXYGEN__) +# define HAL_USE_SIO FALSE +# endif + +/** + * @brief Enables the SPI subsystem. + */ +# if !defined(HAL_USE_SPI) || defined(__DOXYGEN__) +# define HAL_USE_SPI FALSE +# endif + +/** + * @brief Enables the TRNG subsystem. + */ +# if !defined(HAL_USE_TRNG) || defined(__DOXYGEN__) +# define HAL_USE_TRNG FALSE +# endif + +/** + * @brief Enables the UART subsystem. + */ +# if !defined(HAL_USE_UART) || defined(__DOXYGEN__) +# define HAL_USE_UART FALSE +# endif + +/** + * @brief Enables the USB subsystem. + */ +# if !defined(HAL_USE_USB) || defined(__DOXYGEN__) +# define HAL_USE_USB TRUE +# endif + +/** + * @brief Enables the WDG subsystem. + */ +# if !defined(HAL_USE_WDG) || defined(__DOXYGEN__) +# define HAL_USE_WDG FALSE +# endif + +/** + * @brief Enables the WSPI subsystem. + */ +# if !defined(HAL_USE_WSPI) || defined(__DOXYGEN__) +# define HAL_USE_WSPI FALSE +# endif + +/*===========================================================================*/ +/* PAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +# if !defined(PAL_USE_CALLBACKS) || defined(__DOXYGEN__) +# define PAL_USE_CALLBACKS FALSE +# endif + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +# if !defined(PAL_USE_WAIT) || defined(__DOXYGEN__) +# define PAL_USE_WAIT FALSE +# endif + +/*===========================================================================*/ +/* ADC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +# if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__) +# define ADC_USE_WAIT TRUE +# endif + +/** + * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +# if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +# define ADC_USE_MUTUAL_EXCLUSION TRUE +# endif + +/*===========================================================================*/ +/* CAN driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Sleep mode related APIs inclusion switch. + */ +# if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__) +# define CAN_USE_SLEEP_MODE TRUE +# endif + +/** + * @brief Enforces the driver to use direct callbacks rather than OSAL events. + */ +# if !defined(CAN_ENFORCE_USE_CALLBACKS) || defined(__DOXYGEN__) +# define CAN_ENFORCE_USE_CALLBACKS FALSE +# endif + +/*===========================================================================*/ +/* CRY driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the SW fall-back of the cryptographic driver. + * @details When enabled, this option, activates a fall-back software + * implementation for algorithms not supported by the underlying + * hardware. + * @note Fall-back implementations may not be present for all algorithms. + */ +# if !defined(HAL_CRY_USE_FALLBACK) || defined(__DOXYGEN__) +# define HAL_CRY_USE_FALLBACK FALSE +# endif + +/** + * @brief Makes the driver forcibly use the fall-back implementations. + */ +# if !defined(HAL_CRY_ENFORCE_FALLBACK) || defined(__DOXYGEN__) +# define HAL_CRY_ENFORCE_FALLBACK FALSE +# endif + +/*===========================================================================*/ +/* DAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +# if !defined(DAC_USE_WAIT) || defined(__DOXYGEN__) +# define DAC_USE_WAIT TRUE +# endif + +/** + * @brief Enables the @p dacAcquireBus() and @p dacReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +# if !defined(DAC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +# define DAC_USE_MUTUAL_EXCLUSION TRUE +# endif + +/*===========================================================================*/ +/* I2C driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the mutual exclusion APIs on the I2C bus. + */ +# if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +# define I2C_USE_MUTUAL_EXCLUSION TRUE +# endif + +/*===========================================================================*/ +/* MAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the zero-copy API. + */ +# if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__) +# define MAC_USE_ZERO_COPY FALSE +# endif + +/** + * @brief Enables an event sources for incoming packets. + */ +# if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__) +# define MAC_USE_EVENTS TRUE +# endif + +/*===========================================================================*/ +/* MMC_SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + * This option is recommended also if the SPI driver does not + * use a DMA channel and heavily loads the CPU. + */ +# if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__) +# define MMC_NICE_WAITING TRUE +# endif + +/*===========================================================================*/ +/* SDC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Number of initialization attempts before rejecting the card. + * @note Attempts are performed at 10mS intervals. + */ +# if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__) +# define SDC_INIT_RETRY 100 +# endif + +/** + * @brief Include support for MMC cards. + * @note MMC support is not yet implemented so this option must be kept + * at @p FALSE. + */ +# if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__) +# define SDC_MMC_SUPPORT FALSE +# endif + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + */ +# if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__) +# define SDC_NICE_WAITING TRUE +# endif + +/** + * @brief OCR initialization constant for V20 cards. + */ +# if !defined(SDC_INIT_OCR_V20) || defined(__DOXYGEN__) +# define SDC_INIT_OCR_V20 0x50FF8000U +# endif + +/** + * @brief OCR initialization constant for non-V20 cards. + */ +# if !defined(SDC_INIT_OCR) || defined(__DOXYGEN__) +# define SDC_INIT_OCR 0x80100000U +# endif + +/*===========================================================================*/ +/* SERIAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Default bit rate. + * @details Configuration parameter, this is the baud rate selected for the + * default configuration. + */ +# if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__) +# define SERIAL_DEFAULT_BITRATE 38400 +# endif + +/** + * @brief Serial buffers size. + * @details Configuration parameter, you can change the depth of the queue + * buffers depending on the requirements of your application. + * @note The default is 16 bytes for both the transmission and receive + * buffers. + */ +# if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__) +# define SERIAL_BUFFERS_SIZE 16 +# endif + +/*===========================================================================*/ +/* SERIAL_USB driver related setting. */ +/*===========================================================================*/ + +/** + * @brief Serial over USB buffers size. + * @details Configuration parameter, the buffer size must be a multiple of + * the USB data endpoint maximum packet size. + * @note The default is 256 bytes for both the transmission and receive + * buffers. + */ +# if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__) +# define SERIAL_USB_BUFFERS_SIZE 1 +# endif + +/** + * @brief Serial over USB number of buffers. + * @note The default is 2 buffers. + */ +# if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__) +# define SERIAL_USB_BUFFERS_NUMBER 2 +# endif + +/*===========================================================================*/ +/* SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +# if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__) +# define SPI_USE_WAIT TRUE +# endif + +/** + * @brief Enables circular transfers APIs. + * @note Disabling this option saves both code and data space. + */ +# if !defined(SPI_USE_CIRCULAR) || defined(__DOXYGEN__) +# define SPI_USE_CIRCULAR FALSE +# endif + +/** + * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +# if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +# define SPI_USE_MUTUAL_EXCLUSION TRUE +# endif + +/** + * @brief Handling method for SPI CS line. + * @note Disabling this option saves both code and data space. + */ +# if !defined(SPI_SELECT_MODE) || defined(__DOXYGEN__) +# define SPI_SELECT_MODE SPI_SELECT_MODE_PAD +# endif + +/*===========================================================================*/ +/* UART driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +# if !defined(UART_USE_WAIT) || defined(__DOXYGEN__) +# define UART_USE_WAIT FALSE +# endif + +/** + * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +# if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +# define UART_USE_MUTUAL_EXCLUSION FALSE +# endif + +/*===========================================================================*/ +/* USB driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +# if !defined(USB_USE_WAIT) || defined(__DOXYGEN__) +# define USB_USE_WAIT TRUE +# endif + +/*===========================================================================*/ +/* WSPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +# if !defined(WSPI_USE_WAIT) || defined(__DOXYGEN__) +# define WSPI_USE_WAIT TRUE +# endif + +/** + * @brief Enables the @p wspiAcquireBus() and @p wspiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +# if !defined(WSPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +# define WSPI_USE_MUTUAL_EXCLUSION TRUE +# endif + +#endif /* HALCONF_H */ + +/** @} */ diff --git a/keyboards/handwired/onekey/keymaps/joystick/mcuconf.h b/keyboards/handwired/onekey/keymaps/joystick/mcuconf.h new file mode 100644 index 000000000000..dbe98b6d87e1 --- /dev/null +++ b/keyboards/handwired/onekey/keymaps/joystick/mcuconf.h @@ -0,0 +1,273 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#ifndef MCUCONF_H +#define MCUCONF_H + +/* + * STM32F3xx drivers configuration. + * The following settings override the default settings present in + * the various device driver implementation headers. + * Note that the settings for each driver only have effect if the whole + * driver is enabled in halconf.h. + * + * IRQ priorities: + * 15...0 Lowest...Highest. + * + * DMA priorities: + * 0...3 Lowest...Highest. + */ + +#define STM32F3xx_MCUCONF +#define STM32F303_MCUCONF + +/* + * HAL driver system settings. + */ +#define STM32_NO_INIT FALSE +#define STM32_PVD_ENABLE FALSE +#define STM32_PLS STM32_PLS_LEV0 +#define STM32_HSI_ENABLED TRUE +#define STM32_LSI_ENABLED TRUE +#define STM32_HSE_ENABLED TRUE +#define STM32_LSE_ENABLED FALSE +#define STM32_SW STM32_SW_PLL +#define STM32_PLLSRC STM32_PLLSRC_HSE +#define STM32_PREDIV_VALUE 1 +#define STM32_PLLMUL_VALUE 9 +#define STM32_HPRE STM32_HPRE_DIV1 +#define STM32_PPRE1 STM32_PPRE1_DIV2 +#define STM32_PPRE2 STM32_PPRE2_DIV2 +#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK +#define STM32_ADC12PRES STM32_ADC12PRES_DIV1 +#define STM32_ADC34PRES STM32_ADC34PRES_DIV1 +#define STM32_USART1SW STM32_USART1SW_PCLK +#define STM32_USART2SW STM32_USART2SW_PCLK +#define STM32_USART3SW STM32_USART3SW_PCLK +#define STM32_UART4SW STM32_UART4SW_PCLK +#define STM32_UART5SW STM32_UART5SW_PCLK +#define STM32_I2C1SW STM32_I2C1SW_SYSCLK +#define STM32_I2C2SW STM32_I2C2SW_SYSCLK +#define STM32_TIM1SW STM32_TIM1SW_PCLK2 +#define STM32_TIM8SW STM32_TIM8SW_PCLK2 +#define STM32_RTCSEL STM32_RTCSEL_LSI +#define STM32_USB_CLOCK_REQUIRED TRUE +#define STM32_USBPRE STM32_USBPRE_DIV1P5 + +/* + * IRQ system settings. + */ +#define STM32_IRQ_EXTI0_PRIORITY 6 +#define STM32_IRQ_EXTI1_PRIORITY 6 +#define STM32_IRQ_EXTI2_PRIORITY 6 +#define STM32_IRQ_EXTI3_PRIORITY 6 +#define STM32_IRQ_EXTI4_PRIORITY 6 +#define STM32_IRQ_EXTI5_9_PRIORITY 6 +#define STM32_IRQ_EXTI10_15_PRIORITY 6 +#define STM32_IRQ_EXTI16_PRIORITY 6 +#define STM32_IRQ_EXTI17_PRIORITY 15 +#define STM32_IRQ_EXTI18_PRIORITY 6 +#define STM32_IRQ_EXTI19_PRIORITY 15 +#define STM32_IRQ_EXTI20_PRIORITY 15 +#define STM32_IRQ_EXTI21_22_29_PRIORITY 6 +#define STM32_IRQ_EXTI30_32_PRIORITY 6 +#define STM32_IRQ_EXTI33_PRIORITY 6 +#define STM32_IRQ_TIM1_BRK_TIM15_PRIORITY 7 +#define STM32_IRQ_TIM1_UP_TIM16_PRIORITY 7 +#define STM32_IRQ_TIM1_TRGCO_TIM17_PRIORITY 7 +#define STM32_IRQ_TIM1_CC_PRIORITY 7 + +/* + * ADC driver system settings. + */ +#define STM32_ADC_DUAL_MODE FALSE +#define STM32_ADC_COMPACT_SAMPLES FALSE +#define STM32_ADC_USE_ADC1 TRUE +#define STM32_ADC_USE_ADC2 FALSE +#define STM32_ADC_USE_ADC3 FALSE +#define STM32_ADC_USE_ADC4 FALSE +#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) +#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) +#define STM32_ADC_ADC4_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#define STM32_ADC_ADC2_DMA_PRIORITY 2 +#define STM32_ADC_ADC3_DMA_PRIORITY 2 +#define STM32_ADC_ADC4_DMA_PRIORITY 2 +#define STM32_ADC_ADC12_IRQ_PRIORITY 5 +#define STM32_ADC_ADC3_IRQ_PRIORITY 5 +#define STM32_ADC_ADC4_IRQ_PRIORITY 5 +#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 5 +#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 5 +#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 5 +#define STM32_ADC_ADC4_DMA_IRQ_PRIORITY 5 +#define STM32_ADC_ADC12_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV1 +#define STM32_ADC_ADC34_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV1 + +/* + * CAN driver system settings. + */ +#define STM32_CAN_USE_CAN1 FALSE +#define STM32_CAN_CAN1_IRQ_PRIORITY 11 + +/* + * DAC driver system settings. + */ +#define STM32_DAC_DUAL_MODE FALSE +#define STM32_DAC_USE_DAC1_CH1 TRUE +#define STM32_DAC_USE_DAC1_CH2 TRUE +#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2 + +/* + * GPT driver system settings. + */ +#define STM32_GPT_USE_TIM1 FALSE +#define STM32_GPT_USE_TIM2 FALSE +#define STM32_GPT_USE_TIM3 FALSE +#define STM32_GPT_USE_TIM4 FALSE +#define STM32_GPT_USE_TIM6 TRUE +#define STM32_GPT_USE_TIM7 TRUE +#define STM32_GPT_USE_TIM8 TRUE +#define STM32_GPT_USE_TIM15 FALSE +#define STM32_GPT_USE_TIM16 FALSE +#define STM32_GPT_USE_TIM17 FALSE +#define STM32_GPT_TIM1_IRQ_PRIORITY 7 +#define STM32_GPT_TIM2_IRQ_PRIORITY 7 +#define STM32_GPT_TIM3_IRQ_PRIORITY 7 +#define STM32_GPT_TIM4_IRQ_PRIORITY 7 +#define STM32_GPT_TIM6_IRQ_PRIORITY 7 +#define STM32_GPT_TIM7_IRQ_PRIORITY 7 +#define STM32_GPT_TIM8_IRQ_PRIORITY 7 + +/* + * I2C driver system settings. + */ +#define STM32_I2C_USE_I2C1 TRUE +#define STM32_I2C_USE_I2C2 FALSE +#define STM32_I2C_BUSY_TIMEOUT 50 +#define STM32_I2C_I2C1_IRQ_PRIORITY 10 +#define STM32_I2C_I2C2_IRQ_PRIORITY 10 +#define STM32_I2C_USE_DMA TRUE +#define STM32_I2C_I2C1_DMA_PRIORITY 1 +#define STM32_I2C_I2C2_DMA_PRIORITY 1 +#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") + +/* + * ICU driver system settings. + */ +#define STM32_ICU_USE_TIM1 FALSE +#define STM32_ICU_USE_TIM2 FALSE +#define STM32_ICU_USE_TIM3 FALSE +#define STM32_ICU_USE_TIM4 FALSE +#define STM32_ICU_USE_TIM8 FALSE +#define STM32_ICU_USE_TIM15 FALSE +#define STM32_ICU_TIM1_IRQ_PRIORITY 7 +#define STM32_ICU_TIM2_IRQ_PRIORITY 7 +#define STM32_ICU_TIM3_IRQ_PRIORITY 7 +#define STM32_ICU_TIM4_IRQ_PRIORITY 7 +#define STM32_ICU_TIM8_IRQ_PRIORITY 7 + +/* + * PWM driver system settings. + */ +#define STM32_PWM_USE_ADVANCED FALSE +#define STM32_PWM_USE_TIM1 FALSE +#define STM32_PWM_USE_TIM2 FALSE +#define STM32_PWM_USE_TIM3 TRUE +#define STM32_PWM_USE_TIM4 TRUE +#define STM32_PWM_USE_TIM8 FALSE +#define STM32_PWM_USE_TIM15 FALSE +#define STM32_PWM_USE_TIM16 FALSE +#define STM32_PWM_USE_TIM17 FALSE +#define STM32_PWM_TIM1_IRQ_PRIORITY 7 +#define STM32_PWM_TIM2_IRQ_PRIORITY 7 +#define STM32_PWM_TIM3_IRQ_PRIORITY 7 +#define STM32_PWM_TIM4_IRQ_PRIORITY 7 +#define STM32_PWM_TIM8_IRQ_PRIORITY 7 + +/* + * RTC driver system settings. + */ +#define STM32_RTC_PRESA_VALUE 32 +#define STM32_RTC_PRESS_VALUE 1024 +#define STM32_RTC_CR_INIT 0 +#define STM32_RTC_TAMPCR_INIT 0 + +/* + * SERIAL driver system settings. + */ +#define STM32_SERIAL_USE_USART1 FALSE +#define STM32_SERIAL_USE_USART2 +#define STM32_SERIAL_USE_USART3 FALSE +#define STM32_SERIAL_USE_UART4 FALSE +#define STM32_SERIAL_USE_UART5 FALSE +#define STM32_SERIAL_USART1_PRIORITY 12 +#define STM32_SERIAL_USART2_PRIORITY 12 +#define STM32_SERIAL_USART3_PRIORITY 12 +#define STM32_SERIAL_UART4_PRIORITY 12 +#define STM32_SERIAL_UART5_PRIORITY 12 + +/* + * SPI driver system settings. + */ +#define STM32_SPI_USE_SPI1 FALSE +#define STM32_SPI_USE_SPI2 FALSE +#define STM32_SPI_USE_SPI3 FALSE +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#define STM32_SPI_SPI3_DMA_PRIORITY 1 +#define STM32_SPI_SPI1_IRQ_PRIORITY 10 +#define STM32_SPI_SPI2_IRQ_PRIORITY 10 +#define STM32_SPI_SPI3_IRQ_PRIORITY 10 +#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") + +/* + * ST driver system settings. + */ +#define STM32_ST_IRQ_PRIORITY 8 +#define STM32_ST_USE_TIMER 2 + +/* + * UART driver system settings. + */ +#define STM32_UART_USE_USART1 FALSE +#define STM32_UART_USE_USART2 FALSE +#define STM32_UART_USE_USART3 FALSE +#define STM32_UART_USART1_IRQ_PRIORITY 12 +#define STM32_UART_USART2_IRQ_PRIORITY 12 +#define STM32_UART_USART3_IRQ_PRIORITY 12 +#define STM32_UART_USART1_DMA_PRIORITY 0 +#define STM32_UART_USART2_DMA_PRIORITY 0 +#define STM32_UART_USART3_DMA_PRIORITY 0 +#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") + +/* + * USB driver system settings. + */ +#define STM32_USB_USE_USB1 TRUE +#define STM32_USB_LOW_POWER_ON_SUSPEND FALSE +#define STM32_USB_USB1_HP_IRQ_PRIORITY 13 +#define STM32_USB_USB1_LP_IRQ_PRIORITY 14 + +/* + * WDG driver system settings. + */ +#define STM32_WDG_USE_IWDG FALSE + +#endif /* MCUCONF_H */ diff --git a/quantum/joystick.h b/quantum/joystick.h index 37a18df570cc..100e22b0e8b3 100644 --- a/quantum/joystick.h +++ b/quantum/joystick.h @@ -25,9 +25,9 @@ { OUTPUT_PIN, INPUT_PIN, GROUND_PIN, LOW, REST, HIGH } typedef struct { - uint32_t output_pin; - uint32_t input_pin; - uint32_t ground_pin; + pin_t output_pin; + pin_t input_pin; + pin_t ground_pin; // the AVR ADC offers 10 bit precision, with significant bits on the higher part uint16_t min_digit; diff --git a/quantum/process_keycode/process_joystick.c b/quantum/process_keycode/process_joystick.c index ef9d43aa4128..c12f7568544f 100644 --- a/quantum/process_keycode/process_joystick.c +++ b/quantum/process_keycode/process_joystick.c @@ -41,7 +41,7 @@ bool process_joystick_buttons(uint16_t keycode, keyrecord_t *record) { return true; } -uint16_t savePinState(uint32_t pin) { +uint16_t savePinState(pin_t pin) { #ifdef __AVR__ uint8_t pinNumber = pin & 0xF; return ((PORTx_ADDRESS(pin) >> pinNumber) & 0x1) << 1 | ((DDRx_ADDRESS(pin) >> pinNumber) & 0x1); @@ -62,8 +62,8 @@ uint16_t savePinState(uint32_t pin) { #endif } -void restorePinState(uint32_t pin, uint16_t restoreState) { -#ifdef __AVR__ +void restorePinState(pin_t pin, uint16_t restoreState) { +#if defined(PROTOCOL_LUFA) uint8_t pinNumber = pin & 0xF; PORTx_ADDRESS(pin) = (PORTx_ADDRESS(pin) & ~_BV(pinNumber)) | (((restoreState >> 1) & 0x1) << pinNumber); DDRx_ADDRESS(pin) = (DDRx_ADDRESS(pin) & ~_BV(pinNumber)) | ((restoreState & 0x1) << pinNumber); @@ -135,17 +135,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) * -127) / (range - ref) ; - if (ranged_val > 0){ + 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) * 127) / (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 < -127 ? -127 : ranged_val; + ranged_val = ranged_val > 127 ? 127 : ranged_val; if (ranged_val != joystick_status.axes[axis_index]) { joystick_status.axes[axis_index] = ranged_val; diff --git a/tmk_core/protocol/usb_descriptor.c b/tmk_core/protocol/usb_descriptor.c index 207a8ced61c5..e8842d27a17b 100644 --- a/tmk_core/protocol/usb_descriptor.c +++ b/tmk_core/protocol/usb_descriptor.c @@ -344,6 +344,7 @@ const USB_Descriptor_Device_t PROGMEM DeviceDescriptor = { .Type = DTYPE_Device }, .USBSpecification = VERSION_BCD(1, 1, 0), + #if VIRTSER_ENABLE .Class = USB_CSCP_IADDeviceClass, .SubClass = USB_CSCP_IADDeviceSubclass, From 1d8102183f34feebfa6407d8553dec45a23f4b63 Mon Sep 17 00:00:00 2001 From: a-chol Date: Mon, 30 Mar 2020 14:11:44 +0200 Subject: [PATCH 17/22] Switch saveState and restoreState signature to use pin_t type. onekey:joystick : add a second axis, virtual and programmatically animated. --- .../handwired/onekey/keymaps/joystick/config.h | 2 +- .../handwired/onekey/keymaps/joystick/keymap.c | 16 +++++++++++++++- keyboards/handwired/onekey/promicro/config.h | 2 ++ keyboards/handwired/onekey/proton_c/config.h | 2 ++ quantum/joystick.h | 2 ++ 5 files changed, 22 insertions(+), 2 deletions(-) diff --git a/keyboards/handwired/onekey/keymaps/joystick/config.h b/keyboards/handwired/onekey/keymaps/joystick/config.h index c43f204802b8..5701d80c84c0 100644 --- a/keyboards/handwired/onekey/keymaps/joystick/config.h +++ b/keyboards/handwired/onekey/keymaps/joystick/config.h @@ -1,3 +1,3 @@ #pragma once -#define JOYSTICK_AXES_COUNT 1 +#define JOYSTICK_AXES_COUNT 2 #define JOYSTICK_BUTTON_COUNT 1 diff --git a/keyboards/handwired/onekey/keymaps/joystick/keymap.c b/keyboards/handwired/onekey/keymaps/joystick/keymap.c index 353d31e2835e..60802f464a90 100644 --- a/keyboards/handwired/onekey/keymaps/joystick/keymap.c +++ b/keyboards/handwired/onekey/keymaps/joystick/keymap.c @@ -2,10 +2,24 @@ #include "joystick.h" +#ifndef ADC_PIN +# define ADC_PIN F6 +#endif + const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { LAYOUT( JS_BUTTON0 ) }; + +void matrix_scan_user() { + int16_t val = (((uint32_t)timer_read()%5000 - 2500) * 255) / 5000; + if (val != joystick_status.axes[1]) { + joystick_status.axes[1] = val; + joystick_status.status |= JS_UPDATED; + } +} + //joystick config joystick_config_t joystick_axes[JOYSTICK_AXES_COUNT] = { - [0] = JOYSTICK_AXIS_IN(A0, 0, 512, 1024) + [0] = JOYSTICK_AXIS_IN(ADC_PIN, 0, 512, 1023) + , [1] = JOYSTICK_AXIS_VIRTUAL }; \ No newline at end of file diff --git a/keyboards/handwired/onekey/promicro/config.h b/keyboards/handwired/onekey/promicro/config.h index fbcd630d7900..c82cf9b78f51 100644 --- a/keyboards/handwired/onekey/promicro/config.h +++ b/keyboards/handwired/onekey/promicro/config.h @@ -21,3 +21,5 @@ #define MATRIX_COL_PINS { F4 } #define MATRIX_ROW_PINS { F5 } #define UNUSED_PINS + +#define ADC_PIN F6 diff --git a/keyboards/handwired/onekey/proton_c/config.h b/keyboards/handwired/onekey/proton_c/config.h index fe34f94add3f..0836fb467765 100644 --- a/keyboards/handwired/onekey/proton_c/config.h +++ b/keyboards/handwired/onekey/proton_c/config.h @@ -28,3 +28,5 @@ #define BACKLIGHT_PAL_MODE 2 #define RGB_DI_PIN A1 + +#define ADC_PIN A0 diff --git a/quantum/joystick.h b/quantum/joystick.h index 100e22b0e8b3..5a6995f5f6ba 100644 --- a/quantum/joystick.h +++ b/quantum/joystick.h @@ -8,6 +8,8 @@ # define JOYSTICK_AXES_COUNT 4 #endif +#include "quantum.h" + #include // configure on input_pin of the joystick_axes array entry to JS_VIRTUAL_AXIS From 16fe12e6b6f247c924d0bca1e95ebad772321912 Mon Sep 17 00:00:00 2001 From: a-chol Date: Mon, 30 Mar 2020 14:24:48 +0200 Subject: [PATCH 18/22] Update docs/feature_joystick.md Co-Authored-By: Ryan --- docs/feature_joystick.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/feature_joystick.md b/docs/feature_joystick.md index 70c2338d5a13..53418690b46f 100644 --- a/docs/feature_joystick.md +++ b/docs/feature_joystick.md @@ -11,7 +11,7 @@ JOYSTICK_ENABLE = yes !> Joystick support is not currently available on V-USB devices. The joystick feature provides two services: - * reading an analog input device + * reading analog input devices (eg. potentiometers) * sending gamepad HID reports Both services can be used without the other, depending on whether you just want to read a device but not send gamepad reports (for volume control for instance) @@ -146,4 +146,3 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) { Joystick buttons are normal quantum keycode, defined as JS_BUTTON0 to JS_BUTTON_MAX, which depends on the number of buttons you have configured. To trigger a joystick button, just add the corresponding keycode to your keymap. - From 92c6466089350dfeb16f62aaee5cc8529eb23932 Mon Sep 17 00:00:00 2001 From: a-chol Date: Mon, 30 Mar 2020 14:25:49 +0200 Subject: [PATCH 19/22] Update docs/feature_joystick.md Co-Authored-By: Ryan --- docs/feature_joystick.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/feature_joystick.md b/docs/feature_joystick.md index 53418690b46f..69712b3117a9 100644 --- a/docs/feature_joystick.md +++ b/docs/feature_joystick.md @@ -17,7 +17,6 @@ The joystick feature provides two services: Both services can be used without the other, depending on whether you just want to read a device but not send gamepad reports (for volume control for instance) or send gamepad reports based on values computed by the keyboard. -!> Reading analog axes is not currently functional on ARM MCUs. ### Analog circuit From a03d1eb66bf1bd040bd49ce39d0f156c7a41dafb Mon Sep 17 00:00:00 2001 From: a-chol Date: Mon, 30 Mar 2020 14:38:06 +0200 Subject: [PATCH 20/22] Add PR corrections --- docs/feature_joystick.md | 156 +++++++++++++++++++-------------------- quantum/joystick.h | 2 +- 2 files changed, 78 insertions(+), 80 deletions(-) diff --git a/docs/feature_joystick.md b/docs/feature_joystick.md index 69712b3117a9..58dfc7b8df55 100644 --- a/docs/feature_joystick.md +++ b/docs/feature_joystick.md @@ -17,23 +17,22 @@ The joystick feature provides two services: Both services can be used without the other, depending on whether you just want to read a device but not send gamepad reports (for volume control for instance) or send gamepad reports based on values computed by the keyboard. - -### Analog circuit +### Analog Input An analog device such as a potentiometer found on a gamepad's analog axes is based on a [voltage divider](https://en.wikipedia.org/wiki/Voltage_divider). It is composed of three connectors linked to the ground, the power input and power output (usually the middle one). The power output holds the voltage that varies based on the position of the cursor, which value will be read using your MCU's [ADC](https://en.wikipedia.org/wiki/Analog-to-digital_converter). -Depending on what pins are already used by your keyboard's matrix, the rest of the circuit can get a little bit more complicated, +Depending on which pins are already used by your keyboard's matrix, the rest of the circuit can get a little bit more complicated, feeding the power input and ground connection through pins and using diodes to avoid bad interactions with the matrix scanning procedures. -### Configuring the joystick +### Configuring the Joystick -The default joystick has 2 axes and and 8 buttons. This can be changed from the config.h file : +By default, two axes and eight buttons are defined. This can be changed in your `config.h`: ```c -//max 32 for JOYSTICK_BUTTON_COUNT +// Max 32 #define JOYSTICK_BUTTON_COUNT 16 -//max 6 for JOYSTICK_AXES_COUNT +// Max 6: X, Y, Z, Rx, Ry, Rz #define JOYSTICK_AXES_COUNT 3 ``` @@ -42,106 +41,105 @@ A joystick will either be read from an input pin that allows the use of the ADC, You have to define an array of type ''joystick_config_t'' and of proper size. There are three ways for your circuit to work with the ADC, that relies on the use of 1, 2 or 3 pins of the MCU: - * 1 pin : your analog device is directly connected to your device Ground and Vcc. The only pin used is the ADC pin of your choice. - * 2 pins : your analog device is powered through a pin that allows toggling it on or off. The other pin is used to read the input value through the ADC - * 3 pins : both the power input and ground are connected to pins that must be set to a proper state before reading and restored afterwards. + * 1 pin: your analog device is directly connected to your device GND and VCC. The only pin used is the ADC pin of your choice. + * 2 pins: your analog device is powered through a pin that allows toggling it on or off. The other pin is used to read the input value through the ADC. + * 3 pins: both the power input and ground are connected to pins that must be set to a proper state before reading and restored afterwards. The configuration of each axis is performed using one of four macros: - * JOYSTICK_AXIS_VIRTUAL : no ADC reading must be performed, that value will be provided by keyboard/keymap-level code - * JOYSTICK_AXIS_IN (INPUT_PIN, LOW, REST, HIGH) : a voltage will be read on the provided pin, which must be an ADC-capable pin. - * JOYSTICK_AXIS_IN_OUT (INPUT_PIN, OUTPUT_PIN, LOW, REST, HIGH) : the provided OUTPUT_PIN will be set high before INPUT_PIN is read. - * JOYSTICK_AXIS_IN_OUT_GROUND(INPUT_PIN, OUTPUT_PIN, GROUND_PIN, LOW, REST, HIGH) : the OUTPUT_PIN will be set high and GROUND_PIN will be set low before reading from INPUT_PIN + * `JOYSTICK_AXIS_VIRTUAL`: no ADC reading must be performed, that value will be provided by keyboard/keymap-level code + * `JOYSTICK_AXIS_IN(INPUT_PIN, LOW, REST, HIGH)`: a voltage will be read on the provided pin, which must be an ADC-capable pin. + * `JOYSTICK_AXIS_IN_OUT(INPUT_PIN, OUTPUT_PIN, LOW, REST, HIGH)`: the provided `OUTPUT_PIN` will be set high before `INPUT_PIN` is read. + * `JOYSTICK_AXIS_IN_OUT_GROUND(INPUT_PIN, OUTPUT_PIN, GROUND_PIN, LOW, REST, HIGH)`: the `OUTPUT_PIN` will be set high and `GROUND_PIN` will be set low before reading from `INPUT_PIN`. -In any case where an ADC reading takes place (when INPUT_PIN is provided), additional LOW, REST and HIGH parameters are used. -They implement the calibration of the analog device by defining the range of read values that will be mapped to the lowest, resting position and highest possible value for the axis (-127 to 127). -In practice, you have to provide the lowest/highest raw adc reading, and the raw reading at resting position, when no deflection is applied. You can provide inverted LOW and HIGH to invert the axis. +In any case where an ADC reading takes place (when `INPUT_PIN` is provided), additional `LOW`, `REST` and `HIGH` parameters are used. +These implement the calibration of the analog device by defining the range of read values that will be mapped to the lowest, resting position and highest possible value for the axis (-127 to 127). +In practice, you have to provide the lowest/highest raw ADC reading, and the raw reading at resting position, when no deflection is applied. You can provide inverted `LOW` and `HIGH` to invert the axis. -For instance, an axes configuration can be defined in the following way : +For instance, an axes configuration can be defined in the following way: ```c //joystick config joystick_config_t joystick_axes[JOYSTICK_AXES_COUNT] = { - [0] = JOYSTICK_AXIS_IN_OUT_GROUND(A4, B0, A7, 900, 575, 285) -, [1] = JOYSTICK_AXIS_VIRTUAL + [0] = JOYSTICK_AXIS_IN_OUT_GROUND(A4, B0, A7, 900, 575, 285), + [1] = JOYSTICK_AXIS_VIRTUAL }; ``` When the ADC reads 900 or higher, the returned axis value will be -127, whereas it will be 127 when the ADC reads 285 or lower. Zero is returned when 575 is read. -In this example, the first axis will be read from the A4 pin while B0 is set high and A7 is set low, using an analogRead, whereas the second axis will not be read. +In this example, the first axis will be read from the `A4` pin while `B0` is set high and `A7` is set low, using `analogReadPin()`, whereas the second axis will not be read. -In order to give a value to the second axis, you can do so in any customizable entry point of quantum : as an action, in process_record_user or in matrix_scan_user, or even in joystick_task(void) which is called even when no key has been pressed. -You assign a value by writing to joystick_status.axes[axis_index] a signed 8bit value (ranging from -127 to 127). Then it is necessary to assign the flag JS_UPDATED to joystick_status.status in order for an updated HID report to be sent. +In order to give a value to the second axis, you can do so in any customizable entry point: as an action, in `process_record_user()` or in `matrix_scan_user()`, or even in `joystick_task()` which is called even when no key has been pressed. +You assign a value by writing to `joystick_status.axes[axis_index]` a signed 8-bit value (ranging from -127 to 127). Then it is necessary to assign the flag `JS_UPDATED` to `joystick_status.status` in order for an updated HID report to be sent. -The following example writes two axes based on keypad presses, with KP_5 as a precision modifier : +The following example writes two axes based on keypad presses, with `KC_P5` as a precision modifier: ```c #ifdef JOYSTICK_ENABLE static uint8_t precision_val = 70; static uint8_t axesFlags = 0; -enum Axes{ - Precision = 1, - Axis1High = 2, - Axis1Low = 4, - Axis2High = 8, - Axis2Low = 16 +enum axes { + Precision = 1, + Axis1High = 2, + Axis1Low = 4, + Axis2High = 8, + Axis2Low = 16 }; #endif bool process_record_user(uint16_t keycode, keyrecord_t *record) { - switch(keycode){ + switch(keycode) { #ifdef JOYSTICK_ENABLE - // virtual joystick - #if JOYSTICK_AXES_COUNT>1 - case KC_P8: - if (record->event.pressed){ - axesFlags |= Axis2Low; - } else { - axesFlags &= ~Axis2Low; - } - joystick_status.status |= JS_UPDATED; - break; - case KC_P2: - if (record->event.pressed){ - axesFlags |= Axis2High; - } else { - axesFlags &= ~Axis2High; - } - joystick_status.status |= JS_UPDATED; - break; - #endif - case KC_P4: - if (record->event.pressed){ - axesFlags |= Axis1Low; - } else { - axesFlags &= ~Axis1Low; - } - joystick_status.status |= JS_UPDATED; - break; - case KC_P6: - if (record->event.pressed){ - axesFlags |= Axis1High; - } else { - axesFlags &= ~Axis1High; - } - joystick_status.status |= JS_UPDATED; - break; - case KC_P5: - if (record->event.pressed){ - axesFlags |= Precision; - } else { - axesFlags &= ~Precision; - } - joystick_status.status |= JS_UPDATED; - break; + // virtual joystick +# if JOYSTICK_AXES_COUNT > 1 + case KC_P8: + if (record->event.pressed) { + axesFlags |= Axis2Low; + } else { + axesFlags &= ~Axis2Low; + } + joystick_status.status |= JS_UPDATED; + break; + case KC_P2: + if (record->event.pressed) { + axesFlags |= Axis2High; + } else { + axesFlags &= ~Axis2High; + } + joystick_status.status |= JS_UPDATED; + break; +# endif + case KC_P4: + if (record->event.pressed) { + axesFlags |= Axis1Low; + } else { + axesFlags &= ~Axis1Low; + } + joystick_status.status |= JS_UPDATED; + break; + case KC_P6: + if (record->event.pressed) { + axesFlags |= Axis1High; + } else { + axesFlags &= ~Axis1High; + } + joystick_status.status |= JS_UPDATED; + break; + case KC_P5: + if (record->event.pressed) { + axesFlags |= Precision; + } else { + axesFlags &= ~Precision; + } + joystick_status.status |= JS_UPDATED; + break; #endif - } - - return true; + } + return true; } ``` -### Triggering joystick buttons +### Triggering Joystick Buttons -Joystick buttons are normal quantum keycode, defined as JS_BUTTON0 to JS_BUTTON_MAX, which depends on the number of buttons you have configured. +Joystick buttons are normal Quantum keycodes, defined as `JS_BUTTON0` to `JS_BUTTON31`, depending on the number of buttons you have configured. To trigger a joystick button, just add the corresponding keycode to your keymap. diff --git a/quantum/joystick.h b/quantum/joystick.h index 5a6995f5f6ba..a95472b9fd44 100644 --- a/quantum/joystick.h +++ b/quantum/joystick.h @@ -51,4 +51,4 @@ typedef struct { extern joystick_t joystick_status; // to be implemented in the hid protocol library -void send_joystick_packet(joystick_t* joystick); +void send_joystick_packet(joystick_t *joystick); From a18eef2ffcfdec6e55f75c19140136a50ef186b6 Mon Sep 17 00:00:00 2001 From: a-chol Date: Sat, 9 May 2020 21:04:19 +0200 Subject: [PATCH 21/22] Remove halconf.h and mcuconf.h from onekey keymaps --- .../onekey/keymaps/joystick/halconf.h | 524 ------------------ .../onekey/keymaps/joystick/mcuconf.h | 273 --------- 2 files changed, 797 deletions(-) delete mode 100644 keyboards/handwired/onekey/keymaps/joystick/halconf.h delete mode 100644 keyboards/handwired/onekey/keymaps/joystick/mcuconf.h diff --git a/keyboards/handwired/onekey/keymaps/joystick/halconf.h b/keyboards/handwired/onekey/keymaps/joystick/halconf.h deleted file mode 100644 index 0a8c978676a1..000000000000 --- a/keyboards/handwired/onekey/keymaps/joystick/halconf.h +++ /dev/null @@ -1,524 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file templates/halconf.h - * @brief HAL configuration header. - * @details HAL configuration file, this file allows to enable or disable the - * various device drivers from your application. You may also use - * this file in order to override the device drivers default settings. - * - * @addtogroup HAL_CONF - * @{ - */ - -#ifndef HALCONF_H -# define HALCONF_H - -# define _CHIBIOS_HAL_CONF_ -# define _CHIBIOS_HAL_CONF_VER_7_0_ - -# include "mcuconf.h" - -/** - * @brief Enables the PAL subsystem. - */ -# if !defined(HAL_USE_PAL) || defined(__DOXYGEN__) -# define HAL_USE_PAL TRUE -# endif - -/** - * @brief Enables the ADC subsystem. - */ -# if !defined(HAL_USE_ADC) || defined(__DOXYGEN__) -# define HAL_USE_ADC TRUE -# endif - -/** - * @brief Enables the CAN subsystem. - */ -# if !defined(HAL_USE_CAN) || defined(__DOXYGEN__) -# define HAL_USE_CAN FALSE -# endif - -/** - * @brief Enables the cryptographic subsystem. - */ -# if !defined(HAL_USE_CRY) || defined(__DOXYGEN__) -# define HAL_USE_CRY FALSE -# endif - -/** - * @brief Enables the DAC subsystem. - */ -# if !defined(HAL_USE_DAC) || defined(__DOXYGEN__) -# define HAL_USE_DAC TRUE -# endif - -/** - * @brief Enables the GPT subsystem. - */ -# if !defined(HAL_USE_GPT) || defined(__DOXYGEN__) -# define HAL_USE_GPT TRUE -# endif - -/** - * @brief Enables the I2C subsystem. - */ -# if !defined(HAL_USE_I2C) || defined(__DOXYGEN__) -# define HAL_USE_I2C TRUE -# endif - -/** - * @brief Enables the I2S subsystem. - */ -# if !defined(HAL_USE_I2S) || defined(__DOXYGEN__) -# define HAL_USE_I2S FALSE -# endif - -/** - * @brief Enables the ICU subsystem. - */ -# if !defined(HAL_USE_ICU) || defined(__DOXYGEN__) -# define HAL_USE_ICU FALSE -# endif - -/** - * @brief Enables the MAC subsystem. - */ -# if !defined(HAL_USE_MAC) || defined(__DOXYGEN__) -# define HAL_USE_MAC FALSE -# endif - -/** - * @brief Enables the MMC_SPI subsystem. - */ -# if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__) -# define HAL_USE_MMC_SPI FALSE -# endif - -/** - * @brief Enables the PWM subsystem. - */ -# if !defined(HAL_USE_PWM) || defined(__DOXYGEN__) -# define HAL_USE_PWM TRUE -# endif - -/** - * @brief Enables the RTC subsystem. - */ -# if !defined(HAL_USE_RTC) || defined(__DOXYGEN__) -# define HAL_USE_RTC FALSE -# endif - -/** - * @brief Enables the SDC subsystem. - */ -# if !defined(HAL_USE_SDC) || defined(__DOXYGEN__) -# define HAL_USE_SDC FALSE -# endif - -/** - * @brief Enables the SERIAL subsystem. - */ -# if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__) -# define HAL_USE_SERIAL FALSE -# endif - -/** - * @brief Enables the SERIAL over USB subsystem. - */ -# if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__) -# define HAL_USE_SERIAL_USB TRUE -# endif - -/** - * @brief Enables the SIO subsystem. - */ -# if !defined(HAL_USE_SIO) || defined(__DOXYGEN__) -# define HAL_USE_SIO FALSE -# endif - -/** - * @brief Enables the SPI subsystem. - */ -# if !defined(HAL_USE_SPI) || defined(__DOXYGEN__) -# define HAL_USE_SPI FALSE -# endif - -/** - * @brief Enables the TRNG subsystem. - */ -# if !defined(HAL_USE_TRNG) || defined(__DOXYGEN__) -# define HAL_USE_TRNG FALSE -# endif - -/** - * @brief Enables the UART subsystem. - */ -# if !defined(HAL_USE_UART) || defined(__DOXYGEN__) -# define HAL_USE_UART FALSE -# endif - -/** - * @brief Enables the USB subsystem. - */ -# if !defined(HAL_USE_USB) || defined(__DOXYGEN__) -# define HAL_USE_USB TRUE -# endif - -/** - * @brief Enables the WDG subsystem. - */ -# if !defined(HAL_USE_WDG) || defined(__DOXYGEN__) -# define HAL_USE_WDG FALSE -# endif - -/** - * @brief Enables the WSPI subsystem. - */ -# if !defined(HAL_USE_WSPI) || defined(__DOXYGEN__) -# define HAL_USE_WSPI FALSE -# endif - -/*===========================================================================*/ -/* PAL driver related settings. */ -/*===========================================================================*/ - -/** - * @brief Enables synchronous APIs. - * @note Disabling this option saves both code and data space. - */ -# if !defined(PAL_USE_CALLBACKS) || defined(__DOXYGEN__) -# define PAL_USE_CALLBACKS FALSE -# endif - -/** - * @brief Enables synchronous APIs. - * @note Disabling this option saves both code and data space. - */ -# if !defined(PAL_USE_WAIT) || defined(__DOXYGEN__) -# define PAL_USE_WAIT FALSE -# endif - -/*===========================================================================*/ -/* ADC driver related settings. */ -/*===========================================================================*/ - -/** - * @brief Enables synchronous APIs. - * @note Disabling this option saves both code and data space. - */ -# if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__) -# define ADC_USE_WAIT TRUE -# endif - -/** - * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs. - * @note Disabling this option saves both code and data space. - */ -# if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) -# define ADC_USE_MUTUAL_EXCLUSION TRUE -# endif - -/*===========================================================================*/ -/* CAN driver related settings. */ -/*===========================================================================*/ - -/** - * @brief Sleep mode related APIs inclusion switch. - */ -# if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__) -# define CAN_USE_SLEEP_MODE TRUE -# endif - -/** - * @brief Enforces the driver to use direct callbacks rather than OSAL events. - */ -# if !defined(CAN_ENFORCE_USE_CALLBACKS) || defined(__DOXYGEN__) -# define CAN_ENFORCE_USE_CALLBACKS FALSE -# endif - -/*===========================================================================*/ -/* CRY driver related settings. */ -/*===========================================================================*/ - -/** - * @brief Enables the SW fall-back of the cryptographic driver. - * @details When enabled, this option, activates a fall-back software - * implementation for algorithms not supported by the underlying - * hardware. - * @note Fall-back implementations may not be present for all algorithms. - */ -# if !defined(HAL_CRY_USE_FALLBACK) || defined(__DOXYGEN__) -# define HAL_CRY_USE_FALLBACK FALSE -# endif - -/** - * @brief Makes the driver forcibly use the fall-back implementations. - */ -# if !defined(HAL_CRY_ENFORCE_FALLBACK) || defined(__DOXYGEN__) -# define HAL_CRY_ENFORCE_FALLBACK FALSE -# endif - -/*===========================================================================*/ -/* DAC driver related settings. */ -/*===========================================================================*/ - -/** - * @brief Enables synchronous APIs. - * @note Disabling this option saves both code and data space. - */ -# if !defined(DAC_USE_WAIT) || defined(__DOXYGEN__) -# define DAC_USE_WAIT TRUE -# endif - -/** - * @brief Enables the @p dacAcquireBus() and @p dacReleaseBus() APIs. - * @note Disabling this option saves both code and data space. - */ -# if !defined(DAC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) -# define DAC_USE_MUTUAL_EXCLUSION TRUE -# endif - -/*===========================================================================*/ -/* I2C driver related settings. */ -/*===========================================================================*/ - -/** - * @brief Enables the mutual exclusion APIs on the I2C bus. - */ -# if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) -# define I2C_USE_MUTUAL_EXCLUSION TRUE -# endif - -/*===========================================================================*/ -/* MAC driver related settings. */ -/*===========================================================================*/ - -/** - * @brief Enables the zero-copy API. - */ -# if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__) -# define MAC_USE_ZERO_COPY FALSE -# endif - -/** - * @brief Enables an event sources for incoming packets. - */ -# if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__) -# define MAC_USE_EVENTS TRUE -# endif - -/*===========================================================================*/ -/* MMC_SPI driver related settings. */ -/*===========================================================================*/ - -/** - * @brief Delays insertions. - * @details If enabled this options inserts delays into the MMC waiting - * routines releasing some extra CPU time for the threads with - * lower priority, this may slow down the driver a bit however. - * This option is recommended also if the SPI driver does not - * use a DMA channel and heavily loads the CPU. - */ -# if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__) -# define MMC_NICE_WAITING TRUE -# endif - -/*===========================================================================*/ -/* SDC driver related settings. */ -/*===========================================================================*/ - -/** - * @brief Number of initialization attempts before rejecting the card. - * @note Attempts are performed at 10mS intervals. - */ -# if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__) -# define SDC_INIT_RETRY 100 -# endif - -/** - * @brief Include support for MMC cards. - * @note MMC support is not yet implemented so this option must be kept - * at @p FALSE. - */ -# if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__) -# define SDC_MMC_SUPPORT FALSE -# endif - -/** - * @brief Delays insertions. - * @details If enabled this options inserts delays into the MMC waiting - * routines releasing some extra CPU time for the threads with - * lower priority, this may slow down the driver a bit however. - */ -# if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__) -# define SDC_NICE_WAITING TRUE -# endif - -/** - * @brief OCR initialization constant for V20 cards. - */ -# if !defined(SDC_INIT_OCR_V20) || defined(__DOXYGEN__) -# define SDC_INIT_OCR_V20 0x50FF8000U -# endif - -/** - * @brief OCR initialization constant for non-V20 cards. - */ -# if !defined(SDC_INIT_OCR) || defined(__DOXYGEN__) -# define SDC_INIT_OCR 0x80100000U -# endif - -/*===========================================================================*/ -/* SERIAL driver related settings. */ -/*===========================================================================*/ - -/** - * @brief Default bit rate. - * @details Configuration parameter, this is the baud rate selected for the - * default configuration. - */ -# if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__) -# define SERIAL_DEFAULT_BITRATE 38400 -# endif - -/** - * @brief Serial buffers size. - * @details Configuration parameter, you can change the depth of the queue - * buffers depending on the requirements of your application. - * @note The default is 16 bytes for both the transmission and receive - * buffers. - */ -# if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__) -# define SERIAL_BUFFERS_SIZE 16 -# endif - -/*===========================================================================*/ -/* SERIAL_USB driver related setting. */ -/*===========================================================================*/ - -/** - * @brief Serial over USB buffers size. - * @details Configuration parameter, the buffer size must be a multiple of - * the USB data endpoint maximum packet size. - * @note The default is 256 bytes for both the transmission and receive - * buffers. - */ -# if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__) -# define SERIAL_USB_BUFFERS_SIZE 1 -# endif - -/** - * @brief Serial over USB number of buffers. - * @note The default is 2 buffers. - */ -# if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__) -# define SERIAL_USB_BUFFERS_NUMBER 2 -# endif - -/*===========================================================================*/ -/* SPI driver related settings. */ -/*===========================================================================*/ - -/** - * @brief Enables synchronous APIs. - * @note Disabling this option saves both code and data space. - */ -# if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__) -# define SPI_USE_WAIT TRUE -# endif - -/** - * @brief Enables circular transfers APIs. - * @note Disabling this option saves both code and data space. - */ -# if !defined(SPI_USE_CIRCULAR) || defined(__DOXYGEN__) -# define SPI_USE_CIRCULAR FALSE -# endif - -/** - * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs. - * @note Disabling this option saves both code and data space. - */ -# if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) -# define SPI_USE_MUTUAL_EXCLUSION TRUE -# endif - -/** - * @brief Handling method for SPI CS line. - * @note Disabling this option saves both code and data space. - */ -# if !defined(SPI_SELECT_MODE) || defined(__DOXYGEN__) -# define SPI_SELECT_MODE SPI_SELECT_MODE_PAD -# endif - -/*===========================================================================*/ -/* UART driver related settings. */ -/*===========================================================================*/ - -/** - * @brief Enables synchronous APIs. - * @note Disabling this option saves both code and data space. - */ -# if !defined(UART_USE_WAIT) || defined(__DOXYGEN__) -# define UART_USE_WAIT FALSE -# endif - -/** - * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs. - * @note Disabling this option saves both code and data space. - */ -# if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) -# define UART_USE_MUTUAL_EXCLUSION FALSE -# endif - -/*===========================================================================*/ -/* USB driver related settings. */ -/*===========================================================================*/ - -/** - * @brief Enables synchronous APIs. - * @note Disabling this option saves both code and data space. - */ -# if !defined(USB_USE_WAIT) || defined(__DOXYGEN__) -# define USB_USE_WAIT TRUE -# endif - -/*===========================================================================*/ -/* WSPI driver related settings. */ -/*===========================================================================*/ - -/** - * @brief Enables synchronous APIs. - * @note Disabling this option saves both code and data space. - */ -# if !defined(WSPI_USE_WAIT) || defined(__DOXYGEN__) -# define WSPI_USE_WAIT TRUE -# endif - -/** - * @brief Enables the @p wspiAcquireBus() and @p wspiReleaseBus() APIs. - * @note Disabling this option saves both code and data space. - */ -# if !defined(WSPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) -# define WSPI_USE_MUTUAL_EXCLUSION TRUE -# endif - -#endif /* HALCONF_H */ - -/** @} */ diff --git a/keyboards/handwired/onekey/keymaps/joystick/mcuconf.h b/keyboards/handwired/onekey/keymaps/joystick/mcuconf.h deleted file mode 100644 index dbe98b6d87e1..000000000000 --- a/keyboards/handwired/onekey/keymaps/joystick/mcuconf.h +++ /dev/null @@ -1,273 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -#ifndef MCUCONF_H -#define MCUCONF_H - -/* - * STM32F3xx drivers configuration. - * The following settings override the default settings present in - * the various device driver implementation headers. - * Note that the settings for each driver only have effect if the whole - * driver is enabled in halconf.h. - * - * IRQ priorities: - * 15...0 Lowest...Highest. - * - * DMA priorities: - * 0...3 Lowest...Highest. - */ - -#define STM32F3xx_MCUCONF -#define STM32F303_MCUCONF - -/* - * HAL driver system settings. - */ -#define STM32_NO_INIT FALSE -#define STM32_PVD_ENABLE FALSE -#define STM32_PLS STM32_PLS_LEV0 -#define STM32_HSI_ENABLED TRUE -#define STM32_LSI_ENABLED TRUE -#define STM32_HSE_ENABLED TRUE -#define STM32_LSE_ENABLED FALSE -#define STM32_SW STM32_SW_PLL -#define STM32_PLLSRC STM32_PLLSRC_HSE -#define STM32_PREDIV_VALUE 1 -#define STM32_PLLMUL_VALUE 9 -#define STM32_HPRE STM32_HPRE_DIV1 -#define STM32_PPRE1 STM32_PPRE1_DIV2 -#define STM32_PPRE2 STM32_PPRE2_DIV2 -#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK -#define STM32_ADC12PRES STM32_ADC12PRES_DIV1 -#define STM32_ADC34PRES STM32_ADC34PRES_DIV1 -#define STM32_USART1SW STM32_USART1SW_PCLK -#define STM32_USART2SW STM32_USART2SW_PCLK -#define STM32_USART3SW STM32_USART3SW_PCLK -#define STM32_UART4SW STM32_UART4SW_PCLK -#define STM32_UART5SW STM32_UART5SW_PCLK -#define STM32_I2C1SW STM32_I2C1SW_SYSCLK -#define STM32_I2C2SW STM32_I2C2SW_SYSCLK -#define STM32_TIM1SW STM32_TIM1SW_PCLK2 -#define STM32_TIM8SW STM32_TIM8SW_PCLK2 -#define STM32_RTCSEL STM32_RTCSEL_LSI -#define STM32_USB_CLOCK_REQUIRED TRUE -#define STM32_USBPRE STM32_USBPRE_DIV1P5 - -/* - * IRQ system settings. - */ -#define STM32_IRQ_EXTI0_PRIORITY 6 -#define STM32_IRQ_EXTI1_PRIORITY 6 -#define STM32_IRQ_EXTI2_PRIORITY 6 -#define STM32_IRQ_EXTI3_PRIORITY 6 -#define STM32_IRQ_EXTI4_PRIORITY 6 -#define STM32_IRQ_EXTI5_9_PRIORITY 6 -#define STM32_IRQ_EXTI10_15_PRIORITY 6 -#define STM32_IRQ_EXTI16_PRIORITY 6 -#define STM32_IRQ_EXTI17_PRIORITY 15 -#define STM32_IRQ_EXTI18_PRIORITY 6 -#define STM32_IRQ_EXTI19_PRIORITY 15 -#define STM32_IRQ_EXTI20_PRIORITY 15 -#define STM32_IRQ_EXTI21_22_29_PRIORITY 6 -#define STM32_IRQ_EXTI30_32_PRIORITY 6 -#define STM32_IRQ_EXTI33_PRIORITY 6 -#define STM32_IRQ_TIM1_BRK_TIM15_PRIORITY 7 -#define STM32_IRQ_TIM1_UP_TIM16_PRIORITY 7 -#define STM32_IRQ_TIM1_TRGCO_TIM17_PRIORITY 7 -#define STM32_IRQ_TIM1_CC_PRIORITY 7 - -/* - * ADC driver system settings. - */ -#define STM32_ADC_DUAL_MODE FALSE -#define STM32_ADC_COMPACT_SAMPLES FALSE -#define STM32_ADC_USE_ADC1 TRUE -#define STM32_ADC_USE_ADC2 FALSE -#define STM32_ADC_USE_ADC3 FALSE -#define STM32_ADC_USE_ADC4 FALSE -#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) -#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) -#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) -#define STM32_ADC_ADC4_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) -#define STM32_ADC_ADC1_DMA_PRIORITY 2 -#define STM32_ADC_ADC2_DMA_PRIORITY 2 -#define STM32_ADC_ADC3_DMA_PRIORITY 2 -#define STM32_ADC_ADC4_DMA_PRIORITY 2 -#define STM32_ADC_ADC12_IRQ_PRIORITY 5 -#define STM32_ADC_ADC3_IRQ_PRIORITY 5 -#define STM32_ADC_ADC4_IRQ_PRIORITY 5 -#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 5 -#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 5 -#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 5 -#define STM32_ADC_ADC4_DMA_IRQ_PRIORITY 5 -#define STM32_ADC_ADC12_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV1 -#define STM32_ADC_ADC34_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV1 - -/* - * CAN driver system settings. - */ -#define STM32_CAN_USE_CAN1 FALSE -#define STM32_CAN_CAN1_IRQ_PRIORITY 11 - -/* - * DAC driver system settings. - */ -#define STM32_DAC_DUAL_MODE FALSE -#define STM32_DAC_USE_DAC1_CH1 TRUE -#define STM32_DAC_USE_DAC1_CH2 TRUE -#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10 -#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10 -#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2 -#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2 - -/* - * GPT driver system settings. - */ -#define STM32_GPT_USE_TIM1 FALSE -#define STM32_GPT_USE_TIM2 FALSE -#define STM32_GPT_USE_TIM3 FALSE -#define STM32_GPT_USE_TIM4 FALSE -#define STM32_GPT_USE_TIM6 TRUE -#define STM32_GPT_USE_TIM7 TRUE -#define STM32_GPT_USE_TIM8 TRUE -#define STM32_GPT_USE_TIM15 FALSE -#define STM32_GPT_USE_TIM16 FALSE -#define STM32_GPT_USE_TIM17 FALSE -#define STM32_GPT_TIM1_IRQ_PRIORITY 7 -#define STM32_GPT_TIM2_IRQ_PRIORITY 7 -#define STM32_GPT_TIM3_IRQ_PRIORITY 7 -#define STM32_GPT_TIM4_IRQ_PRIORITY 7 -#define STM32_GPT_TIM6_IRQ_PRIORITY 7 -#define STM32_GPT_TIM7_IRQ_PRIORITY 7 -#define STM32_GPT_TIM8_IRQ_PRIORITY 7 - -/* - * I2C driver system settings. - */ -#define STM32_I2C_USE_I2C1 TRUE -#define STM32_I2C_USE_I2C2 FALSE -#define STM32_I2C_BUSY_TIMEOUT 50 -#define STM32_I2C_I2C1_IRQ_PRIORITY 10 -#define STM32_I2C_I2C2_IRQ_PRIORITY 10 -#define STM32_I2C_USE_DMA TRUE -#define STM32_I2C_I2C1_DMA_PRIORITY 1 -#define STM32_I2C_I2C2_DMA_PRIORITY 1 -#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") - -/* - * ICU driver system settings. - */ -#define STM32_ICU_USE_TIM1 FALSE -#define STM32_ICU_USE_TIM2 FALSE -#define STM32_ICU_USE_TIM3 FALSE -#define STM32_ICU_USE_TIM4 FALSE -#define STM32_ICU_USE_TIM8 FALSE -#define STM32_ICU_USE_TIM15 FALSE -#define STM32_ICU_TIM1_IRQ_PRIORITY 7 -#define STM32_ICU_TIM2_IRQ_PRIORITY 7 -#define STM32_ICU_TIM3_IRQ_PRIORITY 7 -#define STM32_ICU_TIM4_IRQ_PRIORITY 7 -#define STM32_ICU_TIM8_IRQ_PRIORITY 7 - -/* - * PWM driver system settings. - */ -#define STM32_PWM_USE_ADVANCED FALSE -#define STM32_PWM_USE_TIM1 FALSE -#define STM32_PWM_USE_TIM2 FALSE -#define STM32_PWM_USE_TIM3 TRUE -#define STM32_PWM_USE_TIM4 TRUE -#define STM32_PWM_USE_TIM8 FALSE -#define STM32_PWM_USE_TIM15 FALSE -#define STM32_PWM_USE_TIM16 FALSE -#define STM32_PWM_USE_TIM17 FALSE -#define STM32_PWM_TIM1_IRQ_PRIORITY 7 -#define STM32_PWM_TIM2_IRQ_PRIORITY 7 -#define STM32_PWM_TIM3_IRQ_PRIORITY 7 -#define STM32_PWM_TIM4_IRQ_PRIORITY 7 -#define STM32_PWM_TIM8_IRQ_PRIORITY 7 - -/* - * RTC driver system settings. - */ -#define STM32_RTC_PRESA_VALUE 32 -#define STM32_RTC_PRESS_VALUE 1024 -#define STM32_RTC_CR_INIT 0 -#define STM32_RTC_TAMPCR_INIT 0 - -/* - * SERIAL driver system settings. - */ -#define STM32_SERIAL_USE_USART1 FALSE -#define STM32_SERIAL_USE_USART2 -#define STM32_SERIAL_USE_USART3 FALSE -#define STM32_SERIAL_USE_UART4 FALSE -#define STM32_SERIAL_USE_UART5 FALSE -#define STM32_SERIAL_USART1_PRIORITY 12 -#define STM32_SERIAL_USART2_PRIORITY 12 -#define STM32_SERIAL_USART3_PRIORITY 12 -#define STM32_SERIAL_UART4_PRIORITY 12 -#define STM32_SERIAL_UART5_PRIORITY 12 - -/* - * SPI driver system settings. - */ -#define STM32_SPI_USE_SPI1 FALSE -#define STM32_SPI_USE_SPI2 FALSE -#define STM32_SPI_USE_SPI3 FALSE -#define STM32_SPI_SPI1_DMA_PRIORITY 1 -#define STM32_SPI_SPI2_DMA_PRIORITY 1 -#define STM32_SPI_SPI3_DMA_PRIORITY 1 -#define STM32_SPI_SPI1_IRQ_PRIORITY 10 -#define STM32_SPI_SPI2_IRQ_PRIORITY 10 -#define STM32_SPI_SPI3_IRQ_PRIORITY 10 -#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") - -/* - * ST driver system settings. - */ -#define STM32_ST_IRQ_PRIORITY 8 -#define STM32_ST_USE_TIMER 2 - -/* - * UART driver system settings. - */ -#define STM32_UART_USE_USART1 FALSE -#define STM32_UART_USE_USART2 FALSE -#define STM32_UART_USE_USART3 FALSE -#define STM32_UART_USART1_IRQ_PRIORITY 12 -#define STM32_UART_USART2_IRQ_PRIORITY 12 -#define STM32_UART_USART3_IRQ_PRIORITY 12 -#define STM32_UART_USART1_DMA_PRIORITY 0 -#define STM32_UART_USART2_DMA_PRIORITY 0 -#define STM32_UART_USART3_DMA_PRIORITY 0 -#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") - -/* - * USB driver system settings. - */ -#define STM32_USB_USE_USB1 TRUE -#define STM32_USB_LOW_POWER_ON_SUSPEND FALSE -#define STM32_USB_USB1_HP_IRQ_PRIORITY 13 -#define STM32_USB_USB1_LP_IRQ_PRIORITY 14 - -/* - * WDG driver system settings. - */ -#define STM32_WDG_USE_IWDG FALSE - -#endif /* MCUCONF_H */ From 1d76ab481f7b641a9f71c2e8419eaa82be87dded Mon Sep 17 00:00:00 2001 From: a-chol Date: Sat, 9 May 2020 21:18:30 +0200 Subject: [PATCH 22/22] Change ADC_PIN to A0 --- keyboards/handwired/onekey/proton_c/config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/keyboards/handwired/onekey/proton_c/config.h b/keyboards/handwired/onekey/proton_c/config.h index 68aec22f0d3f..3ba4ba649962 100644 --- a/keyboards/handwired/onekey/proton_c/config.h +++ b/keyboards/handwired/onekey/proton_c/config.h @@ -29,4 +29,4 @@ #define RGB_DI_PIN A0 -#define ADC_PIN A1 +#define ADC_PIN A0