mirror of
https://github.com/qmk/qmk_firmware.git
synced 2026-10-01 22:40:11 +02:00
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
This commit is contained in:
@@ -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] = {};
|
||||
@@ -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 <stdint.h>
|
||||
|
||||
//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
|
||||
@@ -0,0 +1,79 @@
|
||||
#include "process_joystick.h"
|
||||
|
||||
#include <quantum/joystick.h>
|
||||
#include <quantum/quantum_keycodes.h>
|
||||
|
||||
#ifdef __AVR__
|
||||
# include <drivers/avr/analog.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
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<JOYSTICK_AXES_COUNT ; ++axis_index){
|
||||
if (joystick_axes[axis_index].output_pin==JS_VIRTUAL_AXIS || joystick_axes[axis_index].input_pin==JS_VIRTUAL_AXIS){
|
||||
continue;
|
||||
}
|
||||
|
||||
setPinOutput(joystick_axes[axis_index].output_pin);
|
||||
writePinHigh(joystick_axes[axis_index].output_pin);
|
||||
|
||||
//disable pull-up resistance
|
||||
setPinInput(joystick_axes[axis_index].input_pin);
|
||||
writePinLow(joystick_axes[axis_index].input_pin);
|
||||
|
||||
#ifdef __AVR__
|
||||
int16_t axis_val = analogReadPin(joystick_axes[axis_index].input_pin);
|
||||
#else
|
||||
int16_t axis_val = 0;
|
||||
#endif
|
||||
if (axis_val!=joystick_status.axes[axis_index]){
|
||||
joystick_status.axes[axis_index] = axis_val;
|
||||
joystick_status.status |= JS_UPDATED;
|
||||
}
|
||||
|
||||
writePinLow(joystick_axes[axis_index].output_pin);
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#ifndef PROCESS_JOYSTICK_H
|
||||
#define PROCESS_JOYSTICK_H
|
||||
|
||||
#include <stdint.h>
|
||||
#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
|
||||
@@ -63,6 +63,10 @@ float bell_song[][2] = SONG(TERMINAL_SOUND);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef JOYSTICK_ENABLE
|
||||
#include <process_keycode/process_joystick.h>
|
||||
#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;
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user