diff --git a/common_features.mk b/common_features.mk index a4e744bdb76..a76c522bfc0 100644 --- a/common_features.mk +++ b/common_features.mk @@ -209,6 +209,12 @@ ifeq ($(strip $(I2C_SLAVE_ENABLE)), yes) OPT_DEFS += -DI2C_SLAVE_ENABLE endif +ifeq ($(strip $(ENCODER_ENABLE)), yes) + OPT_DEFS += -DENCODER_ENABLE + SRC += $(QUANTUM_DIR)/encoder.c +endif + + QUANTUM_SRC:= \ $(QUANTUM_DIR)/quantum.c \ $(QUANTUM_DIR)/keymap_common.c \ diff --git a/keyboards/planck/light/rev1/config.h b/keyboards/planck/light/rev1/config.h index 17c015ed0fd..b1f356c4255 100644 --- a/keyboards/planck/light/rev1/config.h +++ b/keyboards/planck/light/rev1/config.h @@ -41,5 +41,8 @@ #define DRIVER_2_LED_TOTAL 24 #define DRIVER_LED_TOTAL DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL +#define NUMBER_OF_ENCODERS 1 +#define ENCODERS_PAD_A { F6 } +#define ENCODERS_PAD_B { F7 } #endif diff --git a/keyboards/planck/light/rev1/rules.mk b/keyboards/planck/light/rev1/rules.mk index c10b8fd1da5..4de2f210866 100644 --- a/keyboards/planck/light/rev1/rules.mk +++ b/keyboards/planck/light/rev1/rules.mk @@ -1,5 +1,6 @@ MIDI_ENABLE = yes AUDIO_ENABLE = yes # Audio output on port C6 RGB_MATRIX_ENABLE = yes +ENCODER_ENABLE = yes -MCU = at90usb1286 \ No newline at end of file +MCU = at90usb1286 diff --git a/keyboards/planck/light/rev2/config.h b/keyboards/planck/light/rev2/config.h index ebfb1ddea59..e8cf383c626 100644 --- a/keyboards/planck/light/rev2/config.h +++ b/keyboards/planck/light/rev2/config.h @@ -52,8 +52,12 @@ #undef AUDIO_VOICES #undef C6_AUDIO +#define NUMBER_OF_ENCODERS 1 +#define ENCODERS_PAD_A { B12 } +#define ENCODERS_PAD_B { B13 } + /* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */ -#define DEBOUNCE 6 +#define DEBOUNCE 0 /* Prevent modifiers from being stuck on after layer changes. */ #define PREVENT_STUCK_MODIFIERS diff --git a/keyboards/planck/light/rev2/matrix.c b/keyboards/planck/light/rev2/matrix.c index 0a0f84ece36..0de8b202856 100644 --- a/keyboards/planck/light/rev2/matrix.c +++ b/keyboards/planck/light/rev2/matrix.c @@ -21,10 +21,6 @@ static matrix_row_t matrix_debouncing[MATRIX_COLS]; static bool debouncing = false; static uint16_t debouncing_time = 0; -static uint8_t encoder_state = 0; -static int8_t encoder_value = 0; -static int8_t encoder_LUT[] = { 0, -1, 1, 0, 1, 0, 0, -1, -1, 0, 0, 1, 0, 1, -1, 0 }; - static LINE_TYPE matrix_col_pins[MATRIX_COLS] = MATRIX_COL_PINS; static LINE_TYPE matrix_row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; @@ -48,12 +44,6 @@ void matrix_init(void) { printf("matrix init\n"); //debug_matrix = true; - // encoder setup - palSetPadMode(GPIOB, 12, PAL_MODE_INPUT_PULLUP); - palSetPadMode(GPIOB, 13, PAL_MODE_INPUT_PULLUP); - - encoder_state = (palReadPad(GPIOB, 12) << 0) | (palReadPad(GPIOB, 13) << 1); - // actual matrix setup for (int i = 0; i < MATRIX_COLS; i++) { setPadMode(matrix_col_pins[i], PAL_MODE_OUTPUT_PUSHPULL); @@ -69,29 +59,8 @@ void matrix_init(void) { matrix_init_quantum(); } -__attribute__ ((weak)) -void encoder_update(bool clockwise) { } - -#ifndef ENCODER_RESOLUTION - #define ENCODER_RESOLUTION 4 -#endif - -#define COUNTRECLOCKWISE 0 -#define CLOCKWISE 1 - uint8_t matrix_scan(void) { - // encoder on B12 and B13 - encoder_state <<= 2; - encoder_state |= (palReadPad(GPIOB, 12) << 0) | (palReadPad(GPIOB, 13) << 1); - encoder_value += encoder_LUT[encoder_state & 0xF]; - if (encoder_value >= ENCODER_RESOLUTION) { - encoder_update(COUNTRECLOCKWISE); - } - if (encoder_value <= -ENCODER_RESOLUTION) { // direction is arbitrary here, but this clockwise - encoder_update(CLOCKWISE); - } - encoder_value %= ENCODER_RESOLUTION; // actual matrix for (int col = 0; col < MATRIX_COLS; col++) { diff --git a/keyboards/planck/light/rev2/rules.mk b/keyboards/planck/light/rev2/rules.mk index f037375bc1a..4d90354c959 100644 --- a/keyboards/planck/light/rev2/rules.mk +++ b/keyboards/planck/light/rev2/rules.mk @@ -53,4 +53,5 @@ NKRO_ENABLE = yes # USB Nkey Rollover CUSTOM_MATRIX = yes # Custom matrix file AUDIO_ENABLE = yes RGB_MATRIX_ENABLE = yes +ENCODER_ENABLE = yes # SERIAL_LINK_ENABLE = yes diff --git a/quantum/config_common.h b/quantum/config_common.h index 34cfefb0886..5de2d139932 100644 --- a/quantum/config_common.h +++ b/quantum/config_common.h @@ -1,4 +1,4 @@ -/* Copyright 2015-2017 Jack Humbert +/* Copyright 2015-2018 Jack Humbert * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,6 +23,7 @@ #define CUSTOM_MATRIX 2 /* Disables built-in matrix scanning code */ #ifdef __AVR__ + #include #define LINE_TYPE uint8_t /* I/O pins */ @@ -76,6 +77,15 @@ #define A6 0x06 #define A7 0x07 #endif + + #define setPadMode(line, mode) _SFR_IO8((line >> 4) + 1) mode _BV(line & 0xF) + #define setPad(line) _SFR_IO8((line >> 4) + 2) |= _BV(line & 0xF) + #define clearPad(line) _SFR_IO8((line >> 4) + 2) &= ~_BV(line & 0xF) + #define readPad(line) (_SFR_IO8(line >> 4) & _BV(line & 0xF)) + + #define PAD_MODE_INPUT &= ~ + #define PAD_MODE_OUTPUT |= + #else #include "hal.h" @@ -182,6 +192,8 @@ #define setPad(line) palSetPad(PAL_PORT(line), PAL_PAD(line)) #define clearPad(line) palClearPad(PAL_PORT(line), PAL_PAD(line)) #define readPad(line) palReadPad(PAL_PORT(line), PAL_PAD(line)) + + #define PAD_MODE_INPUT PAL_MODE_INPUT_PULLUP #endif diff --git a/quantum/encoder.c b/quantum/encoder.c new file mode 100644 index 00000000000..022cc1c01c3 --- /dev/null +++ b/quantum/encoder.c @@ -0,0 +1,67 @@ +/* + * Copyright 2018 Jack Humbert + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "encoder.h" +#include + +#ifndef ENCODER_RESOLUTION + #define ENCODER_RESOLUTION 4 +#endif + +#if !defined(ENCODERS_PAD_A) || !defined(ENCODERS_PAD_B) + #error "No encoder pads defined by ENCODERS_PAD_A and ENCODERS_PAD_B" +#endif + +static LINE_TYPE encoders_pad_a[NUMBER_OF_ENCODERS] = ENCODERS_PAD_A; +static LINE_TYPE encoders_pad_b[NUMBER_OF_ENCODERS] = ENCODERS_PAD_B; + +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_value[NUMBER_OF_ENCODERS] = {0}; + +__attribute__ ((weak)) +void encoder_update_user(bool clockwise) { } + +__attribute__ ((weak)) +void encoder_update_kb(bool clockwise) { + encoder_update_user(clockwise); +} + +void encoder_init(void) { + for (int i = 0; i < NUMBER_OF_ENCODERS; i++) { + setPadMode(encoders_pad_a[i], PAD_MODE_INPUT); + setPadMode(encoders_pad_b[i], PAD_MODE_INPUT); + + encoder_state[i] = (readPad(encoders_pad_a[i]) << 0) | (readPad(encoders_pad_b[i]) << 1); + } +} + +void encoder_read(void) { + for (int i = 0; i < NUMBER_OF_ENCODERS; i++) { + encoder_state[i] <<= 2; + encoder_state[i] |= (readPad(encoders_pad_a[i]) << 0) | (readPad(encoders_pad_b[i]) << 1); + encoder_value[i] += encoder_LUT[encoder_state[i] & 0xF]; + if (encoder_value[i] >= ENCODER_RESOLUTION) { + encoder_update_kb(COUNTRECLOCKWISE); + } + if (encoder_value[i] <= -ENCODER_RESOLUTION) { // direction is arbitrary here, but this clockwise + encoder_update_kb(CLOCKWISE); + } + encoder_value[i] %= ENCODER_RESOLUTION; + } +} diff --git a/quantum/encoder.h b/quantum/encoder.h new file mode 100644 index 00000000000..bf2c73bc248 --- /dev/null +++ b/quantum/encoder.h @@ -0,0 +1,27 @@ +/* + * Copyright 2018 Jack Humbert + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef ENCODER_H +#define ENCODER_H + +#define COUNTRECLOCKWISE 0 +#define CLOCKWISE 1 + +void encoder_init(void); +void encoder_read(void); + +#endif diff --git a/quantum/quantum.c b/quantum/quantum.c index f9b3e2197d9..331ed5634c1 100644 --- a/quantum/quantum.c +++ b/quantum/quantum.c @@ -851,6 +851,9 @@ void matrix_init_quantum() { #ifdef RGB_MATRIX_ENABLE rgb_matrix_init_drivers(); #endif + #ifdef ENCODER_ENABLE + encoder_init(); + #endif matrix_init_kb(); } @@ -885,6 +888,10 @@ void matrix_scan_quantum() { rgb_matrix_task_counter = ((rgb_matrix_task_counter + 1) % (RGB_MATRIX_SKIP_FRAMES + 1)); #endif + #ifdef ENCODER_ENABLE + encoder_read(); + #endif + matrix_scan_kb(); } #if defined(BACKLIGHT_ENABLE) && defined(BACKLIGHT_PIN) diff --git a/quantum/quantum.h b/quantum/quantum.h index 36eeedd494a..55ea4a50100 100644 --- a/quantum/quantum.h +++ b/quantum/quantum.h @@ -121,6 +121,10 @@ extern uint32_t default_layer_state; #include "process_terminal_nop.h" #endif +#ifdef ENCODER_ENABLE + #include "encoder.h" +#endif + #ifndef MIN #define MAX(x, y) (((x) > (y)) ? (x) : (y)) #define MIN(x, y) (((x) < (y)) ? (x) : (y))