diff options
27 files changed, 921 insertions, 138 deletions
diff --git a/builddefs/build_test.mk b/builddefs/build_test.mk index 7226004aab..5ad33b19c5 100644 --- a/builddefs/build_test.mk +++ b/builddefs/build_test.mk | |||
| @@ -4,6 +4,8 @@ endif | |||
| 4 | 4 | ||
| 5 | .DEFAULT_GOAL := all | 5 | .DEFAULT_GOAL := all |
| 6 | 6 | ||
| 7 | OPT = g | ||
| 8 | |||
| 7 | include paths.mk | 9 | include paths.mk |
| 8 | include $(BUILDDEFS_PATH)/message.mk | 10 | include $(BUILDDEFS_PATH)/message.mk |
| 9 | 11 | ||
diff --git a/builddefs/testlist.mk b/builddefs/testlist.mk index 86da5668ac..b8d22bce80 100644 --- a/builddefs/testlist.mk +++ b/builddefs/testlist.mk | |||
| @@ -2,6 +2,7 @@ TEST_LIST = $(sort $(patsubst %/test.mk,%, $(shell find $(ROOT_DIR)tests -type f | |||
| 2 | FULL_TESTS := $(notdir $(TEST_LIST)) | 2 | FULL_TESTS := $(notdir $(TEST_LIST)) |
| 3 | 3 | ||
| 4 | include $(QUANTUM_PATH)/debounce/tests/testlist.mk | 4 | include $(QUANTUM_PATH)/debounce/tests/testlist.mk |
| 5 | include $(QUANTUM_PATH)/encoder/tests/testlist.mk | ||
| 5 | include $(QUANTUM_PATH)/sequencer/tests/testlist.mk | 6 | include $(QUANTUM_PATH)/sequencer/tests/testlist.mk |
| 6 | include $(PLATFORM_PATH)/test/testlist.mk | 7 | include $(PLATFORM_PATH)/test/testlist.mk |
| 7 | 8 | ||
diff --git a/docs/feature_encoders.md b/docs/feature_encoders.md index 6a1a3750a6..f71c7e7325 100644 --- a/docs/feature_encoders.md +++ b/docs/feature_encoders.md | |||
| @@ -54,6 +54,19 @@ If you are using different pinouts for the encoders on each half of a split keyb | |||
| 54 | #define ENCODER_RESOLUTIONS_RIGHT { 2, 4 } | 54 | #define ENCODER_RESOLUTIONS_RIGHT { 2, 4 } |
| 55 | ``` | 55 | ``` |
| 56 | 56 | ||
| 57 | If the `_RIGHT` definitions aren't specified in your `config.h`, then the non-`_RIGHT` versions will be applied to both sides of the split. | ||
| 58 | |||
| 59 | Additionally, if one side does not have an encoder, you can specify `{}` for the pins/resolution -- for example, a split keyboard with only a right-side encoder: | ||
| 60 | |||
| 61 | ```c | ||
| 62 | #define ENCODERS_PAD_A { } | ||
| 63 | #define ENCODERS_PAD_B { } | ||
| 64 | #define ENCODER_RESOLUTIONS { } | ||
| 65 | #define ENCODERS_PAD_A_RIGHT { B12 } | ||
| 66 | #define ENCODERS_PAD_B_RIGHT { B13 } | ||
| 67 | #define ENCODER_RESOLUTIONS_RIGHT { 4 } | ||
| 68 | ``` | ||
| 69 | |||
| 57 | ## Callbacks | 70 | ## Callbacks |
| 58 | 71 | ||
| 59 | The callback functions can be inserted into your `<keyboard>.c`: | 72 | The callback functions can be inserted into your `<keyboard>.c`: |
diff --git a/keyboards/draculad/config.h b/keyboards/draculad/config.h index abcdc76b4b..3060f801c6 100644 --- a/keyboards/draculad/config.h +++ b/keyboards/draculad/config.h | |||
| @@ -61,7 +61,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
| 61 | #define ENCODERS_PAD_A {B2 , B4} | 61 | #define ENCODERS_PAD_A {B2 , B4} |
| 62 | #define ENCODERS_PAD_B {B6 , B5} | 62 | #define ENCODERS_PAD_B {B6 , B5} |
| 63 | 63 | ||
| 64 | #define ENCODER_RESOLUTIONS { 4, 4, 4, 1} | 64 | #define ENCODER_RESOLUTIONS { 4, 4 } |
| 65 | #define ENCODER_RESOLUTIONS_RIGHT { 4, 1 } | ||
| 65 | #define UNUSED_PINS | 66 | #define UNUSED_PINS |
| 66 | 67 | ||
| 67 | #define EE_HANDS | 68 | #define EE_HANDS |
diff --git a/keyboards/sofle/keyhive/config.h b/keyboards/sofle/keyhive/config.h index c934754e65..93048f3cd1 100755 --- a/keyboards/sofle/keyhive/config.h +++ b/keyboards/sofle/keyhive/config.h | |||
| @@ -42,11 +42,12 @@ | |||
| 42 | #define DEBOUNCE 5 | 42 | #define DEBOUNCE 5 |
| 43 | 43 | ||
| 44 | // Encoder support | 44 | // Encoder support |
| 45 | #define ENCODERS_PAD_A { F5 } | 45 | #define ENCODERS_PAD_A { F5 } |
| 46 | #define ENCODERS_PAD_B { F4 } | 46 | #define ENCODERS_PAD_B { F4 } |
| 47 | #define ENCODERS_PAD_A_RIGHT { F4 } | 47 | #define ENCODERS_PAD_A_RIGHT { F4 } |
| 48 | #define ENCODERS_PAD_B_RIGHT { F5 } | 48 | #define ENCODERS_PAD_B_RIGHT { F5 } |
| 49 | #define ENCODER_RESOLUTIONS { 4, 2 } // Left encoder seems to have double-output issue but right does not. | 49 | #define ENCODER_RESOLUTIONS { 4 } |
| 50 | #define ENCODER_RESOLUTIONS_RIGHT { 2 } // Left encoder seems to have double-output issue but right does not. | ||
| 50 | 51 | ||
| 51 | #define TAP_CODE_DELAY 10 | 52 | #define TAP_CODE_DELAY 10 |
| 52 | 53 | ||
diff --git a/keyboards/viktus/sp_mini/config.h b/keyboards/viktus/sp_mini/config.h index 06b8c2f51a..ec13a240c2 100644 --- a/keyboards/viktus/sp_mini/config.h +++ b/keyboards/viktus/sp_mini/config.h | |||
| @@ -35,7 +35,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
| 35 | 35 | ||
| 36 | // wiring of each half | 36 | // wiring of each half |
| 37 | #define MATRIX_ROW_PINS { F0, B5, B4, D7, D6 } | 37 | #define MATRIX_ROW_PINS { F0, B5, B4, D7, D6 } |
| 38 | #define MATRIX_COL_PINS { B6, C6, C7, D4, D2, D3, D5 } // no B7 on left hand | 38 | #define MATRIX_COL_PINS { B6, C6, C7, D4, D2, D3, D5, NO_PIN } // no B7 on left hand |
| 39 | #define MATRIX_ROW_PINS_RIGHT { F0, B5, B4, D7, D6 } | 39 | #define MATRIX_ROW_PINS_RIGHT { F0, B5, B4, D7, D6 } |
| 40 | #define MATRIX_COL_PINS_RIGHT { B6, C6, C7, D4, D2, D3, D5, B7 } | 40 | #define MATRIX_COL_PINS_RIGHT { B6, C6, C7, D4, D2, D3, D5, B7 } |
| 41 | 41 | ||
| @@ -78,7 +78,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
| 78 | //#define ENCODERS_PAD_A_RIGHT {F4} | 78 | //#define ENCODERS_PAD_A_RIGHT {F4} |
| 79 | //#define ENCODERS_PAD_B_RIGHT {F1} | 79 | //#define ENCODERS_PAD_B_RIGHT {F1} |
| 80 | 80 | ||
| 81 | #define ENCODER_RESOLUTIONS { 8, 8 } | 81 | #define ENCODER_RESOLUTIONS { 8 } |
| 82 | 82 | ||
| 83 | /* | 83 | /* |
| 84 | * Feature disable options | 84 | * Feature disable options |
diff --git a/quantum/encoder.c b/quantum/encoder.c index 438c7d8564..0a3d6f577c 100644 --- a/quantum/encoder.c +++ b/quantum/encoder.c | |||
| @@ -31,11 +31,13 @@ | |||
| 31 | # error "No encoder pads defined by ENCODERS_PAD_A and ENCODERS_PAD_B" | 31 | # error "No encoder pads defined by ENCODERS_PAD_A and ENCODERS_PAD_B" |
| 32 | #endif | 32 | #endif |
| 33 | 33 | ||
| 34 | #define NUMBER_OF_ENCODERS (sizeof(encoders_pad_a) / sizeof(pin_t)) | 34 | extern volatile bool isLeftHand; |
| 35 | static pin_t encoders_pad_a[] = ENCODERS_PAD_A; | 35 | |
| 36 | static pin_t encoders_pad_b[] = ENCODERS_PAD_B; | 36 | static pin_t encoders_pad_a[NUM_ENCODERS_MAX_PER_SIDE] = ENCODERS_PAD_A; |
| 37 | static pin_t encoders_pad_b[NUM_ENCODERS_MAX_PER_SIDE] = ENCODERS_PAD_B; | ||
| 38 | |||
| 37 | #ifdef ENCODER_RESOLUTIONS | 39 | #ifdef ENCODER_RESOLUTIONS |
| 38 | static uint8_t encoder_resolutions[] = ENCODER_RESOLUTIONS; | 40 | static uint8_t encoder_resolutions[NUM_ENCODERS] = ENCODER_RESOLUTIONS; |
| 39 | #endif | 41 | #endif |
| 40 | 42 | ||
| 41 | #ifndef ENCODER_DIRECTION_FLIP | 43 | #ifndef ENCODER_DIRECTION_FLIP |
| @@ -47,18 +49,20 @@ static uint8_t encoder_resolutions[] = ENCODER_RESOLUTIONS; | |||
| 47 | #endif | 49 | #endif |
| 48 | static int8_t encoder_LUT[] = {0, -1, 1, 0, 1, 0, 0, -1, -1, 0, 0, 1, 0, 1, -1, 0}; | 50 | static int8_t encoder_LUT[] = {0, -1, 1, 0, 1, 0, 0, -1, -1, 0, 0, 1, 0, 1, -1, 0}; |
| 49 | 51 | ||
| 50 | static uint8_t encoder_state[NUMBER_OF_ENCODERS] = {0}; | 52 | static uint8_t encoder_state[NUM_ENCODERS] = {0}; |
| 51 | static int8_t encoder_pulses[NUMBER_OF_ENCODERS] = {0}; | 53 | static int8_t encoder_pulses[NUM_ENCODERS] = {0}; |
| 52 | 54 | ||
| 55 | // encoder counts | ||
| 56 | static uint8_t thisCount; | ||
| 53 | #ifdef SPLIT_KEYBOARD | 57 | #ifdef SPLIT_KEYBOARD |
| 54 | // right half encoders come over as second set of encoders | 58 | // encoder offsets for each hand |
| 55 | static uint8_t encoder_value[NUMBER_OF_ENCODERS * 2] = {0}; | ||
| 56 | // row offsets for each hand | ||
| 57 | static uint8_t thisHand, thatHand; | 59 | static uint8_t thisHand, thatHand; |
| 58 | #else | 60 | // encoder counts for each hand |
| 59 | static uint8_t encoder_value[NUMBER_OF_ENCODERS] = {0}; | 61 | static uint8_t thatCount; |
| 60 | #endif | 62 | #endif |
| 61 | 63 | ||
| 64 | static uint8_t encoder_value[NUM_ENCODERS] = {0}; | ||
| 65 | |||
| 62 | __attribute__((weak)) void encoder_wait_pullup_charge(void) { | 66 | __attribute__((weak)) void encoder_wait_pullup_charge(void) { |
| 63 | wait_us(100); | 67 | wait_us(100); |
| 64 | } | 68 | } |
| @@ -72,36 +76,63 @@ __attribute__((weak)) bool encoder_update_kb(uint8_t index, bool clockwise) { | |||
| 72 | } | 76 | } |
| 73 | 77 | ||
| 74 | void encoder_init(void) { | 78 | void encoder_init(void) { |
| 79 | #ifdef SPLIT_KEYBOARD | ||
| 80 | thisHand = isLeftHand ? 0 : NUM_ENCODERS_LEFT; | ||
| 81 | thatHand = NUM_ENCODERS_LEFT - thisHand; | ||
| 82 | thisCount = isLeftHand ? NUM_ENCODERS_LEFT : NUM_ENCODERS_RIGHT; | ||
| 83 | thatCount = isLeftHand ? NUM_ENCODERS_RIGHT : NUM_ENCODERS_LEFT; | ||
| 84 | #else // SPLIT_KEYBOARD | ||
| 85 | thisCount = NUM_ENCODERS; | ||
| 86 | #endif | ||
| 87 | |||
| 88 | #ifdef ENCODER_TESTS | ||
| 89 | // Annoying that we have to clear out values during initialisation here, but | ||
| 90 | // because all the arrays are static locals, rerunning tests in the same | ||
| 91 | // executable doesn't reset any of these. Kinda crappy having test-only code | ||
| 92 | // here, but it's the simplest solution. | ||
| 93 | memset(encoder_value, 0, sizeof(encoder_value)); | ||
| 94 | memset(encoder_state, 0, sizeof(encoder_state)); | ||
| 95 | memset(encoder_pulses, 0, sizeof(encoder_pulses)); | ||
| 96 | static const pin_t encoders_pad_a_left[] = ENCODERS_PAD_A; | ||
| 97 | static const pin_t encoders_pad_b_left[] = ENCODERS_PAD_B; | ||
| 98 | for (uint8_t i = 0; i < thisCount; i++) { | ||
| 99 | encoders_pad_a[i] = encoders_pad_a_left[i]; | ||
| 100 | encoders_pad_b[i] = encoders_pad_b_left[i]; | ||
| 101 | } | ||
| 102 | #endif | ||
| 103 | |||
| 75 | #if defined(SPLIT_KEYBOARD) && defined(ENCODERS_PAD_A_RIGHT) && defined(ENCODERS_PAD_B_RIGHT) | 104 | #if defined(SPLIT_KEYBOARD) && defined(ENCODERS_PAD_A_RIGHT) && defined(ENCODERS_PAD_B_RIGHT) |
| 105 | // Re-initialise the pads if it's the right-hand side | ||
| 76 | if (!isLeftHand) { | 106 | if (!isLeftHand) { |
| 77 | const pin_t encoders_pad_a_right[] = ENCODERS_PAD_A_RIGHT; | 107 | static const pin_t encoders_pad_a_right[] = ENCODERS_PAD_A_RIGHT; |
| 78 | const pin_t encoders_pad_b_right[] = ENCODERS_PAD_B_RIGHT; | 108 | static const pin_t encoders_pad_b_right[] = ENCODERS_PAD_B_RIGHT; |
| 79 | # if defined(ENCODER_RESOLUTIONS_RIGHT) | 109 | for (uint8_t i = 0; i < thisCount; i++) { |
| 80 | const uint8_t encoder_resolutions_right[] = ENCODER_RESOLUTIONS_RIGHT; | ||
| 81 | # endif | ||
| 82 | for (uint8_t i = 0; i < NUMBER_OF_ENCODERS; i++) { | ||
| 83 | encoders_pad_a[i] = encoders_pad_a_right[i]; | 110 | encoders_pad_a[i] = encoders_pad_a_right[i]; |
| 84 | encoders_pad_b[i] = encoders_pad_b_right[i]; | 111 | encoders_pad_b[i] = encoders_pad_b_right[i]; |
| 85 | # if defined(ENCODER_RESOLUTIONS_RIGHT) | ||
| 86 | encoder_resolutions[i] = encoder_resolutions_right[i]; | ||
| 87 | # endif | ||
| 88 | } | 112 | } |
| 89 | } | 113 | } |
| 90 | #endif | 114 | #endif // defined(SPLIT_KEYBOARD) && defined(ENCODERS_PAD_A_RIGHT) && defined(ENCODERS_PAD_B_RIGHT) |
| 115 | |||
| 116 | // Encoder resolutions is handled purely master-side, so concatenate the two arrays | ||
| 117 | #if defined(SPLIT_KEYBOARD) && defined(ENCODER_RESOLUTIONS) | ||
| 118 | # if defined(ENCODER_RESOLUTIONS_RIGHT) | ||
| 119 | static const uint8_t encoder_resolutions_right[NUM_ENCODERS_RIGHT] = ENCODER_RESOLUTIONS_RIGHT; | ||
| 120 | # else // defined(ENCODER_RESOLUTIONS_RIGHT) | ||
| 121 | static const uint8_t encoder_resolutions_right[NUM_ENCODERS_RIGHT] = ENCODER_RESOLUTIONS; | ||
| 122 | # endif // defined(ENCODER_RESOLUTIONS_RIGHT) | ||
| 123 | for (uint8_t i = 0; i < NUM_ENCODERS_RIGHT; i++) { | ||
| 124 | encoder_resolutions[NUM_ENCODERS_LEFT + i] = encoder_resolutions_right[i]; | ||
| 125 | } | ||
| 126 | #endif // defined(SPLIT_KEYBOARD) && defined(ENCODER_RESOLUTIONS) | ||
| 91 | 127 | ||
| 92 | for (int i = 0; i < NUMBER_OF_ENCODERS; i++) { | 128 | for (uint8_t i = 0; i < thisCount; i++) { |
| 93 | setPinInputHigh(encoders_pad_a[i]); | 129 | setPinInputHigh(encoders_pad_a[i]); |
| 94 | setPinInputHigh(encoders_pad_b[i]); | 130 | setPinInputHigh(encoders_pad_b[i]); |
| 95 | } | 131 | } |
| 96 | encoder_wait_pullup_charge(); | 132 | encoder_wait_pullup_charge(); |
| 97 | for (int i = 0; i < NUMBER_OF_ENCODERS; i++) { | 133 | for (uint8_t i = 0; i < thisCount; i++) { |
| 98 | encoder_state[i] = (readPin(encoders_pad_a[i]) << 0) | (readPin(encoders_pad_b[i]) << 1); | 134 | encoder_state[i] = (readPin(encoders_pad_a[i]) << 0) | (readPin(encoders_pad_b[i]) << 1); |
| 99 | } | 135 | } |
| 100 | |||
| 101 | #ifdef SPLIT_KEYBOARD | ||
| 102 | thisHand = isLeftHand ? 0 : NUMBER_OF_ENCODERS; | ||
| 103 | thatHand = NUMBER_OF_ENCODERS - thisHand; | ||
| 104 | #endif | ||
| 105 | } | 136 | } |
| 106 | 137 | ||
| 107 | static bool encoder_update(uint8_t index, uint8_t state) { | 138 | static bool encoder_update(uint8_t index, uint8_t state) { |
| @@ -109,9 +140,9 @@ static bool encoder_update(uint8_t index, uint8_t state) { | |||
| 109 | uint8_t i = index; | 140 | uint8_t i = index; |
| 110 | 141 | ||
| 111 | #ifdef ENCODER_RESOLUTIONS | 142 | #ifdef ENCODER_RESOLUTIONS |
| 112 | uint8_t resolution = encoder_resolutions[i]; | 143 | const uint8_t resolution = encoder_resolutions[i]; |
| 113 | #else | 144 | #else |
| 114 | uint8_t resolution = ENCODER_RESOLUTION; | 145 | const uint8_t resolution = ENCODER_RESOLUTION; |
| 115 | #endif | 146 | #endif |
| 116 | 147 | ||
| 117 | #ifdef SPLIT_KEYBOARD | 148 | #ifdef SPLIT_KEYBOARD |
| @@ -139,10 +170,13 @@ static bool encoder_update(uint8_t index, uint8_t state) { | |||
| 139 | 170 | ||
| 140 | bool encoder_read(void) { | 171 | bool encoder_read(void) { |
| 141 | bool changed = false; | 172 | bool changed = false; |
| 142 | for (uint8_t i = 0; i < NUMBER_OF_ENCODERS; i++) { | 173 | for (uint8_t i = 0; i < thisCount; i++) { |
| 143 | encoder_state[i] <<= 2; | 174 | uint8_t new_status = (readPin(encoders_pad_a[i]) << 0) | (readPin(encoders_pad_b[i]) << 1); |
| 144 | encoder_state[i] |= (readPin(encoders_pad_a[i]) << 0) | (readPin(encoders_pad_b[i]) << 1); | 175 | if ((encoder_state[i] & 0x3) != new_status) { |
| 145 | changed |= encoder_update(i, encoder_state[i]); | 176 | encoder_state[i] <<= 2; |
| 177 | encoder_state[i] |= new_status; | ||
| 178 | changed |= encoder_update(i, encoder_state[i]); | ||
| 179 | } | ||
| 146 | } | 180 | } |
| 147 | return changed; | 181 | return changed; |
| 148 | } | 182 | } |
| @@ -150,15 +184,15 @@ bool encoder_read(void) { | |||
| 150 | #ifdef SPLIT_KEYBOARD | 184 | #ifdef SPLIT_KEYBOARD |
| 151 | void last_encoder_activity_trigger(void); | 185 | void last_encoder_activity_trigger(void); |
| 152 | 186 | ||
| 153 | void encoder_state_raw(uint8_t* slave_state) { | 187 | void encoder_state_raw(uint8_t *slave_state) { |
| 154 | memcpy(slave_state, &encoder_value[thisHand], sizeof(uint8_t) * NUMBER_OF_ENCODERS); | 188 | memcpy(slave_state, &encoder_value[thisHand], sizeof(uint8_t) * thisCount); |
| 155 | } | 189 | } |
| 156 | 190 | ||
| 157 | void encoder_update_raw(uint8_t* slave_state) { | 191 | void encoder_update_raw(uint8_t *slave_state) { |
| 158 | bool changed = false; | 192 | bool changed = false; |
| 159 | for (uint8_t i = 0; i < NUMBER_OF_ENCODERS; i++) { | 193 | for (uint8_t i = 0; i < thatCount; i++) { // Note inverted logic -- we want the opposite side |
| 160 | uint8_t index = i + thatHand; | 194 | const uint8_t index = i + thatHand; |
| 161 | int8_t delta = slave_state[i] - encoder_value[index]; | 195 | int8_t delta = slave_state[i] - encoder_value[index]; |
| 162 | while (delta > 0) { | 196 | while (delta > 0) { |
| 163 | delta--; | 197 | delta--; |
| 164 | encoder_value[index]++; | 198 | encoder_value[index]++; |
diff --git a/quantum/encoder.h b/quantum/encoder.h index 25dc77721d..dd6db14629 100644 --- a/quantum/encoder.h +++ b/quantum/encoder.h | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #pragma once | 18 | #pragma once |
| 19 | 19 | ||
| 20 | #include "quantum.h" | 20 | #include "quantum.h" |
| 21 | #include "util.h" | ||
| 21 | 22 | ||
| 22 | void encoder_init(void); | 23 | void encoder_init(void); |
| 23 | bool encoder_read(void); | 24 | bool encoder_read(void); |
| @@ -26,6 +27,31 @@ bool encoder_update_kb(uint8_t index, bool clockwise); | |||
| 26 | bool encoder_update_user(uint8_t index, bool clockwise); | 27 | bool encoder_update_user(uint8_t index, bool clockwise); |
| 27 | 28 | ||
| 28 | #ifdef SPLIT_KEYBOARD | 29 | #ifdef SPLIT_KEYBOARD |
| 30 | |||
| 29 | void encoder_state_raw(uint8_t* slave_state); | 31 | void encoder_state_raw(uint8_t* slave_state); |
| 30 | void encoder_update_raw(uint8_t* slave_state); | 32 | void encoder_update_raw(uint8_t* slave_state); |
| 31 | #endif | 33 | |
| 34 | # if defined(ENCODERS_PAD_A_RIGHT) | ||
| 35 | # define NUM_ENCODERS_LEFT (sizeof(((pin_t[])ENCODERS_PAD_A)) / sizeof(pin_t)) | ||
| 36 | # define NUM_ENCODERS_RIGHT (sizeof(((pin_t[])ENCODERS_PAD_A_RIGHT)) / sizeof(pin_t)) | ||
| 37 | # else | ||
| 38 | # define NUM_ENCODERS_LEFT (sizeof(((pin_t[])ENCODERS_PAD_A)) / sizeof(pin_t)) | ||
| 39 | # define NUM_ENCODERS_RIGHT NUM_ENCODERS_LEFT | ||
| 40 | # endif | ||
| 41 | # define NUM_ENCODERS (NUM_ENCODERS_LEFT + NUM_ENCODERS_RIGHT) | ||
| 42 | |||
| 43 | #else // SPLIT_KEYBOARD | ||
| 44 | |||
| 45 | # define NUM_ENCODERS (sizeof(((pin_t[])ENCODERS_PAD_A)) / sizeof(pin_t)) | ||
| 46 | # define NUM_ENCODERS_LEFT NUM_ENCODERS | ||
| 47 | # define NUM_ENCODERS_RIGHT 0 | ||
| 48 | |||
| 49 | #endif // SPLIT_KEYBOARD | ||
| 50 | |||
| 51 | #ifndef NUM_ENCODERS | ||
| 52 | # define NUM_ENCODERS 0 | ||
| 53 | # define NUM_ENCODERS_LEFT 0 | ||
| 54 | # define NUM_ENCODERS_RIGHT 0 | ||
| 55 | #endif // NUM_ENCODERS | ||
| 56 | |||
| 57 | #define NUM_ENCODERS_MAX_PER_SIDE MAX(NUM_ENCODERS_LEFT, NUM_ENCODERS_RIGHT) | ||
diff --git a/quantum/encoder/tests/config_mock.h b/quantum/encoder/tests/config_mock.h new file mode 100644 index 0000000000..703dcaf103 --- /dev/null +++ b/quantum/encoder/tests/config_mock.h | |||
| @@ -0,0 +1,22 @@ | |||
| 1 | // Copyright 2022 Nick Brassel (@tzarc) | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | #pragma once | ||
| 4 | |||
| 5 | #define MATRIX_ROWS 1 | ||
| 6 | #define MATRIX_COLS 1 | ||
| 7 | |||
| 8 | /* Here, "pins" from 0 to 31 are allowed. */ | ||
| 9 | #define ENCODERS_PAD_A \ | ||
| 10 | { 0 } | ||
| 11 | #define ENCODERS_PAD_B \ | ||
| 12 | { 1 } | ||
| 13 | |||
| 14 | #ifdef __cplusplus | ||
| 15 | extern "C" { | ||
| 16 | #endif | ||
| 17 | |||
| 18 | #include "mock.h" | ||
| 19 | |||
| 20 | #ifdef __cplusplus | ||
| 21 | }; | ||
| 22 | #endif | ||
diff --git a/quantum/encoder/tests/config_mock_split_left_eq_right.h b/quantum/encoder/tests/config_mock_split_left_eq_right.h new file mode 100644 index 0000000000..c80ac4d519 --- /dev/null +++ b/quantum/encoder/tests/config_mock_split_left_eq_right.h | |||
| @@ -0,0 +1,26 @@ | |||
| 1 | // Copyright 2022 Nick Brassel (@tzarc) | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | #pragma once | ||
| 4 | |||
| 5 | #define MATRIX_ROWS 1 | ||
| 6 | #define MATRIX_COLS 1 | ||
| 7 | |||
| 8 | /* Here, "pins" from 0 to 31 are allowed. */ | ||
| 9 | #define ENCODERS_PAD_A \ | ||
| 10 | { 0, 2 } | ||
| 11 | #define ENCODERS_PAD_B \ | ||
| 12 | { 1, 3 } | ||
| 13 | #define ENCODERS_PAD_A_RIGHT \ | ||
| 14 | { 4, 6 } | ||
| 15 | #define ENCODERS_PAD_B_RIGHT \ | ||
| 16 | { 5, 7 } | ||
| 17 | |||
| 18 | #ifdef __cplusplus | ||
| 19 | extern "C" { | ||
| 20 | #endif | ||
| 21 | |||
| 22 | #include "mock_split.h" | ||
| 23 | |||
| 24 | #ifdef __cplusplus | ||
| 25 | }; | ||
| 26 | #endif | ||
diff --git a/quantum/encoder/tests/config_mock_split_left_gt_right.h b/quantum/encoder/tests/config_mock_split_left_gt_right.h new file mode 100644 index 0000000000..91d5f3d605 --- /dev/null +++ b/quantum/encoder/tests/config_mock_split_left_gt_right.h | |||
| @@ -0,0 +1,26 @@ | |||
| 1 | // Copyright 2022 Nick Brassel (@tzarc) | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | #pragma once | ||
| 4 | |||
| 5 | #define MATRIX_ROWS 1 | ||
| 6 | #define MATRIX_COLS 1 | ||
| 7 | |||
| 8 | /* Here, "pins" from 0 to 31 are allowed. */ | ||
| 9 | #define ENCODERS_PAD_A \ | ||
| 10 | { 0, 2, 4 } | ||
| 11 | #define ENCODERS_PAD_B \ | ||
| 12 | { 1, 3, 5 } | ||
| 13 | #define ENCODERS_PAD_A_RIGHT \ | ||
| 14 | { 6, 8 } | ||
| 15 | #define ENCODERS_PAD_B_RIGHT \ | ||
| 16 | { 7, 9 } | ||
| 17 | |||
| 18 | #ifdef __cplusplus | ||
| 19 | extern "C" { | ||
| 20 | #endif | ||
| 21 | |||
| 22 | #include "mock_split.h" | ||
| 23 | |||
| 24 | #ifdef __cplusplus | ||
| 25 | }; | ||
| 26 | #endif | ||
diff --git a/quantum/encoder/tests/config_mock_split_left_lt_right.h b/quantum/encoder/tests/config_mock_split_left_lt_right.h new file mode 100644 index 0000000000..4108a184a6 --- /dev/null +++ b/quantum/encoder/tests/config_mock_split_left_lt_right.h | |||
| @@ -0,0 +1,26 @@ | |||
| 1 | // Copyright 2022 Nick Brassel (@tzarc) | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | #pragma once | ||
| 4 | |||
| 5 | #define MATRIX_ROWS 1 | ||
| 6 | #define MATRIX_COLS 1 | ||
| 7 | |||
| 8 | /* Here, "pins" from 0 to 31 are allowed. */ | ||
| 9 | #define ENCODERS_PAD_A \ | ||
| 10 | { 0, 2 } | ||
| 11 | #define ENCODERS_PAD_B \ | ||
| 12 | { 1, 3 } | ||
| 13 | #define ENCODERS_PAD_A_RIGHT \ | ||
| 14 | { 4, 6, 8 } | ||
| 15 | #define ENCODERS_PAD_B_RIGHT \ | ||
| 16 | { 5, 7, 9 } | ||
| 17 | |||
| 18 | #ifdef __cplusplus | ||
| 19 | extern "C" { | ||
| 20 | #endif | ||
| 21 | |||
| 22 | #include "mock_split.h" | ||
| 23 | |||
| 24 | #ifdef __cplusplus | ||
| 25 | }; | ||
| 26 | #endif | ||
diff --git a/quantum/encoder/tests/config_mock_split_no_left.h b/quantum/encoder/tests/config_mock_split_no_left.h new file mode 100644 index 0000000000..9db7fa7e41 --- /dev/null +++ b/quantum/encoder/tests/config_mock_split_no_left.h | |||
| @@ -0,0 +1,26 @@ | |||
| 1 | // Copyright 2022 Nick Brassel (@tzarc) | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | #pragma once | ||
| 4 | |||
| 5 | #define MATRIX_ROWS 1 | ||
| 6 | #define MATRIX_COLS 1 | ||
| 7 | |||
| 8 | /* Here, "pins" from 0 to 31 are allowed. */ | ||
| 9 | #define ENCODERS_PAD_A \ | ||
| 10 | {} | ||
| 11 | #define ENCODERS_PAD_B \ | ||
| 12 | {} | ||
| 13 | #define ENCODERS_PAD_A_RIGHT \ | ||
| 14 | { 0, 2 } | ||
| 15 | #define ENCODERS_PAD_B_RIGHT \ | ||
| 16 | { 1, 3 } | ||
| 17 | |||
| 18 | #ifdef __cplusplus | ||
| 19 | extern "C" { | ||
| 20 | #endif | ||
| 21 | |||
| 22 | #include "mock_split.h" | ||
| 23 | |||
| 24 | #ifdef __cplusplus | ||
| 25 | }; | ||
| 26 | #endif | ||
diff --git a/quantum/encoder/tests/config_mock_split_no_right.h b/quantum/encoder/tests/config_mock_split_no_right.h new file mode 100644 index 0000000000..14f18015e6 --- /dev/null +++ b/quantum/encoder/tests/config_mock_split_no_right.h | |||
| @@ -0,0 +1,26 @@ | |||
| 1 | // Copyright 2022 Nick Brassel (@tzarc) | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | #pragma once | ||
| 4 | |||
| 5 | #define MATRIX_ROWS 1 | ||
| 6 | #define MATRIX_COLS 1 | ||
| 7 | |||
| 8 | /* Here, "pins" from 0 to 31 are allowed. */ | ||
| 9 | #define ENCODERS_PAD_A \ | ||
| 10 | { 0, 2 } | ||
| 11 | #define ENCODERS_PAD_B \ | ||
| 12 | { 1, 3 } | ||
| 13 | #define ENCODERS_PAD_A_RIGHT \ | ||
| 14 | {} | ||
| 15 | #define ENCODERS_PAD_B_RIGHT \ | ||
| 16 | {} | ||
| 17 | |||
| 18 | #ifdef __cplusplus | ||
| 19 | extern "C" { | ||
| 20 | #endif | ||
| 21 | |||
| 22 | #include "mock_split.h" | ||
| 23 | |||
| 24 | #ifdef __cplusplus | ||
| 25 | }; | ||
| 26 | #endif | ||
diff --git a/quantum/encoder/tests/encoder_tests.cpp b/quantum/encoder/tests/encoder_tests.cpp index 1888fdab8d..b7c18aeec0 100644 --- a/quantum/encoder/tests/encoder_tests.cpp +++ b/quantum/encoder/tests/encoder_tests.cpp | |||
| @@ -30,12 +30,12 @@ struct update { | |||
| 30 | bool clockwise; | 30 | bool clockwise; |
| 31 | }; | 31 | }; |
| 32 | 32 | ||
| 33 | uint8_t uidx = 0; | 33 | uint8_t updates_array_idx = 0; |
| 34 | update updates[32]; | 34 | update updates[32]; |
| 35 | 35 | ||
| 36 | bool encoder_update_kb(uint8_t index, bool clockwise) { | 36 | bool encoder_update_kb(uint8_t index, bool clockwise) { |
| 37 | updates[uidx % 32] = {index, clockwise}; | 37 | updates[updates_array_idx % 32] = {index, clockwise}; |
| 38 | uidx++; | 38 | updates_array_idx++; |
| 39 | return true; | 39 | return true; |
| 40 | } | 40 | } |
| 41 | 41 | ||
| @@ -47,15 +47,15 @@ bool setAndRead(pin_t pin, bool val) { | |||
| 47 | class EncoderTest : public ::testing::Test {}; | 47 | class EncoderTest : public ::testing::Test {}; |
| 48 | 48 | ||
| 49 | TEST_F(EncoderTest, TestInit) { | 49 | TEST_F(EncoderTest, TestInit) { |
| 50 | uidx = 0; | 50 | updates_array_idx = 0; |
| 51 | encoder_init(); | 51 | encoder_init(); |
| 52 | EXPECT_EQ(pinIsInputHigh[0], true); | 52 | EXPECT_EQ(pinIsInputHigh[0], true); |
| 53 | EXPECT_EQ(pinIsInputHigh[1], true); | 53 | EXPECT_EQ(pinIsInputHigh[1], true); |
| 54 | EXPECT_EQ(uidx, 0); | 54 | EXPECT_EQ(updates_array_idx, 0); |
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | TEST_F(EncoderTest, TestOneClockwise) { | 57 | TEST_F(EncoderTest, TestOneClockwise) { |
| 58 | uidx = 0; | 58 | updates_array_idx = 0; |
| 59 | encoder_init(); | 59 | encoder_init(); |
| 60 | // send 4 pulses. with resolution 4, that's one step and we should get 1 update. | 60 | // send 4 pulses. with resolution 4, that's one step and we should get 1 update. |
| 61 | setAndRead(0, false); | 61 | setAndRead(0, false); |
| @@ -63,26 +63,26 @@ TEST_F(EncoderTest, TestOneClockwise) { | |||
| 63 | setAndRead(0, true); | 63 | setAndRead(0, true); |
| 64 | setAndRead(1, true); | 64 | setAndRead(1, true); |
| 65 | 65 | ||
| 66 | EXPECT_EQ(uidx, 1); | 66 | EXPECT_EQ(updates_array_idx, 1); |
| 67 | EXPECT_EQ(updates[0].index, 0); | 67 | EXPECT_EQ(updates[0].index, 0); |
| 68 | EXPECT_EQ(updates[0].clockwise, true); | 68 | EXPECT_EQ(updates[0].clockwise, true); |
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | TEST_F(EncoderTest, TestOneCounterClockwise) { | 71 | TEST_F(EncoderTest, TestOneCounterClockwise) { |
| 72 | uidx = 0; | 72 | updates_array_idx = 0; |
| 73 | encoder_init(); | 73 | encoder_init(); |
| 74 | setAndRead(1, false); | 74 | setAndRead(1, false); |
| 75 | setAndRead(0, false); | 75 | setAndRead(0, false); |
| 76 | setAndRead(1, true); | 76 | setAndRead(1, true); |
| 77 | setAndRead(0, true); | 77 | setAndRead(0, true); |
| 78 | 78 | ||
| 79 | EXPECT_EQ(uidx, 1); | 79 | EXPECT_EQ(updates_array_idx, 1); |
| 80 | EXPECT_EQ(updates[0].index, 0); | 80 | EXPECT_EQ(updates[0].index, 0); |
| 81 | EXPECT_EQ(updates[0].clockwise, false); | 81 | EXPECT_EQ(updates[0].clockwise, false); |
| 82 | } | 82 | } |
| 83 | 83 | ||
| 84 | TEST_F(EncoderTest, TestTwoClockwiseOneCC) { | 84 | TEST_F(EncoderTest, TestTwoClockwiseOneCC) { |
| 85 | uidx = 0; | 85 | updates_array_idx = 0; |
| 86 | encoder_init(); | 86 | encoder_init(); |
| 87 | setAndRead(0, false); | 87 | setAndRead(0, false); |
| 88 | setAndRead(1, false); | 88 | setAndRead(1, false); |
| @@ -97,7 +97,7 @@ TEST_F(EncoderTest, TestTwoClockwiseOneCC) { | |||
| 97 | setAndRead(1, true); | 97 | setAndRead(1, true); |
| 98 | setAndRead(0, true); | 98 | setAndRead(0, true); |
| 99 | 99 | ||
| 100 | EXPECT_EQ(uidx, 3); | 100 | EXPECT_EQ(updates_array_idx, 3); |
| 101 | EXPECT_EQ(updates[0].index, 0); | 101 | EXPECT_EQ(updates[0].index, 0); |
| 102 | EXPECT_EQ(updates[0].clockwise, true); | 102 | EXPECT_EQ(updates[0].clockwise, true); |
| 103 | EXPECT_EQ(updates[1].index, 0); | 103 | EXPECT_EQ(updates[1].index, 0); |
| @@ -107,38 +107,38 @@ TEST_F(EncoderTest, TestTwoClockwiseOneCC) { | |||
| 107 | } | 107 | } |
| 108 | 108 | ||
| 109 | TEST_F(EncoderTest, TestNoEarly) { | 109 | TEST_F(EncoderTest, TestNoEarly) { |
| 110 | uidx = 0; | 110 | updates_array_idx = 0; |
| 111 | encoder_init(); | 111 | encoder_init(); |
| 112 | // send 3 pulses. with resolution 4, that's not enough for a step. | 112 | // send 3 pulses. with resolution 4, that's not enough for a step. |
| 113 | setAndRead(0, false); | 113 | setAndRead(0, false); |
| 114 | setAndRead(1, false); | 114 | setAndRead(1, false); |
| 115 | setAndRead(0, true); | 115 | setAndRead(0, true); |
| 116 | EXPECT_EQ(uidx, 0); | 116 | EXPECT_EQ(updates_array_idx, 0); |
| 117 | // now send last pulse | 117 | // now send last pulse |
| 118 | setAndRead(1, true); | 118 | setAndRead(1, true); |
| 119 | EXPECT_EQ(uidx, 1); | 119 | EXPECT_EQ(updates_array_idx, 1); |
| 120 | EXPECT_EQ(updates[0].index, 0); | 120 | EXPECT_EQ(updates[0].index, 0); |
| 121 | EXPECT_EQ(updates[0].clockwise, true); | 121 | EXPECT_EQ(updates[0].clockwise, true); |
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | TEST_F(EncoderTest, TestHalfway) { | 124 | TEST_F(EncoderTest, TestHalfway) { |
| 125 | uidx = 0; | 125 | updates_array_idx = 0; |
| 126 | encoder_init(); | 126 | encoder_init(); |
| 127 | // go halfway | 127 | // go halfway |
| 128 | setAndRead(0, false); | 128 | setAndRead(0, false); |
| 129 | setAndRead(1, false); | 129 | setAndRead(1, false); |
| 130 | EXPECT_EQ(uidx, 0); | 130 | EXPECT_EQ(updates_array_idx, 0); |
| 131 | // back off | 131 | // back off |
| 132 | setAndRead(1, true); | 132 | setAndRead(1, true); |
| 133 | setAndRead(0, true); | 133 | setAndRead(0, true); |
| 134 | EXPECT_EQ(uidx, 0); | 134 | EXPECT_EQ(updates_array_idx, 0); |
| 135 | // go all the way | 135 | // go all the way |
| 136 | setAndRead(0, false); | 136 | setAndRead(0, false); |
| 137 | setAndRead(1, false); | 137 | setAndRead(1, false); |
| 138 | setAndRead(0, true); | 138 | setAndRead(0, true); |
| 139 | setAndRead(1, true); | 139 | setAndRead(1, true); |
| 140 | // should result in 1 update | 140 | // should result in 1 update |
| 141 | EXPECT_EQ(uidx, 1); | 141 | EXPECT_EQ(updates_array_idx, 1); |
| 142 | EXPECT_EQ(updates[0].index, 0); | 142 | EXPECT_EQ(updates[0].index, 0); |
| 143 | EXPECT_EQ(updates[0].clockwise, true); | 143 | EXPECT_EQ(updates[0].clockwise, true); |
| 144 | } | 144 | } |
diff --git a/quantum/encoder/tests/encoder_tests_split_left_eq_right.cpp b/quantum/encoder/tests/encoder_tests_split_left_eq_right.cpp new file mode 100644 index 0000000000..916e47b185 --- /dev/null +++ b/quantum/encoder/tests/encoder_tests_split_left_eq_right.cpp | |||
| @@ -0,0 +1,135 @@ | |||
| 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 | |||
| 23 | extern "C" { | ||
| 24 | #include "encoder.h" | ||
| 25 | #include "encoder/tests/mock_split.h" | ||
| 26 | } | ||
| 27 | |||
| 28 | struct update { | ||
| 29 | int8_t index; | ||
| 30 | bool clockwise; | ||
| 31 | }; | ||
| 32 | |||
| 33 | uint8_t updates_array_idx = 0; | ||
| 34 | update updates[32]; | ||
| 35 | |||
| 36 | bool isLeftHand; | ||
| 37 | |||
| 38 | bool 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[updates_array_idx % 32] = {index, clockwise}; | ||
| 45 | updates_array_idx++; | ||
| 46 | return true; | ||
| 47 | } | ||
| 48 | |||
| 49 | bool setAndRead(pin_t pin, bool val) { | ||
| 50 | setPin(pin, val); | ||
| 51 | return encoder_read(); | ||
| 52 | } | ||
| 53 | |||
| 54 | class EncoderSplitTestLeftEqRight : public ::testing::Test { | ||
| 55 | protected: | ||
| 56 | void SetUp() override { | ||
| 57 | updates_array_idx = 0; | ||
| 58 | for (int i = 0; i < 32; i++) { | ||
| 59 | pinIsInputHigh[i] = 0; | ||
| 60 | pins[i] = 0; | ||
| 61 | } | ||
| 62 | } | ||
| 63 | }; | ||
| 64 | |||
| 65 | TEST_F(EncoderSplitTestLeftEqRight, TestInitLeft) { | ||
| 66 | isLeftHand = true; | ||
| 67 | encoder_init(); | ||
| 68 | EXPECT_EQ(pinIsInputHigh[0], true); | ||
| 69 | EXPECT_EQ(pinIsInputHigh[1], true); | ||
| 70 | EXPECT_EQ(pinIsInputHigh[2], true); | ||
| 71 | EXPECT_EQ(pinIsInputHigh[3], true); | ||
| 72 | EXPECT_EQ(pinIsInputHigh[4], false); | ||
| 73 | EXPECT_EQ(pinIsInputHigh[5], false); | ||
| 74 | EXPECT_EQ(pinIsInputHigh[6], false); | ||
| 75 | EXPECT_EQ(pinIsInputHigh[7], false); | ||
| 76 | EXPECT_EQ(updates_array_idx, 0); // no updates received | ||
| 77 | } | ||
| 78 | |||
| 79 | TEST_F(EncoderSplitTestLeftEqRight, TestInitRight) { | ||
| 80 | isLeftHand = false; | ||
| 81 | encoder_init(); | ||
| 82 | EXPECT_EQ(pinIsInputHigh[0], false); | ||
| 83 | EXPECT_EQ(pinIsInputHigh[1], false); | ||
| 84 | EXPECT_EQ(pinIsInputHigh[2], false); | ||
| 85 | EXPECT_EQ(pinIsInputHigh[3], false); | ||
| 86 | EXPECT_EQ(pinIsInputHigh[4], true); | ||
| 87 | EXPECT_EQ(pinIsInputHigh[5], true); | ||
| 88 | EXPECT_EQ(pinIsInputHigh[6], true); | ||
| 89 | EXPECT_EQ(pinIsInputHigh[7], true); | ||
| 90 | EXPECT_EQ(updates_array_idx, 0); // no updates received | ||
| 91 | } | ||
| 92 | |||
| 93 | TEST_F(EncoderSplitTestLeftEqRight, TestOneClockwiseLeft) { | ||
| 94 | isLeftHand = true; | ||
| 95 | encoder_init(); | ||
| 96 | // send 4 pulses. with resolution 4, that's one step and we should get 1 update. | ||
| 97 | setAndRead(0, false); | ||
| 98 | setAndRead(1, false); | ||
| 99 | setAndRead(0, true); | ||
| 100 | setAndRead(1, true); | ||
| 101 | |||
| 102 | EXPECT_EQ(updates_array_idx, 1); // one update received | ||
| 103 | EXPECT_EQ(updates[0].index, 0); | ||
| 104 | EXPECT_EQ(updates[0].clockwise, true); | ||
| 105 | } | ||
| 106 | |||
| 107 | TEST_F(EncoderSplitTestLeftEqRight, TestOneClockwiseRightSent) { | ||
| 108 | isLeftHand = false; | ||
| 109 | encoder_init(); | ||
| 110 | // send 4 pulses. with resolution 4, that's one step and we should get 1 update. | ||
| 111 | setAndRead(6, false); | ||
| 112 | setAndRead(7, false); | ||
| 113 | setAndRead(6, true); | ||
| 114 | setAndRead(7, true); | ||
| 115 | |||
| 116 | uint8_t slave_state[32] = {0}; | ||
| 117 | encoder_state_raw(slave_state); | ||
| 118 | |||
| 119 | EXPECT_EQ(slave_state[0], 0); | ||
| 120 | EXPECT_EQ(slave_state[1], 0xFF); | ||
| 121 | } | ||
| 122 | |||
| 123 | TEST_F(EncoderSplitTestLeftEqRight, TestMultipleEncodersRightReceived) { | ||
| 124 | isLeftHand = true; | ||
| 125 | encoder_init(); | ||
| 126 | |||
| 127 | uint8_t slave_state[32] = {1, 0xFF}; // First right encoder is CCW, Second right encoder CW | ||
| 128 | encoder_update_raw(slave_state); | ||
| 129 | |||
| 130 | EXPECT_EQ(updates_array_idx, 2); // two updates received, one for each changed item on the right side | ||
| 131 | EXPECT_EQ(updates[0].index, 2); | ||
| 132 | EXPECT_EQ(updates[0].clockwise, false); | ||
| 133 | EXPECT_EQ(updates[1].index, 3); | ||
| 134 | EXPECT_EQ(updates[1].clockwise, true); | ||
| 135 | } | ||
diff --git a/quantum/encoder/tests/encoder_tests_split_left_gt_right.cpp b/quantum/encoder/tests/encoder_tests_split_left_gt_right.cpp new file mode 100644 index 0000000000..7b64bb2981 --- /dev/null +++ b/quantum/encoder/tests/encoder_tests_split_left_gt_right.cpp | |||
| @@ -0,0 +1,139 @@ | |||
| 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 | |||
| 23 | extern "C" { | ||
| 24 | #include "encoder.h" | ||
| 25 | #include "encoder/tests/mock_split.h" | ||
| 26 | } | ||
| 27 | |||
| 28 | struct update { | ||
| 29 | int8_t index; | ||
| 30 | bool clockwise; | ||
| 31 | }; | ||
| 32 | |||
| 33 | uint8_t updates_array_idx = 0; | ||
| 34 | update updates[32]; | ||
| 35 | |||
| 36 | bool isLeftHand; | ||
| 37 | |||
| 38 | bool 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[updates_array_idx % 32] = {index, clockwise}; | ||
| 45 | updates_array_idx++; | ||
| 46 | return true; | ||
| 47 | } | ||
| 48 | |||
| 49 | bool setAndRead(pin_t pin, bool val) { | ||
| 50 | setPin(pin, val); | ||
| 51 | return encoder_read(); | ||
| 52 | } | ||
| 53 | |||
| 54 | class EncoderSplitTestLeftGreaterThanRight : public ::testing::Test { | ||
| 55 | protected: | ||
| 56 | void SetUp() override { | ||
| 57 | updates_array_idx = 0; | ||
| 58 | for (int i = 0; i < 32; i++) { | ||
| 59 | pinIsInputHigh[i] = 0; | ||
| 60 | pins[i] = 0; | ||
| 61 | } | ||
| 62 | } | ||
| 63 | }; | ||
| 64 | |||
| 65 | TEST_F(EncoderSplitTestLeftGreaterThanRight, TestInitLeft) { | ||
| 66 | isLeftHand = true; | ||
| 67 | encoder_init(); | ||
| 68 | EXPECT_EQ(pinIsInputHigh[0], true); | ||
| 69 | EXPECT_EQ(pinIsInputHigh[1], true); | ||
| 70 | EXPECT_EQ(pinIsInputHigh[2], true); | ||
| 71 | EXPECT_EQ(pinIsInputHigh[3], true); | ||
| 72 | EXPECT_EQ(pinIsInputHigh[4], true); | ||
| 73 | EXPECT_EQ(pinIsInputHigh[5], true); | ||
| 74 | EXPECT_EQ(pinIsInputHigh[6], false); | ||
| 75 | EXPECT_EQ(pinIsInputHigh[7], false); | ||
| 76 | EXPECT_EQ(pinIsInputHigh[8], false); | ||
| 77 | EXPECT_EQ(pinIsInputHigh[9], false); | ||
| 78 | EXPECT_EQ(updates_array_idx, 0); // no updates received | ||
| 79 | } | ||
| 80 | |||
| 81 | TEST_F(EncoderSplitTestLeftGreaterThanRight, TestInitRight) { | ||
| 82 | isLeftHand = false; | ||
| 83 | encoder_init(); | ||
| 84 | EXPECT_EQ(pinIsInputHigh[0], false); | ||
| 85 | EXPECT_EQ(pinIsInputHigh[1], false); | ||
| 86 | EXPECT_EQ(pinIsInputHigh[2], false); | ||
| 87 | EXPECT_EQ(pinIsInputHigh[3], false); | ||
| 88 | EXPECT_EQ(pinIsInputHigh[4], false); | ||
| 89 | EXPECT_EQ(pinIsInputHigh[5], false); | ||
| 90 | EXPECT_EQ(pinIsInputHigh[6], true); | ||
| 91 | EXPECT_EQ(pinIsInputHigh[7], true); | ||
| 92 | EXPECT_EQ(pinIsInputHigh[8], true); | ||
| 93 | EXPECT_EQ(pinIsInputHigh[9], true); | ||
| 94 | EXPECT_EQ(updates_array_idx, 0); // no updates received | ||
| 95 | } | ||
| 96 | |||
| 97 | TEST_F(EncoderSplitTestLeftGreaterThanRight, TestOneClockwiseLeft) { | ||
| 98 | isLeftHand = true; | ||
| 99 | encoder_init(); | ||
| 100 | // send 4 pulses. with resolution 4, that's one step and we should get 1 update. | ||
| 101 | setAndRead(0, false); | ||
| 102 | setAndRead(1, false); | ||
| 103 | setAndRead(0, true); | ||
| 104 | setAndRead(1, true); | ||
| 105 | |||
| 106 | EXPECT_EQ(updates_array_idx, 1); // one update received | ||
| 107 | EXPECT_EQ(updates[0].index, 0); | ||
| 108 | EXPECT_EQ(updates[0].clockwise, true); | ||
| 109 | } | ||
| 110 | |||
| 111 | TEST_F(EncoderSplitTestLeftGreaterThanRight, TestOneClockwiseRightSent) { | ||
| 112 | isLeftHand = false; | ||
| 113 | encoder_init(); | ||
| 114 | // send 4 pulses. with resolution 4, that's one step and we should get 1 update. | ||
| 115 | setAndRead(6, false); | ||
| 116 | setAndRead(7, false); | ||
| 117 | setAndRead(6, true); | ||
| 118 | setAndRead(7, true); | ||
| 119 | |||
| 120 | uint8_t slave_state[32] = {0}; | ||
| 121 | encoder_state_raw(slave_state); | ||
| 122 | |||
| 123 | EXPECT_EQ(slave_state[0], 0xFF); | ||
| 124 | EXPECT_EQ(slave_state[1], 0); | ||
| 125 | } | ||
| 126 | |||
| 127 | TEST_F(EncoderSplitTestLeftGreaterThanRight, TestMultipleEncodersRightReceived) { | ||
| 128 | isLeftHand = true; | ||
| 129 | encoder_init(); | ||
| 130 | |||
| 131 | uint8_t slave_state[32] = {1, 0xFF}; // First right encoder is CCW, Second right encoder no change, third right encoder CW | ||
| 132 | encoder_update_raw(slave_state); | ||
| 133 | |||
| 134 | EXPECT_EQ(updates_array_idx, 2); // two updates received, one for each changed item on the right side | ||
| 135 | EXPECT_EQ(updates[0].index, 3); | ||
| 136 | EXPECT_EQ(updates[0].clockwise, false); | ||
| 137 | EXPECT_EQ(updates[1].index, 4); | ||
| 138 | EXPECT_EQ(updates[1].clockwise, true); | ||
| 139 | } | ||
diff --git a/quantum/encoder/tests/encoder_tests_split_left_lt_right.cpp b/quantum/encoder/tests/encoder_tests_split_left_lt_right.cpp new file mode 100644 index 0000000000..a6519c5762 --- /dev/null +++ b/quantum/encoder/tests/encoder_tests_split_left_lt_right.cpp | |||
| @@ -0,0 +1,139 @@ | |||
| 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 | |||
| 23 | extern "C" { | ||
| 24 | #include "encoder.h" | ||
| 25 | #include "encoder/tests/mock_split.h" | ||
| 26 | } | ||
| 27 | |||
| 28 | struct update { | ||
| 29 | int8_t index; | ||
| 30 | bool clockwise; | ||
| 31 | }; | ||
| 32 | |||
| 33 | uint8_t updates_array_idx = 0; | ||
| 34 | update updates[32]; | ||
| 35 | |||
| 36 | bool isLeftHand; | ||
| 37 | |||
| 38 | bool 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[updates_array_idx % 32] = {index, clockwise}; | ||
| 45 | updates_array_idx++; | ||
| 46 | return true; | ||
| 47 | } | ||
| 48 | |||
| 49 | bool setAndRead(pin_t pin, bool val) { | ||
| 50 | setPin(pin, val); | ||
| 51 | return encoder_read(); | ||
| 52 | } | ||
| 53 | |||
| 54 | class EncoderSplitTestLeftLessThanRight : public ::testing::Test { | ||
| 55 | protected: | ||
| 56 | void SetUp() override { | ||
| 57 | updates_array_idx = 0; | ||
| 58 | for (int i = 0; i < 32; i++) { | ||
| 59 | pinIsInputHigh[i] = 0; | ||
| 60 | pins[i] = 0; | ||
| 61 | } | ||
| 62 | } | ||
| 63 | }; | ||
| 64 | |||
| 65 | TEST_F(EncoderSplitTestLeftLessThanRight, TestInitLeft) { | ||
| 66 | isLeftHand = true; | ||
| 67 | encoder_init(); | ||
| 68 | EXPECT_EQ(pinIsInputHigh[0], true); | ||
| 69 | EXPECT_EQ(pinIsInputHigh[1], true); | ||
| 70 | EXPECT_EQ(pinIsInputHigh[2], true); | ||
| 71 | EXPECT_EQ(pinIsInputHigh[3], true); | ||
| 72 | EXPECT_EQ(pinIsInputHigh[4], false); | ||
| 73 | EXPECT_EQ(pinIsInputHigh[5], false); | ||
| 74 | EXPECT_EQ(pinIsInputHigh[6], false); | ||
| 75 | EXPECT_EQ(pinIsInputHigh[7], false); | ||
| 76 | EXPECT_EQ(pinIsInputHigh[8], false); | ||
| 77 | EXPECT_EQ(pinIsInputHigh[9], false); | ||
| 78 | EXPECT_EQ(updates_array_idx, 0); // no updates received | ||
| 79 | } | ||
| 80 | |||
| 81 | TEST_F(EncoderSplitTestLeftLessThanRight, TestInitRight) { | ||
| 82 | isLeftHand = false; | ||
| 83 | encoder_init(); | ||
| 84 | EXPECT_EQ(pinIsInputHigh[0], false); | ||
| 85 | EXPECT_EQ(pinIsInputHigh[1], false); | ||
| 86 | EXPECT_EQ(pinIsInputHigh[2], false); | ||
| 87 | EXPECT_EQ(pinIsInputHigh[3], false); | ||
| 88 | EXPECT_EQ(pinIsInputHigh[4], true); | ||
| 89 | EXPECT_EQ(pinIsInputHigh[5], true); | ||
| 90 | EXPECT_EQ(pinIsInputHigh[6], true); | ||
| 91 | EXPECT_EQ(pinIsInputHigh[7], true); | ||
| 92 | EXPECT_EQ(pinIsInputHigh[8], true); | ||
| 93 | EXPECT_EQ(pinIsInputHigh[9], true); | ||
| 94 | EXPECT_EQ(updates_array_idx, 0); // no updates received | ||
| 95 | } | ||
| 96 | |||
| 97 | TEST_F(EncoderSplitTestLeftLessThanRight, TestOneClockwiseLeft) { | ||
| 98 | isLeftHand = true; | ||
| 99 | encoder_init(); | ||
| 100 | // send 4 pulses. with resolution 4, that's one step and we should get 1 update. | ||
| 101 | setAndRead(0, false); | ||
| 102 | setAndRead(1, false); | ||
| 103 | setAndRead(0, true); | ||
| 104 | setAndRead(1, true); | ||
| 105 | |||
| 106 | EXPECT_EQ(updates_array_idx, 1); // one update received | ||
| 107 | EXPECT_EQ(updates[0].index, 0); | ||
| 108 | EXPECT_EQ(updates[0].clockwise, true); | ||
| 109 | } | ||
| 110 | |||
| 111 | TEST_F(EncoderSplitTestLeftLessThanRight, TestOneClockwiseRightSent) { | ||
| 112 | isLeftHand = false; | ||
| 113 | encoder_init(); | ||
| 114 | // send 4 pulses. with resolution 4, that's one step and we should get 1 update. | ||
| 115 | setAndRead(6, false); | ||
| 116 | setAndRead(7, false); | ||
| 117 | setAndRead(6, true); | ||
| 118 | setAndRead(7, true); | ||
| 119 | |||
| 120 | uint8_t slave_state[32] = {0}; | ||
| 121 | encoder_state_raw(slave_state); | ||
| 122 | |||
| 123 | EXPECT_EQ(slave_state[0], 0); | ||
| 124 | EXPECT_EQ(slave_state[1], 0xFF); | ||
| 125 | } | ||
| 126 | |||
| 127 | TEST_F(EncoderSplitTestLeftLessThanRight, TestMultipleEncodersRightReceived) { | ||
| 128 | isLeftHand = true; | ||
| 129 | encoder_init(); | ||
| 130 | |||
| 131 | uint8_t slave_state[32] = {1, 0, 0xFF}; // First right encoder is CCW, Second right encoder no change, third right encoder CW | ||
| 132 | encoder_update_raw(slave_state); | ||
| 133 | |||
| 134 | EXPECT_EQ(updates_array_idx, 2); // two updates received, one for each changed item on the right side | ||
| 135 | EXPECT_EQ(updates[0].index, 2); | ||
| 136 | EXPECT_EQ(updates[0].clockwise, false); | ||
| 137 | EXPECT_EQ(updates[1].index, 4); | ||
| 138 | EXPECT_EQ(updates[1].clockwise, true); | ||
| 139 | } | ||
diff --git a/quantum/encoder/tests/encoder_tests_split.cpp b/quantum/encoder/tests/encoder_tests_split_no_left.cpp index 25e52c83f9..b6b2d7e2d1 100644 --- a/quantum/encoder/tests/encoder_tests_split.cpp +++ b/quantum/encoder/tests/encoder_tests_split_no_left.cpp | |||
| @@ -30,7 +30,7 @@ struct update { | |||
| 30 | bool clockwise; | 30 | bool clockwise; |
| 31 | }; | 31 | }; |
| 32 | 32 | ||
| 33 | uint8_t uidx = 0; | 33 | uint8_t updates_array_idx = 0; |
| 34 | update updates[32]; | 34 | update updates[32]; |
| 35 | 35 | ||
| 36 | bool isLeftHand; | 36 | bool isLeftHand; |
| @@ -41,8 +41,8 @@ bool encoder_update_kb(uint8_t index, bool clockwise) { | |||
| 41 | printf("ignoring update on right hand (%d,%s)\n", index, clockwise ? "CW" : "CC"); | 41 | printf("ignoring update on right hand (%d,%s)\n", index, clockwise ? "CW" : "CC"); |
| 42 | return true; | 42 | return true; |
| 43 | } | 43 | } |
| 44 | updates[uidx % 32] = {index, clockwise}; | 44 | updates[updates_array_idx % 32] = {index, clockwise}; |
| 45 | uidx++; | 45 | updates_array_idx++; |
| 46 | return true; | 46 | return true; |
| 47 | } | 47 | } |
| 48 | 48 | ||
| @@ -51,10 +51,10 @@ bool setAndRead(pin_t pin, bool val) { | |||
| 51 | return encoder_read(); | 51 | return encoder_read(); |
| 52 | } | 52 | } |
| 53 | 53 | ||
| 54 | class EncoderTest : public ::testing::Test { | 54 | class EncoderSplitTestNoLeft : public ::testing::Test { |
| 55 | protected: | 55 | protected: |
| 56 | void SetUp() override { | 56 | void SetUp() override { |
| 57 | uidx = 0; | 57 | updates_array_idx = 0; |
| 58 | for (int i = 0; i < 32; i++) { | 58 | for (int i = 0; i < 32; i++) { |
| 59 | pinIsInputHigh[i] = 0; | 59 | pinIsInputHigh[i] = 0; |
| 60 | pins[i] = 0; | 60 | pins[i] = 0; |
| @@ -62,27 +62,27 @@ class EncoderTest : public ::testing::Test { | |||
| 62 | } | 62 | } |
| 63 | }; | 63 | }; |
| 64 | 64 | ||
| 65 | TEST_F(EncoderTest, TestInitLeft) { | 65 | TEST_F(EncoderSplitTestNoLeft, TestInitLeft) { |
| 66 | isLeftHand = true; | 66 | isLeftHand = true; |
| 67 | encoder_init(); | 67 | encoder_init(); |
| 68 | EXPECT_EQ(pinIsInputHigh[0], true); | 68 | EXPECT_EQ(pinIsInputHigh[0], false); |
| 69 | EXPECT_EQ(pinIsInputHigh[1], true); | 69 | EXPECT_EQ(pinIsInputHigh[1], false); |
| 70 | EXPECT_EQ(pinIsInputHigh[2], false); | 70 | EXPECT_EQ(pinIsInputHigh[2], false); |
| 71 | EXPECT_EQ(pinIsInputHigh[3], false); | 71 | EXPECT_EQ(pinIsInputHigh[3], false); |
| 72 | EXPECT_EQ(uidx, 0); | 72 | EXPECT_EQ(updates_array_idx, 0); // no updates received |
| 73 | } | 73 | } |
| 74 | 74 | ||
| 75 | TEST_F(EncoderTest, TestInitRight) { | 75 | TEST_F(EncoderSplitTestNoLeft, TestInitRight) { |
| 76 | isLeftHand = false; | 76 | isLeftHand = false; |
| 77 | encoder_init(); | 77 | encoder_init(); |
| 78 | EXPECT_EQ(pinIsInputHigh[0], false); | 78 | EXPECT_EQ(pinIsInputHigh[0], true); |
| 79 | EXPECT_EQ(pinIsInputHigh[1], false); | 79 | EXPECT_EQ(pinIsInputHigh[1], true); |
| 80 | EXPECT_EQ(pinIsInputHigh[2], true); | 80 | EXPECT_EQ(pinIsInputHigh[2], true); |
| 81 | EXPECT_EQ(pinIsInputHigh[3], true); | 81 | EXPECT_EQ(pinIsInputHigh[3], true); |
| 82 | EXPECT_EQ(uidx, 0); | 82 | EXPECT_EQ(updates_array_idx, 0); // no updates received |
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | TEST_F(EncoderTest, TestOneClockwiseLeft) { | 85 | TEST_F(EncoderSplitTestNoLeft, TestOneClockwiseLeft) { |
| 86 | isLeftHand = true; | 86 | isLeftHand = true; |
| 87 | encoder_init(); | 87 | encoder_init(); |
| 88 | // send 4 pulses. with resolution 4, that's one step and we should get 1 update. | 88 | // send 4 pulses. with resolution 4, that's one step and we should get 1 update. |
| @@ -91,12 +91,10 @@ TEST_F(EncoderTest, TestOneClockwiseLeft) { | |||
| 91 | setAndRead(0, true); | 91 | setAndRead(0, true); |
| 92 | setAndRead(1, true); | 92 | setAndRead(1, true); |
| 93 | 93 | ||
| 94 | EXPECT_EQ(uidx, 1); | 94 | EXPECT_EQ(updates_array_idx, 0); // no updates received |
| 95 | EXPECT_EQ(updates[0].index, 0); | ||
| 96 | EXPECT_EQ(updates[0].clockwise, true); | ||
| 97 | } | 95 | } |
| 98 | 96 | ||
| 99 | TEST_F(EncoderTest, TestOneClockwiseRightSent) { | 97 | TEST_F(EncoderSplitTestNoLeft, TestOneClockwiseRightSent) { |
| 100 | isLeftHand = false; | 98 | isLeftHand = false; |
| 101 | encoder_init(); | 99 | encoder_init(); |
| 102 | // send 4 pulses. with resolution 4, that's one step and we should get 1 update. | 100 | // send 4 pulses. with resolution 4, that's one step and we should get 1 update. |
| @@ -105,39 +103,23 @@ TEST_F(EncoderTest, TestOneClockwiseRightSent) { | |||
| 105 | setAndRead(2, true); | 103 | setAndRead(2, true); |
| 106 | setAndRead(3, true); | 104 | setAndRead(3, true); |
| 107 | 105 | ||
| 108 | uint8_t slave_state[2] = {0}; | 106 | uint8_t slave_state[32] = {0}; |
| 109 | encoder_state_raw(slave_state); | 107 | encoder_state_raw(slave_state); |
| 110 | 108 | ||
| 111 | EXPECT_EQ((int8_t)slave_state[0], -1); | 109 | EXPECT_EQ(slave_state[0], 0); |
| 110 | EXPECT_EQ(slave_state[1], 0xFF); | ||
| 112 | } | 111 | } |
| 113 | 112 | ||
| 114 | /* this test will not work after the previous test. | 113 | TEST_F(EncoderSplitTestNoLeft, TestMultipleEncodersRightReceived) { |
| 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 | |||
| 133 | TEST_F(EncoderTest, TestOneCounterClockwiseRightReceived) { | ||
| 134 | isLeftHand = true; | 114 | isLeftHand = true; |
| 135 | encoder_init(); | 115 | encoder_init(); |
| 136 | 116 | ||
| 137 | uint8_t slave_state[2] = {0, 0}; | 117 | uint8_t slave_state[32] = {1, 0xFF}; // First right encoder is CCW, Second right encoder no change, third right encoder CW |
| 138 | encoder_update_raw(slave_state); | 118 | encoder_update_raw(slave_state); |
| 139 | 119 | ||
| 140 | EXPECT_EQ(uidx, 1); | 120 | EXPECT_EQ(updates_array_idx, 2); // two updates received, one for each changed item on the right side |
| 141 | EXPECT_EQ(updates[0].index, 1); | 121 | EXPECT_EQ(updates[0].index, 0); |
| 142 | EXPECT_EQ(updates[0].clockwise, false); | 122 | EXPECT_EQ(updates[0].clockwise, false); |
| 123 | EXPECT_EQ(updates[1].index, 1); | ||
| 124 | EXPECT_EQ(updates[1].clockwise, true); | ||
| 143 | } | 125 | } |
diff --git a/quantum/encoder/tests/encoder_tests_split_no_right.cpp b/quantum/encoder/tests/encoder_tests_split_no_right.cpp new file mode 100644 index 0000000000..fa0a7c18a8 --- /dev/null +++ b/quantum/encoder/tests/encoder_tests_split_no_right.cpp | |||
| @@ -0,0 +1,118 @@ | |||
| 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 | |||
| 23 | extern "C" { | ||
| 24 | #include "encoder.h" | ||
| 25 | #include "encoder/tests/mock_split.h" | ||
| 26 | } | ||
| 27 | |||
| 28 | struct update { | ||
| 29 | int8_t index; | ||
| 30 | bool clockwise; | ||
| 31 | }; | ||
| 32 | |||
| 33 | uint8_t updates_array_idx = 0; | ||
| 34 | update updates[32]; | ||
| 35 | |||
| 36 | bool isLeftHand; | ||
| 37 | |||
| 38 | bool 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[updates_array_idx % 32] = {index, clockwise}; | ||
| 45 | updates_array_idx++; | ||
| 46 | return true; | ||
| 47 | } | ||
| 48 | |||
| 49 | bool setAndRead(pin_t pin, bool val) { | ||
| 50 | setPin(pin, val); | ||
| 51 | return encoder_read(); | ||
| 52 | } | ||
| 53 | |||
| 54 | class EncoderSplitTestNoRight : public ::testing::Test { | ||
| 55 | protected: | ||
| 56 | void SetUp() override { | ||
| 57 | updates_array_idx = 0; | ||
| 58 | for (int i = 0; i < 32; i++) { | ||
| 59 | pinIsInputHigh[i] = 0; | ||
| 60 | pins[i] = 0; | ||
| 61 | } | ||
| 62 | } | ||
| 63 | }; | ||
| 64 | |||
| 65 | TEST_F(EncoderSplitTestNoRight, TestInitLeft) { | ||
| 66 | isLeftHand = true; | ||
| 67 | encoder_init(); | ||
| 68 | EXPECT_EQ(pinIsInputHigh[0], true); | ||
| 69 | EXPECT_EQ(pinIsInputHigh[1], true); | ||
| 70 | EXPECT_EQ(pinIsInputHigh[2], true); | ||
| 71 | EXPECT_EQ(pinIsInputHigh[3], true); | ||
| 72 | EXPECT_EQ(updates_array_idx, 0); // no updates received | ||
| 73 | } | ||
| 74 | |||
| 75 | TEST_F(EncoderSplitTestNoRight, TestInitRight) { | ||
| 76 | isLeftHand = false; | ||
| 77 | encoder_init(); | ||
| 78 | EXPECT_EQ(pinIsInputHigh[0], false); | ||
| 79 | EXPECT_EQ(pinIsInputHigh[1], false); | ||
| 80 | EXPECT_EQ(pinIsInputHigh[2], false); | ||
| 81 | EXPECT_EQ(pinIsInputHigh[3], false); | ||
| 82 | EXPECT_EQ(updates_array_idx, 0); // no updates received | ||
| 83 | } | ||
| 84 | |||
| 85 | TEST_F(EncoderSplitTestNoRight, 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(updates_array_idx, 1); // one updates received | ||
| 95 | EXPECT_EQ(updates[0].index, 0); | ||
| 96 | EXPECT_EQ(updates[0].clockwise, true); | ||
| 97 | } | ||
| 98 | |||
| 99 | TEST_F(EncoderSplitTestNoRight, TestOneClockwiseRightSent) { | ||
| 100 | isLeftHand = false; | ||
| 101 | encoder_init(); | ||
| 102 | |||
| 103 | uint8_t slave_state[32] = {0xAA, 0xAA}; | ||
| 104 | encoder_state_raw(slave_state); | ||
| 105 | |||
| 106 | EXPECT_EQ(slave_state[0], 0xAA); | ||
| 107 | EXPECT_EQ(slave_state[1], 0xAA); | ||
| 108 | } | ||
| 109 | |||
| 110 | TEST_F(EncoderSplitTestNoRight, TestMultipleEncodersRightReceived) { | ||
| 111 | isLeftHand = true; | ||
| 112 | encoder_init(); | ||
| 113 | |||
| 114 | uint8_t slave_state[32] = {1, 0xFF}; // These values would trigger updates if there were encoders on the other side | ||
| 115 | encoder_update_raw(slave_state); | ||
| 116 | |||
| 117 | EXPECT_EQ(updates_array_idx, 0); // no updates received -- no right-hand encoders | ||
| 118 | } | ||
diff --git a/quantum/encoder/tests/mock.h b/quantum/encoder/tests/mock.h index dbc25a0846..80c336b5ef 100644 --- a/quantum/encoder/tests/mock.h +++ b/quantum/encoder/tests/mock.h | |||
| @@ -19,12 +19,6 @@ | |||
| 19 | #include <stdint.h> | 19 | #include <stdint.h> |
| 20 | #include <stdbool.h> | 20 | #include <stdbool.h> |
| 21 | 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 | |||
| 28 | typedef uint8_t pin_t; | 22 | typedef uint8_t pin_t; |
| 29 | 23 | ||
| 30 | extern bool pins[]; | 24 | extern bool pins[]; |
diff --git a/quantum/encoder/tests/mock_split.h b/quantum/encoder/tests/mock_split.h index 0ae62652f9..2fc12f1830 100644 --- a/quantum/encoder/tests/mock_split.h +++ b/quantum/encoder/tests/mock_split.h | |||
| @@ -20,20 +20,10 @@ | |||
| 20 | #include <stdbool.h> | 20 | #include <stdbool.h> |
| 21 | 21 | ||
| 22 | #define SPLIT_KEYBOARD | 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 | |||
| 33 | typedef uint8_t pin_t; | 23 | typedef uint8_t pin_t; |
| 34 | extern bool isLeftHand; | 24 | |
| 35 | void encoder_state_raw(uint8_t* slave_state); | 25 | void encoder_state_raw(uint8_t* slave_state); |
| 36 | void encoder_update_raw(uint8_t* slave_state); | 26 | void encoder_update_raw(uint8_t* slave_state); |
| 37 | 27 | ||
| 38 | extern bool pins[]; | 28 | extern bool pins[]; |
| 39 | extern bool pinIsInputHigh[]; | 29 | extern bool pinIsInputHigh[]; |
diff --git a/quantum/encoder/tests/rules.mk b/quantum/encoder/tests/rules.mk index b826ce3aed..6a2611952c 100644 --- a/quantum/encoder/tests/rules.mk +++ b/quantum/encoder/tests/rules.mk | |||
| @@ -1,13 +1,58 @@ | |||
| 1 | encoder_DEFS := -DENCODER_MOCK_SINGLE | 1 | encoder_DEFS := -DENCODER_TESTS -DENCODER_ENABLE -DENCODER_MOCK_SINGLE |
| 2 | encoder_CONFIG := $(QUANTUM_PATH)/encoder/tests/config_mock.h | ||
| 2 | 3 | ||
| 3 | encoder_SRC := \ | 4 | encoder_SRC := \ |
| 5 | platforms/test/timer.c \ | ||
| 4 | $(QUANTUM_PATH)/encoder/tests/mock.c \ | 6 | $(QUANTUM_PATH)/encoder/tests/mock.c \ |
| 5 | $(QUANTUM_PATH)/encoder/tests/encoder_tests.cpp \ | 7 | $(QUANTUM_PATH)/encoder/tests/encoder_tests.cpp \ |
| 6 | $(QUANTUM_PATH)/encoder.c | 8 | $(QUANTUM_PATH)/encoder.c |
| 7 | 9 | ||
| 8 | encoder_split_DEFS := -DENCODER_MOCK_SPLIT | 10 | encoder_split_left_eq_right_DEFS := -DENCODER_TESTS -DENCODER_ENABLE -DENCODER_MOCK_SPLIT |
| 11 | encoder_split_left_eq_right_INC := $(QUANTUM_PATH)/split_common | ||
| 12 | encoder_split_left_eq_right_CONFIG := $(QUANTUM_PATH)/encoder/tests/config_mock_split_left_eq_right.h | ||
| 9 | 13 | ||
| 10 | encoder_split_SRC := \ | 14 | encoder_split_left_eq_right_SRC := \ |
| 15 | platforms/test/timer.c \ | ||
| 11 | $(QUANTUM_PATH)/encoder/tests/mock_split.c \ | 16 | $(QUANTUM_PATH)/encoder/tests/mock_split.c \ |
| 12 | $(QUANTUM_PATH)/encoder/tests/encoder_tests_split.cpp \ | 17 | $(QUANTUM_PATH)/encoder/tests/encoder_tests_split_left_eq_right.cpp \ |
| 18 | $(QUANTUM_PATH)/encoder.c | ||
| 19 | |||
| 20 | encoder_split_left_gt_right_DEFS := -DENCODER_TESTS -DENCODER_ENABLE -DENCODER_MOCK_SPLIT | ||
| 21 | encoder_split_left_gt_right_INC := $(QUANTUM_PATH)/split_common | ||
| 22 | encoder_split_left_gt_right_CONFIG := $(QUANTUM_PATH)/encoder/tests/config_mock_split_left_gt_right.h | ||
| 23 | |||
| 24 | encoder_split_left_gt_right_SRC := \ | ||
| 25 | platforms/test/timer.c \ | ||
| 26 | $(QUANTUM_PATH)/encoder/tests/mock_split.c \ | ||
| 27 | $(QUANTUM_PATH)/encoder/tests/encoder_tests_split_left_gt_right.cpp \ | ||
| 28 | $(QUANTUM_PATH)/encoder.c | ||
| 29 | |||
| 30 | encoder_split_left_lt_right_DEFS := -DENCODER_TESTS -DENCODER_ENABLE -DENCODER_MOCK_SPLIT | ||
| 31 | encoder_split_left_lt_right_INC := $(QUANTUM_PATH)/split_common | ||
| 32 | encoder_split_left_lt_right_CONFIG := $(QUANTUM_PATH)/encoder/tests/config_mock_split_left_lt_right.h | ||
| 33 | |||
| 34 | encoder_split_left_lt_right_SRC := \ | ||
| 35 | platforms/test/timer.c \ | ||
| 36 | $(QUANTUM_PATH)/encoder/tests/mock_split.c \ | ||
| 37 | $(QUANTUM_PATH)/encoder/tests/encoder_tests_split_left_lt_right.cpp \ | ||
| 38 | $(QUANTUM_PATH)/encoder.c | ||
| 39 | |||
| 40 | encoder_split_no_left_DEFS := -DENCODER_TESTS -DENCODER_ENABLE -DENCODER_MOCK_SPLIT | ||
| 41 | encoder_split_no_left_INC := $(QUANTUM_PATH)/split_common | ||
| 42 | encoder_split_no_left_CONFIG := $(QUANTUM_PATH)/encoder/tests/config_mock_split_no_left.h | ||
| 43 | |||
| 44 | encoder_split_no_left_SRC := \ | ||
| 45 | platforms/test/timer.c \ | ||
| 46 | $(QUANTUM_PATH)/encoder/tests/mock_split.c \ | ||
| 47 | $(QUANTUM_PATH)/encoder/tests/encoder_tests_split_no_left.cpp \ | ||
| 48 | $(QUANTUM_PATH)/encoder.c | ||
| 49 | |||
| 50 | encoder_split_no_right_DEFS := -DENCODER_TESTS -DENCODER_ENABLE -DENCODER_MOCK_SPLIT | ||
| 51 | encoder_split_no_right_INC := $(QUANTUM_PATH)/split_common | ||
| 52 | encoder_split_no_right_CONFIG := $(QUANTUM_PATH)/encoder/tests/config_mock_split_no_right.h | ||
| 53 | |||
| 54 | encoder_split_no_right_SRC := \ | ||
| 55 | platforms/test/timer.c \ | ||
| 56 | $(QUANTUM_PATH)/encoder/tests/mock_split.c \ | ||
| 57 | $(QUANTUM_PATH)/encoder/tests/encoder_tests_split_no_right.cpp \ | ||
| 13 | $(QUANTUM_PATH)/encoder.c | 58 | $(QUANTUM_PATH)/encoder.c |
diff --git a/quantum/encoder/tests/testlist.mk b/quantum/encoder/tests/testlist.mk index 1be9f4a054..6b2fd84d96 100644 --- a/quantum/encoder/tests/testlist.mk +++ b/quantum/encoder/tests/testlist.mk | |||
| @@ -1,3 +1,7 @@ | |||
| 1 | TEST_LIST += \ | 1 | TEST_LIST += \ |
| 2 | encoder \ | 2 | encoder \ |
| 3 | encoder_split | 3 | encoder_split_left_eq_right \ |
| 4 | encoder_split_left_gt_right \ | ||
| 5 | encoder_split_left_lt_right \ | ||
| 6 | encoder_split_no_left \ | ||
| 7 | encoder_split_no_right | ||
diff --git a/quantum/split_common/transactions.c b/quantum/split_common/transactions.c index cffbccaeee..105bf918cb 100644 --- a/quantum/split_common/transactions.c +++ b/quantum/split_common/transactions.c | |||
| @@ -180,7 +180,7 @@ static void master_matrix_handlers_slave(matrix_row_t master_matrix[], matrix_ro | |||
| 180 | 180 | ||
| 181 | static bool encoder_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | 181 | static bool encoder_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { |
| 182 | static uint32_t last_update = 0; | 182 | static uint32_t last_update = 0; |
| 183 | uint8_t temp_state[NUMBER_OF_ENCODERS]; | 183 | uint8_t temp_state[NUM_ENCODERS_MAX_PER_SIDE]; |
| 184 | 184 | ||
| 185 | bool okay = read_if_checksum_mismatch(GET_ENCODERS_CHECKSUM, GET_ENCODERS_DATA, &last_update, temp_state, split_shmem->encoders.state, sizeof(temp_state)); | 185 | bool okay = read_if_checksum_mismatch(GET_ENCODERS_CHECKSUM, GET_ENCODERS_DATA, &last_update, temp_state, split_shmem->encoders.state, sizeof(temp_state)); |
| 186 | if (okay) encoder_update_raw(temp_state); | 186 | if (okay) encoder_update_raw(temp_state); |
| @@ -188,7 +188,7 @@ static bool encoder_handlers_master(matrix_row_t master_matrix[], matrix_row_t s | |||
| 188 | } | 188 | } |
| 189 | 189 | ||
| 190 | static void encoder_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { | 190 | static void encoder_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { |
| 191 | uint8_t encoder_state[NUMBER_OF_ENCODERS]; | 191 | uint8_t encoder_state[NUM_ENCODERS_MAX_PER_SIDE]; |
| 192 | encoder_state_raw(encoder_state); | 192 | encoder_state_raw(encoder_state); |
| 193 | // Always prepare the encoder state for read. | 193 | // Always prepare the encoder state for read. |
| 194 | memcpy(split_shmem->encoders.state, encoder_state, sizeof(encoder_state)); | 194 | memcpy(split_shmem->encoders.state, encoder_state, sizeof(encoder_state)); |
diff --git a/quantum/split_common/transport.h b/quantum/split_common/transport.h index 26bd136728..e62679990a 100644 --- a/quantum/split_common/transport.h +++ b/quantum/split_common/transport.h | |||
| @@ -42,7 +42,6 @@ bool transport_execute_transaction(int8_t id, const void *initiator2target_buf, | |||
| 42 | 42 | ||
| 43 | #ifdef ENCODER_ENABLE | 43 | #ifdef ENCODER_ENABLE |
| 44 | # include "encoder.h" | 44 | # include "encoder.h" |
| 45 | # define NUMBER_OF_ENCODERS (sizeof((pin_t[])ENCODERS_PAD_A) / sizeof(pin_t)) | ||
| 46 | #endif // ENCODER_ENABLE | 45 | #endif // ENCODER_ENABLE |
| 47 | 46 | ||
| 48 | #ifdef BACKLIGHT_ENABLE | 47 | #ifdef BACKLIGHT_ENABLE |
| @@ -67,7 +66,7 @@ typedef struct _split_master_matrix_sync_t { | |||
| 67 | #ifdef ENCODER_ENABLE | 66 | #ifdef ENCODER_ENABLE |
| 68 | typedef struct _split_slave_encoder_sync_t { | 67 | typedef struct _split_slave_encoder_sync_t { |
| 69 | uint8_t checksum; | 68 | uint8_t checksum; |
| 70 | uint8_t state[NUMBER_OF_ENCODERS]; | 69 | uint8_t state[NUM_ENCODERS_MAX_PER_SIDE]; |
| 71 | } split_slave_encoder_sync_t; | 70 | } split_slave_encoder_sync_t; |
| 72 | #endif // ENCODER_ENABLE | 71 | #endif // ENCODER_ENABLE |
| 73 | 72 | ||
diff --git a/quantum/util.h b/quantum/util.h index bef3b9abe3..ab96ce4bde 100644 --- a/quantum/util.h +++ b/quantum/util.h | |||
| @@ -24,3 +24,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
| 24 | // convert to string | 24 | // convert to string |
| 25 | #define STR(s) XSTR(s) | 25 | #define STR(s) XSTR(s) |
| 26 | #define XSTR(s) #s | 26 | #define XSTR(s) #s |
| 27 | |||
| 28 | #if !defined(MIN) | ||
| 29 | # define MIN(x, y) (((x) < (y)) ? (x) : (y)) | ||
| 30 | #endif | ||
| 31 | |||
| 32 | #if !defined(MAX) | ||
| 33 | # define MAX(x, y) (((x) > (y)) ? (x) : (y)) | ||
| 34 | #endif | ||
