Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Asymmetric encoders, encoder tests. #16068

Merged
merged 12 commits into from
Mar 8, 2022
2 changes: 2 additions & 0 deletions build_test.mk
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ endif

.DEFAULT_GOAL := all

OPT = g

include paths.mk
include $(BUILDDEFS_PATH)/message.mk

Expand Down
3 changes: 2 additions & 1 deletion keyboards/draculad/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define ENCODERS_PAD_A {B2 , B4}
#define ENCODERS_PAD_B {B6 , B5}

#define ENCODER_RESOLUTIONS { 4, 4, 4, 1}
#define ENCODER_RESOLUTIONS { 4, 4 }
#define ENCODER_RESOLUTIONS_RIGHT { 4, 1 }
#define UNUSED_PINS

#define EE_HANDS
Expand Down
11 changes: 6 additions & 5 deletions keyboards/sofle/keyhive/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,12 @@
#define DEBOUNCE 5

// Encoder support
#define ENCODERS_PAD_A { F5 }
#define ENCODERS_PAD_B { F4 }
#define ENCODERS_PAD_A_RIGHT { F4 }
#define ENCODERS_PAD_B_RIGHT { F5 }
#define ENCODER_RESOLUTIONS { 4, 2 } // Left encoder seems to have double-output issue but right does not.
#define ENCODERS_PAD_A { F5 }
#define ENCODERS_PAD_B { F4 }
#define ENCODERS_PAD_A_RIGHT { F4 }
#define ENCODERS_PAD_B_RIGHT { F5 }
#define ENCODER_RESOLUTIONS { 4 }
#define ENCODER_RESOLUTIONS_RIGHT { 2 } // Left encoder seems to have double-output issue but right does not.

#define TAP_CODE_DELAY 10

Expand Down
4 changes: 2 additions & 2 deletions keyboards/viktus/sp_mini/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.

// wiring of each half
#define MATRIX_ROW_PINS { F0, B5, B4, D7, D6 }
#define MATRIX_COL_PINS { B6, C6, C7, D4, D2, D3, D5 } // no B7 on left hand
#define MATRIX_COL_PINS { B6, C6, C7, D4, D2, D3, D5, NO_PIN } // no B7 on left hand
#define MATRIX_ROW_PINS_RIGHT { F0, B5, B4, D7, D6 }
#define MATRIX_COL_PINS_RIGHT { B6, C6, C7, D4, D2, D3, D5, B7 }

Expand Down Expand Up @@ -78,7 +78,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
//#define ENCODERS_PAD_A_RIGHT {F4}
//#define ENCODERS_PAD_B_RIGHT {F1}

#define ENCODER_RESOLUTIONS { 8, 8 }
#define ENCODER_RESOLUTIONS { 8 }

/*
* Feature disable options
Expand Down
102 changes: 67 additions & 35 deletions quantum/encoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#ifdef SPLIT_KEYBOARD
# include "split_util.h"
#endif
#include "keymap.h"

// for memcpy
#include <string.h>
Expand All @@ -31,11 +32,13 @@
# error "No encoder pads defined by ENCODERS_PAD_A and ENCODERS_PAD_B"
#endif

#define NUMBER_OF_ENCODERS (sizeof(encoders_pad_a) / sizeof(pin_t))
static pin_t encoders_pad_a[] = ENCODERS_PAD_A;
static pin_t encoders_pad_b[] = ENCODERS_PAD_B;
extern volatile bool isLeftHand;

static pin_t encoders_pad_a[NUM_ENCODERS_MAX_PER_SIDE] = ENCODERS_PAD_A;
static pin_t encoders_pad_b[NUM_ENCODERS_MAX_PER_SIDE] = ENCODERS_PAD_B;

#ifdef ENCODER_RESOLUTIONS
static uint8_t encoder_resolutions[] = ENCODER_RESOLUTIONS;
static uint8_t encoder_resolutions[NUM_ENCODERS] = ENCODER_RESOLUTIONS;
#endif

#ifndef ENCODER_DIRECTION_FLIP
Expand All @@ -47,61 +50,90 @@ static uint8_t encoder_resolutions[] = ENCODER_RESOLUTIONS;
#endif
static int8_t encoder_LUT[] = {0, -1, 1, 0, 1, 0, 0, -1, -1, 0, 0, 1, 0, 1, -1, 0};

static uint8_t encoder_state[NUMBER_OF_ENCODERS] = {0};
static int8_t encoder_pulses[NUMBER_OF_ENCODERS] = {0};
static uint8_t encoder_state[NUM_ENCODERS] = {0};
static int8_t encoder_pulses[NUM_ENCODERS] = {0};

// encoder counts
static uint8_t thisCount;
#ifdef SPLIT_KEYBOARD
// right half encoders come over as second set of encoders
static uint8_t encoder_value[NUMBER_OF_ENCODERS * 2] = {0};
// row offsets for each hand
// encoder offsets for each hand
static uint8_t thisHand, thatHand;
#else
static uint8_t encoder_value[NUMBER_OF_ENCODERS] = {0};
// encoder counts for each hand
static uint8_t thatCount;
#endif

static uint8_t encoder_value[NUM_ENCODERS] = {0};

__attribute__((weak)) bool encoder_update_user(uint8_t index, bool clockwise) { return true; }

__attribute__((weak)) bool encoder_update_kb(uint8_t index, bool clockwise) { return encoder_update_user(index, clockwise); }

void encoder_init(void) {
#ifdef SPLIT_KEYBOARD
thisHand = isLeftHand ? 0 : NUM_ENCODERS_LEFT;
thatHand = NUM_ENCODERS_LEFT - thisHand;
thisCount = isLeftHand ? NUM_ENCODERS_LEFT : NUM_ENCODERS_RIGHT;
thatCount = isLeftHand ? NUM_ENCODERS_RIGHT : NUM_ENCODERS_LEFT;
#else // SPLIT_KEYBOARD
thisCount = NUM_ENCODERS;
#endif

#ifdef ENCODER_TESTS
// Annoying that we have to clear out values during initialisation here, but
// because all the arrays are static locals, rerunning tests in the same
// executable doesn't reset any of these. Kinda crappy having test-only code
// here, but it's the simplest solution.
memset(encoder_value, 0, sizeof(encoder_value));
memset(encoder_state, 0, sizeof(encoder_state));
memset(encoder_pulses, 0, sizeof(encoder_pulses));
static const pin_t encoders_pad_a_left[] = ENCODERS_PAD_A;
static const pin_t encoders_pad_b_left[] = ENCODERS_PAD_B;
for (uint8_t i = 0; i < thisCount; i++) {
encoders_pad_a[i] = encoders_pad_a_left[i];
encoders_pad_b[i] = encoders_pad_b_left[i];
}
#endif

#if defined(SPLIT_KEYBOARD) && defined(ENCODERS_PAD_A_RIGHT) && defined(ENCODERS_PAD_B_RIGHT)
// Re-initialise the pads if it's the right-hand side
if (!isLeftHand) {
const pin_t encoders_pad_a_right[] = ENCODERS_PAD_A_RIGHT;
const pin_t encoders_pad_b_right[] = ENCODERS_PAD_B_RIGHT;
# if defined(ENCODER_RESOLUTIONS_RIGHT)
const uint8_t encoder_resolutions_right[] = ENCODER_RESOLUTIONS_RIGHT;
# endif
for (uint8_t i = 0; i < NUMBER_OF_ENCODERS; i++) {
static const pin_t encoders_pad_a_right[] = ENCODERS_PAD_A_RIGHT;
static const pin_t encoders_pad_b_right[] = ENCODERS_PAD_B_RIGHT;
for (uint8_t i = 0; i < thisCount; i++) {
encoders_pad_a[i] = encoders_pad_a_right[i];
encoders_pad_b[i] = encoders_pad_b_right[i];
# if defined(ENCODER_RESOLUTIONS_RIGHT)
encoder_resolutions[i] = encoder_resolutions_right[i];
# endif
}
}
#endif
#endif // defined(SPLIT_KEYBOARD) && defined(ENCODERS_PAD_A_RIGHT) && defined(ENCODERS_PAD_B_RIGHT)

for (int i = 0; i < NUMBER_OF_ENCODERS; i++) {
// Encoder resolutions is handled purely master-side, so concatenate the two arrays
#if defined(SPLIT_KEYBOARD) && defined(ENCODER_RESOLUTIONS)
# if defined(ENCODER_RESOLUTIONS_RIGHT)
static const uint8_t encoder_resolutions_right[NUM_ENCODERS_RIGHT] = ENCODER_RESOLUTIONS_RIGHT;
# else // defined(ENCODER_RESOLUTIONS_RIGHT)
static const uint8_t encoder_resolutions_right[NUM_ENCODERS_RIGHT] = ENCODER_RESOLUTIONS;
# endif // defined(ENCODER_RESOLUTIONS_RIGHT)
for (uint8_t i = 0; i < NUM_ENCODERS_RIGHT; i++) {
encoder_resolutions[NUM_ENCODERS_LEFT + i] = encoder_resolutions_right[i];
}
#endif // defined(SPLIT_KEYBOARD) && defined(ENCODER_RESOLUTIONS)

for (uint8_t i = 0; i < thisCount; i++) {
setPinInputHigh(encoders_pad_a[i]);
setPinInputHigh(encoders_pad_b[i]);

encoder_state[i] = (readPin(encoders_pad_a[i]) << 0) | (readPin(encoders_pad_b[i]) << 1);
}

#ifdef SPLIT_KEYBOARD
thisHand = isLeftHand ? 0 : NUMBER_OF_ENCODERS;
thatHand = NUMBER_OF_ENCODERS - thisHand;
#endif
}

static bool encoder_update(uint8_t index, uint8_t state) {
bool changed = false;
uint8_t i = index;

#ifdef ENCODER_RESOLUTIONS
uint8_t resolution = encoder_resolutions[i];
const uint8_t resolution = encoder_resolutions[i];
#else
uint8_t resolution = ENCODER_RESOLUTION;
const uint8_t resolution = ENCODER_RESOLUTION;
#endif

#ifdef SPLIT_KEYBOARD
Expand Down Expand Up @@ -129,7 +161,7 @@ static bool encoder_update(uint8_t index, uint8_t state) {

bool encoder_read(void) {
bool changed = false;
for (uint8_t i = 0; i < NUMBER_OF_ENCODERS; i++) {
for (uint8_t i = 0; i < thisCount; i++) {
encoder_state[i] <<= 2;
encoder_state[i] |= (readPin(encoders_pad_a[i]) << 0) | (readPin(encoders_pad_b[i]) << 1);
changed |= encoder_update(i, encoder_state[i]);
Expand All @@ -140,13 +172,13 @@ bool encoder_read(void) {
#ifdef SPLIT_KEYBOARD
void last_encoder_activity_trigger(void);

void encoder_state_raw(uint8_t* slave_state) { memcpy(slave_state, &encoder_value[thisHand], sizeof(uint8_t) * NUMBER_OF_ENCODERS); }
void encoder_state_raw(uint8_t *slave_state) { memcpy(slave_state, &encoder_value[thisHand], sizeof(uint8_t) * thisCount); }

void encoder_update_raw(uint8_t* slave_state) {
void encoder_update_raw(uint8_t *slave_state) {
bool changed = false;
for (uint8_t i = 0; i < NUMBER_OF_ENCODERS; i++) {
uint8_t index = i + thatHand;
int8_t delta = slave_state[i] - encoder_value[index];
for (uint8_t i = 0; i < thatCount; i++) { // Note inverted logic -- we want the opposite side
const uint8_t index = i + thatHand;
int8_t delta = slave_state[i] - encoder_value[index];
while (delta > 0) {
delta--;
encoder_value[index]++;
Expand Down
22 changes: 22 additions & 0 deletions quantum/encoder/tests/config_mock.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright 2022 Nick Brassel (@tzarc)
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once

#define MATRIX_ROWS 1
#define MATRIX_COLS 1

/* Here, "pins" from 0 to 31 are allowed. */
#define ENCODERS_PAD_A \
{ 0 }
#define ENCODERS_PAD_B \
{ 1 }

#ifdef __cplusplus
extern "C" {
#endif

#include "mock.h"

#ifdef __cplusplus
};
#endif
26 changes: 26 additions & 0 deletions quantum/encoder/tests/config_mock_split_left_eq_right.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright 2022 Nick Brassel (@tzarc)
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once

#define MATRIX_ROWS 1
#define MATRIX_COLS 1

/* Here, "pins" from 0 to 31 are allowed. */
#define ENCODERS_PAD_A \
{ 0, 2 }
#define ENCODERS_PAD_B \
{ 1, 3 }
#define ENCODERS_PAD_A_RIGHT \
{ 4, 6 }
#define ENCODERS_PAD_B_RIGHT \
{ 5, 7 }

#ifdef __cplusplus
extern "C" {
#endif

#include "mock_split.h"

#ifdef __cplusplus
};
#endif
26 changes: 26 additions & 0 deletions quantum/encoder/tests/config_mock_split_left_gt_right.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright 2022 Nick Brassel (@tzarc)
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once

#define MATRIX_ROWS 1
#define MATRIX_COLS 1

/* Here, "pins" from 0 to 31 are allowed. */
#define ENCODERS_PAD_A \
{ 0, 2, 4 }
#define ENCODERS_PAD_B \
{ 1, 3, 5 }
#define ENCODERS_PAD_A_RIGHT \
{ 6, 8 }
#define ENCODERS_PAD_B_RIGHT \
{ 7, 9 }

#ifdef __cplusplus
extern "C" {
#endif

#include "mock_split.h"

#ifdef __cplusplus
};
#endif
26 changes: 26 additions & 0 deletions quantum/encoder/tests/config_mock_split_left_lt_right.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright 2022 Nick Brassel (@tzarc)
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once

#define MATRIX_ROWS 1
#define MATRIX_COLS 1

/* Here, "pins" from 0 to 31 are allowed. */
#define ENCODERS_PAD_A \
{ 0, 2 }
#define ENCODERS_PAD_B \
{ 1, 3 }
#define ENCODERS_PAD_A_RIGHT \
{ 4, 6, 8 }
#define ENCODERS_PAD_B_RIGHT \
{ 5, 7, 9 }

#ifdef __cplusplus
extern "C" {
#endif

#include "mock_split.h"

#ifdef __cplusplus
};
#endif
26 changes: 26 additions & 0 deletions quantum/encoder/tests/config_mock_split_no_left.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright 2022 Nick Brassel (@tzarc)
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once

#define MATRIX_ROWS 1
#define MATRIX_COLS 1

/* Here, "pins" from 0 to 31 are allowed. */
#define ENCODERS_PAD_A \
{}
#define ENCODERS_PAD_B \
{}
#define ENCODERS_PAD_A_RIGHT \
{ 0, 2 }
#define ENCODERS_PAD_B_RIGHT \
{ 1, 3 }

#ifdef __cplusplus
extern "C" {
#endif

#include "mock_split.h"

#ifdef __cplusplus
};
#endif
26 changes: 26 additions & 0 deletions quantum/encoder/tests/config_mock_split_no_right.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright 2022 Nick Brassel (@tzarc)
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once

#define MATRIX_ROWS 1
#define MATRIX_COLS 1

/* Here, "pins" from 0 to 31 are allowed. */
#define ENCODERS_PAD_A \
{ 0, 2 }
#define ENCODERS_PAD_B \
{ 1, 3 }
#define ENCODERS_PAD_A_RIGHT \
{}
#define ENCODERS_PAD_B_RIGHT \
{}

#ifdef __cplusplus
extern "C" {
#endif

#include "mock_split.h"

#ifdef __cplusplus
};
#endif