aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build_test.mk1
-rw-r--r--docs/feature_encoders.md15
-rw-r--r--quantum/encoder.c146
-rw-r--r--quantum/encoder.h3
-rw-r--r--quantum/encoder/tests/encoder_tests.cpp144
-rw-r--r--quantum/encoder/tests/encoder_tests_split.cpp143
-rw-r--r--quantum/encoder/tests/mock.c34
-rw-r--r--quantum/encoder/tests/mock.h40
-rw-r--r--quantum/encoder/tests/mock_split.c36
-rw-r--r--quantum/encoder/tests/mock_split.h48
-rw-r--r--quantum/encoder/tests/rules.mk13
-rw-r--r--quantum/encoder/tests/testlist.mk3
-rw-r--r--quantum/split_common/transport.h7
-rw-r--r--testlist.mk1
14 files changed, 58 insertions, 576 deletions
diff --git a/build_test.mk b/build_test.mk
index 136a0455f..a5d63adab 100644
--- a/build_test.mk
+++ b/build_test.mk
@@ -58,7 +58,6 @@ include $(BUILDDEFS_PATH)/generic_features.mk
58include $(PLATFORM_PATH)/common.mk 58include $(PLATFORM_PATH)/common.mk
59include $(TMK_PATH)/protocol.mk 59include $(TMK_PATH)/protocol.mk
60include $(QUANTUM_PATH)/debounce/tests/rules.mk 60include $(QUANTUM_PATH)/debounce/tests/rules.mk
61include $(QUANTUM_PATH)/encoder/tests/rules.mk
62include $(QUANTUM_PATH)/sequencer/tests/rules.mk 61include $(QUANTUM_PATH)/sequencer/tests/rules.mk
63include $(PLATFORM_PATH)/test/rules.mk 62include $(PLATFORM_PATH)/test/rules.mk
64ifneq ($(filter $(FULL_TESTS),$(TEST)),) 63ifneq ($(filter $(FULL_TESTS),$(TEST)),)
diff --git a/docs/feature_encoders.md b/docs/feature_encoders.md
index 5b6c3f163..8e854c1e5 100644
--- a/docs/feature_encoders.md
+++ b/docs/feature_encoders.md
@@ -46,9 +46,7 @@ For 4× encoders you also can assign default position if encoder skips pulses wh
46 46
47## Split Keyboards 47## Split Keyboards
48 48
49The above is enough for split keyboards that are symmetrical, i.e. the halves have the same number of encoders and they are on the same pins. 49If you are using different pinouts for the encoders on each half of a split keyboard, you can define the pinout (and optionally, resolutions) for the right half like this:
50If the halves are not symmetrical, you can define the pinout (and optionally, resolutions) of the right half separately.
51The left half will use the definitions above.
52 50
53```c 51```c
54#define ENCODERS_PAD_A_RIGHT { encoder1a, encoder2a } 52#define ENCODERS_PAD_A_RIGHT { encoder1a, encoder2a }
@@ -56,17 +54,6 @@ The left half will use the definitions above.
56#define ENCODER_RESOLUTIONS_RIGHT { 2, 4 } 54#define ENCODER_RESOLUTIONS_RIGHT { 2, 4 }
57``` 55```
58 56
59If only the right half has encoders, you must still define an empty array for the left pads (and resolutions, if you define `ENCODER_RESOLUTIONS_RIGHT`).
60
61```c
62#define ENCODERS_PAD_A { }
63#define ENCODERS_PAD_B { }
64#define ENCODER_RESOLUTIONS { }
65#define ENCODERS_PAD_A_RIGHT { encoder1a, encoder2a }
66#define ENCODERS_PAD_B_RIGHT { encoder1b, encoder2b }
67#define ENCODER_RESOLUTIONS_RIGHT { 2, 4 }
68```
69
70## Callbacks 57## Callbacks
71 58
72The callback functions can be inserted into your `<keyboard>.c`: 59The callback functions can be inserted into your `<keyboard>.c`:
diff --git a/quantum/encoder.c b/quantum/encoder.c
index 7d4e97898..8fb87281c 100644
--- a/quantum/encoder.c
+++ b/quantum/encoder.c
@@ -16,17 +16,8 @@
16 */ 16 */
17 17
18#include "encoder.h" 18#include "encoder.h"
19 19#ifdef SPLIT_KEYBOARD
20// this is for unit testing 20# include "split_util.h"
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
30#endif 21#endif
31 22
32// for memcpy 23// for memcpy
@@ -36,41 +27,17 @@
36# define ENCODER_RESOLUTION 4 27# define ENCODER_RESOLUTION 4
37#endif 28#endif
38 29
39#if (!defined(ENCODERS_PAD_A) || !defined(ENCODERS_PAD_B)) && (!defined(ENCODERS_PAD_A) || !defined(ENCODERS_PAD_B)) 30#if !defined(ENCODERS_PAD_A) || !defined(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" 31# error "No encoder pads defined by ENCODERS_PAD_A and ENCODERS_PAD_B"
41#endif 32#endif
42 33
43// on split keyboards, these are the pads and resolutions for the left half 34#define NUMBER_OF_ENCODERS (sizeof(encoders_pad_a) / sizeof(pin_t))
44static pin_t encoders_pad_a[] = ENCODERS_PAD_A; 35static pin_t encoders_pad_a[] = ENCODERS_PAD_A;
45static pin_t encoders_pad_b[] = ENCODERS_PAD_B; 36static pin_t encoders_pad_b[] = ENCODERS_PAD_B;
46#ifdef ENCODER_RESOLUTIONS 37#ifdef ENCODER_RESOLUTIONS
47static uint8_t encoder_resolutions[] = ENCODER_RESOLUTIONS; 38static uint8_t encoder_resolutions[] = ENCODER_RESOLUTIONS;
48#endif 39#endif
49 40
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
74#ifndef ENCODER_DIRECTION_FLIP 41#ifndef ENCODER_DIRECTION_FLIP
75# define ENCODER_CLOCKWISE true 42# define ENCODER_CLOCKWISE true
76# define ENCODER_COUNTER_CLOCKWISE false 43# define ENCODER_COUNTER_CLOCKWISE false
@@ -83,81 +50,78 @@ static int8_t encoder_LUT[] = {0, -1, 1, 0, 1, 0, 0, -1, -1, 0, 0, 1, 0, 1, -1,
83static uint8_t encoder_state[NUMBER_OF_ENCODERS] = {0}; 50static uint8_t encoder_state[NUMBER_OF_ENCODERS] = {0};
84static int8_t encoder_pulses[NUMBER_OF_ENCODERS] = {0}; 51static int8_t encoder_pulses[NUMBER_OF_ENCODERS] = {0};
85 52
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
86static uint8_t encoder_value[NUMBER_OF_ENCODERS] = {0}; 59static uint8_t encoder_value[NUMBER_OF_ENCODERS] = {0};
60#endif
87 61
88__attribute__((weak)) bool encoder_update_user(uint8_t index, bool clockwise) { return true; } 62__attribute__((weak)) bool encoder_update_user(uint8_t index, bool clockwise) { return true; }
89 63
90__attribute__((weak)) bool encoder_update_kb(uint8_t index, bool clockwise) { return encoder_update_user(index, clockwise); } 64__attribute__((weak)) bool encoder_update_kb(uint8_t index, bool clockwise) { return encoder_update_user(index, clockwise); }
91 65
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
104void encoder_init(void) { 66void encoder_init(void) {
105#ifndef SPLIT_KEYBOARD 67#if defined(SPLIT_KEYBOARD) && defined(ENCODERS_PAD_A_RIGHT) && defined(ENCODERS_PAD_B_RIGHT)
106 numEncodersHere = NUMBER_OF_ENCODERS; 68 if (!isLeftHand) {
107 pad_a = encoders_pad_a; 69 const pin_t encoders_pad_a_right[] = ENCODERS_PAD_A_RIGHT;
108 pad_b = encoders_pad_b; 70 const pin_t encoders_pad_b_right[] = ENCODERS_PAD_B_RIGHT;
109 firstEncoderHere = 0; 71# if defined(ENCODER_RESOLUTIONS_RIGHT)
110#else 72 const uint8_t encoder_resolutions_right[] = ENCODER_RESOLUTIONS_RIGHT;
111 if (isLeftHand) { 73# endif
112 numEncodersHere = NUMBER_OF_ENCODERS_LEFT; 74 for (uint8_t i = 0; i < NUMBER_OF_ENCODERS; i++) {
113 pad_a = encoders_pad_a; 75 encoders_pad_a[i] = encoders_pad_a_right[i];
114 pad_b = encoders_pad_b; 76 encoders_pad_b[i] = encoders_pad_b_right[i];
115 firstEncoderHere = 0; 77# if defined(ENCODER_RESOLUTIONS_RIGHT)
116 firstEncoderThere = NUMBER_OF_ENCODERS_LEFT; 78 encoder_resolutions[i] = encoder_resolutions_right[i];
117 } else { 79# endif
118 numEncodersHere = NUMBER_OF_ENCODERS_RIGHT; 80 }
119 pad_a = encoders_pad_a_right;
120 pad_b = encoders_pad_b_right;
121 firstEncoderHere = NUMBER_OF_ENCODERS_LEFT;
122 firstEncoderThere = 0;
123 } 81 }
124#endif 82#endif
125 83
126 for (int i = 0; i < numEncodersHere; i++) { 84 for (int i = 0; i < NUMBER_OF_ENCODERS; i++) {
127 setPinInputHigh(pad_a[i]); 85 setPinInputHigh(encoders_pad_a[i]);
128 setPinInputHigh(pad_b[i]); 86 setPinInputHigh(encoders_pad_b[i]);
129 87
130 encoder_state[firstEncoderHere + i] = (readPin(pad_a[i]) << 0) | (readPin(pad_b[i]) << 1); 88 encoder_state[i] = (readPin(encoders_pad_a[i]) << 0) | (readPin(encoders_pad_b[i]) << 1);
131 } 89 }
90
91#ifdef SPLIT_KEYBOARD
92 thisHand = isLeftHand ? 0 : NUMBER_OF_ENCODERS;
93 thatHand = NUMBER_OF_ENCODERS - thisHand;
94#endif
132} 95}
133 96
134static bool encoder_update(int8_t index, uint8_t state) { 97static bool encoder_update(uint8_t index, uint8_t state) {
135 bool changed = false; 98 bool changed = false;
99 uint8_t i = index;
136 100
137#ifdef ENCODER_RESOLUTIONS 101#ifdef ENCODER_RESOLUTIONS
138# ifndef SPLIT_KEYBOARD 102 uint8_t resolution = encoder_resolutions[i];
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
143#else 103#else
144 uint8_t resolution = ENCODER_RESOLUTION; 104 uint8_t resolution = ENCODER_RESOLUTION;
145#endif 105#endif
146 encoder_pulses[index] += encoder_LUT[state & 0xF]; 106
147 if (encoder_pulses[index] >= resolution) { 107#ifdef SPLIT_KEYBOARD
108 index += thisHand;
109#endif
110 encoder_pulses[i] += encoder_LUT[state & 0xF];
111 if (encoder_pulses[i] >= resolution) {
148 encoder_value[index]++; 112 encoder_value[index]++;
149 changed = true; 113 changed = true;
150 encoder_update_kb(index, ENCODER_COUNTER_CLOCKWISE); 114 encoder_update_kb(index, ENCODER_COUNTER_CLOCKWISE);
151 } 115 }
152 if (encoder_pulses[index] <= -resolution) { // direction is arbitrary here, but this clockwise 116 if (encoder_pulses[i] <= -resolution) { // direction is arbitrary here, but this clockwise
153 encoder_value[index]--; 117 encoder_value[index]--;
154 changed = true; 118 changed = true;
155 encoder_update_kb(index, ENCODER_CLOCKWISE); 119 encoder_update_kb(index, ENCODER_CLOCKWISE);
156 } 120 }
157 encoder_pulses[index] %= resolution; 121 encoder_pulses[i] %= resolution;
158#ifdef ENCODER_DEFAULT_POS 122#ifdef ENCODER_DEFAULT_POS
159 if ((state & 0x3) == ENCODER_DEFAULT_POS) { 123 if ((state & 0x3) == ENCODER_DEFAULT_POS) {
160 encoder_pulses[index] = 0; 124 encoder_pulses[i] = 0;
161 } 125 }
162#endif 126#endif
163 return changed; 127 return changed;
@@ -165,10 +129,10 @@ static bool encoder_update(int8_t index, uint8_t state) {
165 129
166bool encoder_read(void) { 130bool encoder_read(void) {
167 bool changed = false; 131 bool changed = false;
168 for (uint8_t i = 0; i < numEncodersHere; i++) { 132 for (uint8_t i = 0; i < NUMBER_OF_ENCODERS; i++) {
169 encoder_state[firstEncoderHere + i] <<= 2; 133 encoder_state[i] <<= 2;
170 encoder_state[firstEncoderHere + i] |= (readPin(pad_a[i]) << 0) | (readPin(pad_b[i]) << 1); 134 encoder_state[i] |= (readPin(encoders_pad_a[i]) << 0) | (readPin(encoders_pad_b[i]) << 1);
171 changed |= encoder_update(firstEncoderHere + i, encoder_state[firstEncoderHere + i]); 135 changed |= encoder_update(i, encoder_state[i]);
172 } 136 }
173 return changed; 137 return changed;
174} 138}
@@ -176,12 +140,12 @@ bool encoder_read(void) {
176#ifdef SPLIT_KEYBOARD 140#ifdef SPLIT_KEYBOARD
177void last_encoder_activity_trigger(void); 141void last_encoder_activity_trigger(void);
178 142
179void encoder_state_raw(uint8_t* slave_state) { memcpy(slave_state, &encoder_value[firstEncoderHere], sizeof(uint8_t) * numEncodersHere); } 143void encoder_state_raw(uint8_t* slave_state) { memcpy(slave_state, &encoder_value[thisHand], sizeof(uint8_t) * NUMBER_OF_ENCODERS); }
180 144
181void encoder_update_raw(uint8_t* slave_state) { 145void encoder_update_raw(uint8_t* slave_state) {
182 bool changed = false; 146 bool changed = false;
183 for (uint8_t i = 0; i < NUMBER_OF_ENCODERS - numEncodersHere; i++) { 147 for (uint8_t i = 0; i < NUMBER_OF_ENCODERS; i++) {
184 uint8_t index = firstEncoderThere + i; 148 uint8_t index = i + thatHand;
185 int8_t delta = slave_state[i] - encoder_value[index]; 149 int8_t delta = slave_state[i] - encoder_value[index];
186 while (delta > 0) { 150 while (delta > 0) {
187 delta--; 151 delta--;
diff --git a/quantum/encoder.h b/quantum/encoder.h
index 67f71ec0f..25dc77721 100644
--- a/quantum/encoder.h
+++ b/quantum/encoder.h
@@ -17,8 +17,7 @@
17 17
18#pragma once 18#pragma once
19 19
20#include <stdbool.h> 20#include "quantum.h"
21#include <stdint.h>
22 21
23void encoder_init(void); 22void encoder_init(void);
24bool encoder_read(void); 23bool encoder_read(void);
diff --git a/quantum/encoder/tests/encoder_tests.cpp b/quantum/encoder/tests/encoder_tests.cpp
deleted file mode 100644
index 1888fdab8..000000000
--- a/quantum/encoder/tests/encoder_tests.cpp
+++ /dev/null
@@ -1,144 +0,0 @@
1/* Copyright 2021 Balz Guenat
2 *
3 * This program is free software: you can redistribute it and/or modify
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 */
16
17#include "gtest/gtest.h"
18#include "gmock/gmock.h"
19#include <vector>
20#include <algorithm>
21#include <stdio.h>
22
23extern "C" {
24#include "encoder.h"
25#include "encoder/tests/mock.h"
26}
27
28struct update {
29 int8_t index;
30 bool clockwise;
31};
32
33uint8_t uidx = 0;
34update updates[32];
35
36bool encoder_update_kb(uint8_t index, bool clockwise) {
37 updates[uidx % 32] = {index, clockwise};
38 uidx++;
39 return true;
40}
41
42bool setAndRead(pin_t pin, bool val) {
43 setPin(pin, val);
44 return encoder_read();
45}
46
47class EncoderTest : public ::testing::Test {};
48
49TEST_F(EncoderTest, TestInit) {
50 uidx = 0;
51 encoder_init();
52 EXPECT_EQ(pinIsInputHigh[0], true);
53 EXPECT_EQ(pinIsInputHigh[1], true);
54 EXPECT_EQ(uidx, 0);
55}
56
57TEST_F(EncoderTest, TestOneClockwise) {
58 uidx = 0;
59 encoder_init();
60 // send 4 pulses. with resolution 4, that's one step and we should get 1 update.
61 setAndRead(0, false);
62 setAndRead(1, false);
63 setAndRead(0, true);
64 setAndRead(1, true);
65
66 EXPECT_EQ(uidx, 1);
67 EXPECT_EQ(updates[0].index, 0);
68 EXPECT_EQ(updates[0].clockwise, true);
69}
70
71TEST_F(EncoderTest, TestOneCounterClockwise) {
72 uidx = 0;
73 encoder_init();
74 setAndRead(1, false);
75 setAndRead(0, false);
76 setAndRead(1, true);
77 setAndRead(0, true);
78
79 EXPECT_EQ(uidx, 1);
80 EXPECT_EQ(updates[0].index, 0);
81 EXPECT_EQ(updates[0].clockwise, false);
82}
83
84TEST_F(EncoderTest, TestTwoClockwiseOneCC) {
85 uidx = 0;
86 encoder_init();
87 setAndRead(0, false);
88 setAndRead(1, false);
89 setAndRead(0, true);
90 setAndRead(1, true);
91 setAndRead(0, false);
92 setAndRead(1, false);
93 setAndRead(0, true);
94 setAndRead(1, true);
95 setAndRead(1, false);
96 setAndRead(0, false);
97 setAndRead(1, true);
98 setAndRead(0, true);
99
100 EXPECT_EQ(uidx, 3);
101 EXPECT_EQ(updates[0].index, 0);
102 EXPECT_EQ(updates[0].clockwise, true);
103 EXPECT_EQ(updates[1].index, 0);
104 EXPECT_EQ(updates[1].clockwise, true);
105 EXPECT_EQ(updates[2].index, 0);
106 EXPECT_EQ(updates[2].clockwise, false);
107}
108
109TEST_F(EncoderTest, TestNoEarly) {
110 uidx = 0;
111 encoder_init();
112 // send 3 pulses. with resolution 4, that's not enough for a step.
113 setAndRead(0, false);
114 setAndRead(1, false);
115 setAndRead(0, true);
116 EXPECT_EQ(uidx, 0);
117 // now send last pulse
118 setAndRead(1, true);
119 EXPECT_EQ(uidx, 1);
120 EXPECT_EQ(updates[0].index, 0);
121 EXPECT_EQ(updates[0].clockwise, true);
122}
123
124TEST_F(EncoderTest, TestHalfway) {
125 uidx = 0;
126 encoder_init();
127 // go halfway
128 setAndRead(0, false);
129 setAndRead(1, false);
130 EXPECT_EQ(uidx, 0);
131 // back off
132 setAndRead(1, true);
133 setAndRead(0, true);
134 EXPECT_EQ(uidx, 0);
135 // go all the way
136 setAndRead(0, false);
137 setAndRead(1, false);
138 setAndRead(0, true);
139 setAndRead(1, true);
140 // should result in 1 update
141 EXPECT_EQ(uidx, 1);
142 EXPECT_EQ(updates[0].index, 0);
143 EXPECT_EQ(updates[0].clockwise, true);
144}
diff --git a/quantum/encoder/tests/encoder_tests_split.cpp b/quantum/encoder/tests/encoder_tests_split.cpp
deleted file mode 100644
index 25e52c83f..000000000
--- a/quantum/encoder/tests/encoder_tests_split.cpp
+++ /dev/null
@@ -1,143 +0,0 @@
1/* Copyright 2021 Balz Guenat
2 *
3 * This program is free software: you can redistribute it and/or modify
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 */
16
17#include "gtest/gtest.h"
18#include "gmock/gmock.h"
19#include <vector>
20#include <algorithm>
21#include <stdio.h>
22
23extern "C" {
24#include "encoder.h"
25#include "encoder/tests/mock_split.h"
26}
27
28struct update {
29 int8_t index;
30 bool clockwise;
31};
32
33uint8_t uidx = 0;
34update updates[32];
35
36bool isLeftHand;
37
38bool encoder_update_kb(uint8_t index, bool clockwise) {
39 if (!isLeftHand) {
40 // this method has no effect on slave half
41 printf("ignoring update on right hand (%d,%s)\n", index, clockwise ? "CW" : "CC");
42 return true;
43 }
44 updates[uidx % 32] = {index, clockwise};
45 uidx++;
46 return true;
47}
48
49bool setAndRead(pin_t pin, bool val) {
50 setPin(pin, val);
51 return encoder_read();
52}
53
54class EncoderTest : public ::testing::Test {
55 protected:
56 void SetUp() override {
57 uidx = 0;
58 for (int i = 0; i < 32; i++) {
59 pinIsInputHigh[i] = 0;
60 pins[i] = 0;
61 }
62 }
63};
64
65TEST_F(EncoderTest, TestInitLeft) {
66 isLeftHand = true;
67 encoder_init();
68 EXPECT_EQ(pinIsInputHigh[0], true);
69 EXPECT_EQ(pinIsInputHigh[1], true);
70 EXPECT_EQ(pinIsInputHigh[2], false);
71 EXPECT_EQ(pinIsInputHigh[3], false);
72 EXPECT_EQ(uidx, 0);
73}
74
75TEST_F(EncoderTest, TestInitRight) {
76 isLeftHand = false;
77 encoder_init();
78 EXPECT_EQ(pinIsInputHigh[0], false);
79 EXPECT_EQ(pinIsInputHigh[1], false);
80 EXPECT_EQ(pinIsInputHigh[2], true);
81 EXPECT_EQ(pinIsInputHigh[3], true);
82 EXPECT_EQ(uidx, 0);
83}
84
85TEST_F(EncoderTest, TestOneClockwiseLeft) {
86 isLeftHand = true;
87 encoder_init();
88 // send 4 pulses. with resolution 4, that's one step and we should get 1 update.
89 setAndRead(0, false);
90 setAndRead(1, false);
91 setAndRead(0, true);
92 setAndRead(1, true);
93
94 EXPECT_EQ(uidx, 1);
95 EXPECT_EQ(updates[0].index, 0);
96 EXPECT_EQ(updates[0].clockwise, true);
97}
98
99TEST_F(EncoderTest, TestOneClockwiseRightSent) {
100 isLeftHand = false;
101 encoder_init();
102 // send 4 pulses. with resolution 4, that's one step and we should get 1 update.
103 setAndRead(2, false);
104 setAndRead(3, false);
105 setAndRead(2, true);
106 setAndRead(3, true);
107
108 uint8_t slave_state[2] = {0};
109 encoder_state_raw(slave_state);
110
111 EXPECT_EQ((int8_t)slave_state[0], -1);
112}
113
114/* this test will not work after the previous test.
115 * this is due to encoder_value[1] already being set to -1 when simulating the right half.
116 * When we now receive this update acting as the left half, there is no change.
117 * This is hard to mock, as the static values inside encoder.c normally exist twice, once on each half,
118 * but here, they only exist once.
119 */
120
121// TEST_F(EncoderTest, TestOneClockwiseRightReceived) {
122// isLeftHand = true;
123// encoder_init();
124
125// uint8_t slave_state[2] = {255, 0};
126// encoder_update_raw(slave_state);
127
128// EXPECT_EQ(uidx, 1);
129// EXPECT_EQ(updates[0].index, 1);
130// EXPECT_EQ(updates[0].clockwise, true);
131// }
132
133TEST_F(EncoderTest, TestOneCounterClockwiseRightReceived) {
134 isLeftHand = true;
135 encoder_init();
136
137 uint8_t slave_state[2] = {0, 0};
138 encoder_update_raw(slave_state);
139
140 EXPECT_EQ(uidx, 1);
141 EXPECT_EQ(updates[0].index, 1);
142 EXPECT_EQ(updates[0].clockwise, false);
143}
diff --git a/quantum/encoder/tests/mock.c b/quantum/encoder/tests/mock.c
deleted file mode 100644
index d0506a938..000000000
--- a/quantum/encoder/tests/mock.c
+++ /dev/null
@@ -1,34 +0,0 @@
1/* Copyright 2021 Balz Guenat
2 *
3 * This program is free software: you can redistribute it and/or modify
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 */
16
17#include "mock.h"
18
19bool pins[32] = {0};
20bool pinIsInputHigh[32] = {0};
21
22uint8_t mockSetPinInputHigh(pin_t pin) {
23 // dprintf("Setting pin %d input high.", pin);
24 pins[pin] = true;
25 pinIsInputHigh[pin] = true;
26 return 0;
27}
28
29bool mockReadPin(pin_t pin) { return pins[pin]; }
30
31bool setPin(pin_t pin, bool val) {
32 pins[pin] = val;
33 return val;
34}
diff --git a/quantum/encoder/tests/mock.h b/quantum/encoder/tests/mock.h
deleted file mode 100644
index dbc25a084..000000000
--- a/quantum/encoder/tests/mock.h
+++ /dev/null
@@ -1,40 +0,0 @@
1/* Copyright 2021 Balz Guenat
2 *
3 * This program is free software: you can redistribute it and/or modify
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 */
16
17#pragma once
18
19#include <stdint.h>
20#include <stdbool.h>
21
22/* Here, "pins" from 0 to 31 are allowed. */
23#define ENCODERS_PAD_A \
24 { 0 }
25#define ENCODERS_PAD_B \
26 { 1 }
27
28typedef uint8_t pin_t;
29
30extern bool pins[];
31extern bool pinIsInputHigh[];
32
33#define setPinInputHigh(pin) (mockSetPinInputHigh(pin))
34#define readPin(pin) (mockReadPin(pin))
35
36uint8_t mockSetPinInputHigh(pin_t pin);
37
38bool mockReadPin(pin_t pin);
39
40bool setPin(pin_t pin, bool val);
diff --git a/quantum/encoder/tests/mock_split.c b/quantum/encoder/tests/mock_split.c
deleted file mode 100644
index 68bf3af59..000000000
--- a/quantum/encoder/tests/mock_split.c
+++ /dev/null
@@ -1,36 +0,0 @@
1/* Copyright 2021 Balz Guenat
2 *
3 * This program is free software: you can redistribute it and/or modify
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 */
16
17#include "mock_split.h"
18
19bool pins[32] = {0};
20bool pinIsInputHigh[32] = {0};
21
22uint8_t mockSetPinInputHigh(pin_t pin) {
23 // dprintf("Setting pin %d input high.", pin);
24 pins[pin] = true;
25 pinIsInputHigh[pin] = true;
26 return 0;
27}
28
29bool mockReadPin(pin_t pin) { return pins[pin]; }
30
31bool setPin(pin_t pin, bool val) {
32 pins[pin] = val;
33 return val;
34}
35
36void last_encoder_activity_trigger(void) {}
diff --git a/quantum/encoder/tests/mock_split.h b/quantum/encoder/tests/mock_split.h
deleted file mode 100644
index 0ae62652f..000000000
--- a/quantum/encoder/tests/mock_split.h
+++ /dev/null
@@ -1,48 +0,0 @@
1/* Copyright 2021 Balz Guenat
2 *
3 * This program is free software: you can redistribute it and/or modify
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 */
16
17#pragma once
18
19#include <stdint.h>
20#include <stdbool.h>
21
22#define SPLIT_KEYBOARD
23/* Here, "pins" from 0 to 31 are allowed. */
24#define ENCODERS_PAD_A \
25 { 0 }
26#define ENCODERS_PAD_B \
27 { 1 }
28#define ENCODERS_PAD_A_RIGHT \
29 { 2 }
30#define ENCODERS_PAD_B_RIGHT \
31 { 3 }
32
33typedef uint8_t pin_t;
34extern bool isLeftHand;
35void encoder_state_raw(uint8_t* slave_state);
36void encoder_update_raw(uint8_t* slave_state);
37
38extern bool pins[];
39extern bool pinIsInputHigh[];
40
41#define setPinInputHigh(pin) (mockSetPinInputHigh(pin))
42#define readPin(pin) (mockReadPin(pin))
43
44uint8_t mockSetPinInputHigh(pin_t pin);
45
46bool mockReadPin(pin_t pin);
47
48bool setPin(pin_t pin, bool val);
diff --git a/quantum/encoder/tests/rules.mk b/quantum/encoder/tests/rules.mk
deleted file mode 100644
index b826ce3ae..000000000
--- a/quantum/encoder/tests/rules.mk
+++ /dev/null
@@ -1,13 +0,0 @@
1encoder_DEFS := -DENCODER_MOCK_SINGLE
2
3encoder_SRC := \
4 $(QUANTUM_PATH)/encoder/tests/mock.c \
5 $(QUANTUM_PATH)/encoder/tests/encoder_tests.cpp \
6 $(QUANTUM_PATH)/encoder.c
7
8encoder_split_DEFS := -DENCODER_MOCK_SPLIT
9
10encoder_split_SRC := \
11 $(QUANTUM_PATH)/encoder/tests/mock_split.c \
12 $(QUANTUM_PATH)/encoder/tests/encoder_tests_split.cpp \
13 $(QUANTUM_PATH)/encoder.c
diff --git a/quantum/encoder/tests/testlist.mk b/quantum/encoder/tests/testlist.mk
deleted file mode 100644
index 1be9f4a05..000000000
--- a/quantum/encoder/tests/testlist.mk
+++ /dev/null
@@ -1,3 +0,0 @@
1TEST_LIST += \
2 encoder \
3 encoder_split
diff --git a/quantum/split_common/transport.h b/quantum/split_common/transport.h
index 437d4bc1f..1d4f6ed0c 100644
--- a/quantum/split_common/transport.h
+++ b/quantum/split_common/transport.h
@@ -41,13 +41,8 @@ void transport_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]);
41bool transport_execute_transaction(int8_t id, const void *initiator2target_buf, uint16_t initiator2target_length, void *target2initiator_buf, uint16_t target2initiator_length); 41bool transport_execute_transaction(int8_t id, const void *initiator2target_buf, uint16_t initiator2target_length, void *target2initiator_buf, uint16_t target2initiator_length);
42 42
43#ifdef ENCODER_ENABLE 43#ifdef ENCODER_ENABLE
44# include "gpio.h"
45# include "encoder.h" 44# include "encoder.h"
46// if no pads for right half are defined, we assume the keyboard is symmetric (i.e. same pads) 45# define NUMBER_OF_ENCODERS (sizeof((pin_t[])ENCODERS_PAD_A) / sizeof(pin_t))
47# ifndef ENCODERS_PAD_A_RIGHT
48# define ENCODERS_PAD_A_RIGHT ENCODERS_PAD_A
49# endif
50# define NUMBER_OF_ENCODERS ((sizeof((pin_t[])ENCODERS_PAD_A) + sizeof((pin_t[])ENCODERS_PAD_A_RIGHT)) / sizeof(pin_t))
51#endif // ENCODER_ENABLE 46#endif // ENCODER_ENABLE
52 47
53#ifdef BACKLIGHT_ENABLE 48#ifdef BACKLIGHT_ENABLE
diff --git a/testlist.mk b/testlist.mk
index d2bb571be..904485c15 100644
--- a/testlist.mk
+++ b/testlist.mk
@@ -2,7 +2,6 @@ TEST_LIST = $(sort $(patsubst %/test.mk,%, $(shell find $(ROOT_DIR)tests -type f
2FULL_TESTS := $(notdir $(TEST_LIST)) 2FULL_TESTS := $(notdir $(TEST_LIST))
3 3
4include $(QUANTUM_PATH)/debounce/tests/testlist.mk 4include $(QUANTUM_PATH)/debounce/tests/testlist.mk
5include $(QUANTUM_PATH)/encoder/tests/testlist.mk
6include $(QUANTUM_PATH)/sequencer/tests/testlist.mk 5include $(QUANTUM_PATH)/sequencer/tests/testlist.mk
7include $(PLATFORM_PATH)/test/testlist.mk 6include $(PLATFORM_PATH)/test/testlist.mk
8 7