]> git.donarmstrong.com Git - qmk_firmware.git/commitdiff
add support for encoders to core
authorJack Humbert <jack.humb@gmail.com>
Fri, 26 Oct 2018 20:19:23 +0000 (16:19 -0400)
committerDrashna Jaelre <drashna@live.com>
Fri, 26 Oct 2018 21:24:13 +0000 (14:24 -0700)
common_features.mk
docs/_sidebar.md
docs/_summary.md
docs/feature_encoders.md [new file with mode: 0644]
keyboards/planck/planck.h
keyboards/planck/rev6/config.h
keyboards/planck/rev6/matrix.c
keyboards/planck/rev6/rules.mk
quantum/encoder.c [new file with mode: 0644]
quantum/encoder.h [new file with mode: 0644]
quantum/quantum.c

index 65ff6b5b38440fb66d76a54d984dc5b4d6a74f1a..3fd8361a526cd09d43db6571cc04f0b96694e1ed 100644 (file)
@@ -219,6 +219,11 @@ ifeq ($(strip $(USB_HID_ENABLE)), yes)
     include $(TMK_DIR)/protocol/usb_hid.mk
 endif
 
+ifeq ($(strip $(ENCODER_ENABLE)), yes)
+    SRC += $(QUANTUM_DIR)/encoder.c
+    OPT_DEFS += -DENCODER_ENABLE
+endif
+
 ifeq ($(strip $(HD44780_ENABLE)), yes)
     SRC += drivers/avr/hd44780.c
     OPT_DEFS += -DHD44780_ENABLE
index 465f4657cd3248f1332fab6f98033822c0998575..2c573801220aa7a267f87a3aab17c8f139a5b670 100644 (file)
@@ -52,6 +52,7 @@
   * [Combos](feature_combo)
   * [Command](feature_command.md)
   * [Dynamic Macros](feature_dynamic_macros.md)
+  * [Encoders](feature_encoders.md)
   * [Grave Escape](feature_grave_esc.md)
   * [Key Lock](feature_key_lock.md)
   * [Layouts](feature_layouts.md)
index 465f4657cd3248f1332fab6f98033822c0998575..2c573801220aa7a267f87a3aab17c8f139a5b670 100644 (file)
@@ -52,6 +52,7 @@
   * [Combos](feature_combo)
   * [Command](feature_command.md)
   * [Dynamic Macros](feature_dynamic_macros.md)
+  * [Encoders](feature_encoders.md)
   * [Grave Escape](feature_grave_esc.md)
   * [Key Lock](feature_key_lock.md)
   * [Layouts](feature_layouts.md)
diff --git a/docs/feature_encoders.md b/docs/feature_encoders.md
new file mode 100644 (file)
index 0000000..f482eef
--- /dev/null
@@ -0,0 +1,41 @@
+# Encoders
+
+Basic encoders are supported by adding this to your `rules.mk`:
+
+    ENCODER_ENABLE = yes
+
+and this to your `config.h`:
+
+    #define NUMBER_OF_ENCODERS 1
+    #define ENCODERS_PAD_A { B12 }
+    #define ENCODERS_PAD_B { B13 }
+
+Each PAD_A/B variable defines an array so multiple encoders can be defined, e.g.:
+
+    #define ENCODERS_PAD_A { encoder1a, encoder2a }
+    #define ENCODERS_PAD_B { encoder1a, encoder2b }
+
+If your encoder's clockwise directions are incorrect, you can swap the A & B pad definitions.
+
+Additionally, the resolution can be specified in the same file (the default & suggested is 4):
+
+    #define ENCODER_RESOLUTION 4
+
+## Callbacks
+
+The callback functions can be inserted into your `<keyboard>.c`:
+
+    void encoder_update_kb(uint8_t index, bool clockwise) {
+        encoder_update_user(index, clockwise);
+    }
+
+or `keymap.c`:
+
+    void encoder_update_user(uint8_t index, bool clockwise) {
+        
+    }
+
+
+## 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.
index f0a12d9335b71805cce545d91259206f21150b23..d908d80ec4a3eef001cebcf62eb1d6a728873d30 100644 (file)
@@ -3,6 +3,8 @@
 
 #include "quantum.h"
 
+#define encoder_update(clockwise) encoder_update_user(uint8_t index, clockwise)
+
 #ifdef __AVR__
 #define LAYOUT_planck_mit( \
        k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k0a, k0b, \
index afd69f7d847b8578f0aa45e0e6e5b2c55a48a0bb..c0fbb412ee1b7ade99050b89292f6272b1e82507 100644 (file)
  * #define UNUSED_PINS
  */
 
+#define NUMBER_OF_ENCODERS 1
+#define ENCODERS_PAD_A { B12 }
+#define ENCODERS_PAD_B { B13 }
+
 #define MUSIC_MAP
 #undef AUDIO_VOICES
 #undef C6_AUDIO
index e4ebe48acc698f1108bd9ad93a84b17b548ee64d..2df588cefc34cc39c419db50b1905ffd32b806a0 100644 (file)
@@ -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 bool dip_switch[4] = {0, 0, 0, 0};
 
 __attribute__ ((weak))
@@ -53,12 +49,6 @@ void matrix_init(void) {
     palSetPadMode(GPIOA, 10, PAL_MODE_INPUT_PULLUP);
     palSetPadMode(GPIOB, 9,  PAL_MODE_INPUT_PULLUP);
 
-    // 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
     palSetPadMode(GPIOB, 11, PAL_MODE_OUTPUT_PUSHPULL);
     palSetPadMode(GPIOB, 10, PAL_MODE_OUTPUT_PUSHPULL);
@@ -87,15 +77,8 @@ void matrix_init(void) {
 __attribute__ ((weak))
 void dip_update(uint8_t index, bool active) { }
 
-__attribute__ ((weak))
-void encoder_update(bool clockwise) { }
-
 bool last_dip_switch[4] = {0};
 
-#ifndef ENCODER_RESOLUTION
-  #define ENCODER_RESOLUTION 4
-#endif
-
 uint8_t matrix_scan(void) {
     // dip switch
     dip_switch[0] = !palReadPad(GPIOB, 14);
@@ -108,18 +91,6 @@ uint8_t matrix_scan(void) {
     }
     memcpy(last_dip_switch, dip_switch, sizeof(&dip_switch));
 
-    // 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(0);
-    }
-    if (encoder_value <= -ENCODER_RESOLUTION) { // direction is arbitrary here, but this clockwise
-        encoder_update(1);
-    }
-    encoder_value %= ENCODER_RESOLUTION;
-
     // actual matrix
     for (int col = 0; col < MATRIX_COLS; col++) {
         matrix_row_t data = 0;
index 3603e287b35e8da76ecce560d6f15c28fd12a0ec..dce683a7fff9801fb678359d9b6100f3c8b39f1f 100644 (file)
@@ -54,3 +54,4 @@ CUSTOM_MATRIX = yes # Custom matrix file
 AUDIO_ENABLE = yes
 RGBLIGHT_ENABLE = no
 # SERIAL_LINK_ENABLE = yes
+ENCODER_ENABLE = yes
diff --git a/quantum/encoder.c b/quantum/encoder.c
new file mode 100644 (file)
index 0000000..6629a09
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2018 Jack Humbert <jack.humb@gmail.com>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include "encoder.h"
+
+#ifndef ENCODER_RESOLUTION
+  #define ENCODER_RESOLUTION 4
+#endif
+
+#ifndef NUMBER_OF_ENCODERS
+  #error "Number of encoders not defined by NUMBER_OF_ENCODERS"
+#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 pin_t encoders_pad_a[NUMBER_OF_ENCODERS] = ENCODERS_PAD_A;
+static pin_t 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(int8_t index, bool clockwise) { }
+
+__attribute__ ((weak))
+void encoder_update_kb(int8_t index, bool clockwise) {
+  encoder_update_user(index, clockwise);
+}
+
+void encoder_init(void) {
+  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);
+  }
+}
+
+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);
+    encoder_value[i] += encoder_LUT[encoder_state[i] & 0xF];
+    if (encoder_value[i] >= ENCODER_RESOLUTION) {
+        encoder_update_kb(i, COUNTRECLOCKWISE);
+    }
+    if (encoder_value[i] <= -ENCODER_RESOLUTION) { // direction is arbitrary here, but this clockwise
+        encoder_update_kb(i, CLOCKWISE);
+    }
+    encoder_value[i] %= ENCODER_RESOLUTION;
+  }
+}
diff --git a/quantum/encoder.h b/quantum/encoder.h
new file mode 100644 (file)
index 0000000..2024fa3
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2018 Jack Humbert <jack.humb@gmail.com>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include "quantum.h"
+
+#define COUNTRECLOCKWISE 0
+#define CLOCKWISE 1
+
+void encoder_init(void);
+void encoder_read(void);
+
+void encoder_update_kb(int8_t index, bool clockwise);
+void encoder_update_user(int8_t index, bool clockwise);
index eed59f811e8b429a97e1ac75d8b5bb941bb2e0d3..c9bec6740baaaafc893b98d2b97c67da7e1d4be3 100644 (file)
@@ -42,6 +42,11 @@ extern backlight_config_t backlight_config;
 #include "process_midi.h"
 #endif
 
+
+#ifdef ENCODER_ENABLE
+#include "encoder.h"
+#endif
+
 #ifdef AUDIO_ENABLE
   #ifndef GOODBYE_SONG
     #define GOODBYE_SONG SONG(GOODBYE_SOUND)
@@ -957,6 +962,9 @@ void matrix_init_quantum() {
   #ifdef RGB_MATRIX_ENABLE
     rgb_matrix_init();
   #endif
+  #ifdef ENCODER_ENABLE
+    encoder_init();
+  #endif
   matrix_init_kb();
 }
 
@@ -991,6 +999,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)