Skip to content

Commit

Permalink
add support for encoders to core
Browse files Browse the repository at this point in the history
  • Loading branch information
jackhumbert authored and drashna committed Oct 26, 2018
1 parent e22c399 commit 85688e5
Show file tree
Hide file tree
Showing 11 changed files with 166 additions and 29 deletions.
5 changes: 5 additions & 0 deletions common_features.mk
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions docs/_sidebar.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions docs/_summary.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
41 changes: 41 additions & 0 deletions docs/feature_encoders.md
Original file line number Diff line number Diff line change
@@ -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.
2 changes: 2 additions & 0 deletions keyboards/planck/planck.h
Original file line number Diff line number Diff line change
Expand Up @@ -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, \
Expand Down
4 changes: 4 additions & 0 deletions keyboards/planck/rev6/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@
* #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
Expand Down
29 changes: 0 additions & 29 deletions keyboards/planck/rev6/matrix.c
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand All @@ -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;
Expand Down
1 change: 1 addition & 0 deletions keyboards/planck/rev6/rules.mk
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,4 @@ CUSTOM_MATRIX = yes # Custom matrix file
AUDIO_ENABLE = yes
RGBLIGHT_ENABLE = no
# SERIAL_LINK_ENABLE = yes
ENCODER_ENABLE = yes
70 changes: 70 additions & 0 deletions quantum/encoder.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Copyright 2018 Jack Humbert <[email protected]>
*
* 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;
}
}
29 changes: 29 additions & 0 deletions quantum/encoder.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright 2018 Jack Humbert <[email protected]>
*
* 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);
12 changes: 12 additions & 0 deletions quantum/quantum.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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();
}

Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit 85688e5

Please sign in to comment.