aboutsummaryrefslogtreecommitdiff
path: root/quantum/encoder.c
diff options
context:
space:
mode:
authorBalz Guenat <balz.guenat@gmail.com>2021-11-20 18:06:08 +0100
committerGitHub <noreply@github.com>2021-11-20 09:06:08 -0800
commit32215d5bff52262542a2f8d2a221b0303f02c019 (patch)
tree4f788b0302cdda37e5f3f7165c236a3b9d85e19a /quantum/encoder.c
parentd11d2459ce3840a4549533d1a2136044d1fa7e19 (diff)
downloadqmk_firmware-32215d5bff52262542a2f8d2a221b0303f02c019.tar.gz
qmk_firmware-32215d5bff52262542a2f8d2a221b0303f02c019.zip
Rework encoders to enable asymmetric split keyboards (#12090)
Co-authored-by: Balz Guenat <balz.guenat@siemens.com> Co-authored-by: Nick Brassel <nick@tzarc.org>
Diffstat (limited to 'quantum/encoder.c')
-rw-r--r--quantum/encoder.c146
1 files changed, 91 insertions, 55 deletions
diff --git a/quantum/encoder.c b/quantum/encoder.c
index 8fb87281c..7d4e97898 100644
--- a/quantum/encoder.c
+++ b/quantum/encoder.c
@@ -16,8 +16,17 @@
16 */ 16 */
17 17
18#include "encoder.h" 18#include "encoder.h"
19#ifdef SPLIT_KEYBOARD 19
20# include "split_util.h" 20// this is for unit testing
21#if defined(ENCODER_MOCK_SINGLE)
22# include "encoder/tests/mock.h"
23#elif defined(ENCODER_MOCK_SPLIT)
24# include "encoder/tests/mock_split.h"
25#else
26# include <gpio.h>
27# ifdef SPLIT_KEYBOARD
28# include "split_util.h"
29# endif
21#endif 30#endif
22 31
23// for memcpy 32// for memcpy
@@ -27,17 +36,41 @@
27# define ENCODER_RESOLUTION 4 36# define ENCODER_RESOLUTION 4
28#endif 37#endif
29 38
30#if !defined(ENCODERS_PAD_A) || !defined(ENCODERS_PAD_B) 39#if (!defined(ENCODERS_PAD_A) || !defined(ENCODERS_PAD_B)) && (!defined(ENCODERS_PAD_A) || !defined(ENCODERS_PAD_B))
31# error "No encoder pads defined by ENCODERS_PAD_A and ENCODERS_PAD_B" 40# error "No encoder pads defined by ENCODERS_PAD_A and ENCODERS_PAD_B or ENCODERS_PAD_A_RIGHT and ENCODERS_PAD_B_RIGHT"
32#endif 41#endif
33 42
34#define NUMBER_OF_ENCODERS (sizeof(encoders_pad_a) / sizeof(pin_t)) 43// on split keyboards, these are the pads and resolutions for the left half
35static pin_t encoders_pad_a[] = ENCODERS_PAD_A; 44static pin_t encoders_pad_a[] = ENCODERS_PAD_A;
36static pin_t encoders_pad_b[] = ENCODERS_PAD_B; 45static pin_t encoders_pad_b[] = ENCODERS_PAD_B;
37#ifdef ENCODER_RESOLUTIONS 46#ifdef ENCODER_RESOLUTIONS
38static uint8_t encoder_resolutions[] = ENCODER_RESOLUTIONS; 47static uint8_t encoder_resolutions[] = ENCODER_RESOLUTIONS;
39#endif 48#endif
40 49
50#ifndef SPLIT_KEYBOARD
51# define NUMBER_OF_ENCODERS (sizeof(encoders_pad_a) / sizeof(pin_t))
52#else
53// if no pads for right half are defined, we assume the keyboard is symmetric (i.e. same pads)
54# ifndef ENCODERS_PAD_A_RIGHT
55# define ENCODERS_PAD_A_RIGHT ENCODERS_PAD_A
56# endif
57# ifndef ENCODERS_PAD_B_RIGHT
58# define ENCODERS_PAD_B_RIGHT ENCODERS_PAD_B
59# endif
60# if defined(ENCODER_RESOLUTIONS) && !defined(ENCODER_RESOLUTIONS_RIGHT)
61# define ENCODER_RESOLUTIONS_RIGHT ENCODER_RESOLUTIONS
62# endif
63
64# define NUMBER_OF_ENCODERS ((sizeof(encoders_pad_a) + sizeof(encoders_pad_a_right)) / sizeof(pin_t))
65# define NUMBER_OF_ENCODERS_LEFT (sizeof(encoders_pad_a) / sizeof(pin_t))
66# define NUMBER_OF_ENCODERS_RIGHT (sizeof(encoders_pad_a_right) / sizeof(pin_t))
67static pin_t encoders_pad_a_right[] = ENCODERS_PAD_A_RIGHT;
68static pin_t encoders_pad_b_right[] = ENCODERS_PAD_B_RIGHT;
69# ifdef ENCODER_RESOLUTIONS_RIGHT
70static uint8_t encoder_resolutions_right[] = ENCODER_RESOLUTIONS_RIGHT;
71# endif
72#endif
73
41#ifndef ENCODER_DIRECTION_FLIP 74#ifndef ENCODER_DIRECTION_FLIP
42# define ENCODER_CLOCKWISE true 75# define ENCODER_CLOCKWISE true
43# define ENCODER_COUNTER_CLOCKWISE false 76# define ENCODER_COUNTER_CLOCKWISE false
@@ -50,78 +83,81 @@ static int8_t encoder_LUT[] = {0, -1, 1, 0, 1, 0, 0, -1, -1, 0, 0, 1, 0, 1, -1,
50static uint8_t encoder_state[NUMBER_OF_ENCODERS] = {0}; 83static uint8_t encoder_state[NUMBER_OF_ENCODERS] = {0};
51static int8_t encoder_pulses[NUMBER_OF_ENCODERS] = {0}; 84static int8_t encoder_pulses[NUMBER_OF_ENCODERS] = {0};
52 85
53#ifdef SPLIT_KEYBOARD
54// right half encoders come over as second set of encoders
55static uint8_t encoder_value[NUMBER_OF_ENCODERS * 2] = {0};
56// row offsets for each hand
57static uint8_t thisHand, thatHand;
58#else
59static uint8_t encoder_value[NUMBER_OF_ENCODERS] = {0}; 86static uint8_t encoder_value[NUMBER_OF_ENCODERS] = {0};
60#endif
61 87
62__attribute__((weak)) bool encoder_update_user(uint8_t index, bool clockwise) { return true; } 88__attribute__((weak)) bool encoder_update_user(uint8_t index, bool clockwise) { return true; }
63 89
64__attribute__((weak)) bool encoder_update_kb(uint8_t index, bool clockwise) { return encoder_update_user(index, clockwise); } 90__attribute__((weak)) bool encoder_update_kb(uint8_t index, bool clockwise) { return encoder_update_user(index, clockwise); }
65 91
92// number of encoders connected to this controller
93static uint8_t numEncodersHere;
94// index of the first encoder connected to this controller (only for right halves, this will be nonzero)
95static uint8_t firstEncoderHere;
96#ifdef SPLIT_KEYBOARD
97// index of the first encoder connected to the other half
98static uint8_t firstEncoderThere;
99#endif
100// the pads for this controller
101static pin_t* pad_a;
102static pin_t* pad_b;
103
66void encoder_init(void) { 104void encoder_init(void) {
67#if defined(SPLIT_KEYBOARD) && defined(ENCODERS_PAD_A_RIGHT) && defined(ENCODERS_PAD_B_RIGHT) 105#ifndef SPLIT_KEYBOARD
68 if (!isLeftHand) { 106 numEncodersHere = NUMBER_OF_ENCODERS;
69 const pin_t encoders_pad_a_right[] = ENCODERS_PAD_A_RIGHT; 107 pad_a = encoders_pad_a;
70 const pin_t encoders_pad_b_right[] = ENCODERS_PAD_B_RIGHT; 108 pad_b = encoders_pad_b;
71# if defined(ENCODER_RESOLUTIONS_RIGHT) 109 firstEncoderHere = 0;
72 const uint8_t encoder_resolutions_right[] = ENCODER_RESOLUTIONS_RIGHT; 110#else
73# endif 111 if (isLeftHand) {
74 for (uint8_t i = 0; i < NUMBER_OF_ENCODERS; i++) { 112 numEncodersHere = NUMBER_OF_ENCODERS_LEFT;
75 encoders_pad_a[i] = encoders_pad_a_right[i]; 113 pad_a = encoders_pad_a;
76 encoders_pad_b[i] = encoders_pad_b_right[i]; 114 pad_b = encoders_pad_b;
77# if defined(ENCODER_RESOLUTIONS_RIGHT) 115 firstEncoderHere = 0;
78 encoder_resolutions[i] = encoder_resolutions_right[i]; 116 firstEncoderThere = NUMBER_OF_ENCODERS_LEFT;
79# endif 117 } else {
80 } 118 numEncodersHere = NUMBER_OF_ENCODERS_RIGHT;
119 pad_a = encoders_pad_a_right;
120 pad_b = encoders_pad_b_right;
121 firstEncoderHere = NUMBER_OF_ENCODERS_LEFT;
122 firstEncoderThere = 0;
81 } 123 }
82#endif 124#endif
83 125
84 for (int i = 0; i < NUMBER_OF_ENCODERS; i++) { 126 for (int i = 0; i < numEncodersHere; i++) {
85 setPinInputHigh(encoders_pad_a[i]); 127 setPinInputHigh(pad_a[i]);
86 setPinInputHigh(encoders_pad_b[i]); 128 setPinInputHigh(pad_b[i]);
87 129
88 encoder_state[i] = (readPin(encoders_pad_a[i]) << 0) | (readPin(encoders_pad_b[i]) << 1); 130 encoder_state[firstEncoderHere + i] = (readPin(pad_a[i]) << 0) | (readPin(pad_b[i]) << 1);
89 } 131 }
90
91#ifdef SPLIT_KEYBOARD
92 thisHand = isLeftHand ? 0 : NUMBER_OF_ENCODERS;
93 thatHand = NUMBER_OF_ENCODERS - thisHand;
94#endif
95} 132}
96 133
97static bool encoder_update(uint8_t index, uint8_t state) { 134static bool encoder_update(int8_t index, uint8_t state) {
98 bool changed = false; 135 bool changed = false;
99 uint8_t i = index;
100 136
101#ifdef ENCODER_RESOLUTIONS 137#ifdef ENCODER_RESOLUTIONS
102 uint8_t resolution = encoder_resolutions[i]; 138# ifndef SPLIT_KEYBOARD
139 int8_t resolution = encoder_resolutions[index];
140# else
141 int8_t resolution = isLeftHand ? encoder_resolutions[index] : encoder_resolutions_right[index - NUMBER_OF_ENCODERS_LEFT];
142# endif
103#else 143#else
104 uint8_t resolution = ENCODER_RESOLUTION; 144 uint8_t resolution = ENCODER_RESOLUTION;
105#endif 145#endif
106 146 encoder_pulses[index] += encoder_LUT[state & 0xF];
107#ifdef SPLIT_KEYBOARD 147 if (encoder_pulses[index] >= resolution) {
108 index += thisHand;
109#endif
110 encoder_pulses[i] += encoder_LUT[state & 0xF];
111 if (encoder_pulses[i] >= resolution) {
112 encoder_value[index]++; 148 encoder_value[index]++;
113 changed = true; 149 changed = true;
114 encoder_update_kb(index, ENCODER_COUNTER_CLOCKWISE); 150 encoder_update_kb(index, ENCODER_COUNTER_CLOCKWISE);
115 } 151 }
116 if (encoder_pulses[i] <= -resolution) { // direction is arbitrary here, but this clockwise 152 if (encoder_pulses[index] <= -resolution) { // direction is arbitrary here, but this clockwise
117 encoder_value[index]--; 153 encoder_value[index]--;
118 changed = true; 154 changed = true;
119 encoder_update_kb(index, ENCODER_CLOCKWISE); 155 encoder_update_kb(index, ENCODER_CLOCKWISE);
120 } 156 }
121 encoder_pulses[i] %= resolution; 157 encoder_pulses[index] %= resolution;
122#ifdef ENCODER_DEFAULT_POS 158#ifdef ENCODER_DEFAULT_POS
123 if ((state & 0x3) == ENCODER_DEFAULT_POS) { 159 if ((state & 0x3) == ENCODER_DEFAULT_POS) {
124 encoder_pulses[i] = 0; 160 encoder_pulses[index] = 0;
125 } 161 }
126#endif 162#endif
127 return changed; 163 return changed;
@@ -129,10 +165,10 @@ static bool encoder_update(uint8_t index, uint8_t state) {
129 165
130bool encoder_read(void) { 166bool encoder_read(void) {
131 bool changed = false; 167 bool changed = false;
132 for (uint8_t i = 0; i < NUMBER_OF_ENCODERS; i++) { 168 for (uint8_t i = 0; i < numEncodersHere; i++) {
133 encoder_state[i] <<= 2; 169 encoder_state[firstEncoderHere + i] <<= 2;
134 encoder_state[i] |= (readPin(encoders_pad_a[i]) << 0) | (readPin(encoders_pad_b[i]) << 1); 170 encoder_state[firstEncoderHere + i] |= (readPin(pad_a[i]) << 0) | (readPin(pad_b[i]) << 1);
135 changed |= encoder_update(i, encoder_state[i]); 171 changed |= encoder_update(firstEncoderHere + i, encoder_state[firstEncoderHere + i]);
136 } 172 }
137 return changed; 173 return changed;
138} 174}
@@ -140,12 +176,12 @@ bool encoder_read(void) {
140#ifdef SPLIT_KEYBOARD 176#ifdef SPLIT_KEYBOARD
141void last_encoder_activity_trigger(void); 177void last_encoder_activity_trigger(void);
142 178
143void encoder_state_raw(uint8_t* slave_state) { memcpy(slave_state, &encoder_value[thisHand], sizeof(uint8_t) * NUMBER_OF_ENCODERS); } 179void encoder_state_raw(uint8_t* slave_state) { memcpy(slave_state, &encoder_value[firstEncoderHere], sizeof(uint8_t) * numEncodersHere); }
144 180
145void encoder_update_raw(uint8_t* slave_state) { 181void encoder_update_raw(uint8_t* slave_state) {
146 bool changed = false; 182 bool changed = false;
147 for (uint8_t i = 0; i < NUMBER_OF_ENCODERS; i++) { 183 for (uint8_t i = 0; i < NUMBER_OF_ENCODERS - numEncodersHere; i++) {
148 uint8_t index = i + thatHand; 184 uint8_t index = firstEncoderThere + i;
149 int8_t delta = slave_state[i] - encoder_value[index]; 185 int8_t delta = slave_state[i] - encoder_value[index];
150 while (delta > 0) { 186 while (delta > 0) {
151 delta--; 187 delta--;