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 cformatgc_switch
parent
d88bdc6a1b
commit
801be60473
@ -0,0 +1,5 @@ |
|||||||
|
#include QMK_KEYBOARD_H |
||||||
|
|
||||||
|
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { |
||||||
|
LAYOUT( JS_BUTTON0 ) |
||||||
|
}; |
@ -1,15 +1,13 @@ |
|||||||
#include "joystick.h" |
#include "joystick.h" |
||||||
|
|
||||||
joystick_t joystick_status = {
|
joystick_t joystick_status = {.buttons = {0}, |
||||||
.buttons = {0}, |
.axes = |
||||||
.axes = { |
{ |
||||||
#if JOYSTICK_AXES_COUNT>0 |
#if JOYSTICK_AXES_COUNT > 0 |
||||||
0 |
0 |
||||||
#endif |
#endif |
||||||
}, |
}, |
||||||
.status = 0 |
.status = 0}; |
||||||
}; |
|
||||||
|
|
||||||
//array defining the reading of analog values for each axis
|
// array defining the reading of analog values for each axis
|
||||||
__attribute__ ((weak)) |
__attribute__((weak)) joystick_config_t joystick_axes[JOYSTICK_AXES_COUNT] = {}; |
||||||
joystick_config_t joystick_axes[JOYSTICK_AXES_COUNT] = {}; |
|
||||||
|
@ -1,55 +1,52 @@ |
|||||||
#ifndef JOYSTICK_H |
#pragma once |
||||||
#define JOYSTICK_H |
|
||||||
|
|
||||||
#ifndef JOYSTICK_BUTTON_COUNT |
#ifndef JOYSTICK_BUTTON_COUNT |
||||||
#define JOYSTICK_BUTTON_COUNT 8 |
# define JOYSTICK_BUTTON_COUNT 8 |
||||||
#endif |
#endif |
||||||
|
|
||||||
#ifndef JOYSTICK_AXES_COUNT |
#ifndef JOYSTICK_AXES_COUNT |
||||||
#define JOYSTICK_AXES_COUNT 4 |
# define JOYSTICK_AXES_COUNT 4 |
||||||
#endif |
#endif |
||||||
|
|
||||||
#include <stdint.h> |
#include <stdint.h> |
||||||
|
|
||||||
//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.
|
// to prevent it from being read from the ADC. This allows outputing forged axis value.
|
||||||
//
|
//
|
||||||
#define JS_VIRTUAL_AXIS 0xFF |
#define JS_VIRTUAL_AXIS 0xFF |
||||||
|
|
||||||
#define JOYSTICK_AXIS_VIRTUAL {JS_VIRTUAL_AXIS,JS_VIRTUAL_AXIS,JS_VIRTUAL_AXIS,0 ,1023} |
#define JOYSTICK_AXIS_VIRTUAL \ |
||||||
#define JOYSTICK_AXIS_IN(INPUT_PIN, LOW, REST, HIGH) {JS_VIRTUAL_AXIS,INPUT_PIN ,JS_VIRTUAL_AXIS,LOW,REST,HIGH} |
{ JS_VIRTUAL_AXIS, JS_VIRTUAL_AXIS, JS_VIRTUAL_AXIS, 0, 1023 } |
||||||
#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(INPUT_PIN, 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} |
{ 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 { |
typedef struct { |
||||||
uint8_t output_pin; |
uint8_t output_pin; |
||||||
uint8_t input_pin; |
uint8_t input_pin; |
||||||
uint8_t ground_pin; |
uint8_t ground_pin; |
||||||
|
|
||||||
//the AVR ADC offers 10 bit precision, with significant bits on the higher part
|
// the AVR ADC offers 10 bit precision, with significant bits on the higher part
|
||||||
uint16_t min_digit; |
uint16_t min_digit; |
||||||
uint16_t mid_digit; |
uint16_t mid_digit; |
||||||
uint16_t max_digit; |
uint16_t max_digit; |
||||||
} joystick_config_t; |
} joystick_config_t; |
||||||
|
|
||||||
extern joystick_config_t joystick_axes[JOYSTICK_AXES_COUNT]; |
extern joystick_config_t joystick_axes[JOYSTICK_AXES_COUNT]; |
||||||
|
|
||||||
enum joystick_status{ |
enum joystick_status { JS_INITIALIZED = 1, JS_UPDATED = 2 }; |
||||||
JS_INITIALIZED = 1, |
|
||||||
JS_UPDATED = 2 |
|
||||||
}; |
|
||||||
|
|
||||||
typedef struct { |
typedef struct { |
||||||
|
uint8_t buttons[JOYSTICK_BUTTON_COUNT / 8 + 1]; |
||||||
uint8_t buttons[JOYSTICK_BUTTON_COUNT/8+1]; |
|
||||||
|
int16_t axes[JOYSTICK_AXES_COUNT]; |
||||||
int16_t axes[JOYSTICK_AXES_COUNT]; |
uint8_t status : 2; |
||||||
uint8_t status:2; |
|
||||||
} joystick_t; |
} joystick_t; |
||||||
|
|
||||||
extern joystick_t joystick_status; |
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); |
void send_joystick_packet(joystick_t* joystick); |
||||||
|
|
||||||
#endif //JOYSTICK_H
|
|
@ -1,159 +1,145 @@ |
|||||||
|
#include "joystick.h" |
||||||
#include "process_joystick.h" |
#include "process_joystick.h" |
||||||
|
|
||||||
#include <quantum/joystick.h> |
|
||||||
#include <quantum/quantum_keycodes.h> |
|
||||||
#include <quantum/config_common.h> |
|
||||||
|
|
||||||
#ifdef __AVR__ |
#ifdef __AVR__ |
||||||
# include <drivers/avr/analog.h> |
# include "analog.h" |
||||||
#endif |
#endif |
||||||
|
|
||||||
#include <string.h> |
#include <string.h> |
||||||
|
#include <math.h> |
||||||
|
|
||||||
bool process_joystick_buttons(uint16_t keycode, keyrecord_t *record); |
bool process_joystick_buttons(uint16_t keycode, keyrecord_t *record); |
||||||
|
|
||||||
bool process_joystick(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) { |
||||||
if (process_joystick_buttons(keycode, record)
|
send_joystick_packet(&joystick_status); |
||||||
&& (joystick_status.status & JS_UPDATED)>0){ |
joystick_status.status &= ~JS_UPDATED; |
||||||
send_joystick_packet(&joystick_status); |
} |
||||||
joystick_status.status &= ~JS_UPDATED; |
|
||||||
} |
return true; |
||||||
|
|
||||||
return true; |
|
||||||
} |
} |
||||||
|
|
||||||
__attribute__ ((weak)) |
void joystick_task(void) { |
||||||
void joystick_task(void){ |
if (process_joystick_analogread() && (joystick_status.status & JS_UPDATED)) { |
||||||
if (process_joystick_analogread() && (joystick_status.status & JS_UPDATED)){ |
send_joystick_packet(&joystick_status); |
||||||
send_joystick_packet(&joystick_status); |
joystick_status.status &= ~JS_UPDATED; |
||||||
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; |
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__ |
#ifdef __AVR__ |
||||||
uint8_t pinNumber = pin & 0xF; |
uint8_t pinNumber = pin & 0xF; |
||||||
return ((PORTx_ADDRESS(pin) >> pinNumber) & 0x1) << 1
|
return ((PORTx_ADDRESS(pin) >> pinNumber) & 0x1) << 1 | ((DDRx_ADDRESS(pin) >> pinNumber) & 0x1); |
||||||
| ((DDRx_ADDRESS(pin) >> pinNumber) & 0x1) ; |
|
||||||
#else |
#else |
||||||
return 0; |
return 0; |
||||||
#endif |
#endif |
||||||
} |
} |
||||||
|
|
||||||
void restorePinState(uint8_t pin, uint8_t restoreState){ |
void restorePinState(uint8_t pin, uint8_t restoreState) { |
||||||
#ifdef __AVR__ |
#ifdef __AVR__ |
||||||
uint8_t pinNumber = pin & 0xF; |
uint8_t pinNumber = pin & 0xF; |
||||||
PORTx_ADDRESS(pin) = (PORTx_ADDRESS(pin) & ~_BV(pinNumber)) | (((restoreState >> 1) & 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); |
DDRx_ADDRESS(pin) = (DDRx_ADDRESS(pin) & ~_BV(pinNumber)) | ((restoreState & 0x1) << pinNumber); |
||||||
#else |
#else |
||||||
return; |
return; |
||||||
#endif |
#endif |
||||||
} |
} |
||||||
|
|
||||||
__attribute__ ((weak)) |
__attribute__((weak)) bool process_joystick_analogread() { return process_joystick_analogread_quantum(); } |
||||||
bool process_joystick_analogread(){ |
|
||||||
return process_joystick_analogread_quantum(); |
|
||||||
} |
|
||||||
|
|
||||||
bool process_joystick_analogread_quantum(){ |
|
||||||
|
|
||||||
|
bool process_joystick_analogread_quantum() { |
||||||
#if JOYSTICK_AXES_COUNT > 0 |
#if JOYSTICK_AXES_COUNT > 0 |
||||||
for (int axis_index=0 ; axis_index<JOYSTICK_AXES_COUNT ; ++axis_index){ |
for (int axis_index = 0; axis_index < JOYSTICK_AXES_COUNT; ++axis_index) { |
||||||
if (joystick_axes[axis_index].input_pin==JS_VIRTUAL_AXIS){ |
if (joystick_axes[axis_index].input_pin == JS_VIRTUAL_AXIS) { |
||||||
continue; |
continue; |
||||||
} |
} |
||||||
|
|
||||||
//save previous input pin status as well
|
// save previous input pin status as well
|
||||||
uint8_t inputSavedState = savePinState(joystick_axes[axis_index].input_pin); |
uint8_t inputSavedState = savePinState(joystick_axes[axis_index].input_pin); |
||||||
|
|
||||||
//disable pull-up resistor
|
// disable pull-up resistor
|
||||||
writePinLow(joystick_axes[axis_index].input_pin); |
writePinLow(joystick_axes[axis_index].input_pin); |
||||||
|
|
||||||
//if pin was a pull-up input, we need to uncharge it by turning it low
|
// if pin was a pull-up input, we need to uncharge it by turning it low
|
||||||
// before making it a low input
|
// before making it a low input
|
||||||
setPinOutput(joystick_axes[axis_index].input_pin); |
setPinOutput(joystick_axes[axis_index].input_pin); |
||||||
|
|
||||||
wait_us(10); |
wait_us(10); |
||||||
|
|
||||||
//save and apply output pin status
|
// save and apply output pin status
|
||||||
uint8_t outputSavedState = 0; |
uint8_t outputSavedState = 0; |
||||||
if (joystick_axes[axis_index].output_pin!=JS_VIRTUAL_AXIS) { |
if (joystick_axes[axis_index].output_pin != JS_VIRTUAL_AXIS) { |
||||||
//save previous output pin status
|
// save previous output pin status
|
||||||
outputSavedState = savePinState(joystick_axes[axis_index].output_pin); |
outputSavedState = savePinState(joystick_axes[axis_index].output_pin); |
||||||
|
|
||||||
setPinOutput(joystick_axes[axis_index].output_pin); |
setPinOutput(joystick_axes[axis_index].output_pin); |
||||||
writePinHigh(joystick_axes[axis_index].output_pin); |
writePinHigh(joystick_axes[axis_index].output_pin); |
||||||
} |
} |
||||||
|
|
||||||
uint8_t groundSavedState = 0; |
uint8_t groundSavedState = 0; |
||||||
if (joystick_axes[axis_index].ground_pin!=JS_VIRTUAL_AXIS) { |
if (joystick_axes[axis_index].ground_pin != JS_VIRTUAL_AXIS) { |
||||||
//save previous output pin status
|
// save previous output pin status
|
||||||
groundSavedState = savePinState(joystick_axes[axis_index].ground_pin); |
groundSavedState = savePinState(joystick_axes[axis_index].ground_pin); |
||||||
|
|
||||||
setPinOutput(joystick_axes[axis_index].ground_pin); |
setPinOutput(joystick_axes[axis_index].ground_pin); |
||||||
writePinLow(joystick_axes[axis_index].ground_pin); |
writePinLow(joystick_axes[axis_index].ground_pin); |
||||||
} |
} |
||||||
|
|
||||||
wait_us(10); |
wait_us(10); |
||||||
|
|
||||||
setPinInput(joystick_axes[axis_index].input_pin); |
setPinInput(joystick_axes[axis_index].input_pin); |
||||||
|
|
||||||
wait_us(10); |
wait_us(10); |
||||||
|
|
||||||
#ifdef __AVR__ |
# ifdef __AVR__ |
||||||
int16_t axis_val = analogReadPin(joystick_axes[axis_index].input_pin); |
int16_t axis_val = analogReadPin(joystick_axes[axis_index].input_pin); |
||||||
#else |
# else |
||||||
//default to resting position
|
// default to resting position
|
||||||
int16_t axis_val = joystick_axes[axis_index].mid_digit; |
int16_t axis_val = joystick_axes[axis_index].mid_digit; |
||||||
#endif |
# endif |
||||||
|
|
||||||
//test the converted value against the lower range
|
// test the converted value against the lower range
|
||||||
uint16_t ref = joystick_axes[axis_index].mid_digit; |
uint16_t ref = joystick_axes[axis_index].mid_digit; |
||||||
uint16_t range = joystick_axes[axis_index].min_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)); |
int16_t ranged_val = -127 * fminf(1.f, (axis_val - (float)(ref)) / (range - (float)ref)); |
||||||
if (ranged_val > 0){ |
if (ranged_val > 0) { |
||||||
//the value is in the higher range
|
// the value is in the higher range
|
||||||
range = joystick_axes[axis_index].max_digit; |
range = joystick_axes[axis_index].max_digit; |
||||||
ranged_val = 127*fminf(1.f, (axis_val - (float)(ref)) /(range - (float)ref)); |
ranged_val = 127 * fminf(1.f, (axis_val - (float)(ref)) / (range - (float)ref)); |
||||||
} |
} |
||||||
|
|
||||||
if (ranged_val!=joystick_status.axes[axis_index]){ |
if (ranged_val != joystick_status.axes[axis_index]) { |
||||||
joystick_status.axes[axis_index] = ranged_val; |
joystick_status.axes[axis_index] = ranged_val; |
||||||
joystick_status.status |= JS_UPDATED; |
joystick_status.status |= JS_UPDATED; |
||||||
} |
} |
||||||
|
|
||||||
//restore output, ground and input status
|
// restore output, ground and input status
|
||||||
if (joystick_axes[axis_index].output_pin!=JS_VIRTUAL_AXIS) { |
if (joystick_axes[axis_index].output_pin != JS_VIRTUAL_AXIS) { |
||||||
restorePinState(joystick_axes[axis_index].output_pin, outputSavedState); |
restorePinState(joystick_axes[axis_index].output_pin, outputSavedState); |
||||||
} |
} |
||||||
if (joystick_axes[axis_index].ground_pin!=JS_VIRTUAL_AXIS) { |
if (joystick_axes[axis_index].ground_pin != JS_VIRTUAL_AXIS) { |
||||||
restorePinState(joystick_axes[axis_index].ground_pin, groundSavedState); |
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 |
#endif |
||||||
return true; |
return true; |
||||||
} |
} |
||||||
|
Loading…
Reference in new issue