aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJack Humbert <jack.humb@gmail.com>2018-10-26 16:19:23 -0400
committerDrashna Jaelre <drashna@live.com>2018-10-26 14:24:13 -0700
commit85688e5b52112c86895171d3dc8b26610480e932 (patch)
tree03f3f7bf585ebdf158576aeb6a8cf0c8c5319d6f
parente22c3992454ade93ccaef70ab077e79a4b2a5ef0 (diff)
downloadqmk_firmware-85688e5b52112c86895171d3dc8b26610480e932.tar.gz
qmk_firmware-85688e5b52112c86895171d3dc8b26610480e932.zip
add support for encoders to core
-rw-r--r--common_features.mk5
-rw-r--r--docs/_sidebar.md1
-rw-r--r--docs/_summary.md1
-rw-r--r--docs/feature_encoders.md41
-rw-r--r--keyboards/planck/planck.h2
-rw-r--r--keyboards/planck/rev6/config.h4
-rw-r--r--keyboards/planck/rev6/matrix.c29
-rw-r--r--keyboards/planck/rev6/rules.mk1
-rw-r--r--quantum/encoder.c70
-rw-r--r--quantum/encoder.h29
-rw-r--r--quantum/quantum.c12
11 files changed, 166 insertions, 29 deletions
diff --git a/common_features.mk b/common_features.mk
index 65ff6b5b3..3fd8361a5 100644
--- a/common_features.mk
+++ b/common_features.mk
@@ -219,6 +219,11 @@ ifeq ($(strip $(USB_HID_ENABLE)), yes)
219 include $(TMK_DIR)/protocol/usb_hid.mk 219 include $(TMK_DIR)/protocol/usb_hid.mk
220endif 220endif
221 221
222ifeq ($(strip $(ENCODER_ENABLE)), yes)
223 SRC += $(QUANTUM_DIR)/encoder.c
224 OPT_DEFS += -DENCODER_ENABLE
225endif
226
222ifeq ($(strip $(HD44780_ENABLE)), yes) 227ifeq ($(strip $(HD44780_ENABLE)), yes)
223 SRC += drivers/avr/hd44780.c 228 SRC += drivers/avr/hd44780.c
224 OPT_DEFS += -DHD44780_ENABLE 229 OPT_DEFS += -DHD44780_ENABLE
diff --git a/docs/_sidebar.md b/docs/_sidebar.md
index 465f4657c..2c5738012 100644
--- a/docs/_sidebar.md
+++ b/docs/_sidebar.md
@@ -52,6 +52,7 @@
52 * [Combos](feature_combo) 52 * [Combos](feature_combo)
53 * [Command](feature_command.md) 53 * [Command](feature_command.md)
54 * [Dynamic Macros](feature_dynamic_macros.md) 54 * [Dynamic Macros](feature_dynamic_macros.md)
55 * [Encoders](feature_encoders.md)
55 * [Grave Escape](feature_grave_esc.md) 56 * [Grave Escape](feature_grave_esc.md)
56 * [Key Lock](feature_key_lock.md) 57 * [Key Lock](feature_key_lock.md)
57 * [Layouts](feature_layouts.md) 58 * [Layouts](feature_layouts.md)
diff --git a/docs/_summary.md b/docs/_summary.md
index 465f4657c..2c5738012 100644
--- a/docs/_summary.md
+++ b/docs/_summary.md
@@ -52,6 +52,7 @@
52 * [Combos](feature_combo) 52 * [Combos](feature_combo)
53 * [Command](feature_command.md) 53 * [Command](feature_command.md)
54 * [Dynamic Macros](feature_dynamic_macros.md) 54 * [Dynamic Macros](feature_dynamic_macros.md)
55 * [Encoders](feature_encoders.md)
55 * [Grave Escape](feature_grave_esc.md) 56 * [Grave Escape](feature_grave_esc.md)
56 * [Key Lock](feature_key_lock.md) 57 * [Key Lock](feature_key_lock.md)
57 * [Layouts](feature_layouts.md) 58 * [Layouts](feature_layouts.md)
diff --git a/docs/feature_encoders.md b/docs/feature_encoders.md
new file mode 100644
index 000000000..f482eefec
--- /dev/null
+++ b/docs/feature_encoders.md
@@ -0,0 +1,41 @@
1# Encoders
2
3Basic encoders are supported by adding this to your `rules.mk`:
4
5 ENCODER_ENABLE = yes
6
7and this to your `config.h`:
8
9 #define NUMBER_OF_ENCODERS 1
10 #define ENCODERS_PAD_A { B12 }
11 #define ENCODERS_PAD_B { B13 }
12
13Each PAD_A/B variable defines an array so multiple encoders can be defined, e.g.:
14
15 #define ENCODERS_PAD_A { encoder1a, encoder2a }
16 #define ENCODERS_PAD_B { encoder1a, encoder2b }
17
18If your encoder's clockwise directions are incorrect, you can swap the A & B pad definitions.
19
20Additionally, the resolution can be specified in the same file (the default & suggested is 4):
21
22 #define ENCODER_RESOLUTION 4
23
24## Callbacks
25
26The callback functions can be inserted into your `<keyboard>.c`:
27
28 void encoder_update_kb(uint8_t index, bool clockwise) {
29 encoder_update_user(index, clockwise);
30 }
31
32or `keymap.c`:
33
34 void encoder_update_user(uint8_t index, bool clockwise) {
35
36 }
37
38
39## Hardware
40
41The A an B lines of the encoders should be wired directly to the MCU, and the C/common lines should be wired to ground.
diff --git a/keyboards/planck/planck.h b/keyboards/planck/planck.h
index f0a12d933..d908d80ec 100644
--- a/keyboards/planck/planck.h
+++ b/keyboards/planck/planck.h
@@ -3,6 +3,8 @@
3 3
4#include "quantum.h" 4#include "quantum.h"
5 5
6#define encoder_update(clockwise) encoder_update_user(uint8_t index, clockwise)
7
6#ifdef __AVR__ 8#ifdef __AVR__
7#define LAYOUT_planck_mit( \ 9#define LAYOUT_planck_mit( \
8 k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k0a, k0b, \ 10 k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k0a, k0b, \
diff --git a/keyboards/planck/rev6/config.h b/keyboards/planck/rev6/config.h
index afd69f7d8..c0fbb412e 100644
--- a/keyboards/planck/rev6/config.h
+++ b/keyboards/planck/rev6/config.h
@@ -43,6 +43,10 @@
43 * #define UNUSED_PINS 43 * #define UNUSED_PINS
44 */ 44 */
45 45
46#define NUMBER_OF_ENCODERS 1
47#define ENCODERS_PAD_A { B12 }
48#define ENCODERS_PAD_B { B13 }
49
46#define MUSIC_MAP 50#define MUSIC_MAP
47#undef AUDIO_VOICES 51#undef AUDIO_VOICES
48#undef C6_AUDIO 52#undef C6_AUDIO
diff --git a/keyboards/planck/rev6/matrix.c b/keyboards/planck/rev6/matrix.c
index e4ebe48ac..2df588cef 100644
--- a/keyboards/planck/rev6/matrix.c
+++ b/keyboards/planck/rev6/matrix.c
@@ -21,10 +21,6 @@ static matrix_row_t matrix_debouncing[MATRIX_COLS];
21static bool debouncing = false; 21static bool debouncing = false;
22static uint16_t debouncing_time = 0; 22static uint16_t debouncing_time = 0;
23 23
24static uint8_t encoder_state = 0;
25static int8_t encoder_value = 0;
26static int8_t encoder_LUT[] = { 0, -1, 1, 0, 1, 0, 0, -1, -1, 0, 0, 1, 0, 1, -1, 0 };
27
28static bool dip_switch[4] = {0, 0, 0, 0}; 24static bool dip_switch[4] = {0, 0, 0, 0};
29 25
30__attribute__ ((weak)) 26__attribute__ ((weak))
@@ -53,12 +49,6 @@ void matrix_init(void) {
53 palSetPadMode(GPIOA, 10, PAL_MODE_INPUT_PULLUP); 49 palSetPadMode(GPIOA, 10, PAL_MODE_INPUT_PULLUP);
54 palSetPadMode(GPIOB, 9, PAL_MODE_INPUT_PULLUP); 50 palSetPadMode(GPIOB, 9, PAL_MODE_INPUT_PULLUP);
55 51
56 // encoder setup
57 palSetPadMode(GPIOB, 12, PAL_MODE_INPUT_PULLUP);
58 palSetPadMode(GPIOB, 13, PAL_MODE_INPUT_PULLUP);
59
60 encoder_state = (palReadPad(GPIOB, 12) << 0) | (palReadPad(GPIOB, 13) << 1);
61
62 // actual matrix setup 52 // actual matrix setup
63 palSetPadMode(GPIOB, 11, PAL_MODE_OUTPUT_PUSHPULL); 53 palSetPadMode(GPIOB, 11, PAL_MODE_OUTPUT_PUSHPULL);
64 palSetPadMode(GPIOB, 10, PAL_MODE_OUTPUT_PUSHPULL); 54 palSetPadMode(GPIOB, 10, PAL_MODE_OUTPUT_PUSHPULL);
@@ -87,15 +77,8 @@ void matrix_init(void) {
87__attribute__ ((weak)) 77__attribute__ ((weak))
88void dip_update(uint8_t index, bool active) { } 78void dip_update(uint8_t index, bool active) { }
89 79
90__attribute__ ((weak))
91void encoder_update(bool clockwise) { }
92
93bool last_dip_switch[4] = {0}; 80bool last_dip_switch[4] = {0};
94 81
95#ifndef ENCODER_RESOLUTION
96 #define ENCODER_RESOLUTION 4
97#endif
98
99uint8_t matrix_scan(void) { 82uint8_t matrix_scan(void) {
100 // dip switch 83 // dip switch
101 dip_switch[0] = !palReadPad(GPIOB, 14); 84 dip_switch[0] = !palReadPad(GPIOB, 14);
@@ -108,18 +91,6 @@ uint8_t matrix_scan(void) {
108 } 91 }
109 memcpy(last_dip_switch, dip_switch, sizeof(&dip_switch)); 92 memcpy(last_dip_switch, dip_switch, sizeof(&dip_switch));
110 93
111 // encoder on B12 and B13
112 encoder_state <<= 2;
113 encoder_state |= (palReadPad(GPIOB, 12) << 0) | (palReadPad(GPIOB, 13) << 1);
114 encoder_value += encoder_LUT[encoder_state & 0xF];
115 if (encoder_value >= ENCODER_RESOLUTION) {
116 encoder_update(0);
117 }
118 if (encoder_value <= -ENCODER_RESOLUTION) { // direction is arbitrary here, but this clockwise
119 encoder_update(1);
120 }
121 encoder_value %= ENCODER_RESOLUTION;
122
123 // actual matrix 94 // actual matrix
124 for (int col = 0; col < MATRIX_COLS; col++) { 95 for (int col = 0; col < MATRIX_COLS; col++) {
125 matrix_row_t data = 0; 96 matrix_row_t data = 0;
diff --git a/keyboards/planck/rev6/rules.mk b/keyboards/planck/rev6/rules.mk
index 3603e287b..dce683a7f 100644
--- a/keyboards/planck/rev6/rules.mk
+++ b/keyboards/planck/rev6/rules.mk
@@ -54,3 +54,4 @@ CUSTOM_MATRIX = yes # Custom matrix file
54AUDIO_ENABLE = yes 54AUDIO_ENABLE = yes
55RGBLIGHT_ENABLE = no 55RGBLIGHT_ENABLE = no
56# SERIAL_LINK_ENABLE = yes 56# SERIAL_LINK_ENABLE = yes
57ENCODER_ENABLE = yes
diff --git a/quantum/encoder.c b/quantum/encoder.c
new file mode 100644
index 000000000..6629a098b
--- /dev/null
+++ b/quantum/encoder.c
@@ -0,0 +1,70 @@
1/*
2 * Copyright 2018 Jack Humbert <jack.humb@gmail.com>
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "encoder.h"
19
20#ifndef ENCODER_RESOLUTION
21 #define ENCODER_RESOLUTION 4
22#endif
23
24#ifndef NUMBER_OF_ENCODERS
25 #error "Number of encoders not defined by NUMBER_OF_ENCODERS"
26#endif
27
28#if !defined(ENCODERS_PAD_A) || !defined(ENCODERS_PAD_B)
29 #error "No encoder pads defined by ENCODERS_PAD_A and ENCODERS_PAD_B"
30#endif
31
32static pin_t encoders_pad_a[NUMBER_OF_ENCODERS] = ENCODERS_PAD_A;
33static pin_t encoders_pad_b[NUMBER_OF_ENCODERS] = ENCODERS_PAD_B;
34
35static int8_t encoder_LUT[] = { 0, -1, 1, 0, 1, 0, 0, -1, -1, 0, 0, 1, 0, 1, -1, 0 };
36
37static uint8_t encoder_state[NUMBER_OF_ENCODERS] = {0};
38static int8_t encoder_value[NUMBER_OF_ENCODERS] = {0};
39
40__attribute__ ((weak))
41void encoder_update_user(int8_t index, bool clockwise) { }
42
43__attribute__ ((weak))
44void encoder_update_kb(int8_t index, bool clockwise) {
45 encoder_update_user(index, clockwise);
46}
47
48void encoder_init(void) {
49 for (int i = 0; i < NUMBER_OF_ENCODERS; i++) {
50 setPinInputHigh(encoders_pad_a[i]);
51 setPinInputHigh(encoders_pad_b[i]);
52
53 encoder_state[i] = (readPin(encoders_pad_a[i]) << 0) | (readPin(encoders_pad_b[i]) << 1);
54 }
55}
56
57void encoder_read(void) {
58 for (int i = 0; i < NUMBER_OF_ENCODERS; i++) {
59 encoder_state[i] <<= 2;
60 encoder_state[i] |= (readPin(encoders_pad_a[i]) << 0) | (readPin(encoders_pad_b[i]) << 1);
61 encoder_value[i] += encoder_LUT[encoder_state[i] & 0xF];
62 if (encoder_value[i] >= ENCODER_RESOLUTION) {
63 encoder_update_kb(i, COUNTRECLOCKWISE);
64 }
65 if (encoder_value[i] <= -ENCODER_RESOLUTION) { // direction is arbitrary here, but this clockwise
66 encoder_update_kb(i, CLOCKWISE);
67 }
68 encoder_value[i] %= ENCODER_RESOLUTION;
69 }
70}
diff --git a/quantum/encoder.h b/quantum/encoder.h
new file mode 100644
index 000000000..2024fa303
--- /dev/null
+++ b/quantum/encoder.h
@@ -0,0 +1,29 @@
1/*
2 * Copyright 2018 Jack Humbert <jack.humb@gmail.com>
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#pragma once
19
20#include "quantum.h"
21
22#define COUNTRECLOCKWISE 0
23#define CLOCKWISE 1
24
25void encoder_init(void);
26void encoder_read(void);
27
28void encoder_update_kb(int8_t index, bool clockwise);
29void encoder_update_user(int8_t index, bool clockwise);
diff --git a/quantum/quantum.c b/quantum/quantum.c
index eed59f811..c9bec6740 100644
--- a/quantum/quantum.c
+++ b/quantum/quantum.c
@@ -42,6 +42,11 @@ extern backlight_config_t backlight_config;
42#include "process_midi.h" 42#include "process_midi.h"
43#endif 43#endif
44 44
45
46#ifdef ENCODER_ENABLE
47#include "encoder.h"
48#endif
49
45#ifdef AUDIO_ENABLE 50#ifdef AUDIO_ENABLE
46 #ifndef GOODBYE_SONG 51 #ifndef GOODBYE_SONG
47 #define GOODBYE_SONG SONG(GOODBYE_SOUND) 52 #define GOODBYE_SONG SONG(GOODBYE_SOUND)
@@ -957,6 +962,9 @@ void matrix_init_quantum() {
957 #ifdef RGB_MATRIX_ENABLE 962 #ifdef RGB_MATRIX_ENABLE
958 rgb_matrix_init(); 963 rgb_matrix_init();
959 #endif 964 #endif
965 #ifdef ENCODER_ENABLE
966 encoder_init();
967 #endif
960 matrix_init_kb(); 968 matrix_init_kb();
961} 969}
962 970
@@ -991,6 +999,10 @@ void matrix_scan_quantum() {
991 rgb_matrix_task_counter = ((rgb_matrix_task_counter + 1) % (RGB_MATRIX_SKIP_FRAMES + 1)); 999 rgb_matrix_task_counter = ((rgb_matrix_task_counter + 1) % (RGB_MATRIX_SKIP_FRAMES + 1));
992 #endif 1000 #endif
993 1001
1002 #ifdef ENCODER_ENABLE
1003 encoder_read();
1004 #endif
1005
994 matrix_scan_kb(); 1006 matrix_scan_kb();
995} 1007}
996#if defined(BACKLIGHT_ENABLE) && defined(BACKLIGHT_PIN) 1008#if defined(BACKLIGHT_ENABLE) && defined(BACKLIGHT_PIN)