summaryrefslogtreecommitdiff
path: root/quantum/process_keycode/process_joystick.c
diff options
context:
space:
mode:
authorRyan <fauxpark@gmail.com>2022-09-27 18:37:13 +1000
committerGitHub <noreply@github.com>2022-09-27 18:37:13 +1000
commitbe8907d634ac8967de1ae2ac8346b845f738c9e6 (patch)
tree5a56127946000bbd648f8a5f52d90eb6711be222 /quantum/process_keycode/process_joystick.c
parentfb400f2ac2c57fa0fc82ca803f6450b818bb32f9 (diff)
Further refactoring of joystick feature (#18437)
Diffstat (limited to 'quantum/process_keycode/process_joystick.c')
-rw-r--r--quantum/process_keycode/process_joystick.c152
1 files changed, 17 insertions, 135 deletions
diff --git a/quantum/process_keycode/process_joystick.c b/quantum/process_keycode/process_joystick.c
index e867606074..af69d3aa05 100644
--- a/quantum/process_keycode/process_joystick.c
+++ b/quantum/process_keycode/process_joystick.c
@@ -1,10 +1,21 @@
1#include "joystick.h" 1/* Copyright 2022
2#include "process_joystick.h" 2 *
3 3 * This program is free software: you can redistribute it and/or modify
4#include "analog.h" 4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
5 16
6#include <string.h> 17#include "process_joystick.h"
7#include <math.h> 18#include "joystick.h"
8 19
9bool process_joystick(uint16_t keycode, keyrecord_t *record) { 20bool process_joystick(uint16_t keycode, keyrecord_t *record) {
10 switch (keycode) { 21 switch (keycode) {
@@ -18,132 +29,3 @@ bool process_joystick(uint16_t keycode, keyrecord_t *record) {
18 } 29 }
19 return true; 30 return true;
20} 31}
21
22__attribute__((weak)) void joystick_task(void) {
23 if (process_joystick_analogread()) {
24 joystick_flush();
25 }
26}
27
28uint16_t savePinState(pin_t pin) {
29#ifdef __AVR__
30 uint8_t pinNumber = pin & 0xF;
31 return ((PORTx_ADDRESS(pin) >> pinNumber) & 0x1) << 1 | ((DDRx_ADDRESS(pin) >> pinNumber) & 0x1);
32#elif defined(PROTOCOL_CHIBIOS)
33 /*
34 The pin configuration is backed up in the following format :
35 bit 15 9 8 7 6 5 4 3 2 1 0
36 |unused|ODR|IDR|PUPDR|OSPEEDR|OTYPER|MODER|
37 */
38 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);
39#else
40 return 0;
41#endif
42}
43
44void restorePinState(pin_t pin, uint16_t restoreState) {
45#if defined(PROTOCOL_LUFA)
46 uint8_t pinNumber = pin & 0xF;
47 PORTx_ADDRESS(pin) = (PORTx_ADDRESS(pin) & ~_BV(pinNumber)) | (((restoreState >> 1) & 0x1) << pinNumber);
48 DDRx_ADDRESS(pin) = (DDRx_ADDRESS(pin) & ~_BV(pinNumber)) | ((restoreState & 0x1) << pinNumber);
49#elif defined(PROTOCOL_CHIBIOS)
50 PAL_PORT(pin)->MODER = (PAL_PORT(pin)->MODER & ~(0x3 << (2 * PAL_PAD(pin)))) | (restoreState & 0x3) << (2 * PAL_PAD(pin));
51 PAL_PORT(pin)->OTYPER = (PAL_PORT(pin)->OTYPER & ~(0x1 << (1 * PAL_PAD(pin)))) | ((restoreState >> 2) & 0x1) << (1 * PAL_PAD(pin));
52 PAL_PORT(pin)->OSPEEDR = (PAL_PORT(pin)->OSPEEDR & ~(0x3 << (2 * PAL_PAD(pin)))) | ((restoreState >> 3) & 0x3) << (2 * PAL_PAD(pin));
53 PAL_PORT(pin)->PUPDR = (PAL_PORT(pin)->PUPDR & ~(0x3 << (2 * PAL_PAD(pin)))) | ((restoreState >> 5) & 0x3) << (2 * PAL_PAD(pin));
54 PAL_PORT(pin)->IDR = (PAL_PORT(pin)->IDR & ~(0x1 << (1 * PAL_PAD(pin)))) | ((restoreState >> 7) & 0x1) << (1 * PAL_PAD(pin));
55 PAL_PORT(pin)->ODR = (PAL_PORT(pin)->ODR & ~(0x1 << (1 * PAL_PAD(pin)))) | ((restoreState >> 8) & 0x1) << (1 * PAL_PAD(pin));
56#else
57 return;
58#endif
59}
60
61__attribute__((weak)) bool process_joystick_analogread() {
62 return process_joystick_analogread_quantum();
63}
64
65bool process_joystick_analogread_quantum() {
66#if JOYSTICK_AXES_COUNT > 0
67 for (int axis_index = 0; axis_index < JOYSTICK_AXES_COUNT; ++axis_index) {
68 if (joystick_axes[axis_index].input_pin == JS_VIRTUAL_AXIS) {
69 continue;
70 }
71
72 // save previous input pin status as well
73 uint16_t inputSavedState = savePinState(joystick_axes[axis_index].input_pin);
74
75 // disable pull-up resistor
76 writePinLow(joystick_axes[axis_index].input_pin);
77
78 // if pin was a pull-up input, we need to uncharge it by turning it low
79 // before making it a low input
80 setPinOutput(joystick_axes[axis_index].input_pin);
81
82 wait_us(10);
83
84 // save and apply output pin status
85 uint16_t outputSavedState = 0;
86 if (joystick_axes[axis_index].output_pin != JS_VIRTUAL_AXIS) {
87 // save previous output pin status
88 outputSavedState = savePinState(joystick_axes[axis_index].output_pin);
89
90 setPinOutput(joystick_axes[axis_index].output_pin);
91 writePinHigh(joystick_axes[axis_index].output_pin);
92 }
93
94 uint16_t groundSavedState = 0;
95 if (joystick_axes[axis_index].ground_pin != JS_VIRTUAL_AXIS) {
96 // save previous output pin status
97 groundSavedState = savePinState(joystick_axes[axis_index].ground_pin);
98
99 setPinOutput(joystick_axes[axis_index].ground_pin);
100 writePinLow(joystick_axes[axis_index].ground_pin);
101 }
102
103 wait_us(10);
104
105 setPinInput(joystick_axes[axis_index].input_pin);
106
107 wait_us(10);
108
109# if defined(ANALOG_JOYSTICK_ENABLE) && (defined(__AVR__) || defined(PROTOCOL_CHIBIOS))
110 int16_t axis_val = analogReadPin(joystick_axes[axis_index].input_pin);
111# else
112 // default to resting position
113 int16_t axis_val = joystick_axes[axis_index].mid_digit;
114# endif
115
116 // test the converted value against the lower range
117 int32_t ref = joystick_axes[axis_index].mid_digit;
118 int32_t range = joystick_axes[axis_index].min_digit;
119 int32_t ranged_val = ((axis_val - ref) * -JOYSTICK_RESOLUTION) / (range - ref);
120
121 if (ranged_val > 0) {
122 // the value is in the higher range
123 range = joystick_axes[axis_index].max_digit;
124 ranged_val = ((axis_val - ref) * JOYSTICK_RESOLUTION) / (range - ref);
125 }
126
127 // clamp the result in the valid range
128 ranged_val = ranged_val < -JOYSTICK_RESOLUTION ? -JOYSTICK_RESOLUTION : ranged_val;
129 ranged_val = ranged_val > JOYSTICK_RESOLUTION ? JOYSTICK_RESOLUTION : ranged_val;
130
131 if (ranged_val != joystick_status.axes[axis_index]) {
132 joystick_status.axes[axis_index] = ranged_val;
133 joystick_status.status |= JS_UPDATED;
134 }
135
136 // restore output, ground and input status
137 if (joystick_axes[axis_index].output_pin != JS_VIRTUAL_AXIS) {
138 restorePinState(joystick_axes[axis_index].output_pin, outputSavedState);
139 }
140 if (joystick_axes[axis_index].ground_pin != JS_VIRTUAL_AXIS) {
141 restorePinState(joystick_axes[axis_index].ground_pin, groundSavedState);
142 }
143
144 restorePinState(joystick_axes[axis_index].input_pin, inputSavedState);
145 }
146
147#endif
148 return true;
149}