diff --git a/docs/feature_encoders.md b/docs/feature_encoders.md index cbf72914e9..beda07563a 100644 --- a/docs/feature_encoders.md +++ b/docs/feature_encoders.md @@ -58,3 +58,11 @@ or `keymap.c`: ## Hardware The A an B lines of the encoders should be wired directly to the MCU, and the C/common lines should be wired to ground. + +## Encoder matrix + +You can also wire the C/common line through a diode (arrow towards the row) to each of the rows (or reading pin) in your matrix, and use as many encoders as you have rows (multiplied by the number of A/B lines you have hooked up). To do this, you can add this line to your `config.h` with all of the pins you use: + +```c +#define ENCODERS_PAD_C { encoder1c, encoder2c } +``` \ No newline at end of file diff --git a/quantum/encoder.c b/quantum/encoder.c index 36a6403b36..74af425fc1 100644 --- a/quantum/encoder.c +++ b/quantum/encoder.c @@ -31,10 +31,19 @@ # 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; +#ifdef ENCODERS_PAD_C + #define NUMBER_OF_ENCODERS_AB (sizeof(encoders_pad_a) / sizeof(pin_t)) + #define NUMBER_OF_ENCODERS_C (sizeof(encoders_pad_c) / sizeof(pin_t)) + #define NUMBER_OF_ENCODERS (NUMBER_OF_ENCODERS_C * NUMBER_OF_ENCODERS_AB) + static pin_t encoders_pad_c[] = ENCODERS_PAD_C; +#else + #define NUMBER_OF_ENCODERS (sizeof(encoders_pad_a) / sizeof(pin_t)) + #define NUMBER_OF_ENCODERS_AB (sizeof(encoders_pad_a) / sizeof(pin_t)) +#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}; @@ -57,19 +66,51 @@ void encoder_init(void) { if (!isLeftHand) { const pin_t encoders_pad_a_right[] = ENCODERS_PAD_A_RIGHT; const pin_t encoders_pad_b_right[] = ENCODERS_PAD_B_RIGHT; - for (uint8_t i = 0; i < NUMBER_OF_ENCODERS; i++) { + for (uint8_t i = 0; i < NUMBER_OF_ENCODERS_AB; i++) { encoders_pad_a[i] = encoders_pad_a_right[i]; encoders_pad_b[i] = encoders_pad_b_right[i]; } } #endif - for (int i = 0; i < NUMBER_OF_ENCODERS; i++) { - setPinInputHigh(encoders_pad_a[i]); - setPinInputHigh(encoders_pad_b[i]); + #ifdef ENCODERS_PAD_C + for (int i = 0; i < NUMBER_OF_ENCODERS_C; i++) { + setPinOutput(encoders_pad_c[i]); + if (i != 0) + writePinHigh(encoders_pad_c[i]); + else + writePinLow(encoders_pad_c[i]); + } - encoder_state[i] = (readPin(encoders_pad_a[i]) << 0) | (readPin(encoders_pad_b[i]) << 1); - } + for (int j = 0; j < NUMBER_OF_ENCODERS_C; j++) { + writePinLow(encoders_pad_c[j]); + wait_us(10); + for (int i = 0; i < NUMBER_OF_ENCODERS_AB; i++) { + setPinInputHigh(encoders_pad_a[i]); + setPinInputHigh(encoders_pad_b[i]); + + encoder_state[j+(i*NUMBER_OF_ENCODERS_C)] = (readPin(encoders_pad_a[i]) << 0) | (readPin(encoders_pad_b[i]) << 1); + + } + writePinHigh(encoders_pad_c[j]); + } + // need to disable these pins to prevent matrix activation + for (int i = 0; i < NUMBER_OF_ENCODERS_AB; i++) { + setPinInput(encoders_pad_a[i]); + setPinInput(encoders_pad_b[i]); + } + for (int i = 0; i < NUMBER_OF_ENCODERS_C; i++) { + setPinInputLow(encoders_pad_c[i]); + } + + #else + for (int i = 0; i < NUMBER_OF_ENCODERS; 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); + } + #endif #ifdef SPLIT_KEYBOARD thisHand = isLeftHand ? 0 : NUMBER_OF_ENCODERS; @@ -89,15 +130,55 @@ static void encoder_update(int8_t index, uint8_t state) { } void encoder_read(void) { - for (int i = 0; i < NUMBER_OF_ENCODERS; i++) { - encoder_state[i] <<= 2; - encoder_state[i] |= (readPin(encoders_pad_a[i]) << 0) | (readPin(encoders_pad_b[i]) << 1); -#if SPLIT_KEYBOARD - encoder_update(i + thisHand, encoder_state[i]); -#else - encoder_update(i, encoder_state[i]); -#endif +#ifdef ENCODERS_PAD_C + // setup row pins to act as C pins for the encoders, prep the first one + for (int i = 0; i < NUMBER_OF_ENCODERS_C; i++) { + setPinOutput(encoders_pad_c[i]); + if (i != 0) + writePinHigh(encoders_pad_c[i]); + else + writePinLow(encoders_pad_c[i]); } + // pull these back up because we disabled them earlier + for (int i = 0; i < NUMBER_OF_ENCODERS_AB; i++) { + setPinInputHigh(encoders_pad_a[i]); + setPinInputHigh(encoders_pad_b[i]); + } + for (int j = 0; j < NUMBER_OF_ENCODERS_C; j++) { + writePinLow(encoders_pad_c[j]); + wait_us(10); + for (int i = 0; i < NUMBER_OF_ENCODERS_AB; i++) { + encoder_state[j+(i*NUMBER_OF_ENCODERS_C)] <<= 2; + encoder_state[j+(i*NUMBER_OF_ENCODERS_C)] |= (readPin(encoders_pad_a[i]) << 0) | (readPin(encoders_pad_b[i]) << 1); +#if SPLIT_KEYBOARD + encoder_update(j+(i*NUMBER_OF_ENCODERS_C) + thisHand, encoder_state[j+(i*NUMBER_OF_ENCODERS_C)]); +#else + encoder_update(j+(i*NUMBER_OF_ENCODERS_C), encoder_state[j+(i*NUMBER_OF_ENCODERS_C)]); +#endif + } + writePinHigh(encoders_pad_c[j]); + } + // need to disable these pins again to prevent matrix activation + for (int i = 0; i < NUMBER_OF_ENCODERS_AB; i++) { + setPinInput(encoders_pad_a[i]); + setPinInput(encoders_pad_b[i]); + } + // revert row pins back to input + for (int i = 0; i < NUMBER_OF_ENCODERS_C; i++) { + setPinInputLow(encoders_pad_c[i]); + } + +#else + for (int i = 0; i < NUMBER_OF_ENCODERS; i++) { + encoder_state[i] <<= 2; + encoder_state[i] |= (readPin(encoders_pad_a[i]) << 0) | (readPin(encoders_pad_b[i]) << 1); +#if SPLIT_KEYBOARD + encoder_update(i + thisHand, encoder_state[i]); +#else + encoder_update(i, encoder_state[i]); +#endif + } +#endif } #ifdef SPLIT_KEYBOARD