From 4029395a1b71a9c97fda68ed60cce7467893e072 Mon Sep 17 00:00:00 2001 From: zvecr Date: Sun, 8 Aug 2021 22:33:50 +0100 Subject: [PATCH] Migrate swap_hands to quantum --- quantum/action.c | 145 +---------------- quantum/action.h | 17 -- quantum/action_code.h | 30 ---- quantum/action_util.c | 54 ------- quantum/action_util.h | 8 - quantum/keymap_common.c | 5 - quantum/process_keycode/process_swap_hands.c | 155 +++++++++++++++++++ quantum/process_keycode/process_swap_hands.h | 28 ++++ quantum/quantum.c | 6 + quantum/quantum.h | 4 + quantum/quantum_keycodes.h | 9 ++ 11 files changed, 204 insertions(+), 257 deletions(-) create mode 100644 quantum/process_keycode/process_swap_hands.c create mode 100644 quantum/process_keycode/process_swap_hands.h diff --git a/quantum/action.c b/quantum/action.c index ceaaa551f54..d1c03384ec8 100644 --- a/quantum/action.c +++ b/quantum/action.c @@ -79,12 +79,6 @@ void action_exec(keyevent_t event) { clear_weak_mods(); } -#ifdef SWAP_HANDS_ENABLE - if (!IS_NOEVENT(event)) { - process_hand_swap(&event); - } -#endif - keyrecord_t record = {.event = event}; #ifndef NO_ACTION_ONESHOT @@ -96,11 +90,6 @@ void action_exec(keyevent_t event) { if (has_oneshot_mods_timed_out()) { clear_oneshot_mods(); } -# ifdef SWAP_HANDS_ENABLE - if (has_oneshot_swaphands_timed_out()) { - clear_oneshot_swaphands(); - } -# endif # endif } #endif @@ -121,31 +110,6 @@ void action_exec(keyevent_t event) { #endif } -#ifdef SWAP_HANDS_ENABLE -bool swap_hands = false; -bool swap_held = false; - -/** \brief Process Hand Swap - * - * FIXME: Needs documentation. - */ -void process_hand_swap(keyevent_t *event) { - static swap_state_row_t swap_state[MATRIX_ROWS]; - - keypos_t pos = event->key; - swap_state_row_t col_bit = (swap_state_row_t)1 << pos.col; - bool do_swap = event->pressed ? swap_hands : swap_state[pos.row] & (col_bit); - - if (do_swap) { - event->key.row = pgm_read_byte(&hand_swap_config[pos.row][pos.col].row); - event->key.col = pgm_read_byte(&hand_swap_config[pos.row][pos.col].col); - swap_state[pos.row] |= col_bit; - } else { - swap_state[pos.row] &= ~(col_bit); - } -} -#endif - #if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE) bool disable_action_cache = false; @@ -171,18 +135,8 @@ void process_record_tap_hint(keyrecord_t *record) { action_t action = layer_switch_get_action(record->event.key); switch (action.kind.id) { -# ifdef SWAP_HANDS_ENABLE - case ACT_SWAP_HANDS: - switch (action.swap.code) { - case OP_SH_ONESHOT: - break; - case OP_SH_TAP_TOGGLE: - default: - swap_hands = !swap_hands; - swap_held = true; - } + default: break; -# endif } } #endif @@ -259,11 +213,7 @@ void process_action(keyrecord_t *record, action_t action) { #ifndef NO_ACTION_ONESHOT bool do_release_oneshot = false; // notice we only clear the one shot layer if the pressed key is not a modifier. - if (is_oneshot_layer_active() && event.pressed && (action.kind.id == ACT_USAGE || !IS_MOD(action.key.code)) -# ifdef SWAP_HANDS_ENABLE - && !(action.kind.id == ACT_SWAP_HANDS && action.swap.code == OP_SH_ONESHOT) -# endif - && !keymap_config.oneshot_disable) { + if (is_oneshot_layer_active() && event.pressed && (action.kind.id == ACT_USAGE || !IS_MOD(action.key.code)) && !keymap_config.oneshot_disable) { clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED); do_release_oneshot = !is_oneshot_layer_active(); } @@ -631,79 +581,6 @@ void process_action(keyrecord_t *record, action_t action) { action_macro_play(action_get_macro(record, action.func.id, action.func.opt)); break; #endif -#ifdef SWAP_HANDS_ENABLE - case ACT_SWAP_HANDS: - switch (action.swap.code) { - case OP_SH_TOGGLE: - if (event.pressed) { - swap_hands = !swap_hands; - } - break; - case OP_SH_ON_OFF: - swap_hands = event.pressed; - break; - case OP_SH_OFF_ON: - swap_hands = !event.pressed; - break; - case OP_SH_ON: - if (!event.pressed) { - swap_hands = true; - } - break; - case OP_SH_OFF: - if (!event.pressed) { - swap_hands = false; - } - break; -# ifndef NO_ACTION_ONESHOT - case OP_SH_ONESHOT: - if (event.pressed) { - set_oneshot_swaphands(); - } else { - release_oneshot_swaphands(); - } - break; -# endif - -# ifndef NO_ACTION_TAPPING - case OP_SH_TAP_TOGGLE: - /* tap toggle */ - - if (event.pressed) { - if (swap_held) { - swap_held = false; - } else { - swap_hands = !swap_hands; - } - } else { - if (tap_count < TAPPING_TOGGLE) { - swap_hands = !swap_hands; - } - } - break; - default: - /* tap key */ - if (tap_count > 0) { - if (swap_held) { - swap_hands = !swap_hands; // undo hold set up in _tap_hint - swap_held = false; - } - if (event.pressed) { - register_code(action.swap.code); - } else { - wait_ms(TAP_CODE_DELAY); - unregister_code(action.swap.code); - *record = (keyrecord_t){}; // hack: reset tap mode - } - } else { - if (swap_held && !event.pressed) { - swap_hands = !swap_hands; // undo hold set up in _tap_hint - swap_held = false; - } - } -# endif - } -#endif #ifndef NO_ACTION_FUNCTION case ACT_FUNCTION: action_function(record, action.func.id, action.func.opt); @@ -756,14 +633,6 @@ void process_action(keyrecord_t *record, action_t action) { # endif #endif -#ifdef SWAP_HANDS_ENABLE -# ifndef NO_ACTION_ONESHOT - if (event.pressed && !(action.kind.id == ACT_SWAP_HANDS && action.swap.code == OP_SH_ONESHOT)) { - use_oneshot_swaphands(); - } -# endif -#endif - #ifndef NO_ACTION_ONESHOT /* Because we switch layers after a oneshot event, we need to release the * key before we leave the layer or no key up event will be generated. @@ -1084,13 +953,6 @@ bool is_tap_action(action_t action) { return true; } return false; - case ACT_SWAP_HANDS: - switch (action.swap.code) { - case KC_NO ... KC_RIGHT_GUI: - case OP_SH_TAP_TOGGLE: - return true; - } - return false; case ACT_MACRO: case ACT_FUNCTION: if (action.func.opt & FUNC_TAP) { @@ -1159,9 +1021,6 @@ void debug_action(action_t action) { case ACT_FUNCTION: dprint("ACT_FUNCTION"); break; - case ACT_SWAP_HANDS: - dprint("ACT_SWAP_HANDS"); - break; default: dprint("UNKNOWN"); break; diff --git a/quantum/action.h b/quantum/action.h index b562f18c5b3..472806e66a2 100644 --- a/quantum/action.h +++ b/quantum/action.h @@ -86,23 +86,6 @@ bool process_record_quantum(keyrecord_t *record); extern bool disable_action_cache; #endif -/* Code for handling one-handed key modifiers. */ -#ifdef SWAP_HANDS_ENABLE -extern bool swap_hands; -extern const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS]; -# if (MATRIX_COLS <= 8) -typedef uint8_t swap_state_row_t; -# elif (MATRIX_COLS <= 16) -typedef uint16_t swap_state_row_t; -# elif (MATRIX_COLS <= 32) -typedef uint32_t swap_state_row_t; -# else -# error "MATRIX_COLS: invalid value" -# endif - -void process_hand_swap(keyevent_t *record); -#endif - void process_record_nocache(keyrecord_t *record); void process_record(keyrecord_t *record); void process_record_handler(keyrecord_t *record); diff --git a/quantum/action_code.h b/quantum/action_code.h index eb18c36ae80..4907fc073f5 100644 --- a/quantum/action_code.h +++ b/quantum/action_code.h @@ -48,9 +48,6 @@ along with this program. If not, see . * ACT_MOUSEKEY(0101): TODO: Merge these two actions to conserve space? * 0101|xxxx| keycode Mouse key * - * ACT_SWAP_HANDS(0110): - * 0110|xxxx| keycode Swap hands (keycode on tap, or options) - * * 0111|xxxx xxxx xxxx (reserved) * * Layer Actions(10xx) @@ -104,8 +101,6 @@ enum action_kind_id { /* Other Keys */ ACT_USAGE = 0b0100, ACT_MOUSEKEY = 0b0101, - /* One-hand Support */ - ACT_SWAP_HANDS = 0b0110, /* Layer Actions */ ACT_LAYER = 0b1000, ACT_LAYER_MODS = 0b1001, @@ -169,11 +164,6 @@ typedef union { uint8_t opt : 4; uint8_t kind : 4; } func; - struct action_swap { - uint8_t code : 8; - uint8_t opt : 4; - uint8_t kind : 4; - } swap; } action_t; /* action utility */ @@ -286,23 +276,3 @@ enum function_opts { #define ACTION_FUNCTION(id) ACTION(ACT_FUNCTION, (id)) #define ACTION_FUNCTION_TAP(id) ACTION(ACT_FUNCTION, FUNC_TAP << 8 | (id)) #define ACTION_FUNCTION_OPT(id, opt) ACTION(ACT_FUNCTION, (opt) << 8 | (id)) -/* OneHand Support */ -enum swap_hands_param_tap_op { - OP_SH_TOGGLE = 0xF0, - OP_SH_TAP_TOGGLE, - OP_SH_ON_OFF, - OP_SH_OFF_ON, - OP_SH_OFF, - OP_SH_ON, - OP_SH_ONESHOT, -}; - -#define ACTION_SWAP_HANDS() ACTION_SWAP_HANDS_ON_OFF() -#define ACTION_SWAP_HANDS_TOGGLE() ACTION(ACT_SWAP_HANDS, OP_SH_TOGGLE) -#define ACTION_SWAP_HANDS_TAP_TOGGLE() ACTION(ACT_SWAP_HANDS, OP_SH_TAP_TOGGLE) -#define ACTION_SWAP_HANDS_ONESHOT() ACTION(ACT_SWAP_HANDS, OP_SH_ONESHOT) -#define ACTION_SWAP_HANDS_TAP_KEY(key) ACTION(ACT_SWAP_HANDS, key) -#define ACTION_SWAP_HANDS_ON_OFF() ACTION(ACT_SWAP_HANDS, OP_SH_ON_OFF) -#define ACTION_SWAP_HANDS_OFF_ON() ACTION(ACT_SWAP_HANDS, OP_SH_OFF_ON) -#define ACTION_SWAP_HANDS_ON() ACTION(ACT_SWAP_HANDS, OP_SH_ON) -#define ACTION_SWAP_HANDS_OFF() ACTION(ACT_SWAP_HANDS, OP_SH_OFF) diff --git a/quantum/action_util.c b/quantum/action_util.c index 78e02aec185..0d1dd3da1aa 100644 --- a/quantum/action_util.c +++ b/quantum/action_util.c @@ -77,63 +77,9 @@ static int8_t oneshot_layer_data = 0; inline uint8_t get_oneshot_layer(void) { return oneshot_layer_data >> 3; } inline uint8_t get_oneshot_layer_state(void) { return oneshot_layer_data & 0b111; } -# ifdef SWAP_HANDS_ENABLE -enum { - SHO_OFF, - SHO_ACTIVE, // Swap hands button was pressed, and we didn't send any swapped keys yet - SHO_PRESSED, // Swap hands button is currently pressed - SHO_USED, // Swap hands button is still pressed, and we already sent swapped keys -} swap_hands_oneshot = SHO_OFF; -# endif - # if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) static uint16_t oneshot_layer_time = 0; inline bool has_oneshot_layer_timed_out() { return TIMER_DIFF_16(timer_read(), oneshot_layer_time) >= ONESHOT_TIMEOUT && !(get_oneshot_layer_state() & ONESHOT_TOGGLED); } -# ifdef SWAP_HANDS_ENABLE -static uint16_t oneshot_swaphands_time = 0; -inline bool has_oneshot_swaphands_timed_out() { return TIMER_DIFF_16(timer_read(), oneshot_swaphands_time) >= ONESHOT_TIMEOUT && (swap_hands_oneshot == SHO_ACTIVE); } -# endif -# endif - -# ifdef SWAP_HANDS_ENABLE - -void set_oneshot_swaphands(void) { - swap_hands_oneshot = SHO_PRESSED; - swap_hands = true; -# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) - oneshot_swaphands_time = timer_read(); - if (oneshot_layer_time != 0) { - oneshot_layer_time = oneshot_swaphands_time; - } -# endif -} - -void release_oneshot_swaphands(void) { - if (swap_hands_oneshot == SHO_PRESSED) { - swap_hands_oneshot = SHO_ACTIVE; - } - if (swap_hands_oneshot == SHO_USED) { - clear_oneshot_swaphands(); - } -} - -void use_oneshot_swaphands(void) { - if (swap_hands_oneshot == SHO_PRESSED) { - swap_hands_oneshot = SHO_USED; - } - if (swap_hands_oneshot == SHO_ACTIVE) { - clear_oneshot_swaphands(); - } -} - -void clear_oneshot_swaphands(void) { - swap_hands_oneshot = SHO_OFF; - swap_hands = false; -# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) - oneshot_swaphands_time = 0; -# endif -} - # endif /** \brief Set oneshot layer diff --git a/quantum/action_util.h b/quantum/action_util.h index f2b3897ae50..4a27291a7ac 100644 --- a/quantum/action_util.h +++ b/quantum/action_util.h @@ -76,7 +76,6 @@ void reset_oneshot_layer(void); bool is_oneshot_layer_active(void); uint8_t get_oneshot_layer_state(void); bool has_oneshot_layer_timed_out(void); -bool has_oneshot_swaphands_timed_out(void); void oneshot_locked_mods_changed_user(uint8_t mods); void oneshot_locked_mods_changed_kb(uint8_t mods); @@ -93,13 +92,6 @@ bool is_oneshot_enabled(void); /* inspect */ uint8_t has_anymod(void); -#ifdef SWAP_HANDS_ENABLE -void set_oneshot_swaphands(void); -void release_oneshot_swaphands(void); -void use_oneshot_swaphands(void); -void clear_oneshot_swaphands(void); -#endif - #ifdef __cplusplus } #endif diff --git a/quantum/keymap_common.c b/quantum/keymap_common.c index 5007f15f111..b4d5a116e10 100644 --- a/quantum/keymap_common.c +++ b/quantum/keymap_common.c @@ -152,11 +152,6 @@ action_t action_for_keycode(uint16_t keycode) { action.code = ACTION_MODS_TAP_KEY(mod, keycode & 0xFF); break; #endif -#ifdef SWAP_HANDS_ENABLE - case QK_SWAP_HANDS ... QK_SWAP_HANDS_MAX: - action.code = ACTION(ACT_SWAP_HANDS, keycode & 0xff); - break; -#endif default: action.code = ACTION_NO; diff --git a/quantum/process_keycode/process_swap_hands.c b/quantum/process_keycode/process_swap_hands.c new file mode 100644 index 00000000000..29dfb3b1546 --- /dev/null +++ b/quantum/process_keycode/process_swap_hands.c @@ -0,0 +1,155 @@ +/* Copyright 2021 QMK + * + * 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 "process_swap_hands.h" +#include "quantum_keycodes.h" +#include "action_tapping.h" +#include "matrix.h" + +extern const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS]; + +static matrix_row_t swap_state[MATRIX_ROWS]; + +static bool swap_hands_enabled = false; +static bool oneshot_enabled = false; +static uint16_t oneshot_expiry = 0; + +#if defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0) +static inline bool has_oneshot_swaphands_timed_out(void) { + return (oneshot_expiry && timer_expired(timer_read(), oneshot_expiry)); +} +#endif + +static inline void swap_hands_task(void) { +#if defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0) + if (has_oneshot_swaphands_timed_out()) { + clear_oneshot_swaphands(); + } +#endif +} + +void clear_oneshot_swaphands(void) { + oneshot_expiry = 0; + swap_hands_enabled = false; + oneshot_enabled = false; +} + +void preprocess_swap_hands(keyrecord_t *record) { + // TODO: implement a "real" swap_hands_task called from matrix_scan_quantum? + swap_hands_task(); + + keypos_t pos = record->event.key; + matrix_row_t col_bit = MATRIX_ROW_SHIFTER << pos.col; + bool do_swap = record->event.pressed ? swap_hands_enabled : swap_state[pos.row] & (col_bit); + + if (do_swap) { + record->event.key.row = pgm_read_byte(&hand_swap_config[pos.row][pos.col].row); + record->event.key.col = pgm_read_byte(&hand_swap_config[pos.row][pos.col].col); + swap_state[pos.row] |= col_bit; + } else { + swap_state[pos.row] &= ~(col_bit); + } +} + +bool process_swap_hands(uint16_t keycode, keyrecord_t *record) { + static uint16_t last_keycode = 0; + + bool pressed = record->event.pressed; + + uint16_t previous_keycode = last_keycode; + last_keycode = keycode; + + bool interupted = (previous_keycode != keycode); + + switch (keycode) { + case SH_TG: + if (pressed) { + swap_hands_enabled = !swap_hands_enabled; + } + break; + case SH_MON: + swap_hands_enabled = pressed; + break; + case SH_MOFF: + swap_hands_enabled = !pressed; + break; + case SH_ON: + if (!pressed) { + swap_hands_enabled = true; + } + break; + case SH_OFF: + if (!pressed) { + swap_hands_enabled = false; + } + break; + case SH_TT: { + static uint8_t start_state = 0xFF; + if (pressed && (start_state == 0xFF)) { + start_state = swap_hands_enabled; + } + + static int tap_count = 0; + if (interupted) { + tap_count = 0; + start_state = 0xFF; + } else { + tap_count++; + if (tap_count >= TAPPING_TOGGLE) { + swap_hands_enabled = !start_state; + start_state = 0xFF; + tap_count = 0; + } + } + + swap_hands_enabled = !swap_hands_enabled; + break; + } + case SH_OS: + if (pressed) { + swap_hands_enabled = true; + } else if (!interupted) { + oneshot_enabled = true; +#ifdef ONESHOT_TIMEOUT + oneshot_expiry = timer_read() + ONESHOT_TIMEOUT; +#endif + } else { + swap_hands_enabled = false; + } + break; + case SH_T(0x00)... SH_T(0xEF): + swap_hands_enabled = pressed; + + static uint16_t tap_expiry = 0; + if (pressed) { + tap_expiry = timer_read() + TAPPING_TERM; + } else if (!timer_expired(timer_read(), tap_expiry)) { + tap_code(keycode & 0xFF); + } + break; + default: + if (oneshot_enabled && !pressed) { + clear_oneshot_swaphands(); + } + return true; + } + return false; +} + +bool is_swap_hands_enabled(void) { return swap_hands_enabled; } +void swap_hands_enable(void) { swap_hands_enabled = true; } +void swap_hands_disable(void) { swap_hands_enabled = false; } +void swap_hands_toggle(void) { swap_hands_enabled = !swap_hands_enabled; } diff --git a/quantum/process_keycode/process_swap_hands.h b/quantum/process_keycode/process_swap_hands.h new file mode 100644 index 00000000000..4edf93bc388 --- /dev/null +++ b/quantum/process_keycode/process_swap_hands.h @@ -0,0 +1,28 @@ +/* Copyright 2021 QMK + * + * 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 . + */ + +#pragma once + +#include +#include "action.h" + +void preprocess_swap_hands(keyrecord_t *record); +bool process_swap_hands(uint16_t keycode, keyrecord_t *record); + +bool is_swap_hands_enabled(void); +void swap_hands_enable(void); +void swap_hands_disable(void); +void swap_hands_toggle(void); diff --git a/quantum/quantum.c b/quantum/quantum.c index 0eca329f08b..06b500c3a09 100644 --- a/quantum/quantum.c +++ b/quantum/quantum.c @@ -194,6 +194,9 @@ void post_process_record_quantum(keyrecord_t *record) { then processes internal quantum keycodes, and then processes ACTIONs. */ bool process_record_quantum(keyrecord_t *record) { +#ifdef SWAP_HANDS_ENABLE + preprocess_swap_hands(record); +#endif uint16_t keycode = get_record_keycode(record, true); // This is how you use actions here @@ -235,6 +238,9 @@ bool process_record_quantum(keyrecord_t *record) { #ifdef HAPTIC_ENABLE process_haptic(keycode, record) && #endif +#ifdef SWAP_HANDS_ENABLE + process_swap_hands(keycode, record) && +#endif #if defined(VIA_ENABLE) process_record_via(keycode, record) && #endif diff --git a/quantum/quantum.h b/quantum/quantum.h index 9250f5acce7..f08372f57bd 100644 --- a/quantum/quantum.h +++ b/quantum/quantum.h @@ -155,6 +155,10 @@ extern layer_state_t layer_state; # include "process_grave_esc.h" #endif +#ifdef SWAP_HANDS_ENABLE +# include "process_swap_hands.h" +#endif + #if defined(RGBLIGHT_ENABLE) || defined(RGB_MATRIX_ENABLE) # include "process_rgb.h" #endif diff --git a/quantum/quantum_keycodes.h b/quantum/quantum_keycodes.h index cde97074d39..33c9988a6b1 100644 --- a/quantum/quantum_keycodes.h +++ b/quantum/quantum_keycodes.h @@ -850,6 +850,15 @@ enum quantum_keycodes { #define UC_M_WC UNICODE_MODE_WINC // Swap Hands +enum swap_hands_param_tap_op { + OP_SH_TOGGLE = 0xF0, + OP_SH_TAP_TOGGLE, + OP_SH_ON_OFF, + OP_SH_OFF_ON, + OP_SH_OFF, + OP_SH_ON, + OP_SH_ONESHOT, +}; #define SH_T(kc) (QK_SWAP_HANDS | (kc)) #define SH_TG (QK_SWAP_HANDS | OP_SH_TOGGLE) #define SH_TT (QK_SWAP_HANDS | OP_SH_TAP_TOGGLE)