Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug] Encoder Issues on the Planck Rev 7 #24043

Open
2 tasks
drewlwhitney opened this issue Jul 4, 2024 · 6 comments
Open
2 tasks

[Bug] Encoder Issues on the Planck Rev 7 #24043

drewlwhitney opened this issue Jul 4, 2024 · 6 comments

Comments

@drewlwhitney
Copy link

Describe the Bug

Hello!

I've run into an issue with the current version of QMK and using rotary encoders on the Planck. I have an encoder on the top left, and when I turn it, the keyboard sends only the clockwise action at random detent intervals. I am using this encoder.

People on the Discord server have suggested the encoder is the problem. However, after going through three different encoders, all of them exhibit the same behavior. Furthermore, I can confirm that this issue is specific to the Planck. I have a Nyquist/Levinson Rev 4 that uses the exact same encoder and the exact same keymap as my Planck. As in, I literally copy/pasted the contents of the keymap file from the Planck to the Levinson, and the encoder on the Levinson works properly. I also have identical settings for the config.h and rules.mk files.

I can get the encoder to work QMK versions from before encoder abstraction was added, but encoder mappings for the Planck are not supported at that point in the commit history. Neither encoder mappings nor the user-side encoder function work for the Planck.

Specifically, this encoder works properly before the "Add encoder abstraction" commit, which is 9d9cdaa. I compiled firmware on commit 2eb9ff8 and the encoder worked properly. On 9d9cdaa, the encoder breaks.

I think this can be isolated to the Planck directory, since other keyboards work fine. I am not familiar enough with how encoders are implemented in QMK to find the issue myself, but I am happy to test any solutions. I would also appreciate if any other Planck users with encoders could test them on the current version. I've pasted my keymap below (I know my process_record_user is horrendous. There is a separate issue with the GUI key not being suppressed properly for key overrides that I'm manually fixing).

Let me know what I can do to help!

#include QMK_KEYBOARD_H

const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
    [0] = LAYOUT_ortho_4x12(
        KC_MPLY,          KC_Q,          KC_W,           KC_E,                  KC_R,          KC_T,         KC_Y,         KC_U,           KC_I,         KC_O,          KC_P,          KC_BSPC,
        KC_TAB,           KC_A,          KC_S,           KC_D,                  KC_F,          KC_G,         KC_H,         KC_J,           KC_K,         KC_L,          KC_SCLN,       KC_QUOT,
        KC_LSFT,          KC_Z,          KC_X,           KC_C,                  KC_V,          KC_B,         KC_N,         KC_M,           KC_COMM,      KC_DOT,        KC_SLSH,       ALT_T(KC_ESC),
        KC_LCTL,          LT(5, KC_ESC), KC_LALT,        LGUI_T(LALT(KC_SPC)),  MO(2),         KC_SPC,       KC_ENT,       MO(3),          KC_LEFT,      KC_DOWN,       KC_UP,         KC_RGHT
    ),
    [1] = LAYOUT_ortho_4x12(
        KC_MPLY,          KC_Q,          KC_W,           KC_E,                  KC_R,         KC_T,          KC_Y,         KC_U,           KC_I,         KC_O,          KC_P,          KC_BSPC,
        KC_TAB,           KC_A,          KC_S,           KC_D,                  KC_F,         KC_G,          KC_H,         KC_J,           KC_K,         KC_L,          KC_SCLN,       KC_QUOT,
        KC_LSFT,          KC_Z,          KC_X,           KC_C,                  KC_V,         KC_B,          KC_N,         KC_M,           KC_COMM,      KC_DOT,        KC_SLSH,       ALT_T(KC_ESC),
        KC_LCTL,          LT(5, KC_ESC), KC_LALT,        LGUI_T(LALT(KC_SPC)),  KC_SPC,       KC_SPC,        KC_ENT,       MO(3),          KC_LEFT,      KC_VOLD,       KC_VOLU,       KC_RGHT
    ),
    [2] = LAYOUT_ortho_4x12(
        C(A(KC_DEL)),     KC_EXLM,       KC_AT,          KC_HASH,               KC_DLR,       KC_PERC,       KC_CIRC,      KC_AMPR,        KC_ASTR,      KC_LPRN,       KC_RPRN,       KC_BSPC,
        KC_DOT,           KC_1,          KC_2,           KC_3,                  KC_4,         KC_5,          KC_6,         KC_7,           KC_8,         KC_9,          KC_0,          KC_COLN,
        SFT_T(KC_COMM),   KC_6,          KC_7,           KC_8,                  KC_9,         KC_0,          KC_PLUS,      KC_MINS,        KC_COMM,      KC_DOT,        KC_SLSH,       ALT_T(KC_ESC),
        CTL_T(KC_COLN),   LT(5, KC_ESC), KC_LALT,        LGUI_T(LALT(KC_SPC)),  KC_NO,        KC_SPC,        KC_ENT,       LT(3, KC_SPC),  KC_LEFT,      KC_DOWN,       KC_UP,         KC_RGHT
    ),
    [3] = LAYOUT_ortho_4x12(
        C(A(KC_DEL)),     KC_EXLM,       KC_AT,          KC_HASH,               KC_DLR,       KC_PERC,       KC_CIRC,      KC_AMPR,        KC_ASTR,      KC_LPRN,       KC_RPRN,       KC_BSPC,
        KC_TAB,           KC_BSLS,       KC_LBRC,        KC_RBRC,               KC_MINS,      KC_EQL,        KC_HOME,      KC_LEFT,        KC_DOWN,      KC_UP,         KC_RGHT,       KC_END,
        KC_LSFT,          KC_PIPE,       KC_LCBR,        KC_RCBR,               KC_UNDS,      KC_PLUS,       A(KC_F4),     KC_F2,          KC_COMM,      KC_RABK,       KC_F11,        ALT_T(KC_ESC),
        KC_LCTL,          LT(5, KC_ESC), KC_LALT,        LGUI_T(LALT(KC_SPC)),  MO(4),        KC_SPC,        KC_ENT,       KC_NO,          KC_LEFT,      KC_DOWN,       KC_UP,         KC_RGHT
    ),
    [4] = LAYOUT_ortho_4x12(
        C(A(KC_DEL)),     KC_EXLM,       KC_AT,          KC_HASH,               KC_DLR,       KC_PERC,       KC_CIRC,      KC_AMPR,        KC_ASTR,      KC_LPRN,       KC_RPRN,       KC_BSPC,
        KC_TAB,           KC_1,          KC_2,           KC_3,                  KC_4,         KC_5,          KC_6,         KC_7,           KC_8,         KC_9,          KC_0,          KC_COLN,
        KC_LSFT,          KC_6,          KC_7,           KC_8,                  KC_9,         KC_0,          KC_PLUS,      KC_MINS,        KC_COMM,      KC_DOT,        KC_SLSH,       ALT_T(KC_ESC),
        KC_LCTL,          LT(5, KC_ESC), KC_LALT,        LGUI_T(LALT(KC_SPC)),  KC_NO,        KC_SPC,        KC_ENT,       MO(3),          KC_LEFT,      KC_DOWN,       KC_UP,         KC_RGHT
    ),
    [5] = LAYOUT_ortho_4x12(
        KC_MUTE,          KC_F1,         KC_F2,          KC_F3,                 KC_F4,        KC_F5,         KC_F6,        KC_F7,          KC_F8,        KC_F9,         KC_F10,        KC_F11,
        KC_DEL,           KC_NO,         KC_NO,          KC_NO,                 KC_NO,        TG(1),         KC_NO,        KC_NO,          KC_NO,        KC_NO,         KC_NO,         KC_F12,
        KC_LSFT,          KC_NO,         KC_NO,          KC_NO,                 KC_NO,        KC_NO,         KC_NO,        KC_NO,          KC_NO,        KC_NO,         KC_NO,         QK_BOOT,
        KC_LCTL,          KC_NO,         KC_LALT,        LGUI_T(LALT(KC_SPC)),  MO(2),        KC_SPC,        KC_ENT,       MO(3),          KC_LEFT,      KC_DOWN,       KC_UP,         KC_RGHT
    )
};

#ifdef ENCODER_MAP_ENABLE
enum custom_keycodes {
    ENCODER_VOLU,
    ENCODER_VOLD,
    ENCODER_WH_U,
    ENCODER_WH_D,
};

const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][NUM_DIRECTIONS] = {
    [0] = {ENCODER_CCW_CW(ENCODER_VOLU, ENCODER_VOLD)},
    [1] = {ENCODER_CCW_CW(ENCODER_VOLU, ENCODER_VOLD)},
    [2] = {ENCODER_CCW_CW(KC_RIGHT,     KC_LEFT     )},
    [3] = {ENCODER_CCW_CW(ENCODER_WH_D, ENCODER_WH_U)},
    [4] = {ENCODER_CCW_CW(KC_RIGHT,     KC_LEFT     )},
    [5] = {ENCODER_CCW_CW(KC_MNXT,      KC_MPRV     )},
};
#endif

extern inline void nullify_override(uint8_t mods, uint8_t mods_to_suppress, void action(uint8_t), uint8_t keycode) {
    tap_code(KC_F18);
    unregister_mods(mods_to_suppress);
    action(keycode);
    set_mods(mods);
    if (mods & ~MOD_MASK_GUI) {
        send_keyboard_report();
    }
}
extern inline void nullify_override16(uint8_t mods, uint8_t mods_to_suppress, void action(uint16_t), uint16_t keycode) {
    tap_code(KC_F18);
    unregister_mods(mods_to_suppress);
    action(keycode);
    set_mods(mods);
    if (mods & ~MOD_MASK_GUI) {
        send_keyboard_report();
    }
}

bool process_record_user(uint16_t keycode, keyrecord_t *record) {
    switch (keycode) {
        case LGUI_T(LALT(KC_SPC)):
            if (record->tap.count && record->event.pressed) {tap_code16(LALT(KC_SPC));}
            else {return true;}
            break;
        case ALT_T(KC_ESC):
            if (record->tap.count) {
                const uint8_t mods = get_mods();
                if (mods & MOD_MASK_GUI && !(mods & MOD_MASK_CS)) {nullify_override(mods, MOD_MASK_GUI, record->event.pressed ? register_code : unregister_code, KC_GRV);}
                else if (mods & MOD_MASK_SHIFT && !(mods & MOD_MASK_CG)) {
                    record->event.pressed ? register_code16(KC_TILD) : unregister_code16(KC_TILD);
                }
                else {
                    if (record->event.pressed) {return true;}
                    else {
                        unregister_code(KC_GRV);
                        unregister_code(KC_ESC);
                        unregister_weak_mods(MOD_MASK_SHIFT);
                    }
                }
            } 
            else {return true;}
            break;
        case CTL_T(KC_COLN):
            if (record->tap.count && record->event.pressed) {tap_code16(KC_COLN);} 
            else {return true;}
            break;
        case KC_END: {
            const uint8_t mods = get_mods();
            if (mods & MOD_MASK_GUI) {nullify_override16(mods, MOD_MASK_GUI, record->event.pressed ? register_code16 : unregister_code16, C(KC_END));}
            // prevent ctrl + end
            else if (mods & MOD_MASK_CTRL) {
                if (record->event.pressed) {
                    unregister_mods(MOD_MASK_CTRL);
                    register_code(KC_END);
                    set_mods(mods);
                } else {return true;}
            }
            else {
                if (record->event.pressed) {return true;}
                else {
                    unregister_code(KC_END);
                    unregister_weak_mods(MOD_MASK_CTRL);
                }
            }
            break;
        }
        case KC_HOME: {
            const uint8_t mods = get_mods();
            if (mods & MOD_MASK_GUI) {nullify_override16(mods, MOD_MASK_GUI, record->event.pressed ? register_code16 : unregister_code16, C(KC_HOME));}
            // prevent ctrl + home
            else if (mods & MOD_MASK_CTRL) {
                if (record->event.pressed) {
                    unregister_mods(MOD_MASK_CTRL);
                    register_code(KC_HOME);
                    set_mods(mods);
                } else {return true;}
            }
            else {
                if (record->event.pressed) {return true;}
                else {
                    unregister_code(KC_HOME);
                    unregister_weak_mods(MOD_MASK_CTRL);
                }
            }
            break;
        }
#ifdef ENCODER_MAP_ENABLE
        // Encoder events
        // NOTE TO SELF: You will have to manually suppress the GUI and ALT keys
        // because of separate keyup and keydown events ಥ_ಥ
        case ENCODER_VOLD: {
            if (record->event.pressed) {
                const uint8_t mods = get_mods();
                if (mods & MOD_MASK_CTRL || mods & MOD_MASK_SHIFT) {
                    tap_code(KC_LEFT);
                }
                else if (mods & MOD_MASK_GUI) {
                    register_mods(MOD_MASK_CTRL);
                    unregister_mods(MOD_MASK_GUI);        
                    tap_code(KC_MINS);
                    unregister_mods(MOD_MASK_CTRL);
                    set_mods(mods);
                }
                else if (mods & MOD_MASK_ALT) {
                    del_mods(MOD_MASK_ALT);
                    tap_code16(C(S(KC_TAB)));
                    set_mods(mods);
                }
                else {
                    tap_code(KC_VOLD);
                }                    
            }
            return false;
            break;
        }
        case ENCODER_VOLU: {
            if (record->event.pressed) {
                const uint8_t mods = get_mods();
                if (mods & MOD_MASK_CTRL || mods & MOD_MASK_SHIFT) {
                    tap_code(KC_RGHT);
                }
                else if (mods & MOD_MASK_GUI) {
                    register_mods(MOD_MASK_CTRL);
                    unregister_mods(MOD_MASK_GUI);        
                    tap_code(KC_EQL);
                    unregister_mods(MOD_MASK_CTRL);
                    set_mods(mods);
                }
                else if (mods & MOD_MASK_ALT) {
                    del_mods(MOD_MASK_ALT);
                    tap_code16(C(KC_TAB));
                    set_mods(mods);
                }
                else {
                    tap_code(KC_VOLU);
                }                    
            }
            return false;
            break;
        }                
        case ENCODER_WH_U: {
            if (record->event.pressed) {
                tap_code(KC_WH_U);
                tap_code(KC_WH_U);                    
            }
            return false;
            break;
        }
        case ENCODER_WH_D: {
            if (record->event.pressed) {
                tap_code(KC_WH_D);
                tap_code(KC_WH_D);                    
            }
            return false;
            break;
        }
#endif
        default:
            return true;
            break;
    }
    return false;
}

Keyboard Used

planck/rev7

Link to product page (if applicable)

https://drop.com/buy/planck-mechanical-keyboard

Operating System

Windows 11

qmk doctor Output

Ψ QMK Doctor is checking your environment.
Ψ CLI version: 1.1.5
Ψ QMK home: C:/Users/drewl/qmk_firmware
Ψ Detected Windows 10 (10.0.22631).
Ψ QMK MSYS version: 1.9.0
Ψ Userspace enabled: False
Ψ Git branch: master
Ψ Repo version: 0.25.9
⚠ Git has unstashed/uncommitted changes.
Ψ - Latest master: 2024-07-03 22:00:53 +1000 (bc8ac86422) -- Minimum python version listing. (#23989)
Ψ - Latest upstream/master: 2024-07-03 22:00:53 +1000 (bc8ac86422) -- Minimum python version listing. (#23989)
Ψ - Latest upstream/develop: None
Ψ - Common ancestor with upstream/master: 2024-07-03 22:00:53 +1000 (bc8ac86422) -- Minimum python version listing. (#23989)
Ψ - Common ancestor with upstream/develop: None
Ψ All dependencies are installed.
Ψ Found arm-none-eabi-gcc version 12.2.0
Ψ Found avr-gcc version 12.2.0
⚠ We do not recommend avr-gcc newer than 8. Downgrading to 8.x is recommended.
Ψ Found avrdude version 7.0
Ψ Found dfu-programmer version 1.1.0
Ψ Found dfu-util version 0.11
Ψ Submodules are up to date.
Ψ Submodule status:
Ψ - lib/chibios: 2024-02-17 19:20:06 +0000 --  (be44b3305)
Ψ - lib/chibios-contrib: 2024-04-03 20:39:24 +0800 --  (77cb0a4f)
Ψ - lib/googletest: 2021-06-11 06:37:43 -0700 --  (e2239ee6)
Ψ - lib/lufa: 2022-08-26 12:09:55 +1000 --  (549b97320)
Ψ - lib/vusb: 2022-06-13 09:18:17 +1000 --  (819dbc1)
Ψ - lib/printf: 2022-06-29 23:59:58 +0300 --  (c2e3b4e)
Ψ - lib/pico-sdk: 2023-02-12 20:19:37 +0100 --  (a3398d8)
Ψ - lib/lvgl: 2022-04-11 04:44:53 -0600 --  (e19410f8)
Ψ QMK is ready to go, but minor problems were found

Is AutoHotKey / Karabiner installed

  • AutoHotKey (Windows)
  • Karabiner (macOS)

Other keyboard-related software installed

QMK Toolbox

Additional Context

I have #define ENCODER_MAP_ENABLE in config.h.

@tzarc
Copy link
Member

tzarc commented Jul 4, 2024

Can you try #23967 please?

@drewlwhitney
Copy link
Author

Yes absolutely! My previous solution for gaining access to older versions has been downloading a zip and then sort of stitching it together with the compiler. Is there a Git command that lets me get a specific commit version?

@tzarc
Copy link
Member

tzarc commented Jul 4, 2024

Can try:

# assuming QMK is your upstream remote as per the docs
git fetch -f upstream refs/pull/23967/head:pr/23967
git merge --no-commit --squash pr/23967

@drewlwhitney
Copy link
Author

I'm currently getting this issue:

error: Your local changes to the following files would be overwritten by merge:
keyboards/planck/rev7/keymaps/default/config.h keyboards/planck/rev7/keymaps/default/keymap.c keyboards/planck/rev7/matrix.c keyboards/planck/rev7/readme.md
:279: trailing whitespace.
If you enable ENCODER_MAP_ENABLE, defined const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][NUM_DIRECTIONS] and configure your keycode. And, If you enable ENCODER_MAP_ENABLE, does not use encoder_update_user directly.
warning: 1 line adds whitespace errors.
Merge with strategy ort failed.

@tzarc
Copy link
Member

tzarc commented Jul 4, 2024

That seems to indicate you've modified those files locally? I've just attempted it with current master and it merged fine.

@drewlwhitney
Copy link
Author

Oops! I didn't realize I also needed to run git commit. My Git noobiness is showing.

However, yippee! That version works perfectly! The encoder reads correctly with a resolution of two, and the encoder map is being used. It's even working with mod-tap keys, so I can use my mod-tap Alt/Esc key to cycle through tabs with the encoder now.

I no longer have to have two separate qmk versions on my computer! Thank you so much tzarc! If there are any other tests you would like me to run, I will absolutely do them.

Have a wonderful night!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants