diff --git a/keyboards/ferris/sweep/keymaps/qwerty/config.h b/keyboards/ferris/sweep/keymaps/qwerty/config.h index 1a4d15ff..fd4f1d85 100644 --- a/keyboards/ferris/sweep/keymaps/qwerty/config.h +++ b/keyboards/ferris/sweep/keymaps/qwerty/config.h @@ -34,9 +34,16 @@ along with this program. If not, see . // Pick good defaults for enabling homerow modifiers #define TAPPING_TERM 200 -#define PERMISSIVE_HOLD +// #define PERMISSIVE_HOLD #define QUICK_TAP_TERM 0 +// Chordal Hold: homerow mods only activate for opposite-hand chords +#define CHORDAL_HOLD +#define HOLD_ON_OTHER_KEY_PRESS + +// https://docs.qmk.fm/#/feature_caps_word +#define DOUBLE_TAP_SHIFT_TURNS_ON_CAPS_WORD + // Underglow configuration #ifdef RGBLIGHT_ENABLE # define RGBLIGHT_EFFECT_BREATHING diff --git a/keyboards/ferris/sweep/keymaps/qwerty/keymap.c b/keyboards/ferris/sweep/keymaps/qwerty/keymap.c new file mode 100644 index 00000000..a4d8495b --- /dev/null +++ b/keyboards/ferris/sweep/keymaps/qwerty/keymap.c @@ -0,0 +1,488 @@ +#include QMK_KEYBOARD_H + +// Aliases for characters that don't have a keycode +#define KC_DOUBLE_QUOTE_OPEN LALT(KC_LEFT_BRACKET) +#define KC_DOUBLE_QUOTE_CLOSE LALT(LSFT(KC_LEFT_BRACKET)) +#define KC_SINGLE_QUOTE_OPEN LALT(KC_RIGHT_BRACKET) +#define KC_SINGLE_QUOTE_CLOSE LALT(LSFT(KC_RIGHT_BRACKET)) +#define KC_UK_HASH LALT(KC_3) +#define KC_UK_POUND LSFT(KC_3) +#define KC_EURO LALT(KC_2) + +#define KC_NAV_HISTORY_BACK LGUI(KC_LEFT_BRACKET) +#define KC_NAV_HISTORY_FORWARD LGUI(KC_RIGHT_BRACKET) +#define KC_NAV_PREV_TAB LCTL(LSFT(KC_TAB)) +#define KC_NAV_NEXT_TAB RCTL(KC_TAB) + +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + [0] = LAYOUT_split_3x5_2( + KC_Q, KC_W, KC_E, KC_R, KC_T, + KC_Y, KC_U, KC_I, KC_O, KC_P, + + KC_A, KC_S, MT(MOD_LGUI,KC_D), MT(MOD_LCTL,KC_F), KC_G, + KC_H, MT(MOD_RCTL,KC_J), MT(MOD_RGUI,KC_K), KC_L, KC_SCLN, + + KC_Z, KC_X, KC_C, KC_V, KC_B, + KC_N, KC_M, QK_REPEAT_KEY, KC_DOT, KC_SLSH, + + TO(1), OSM(MOD_LSFT), + OSM(MOD_LALT), KC_SPACE + ), + // QWERTY numbers and navigation + [1] = LAYOUT_split_3x5_2( + KC_ESC, KC_KP_7, KC_KP_8, KC_KP_9, KC_NO, + KC_NAV_HISTORY_BACK, KC_NAV_PREV_TAB, KC_NAV_NEXT_TAB, KC_NAV_HISTORY_FORWARD, KC_BSPC, + + KC_TAB, KC_KP_4, MT(MOD_LGUI,KC_KP_5), MT(MOD_LCTL,KC_KP_6), KC_NO, + KC_LEFT, MT(MOD_RCTL,KC_DOWN), MT(MOD_RGUI,KC_UP), KC_RIGHT, KC_ENTER, + + KC_KP_0, KC_KP_1, KC_KP_2, KC_KP_3, KC_NO, + KC_NO, KC_NO, QK_REPEAT_KEY, KC_DOT, KC_NO, + + TO(2), KC_TRNS, + KC_TRNS, TO(0) + ), + // QWERTY alt-symbols layer (macOS Alt+key symbols - rare) + [2] = LAYOUT_split_3x5_2( + LALT(KC_Q), LALT(KC_W), LALT(KC_E), LALT(KC_R), LALT(KC_T), + LALT(KC_Y), LALT(KC_U), LALT(KC_I), LALT(KC_O), LALT(KC_P), + + LALT(KC_A), LALT(KC_S), LALT(KC_D), LALT(KC_F), LALT(KC_G), + LALT(KC_H), LALT(KC_J), LALT(KC_K), LALT(KC_L), LALT(KC_SCLN), + + LALT(KC_Z), LALT(KC_X), LALT(KC_C), LALT(KC_V), LALT(KC_B), + LALT(KC_N), LALT(KC_M), LALT(KC_COMMA), LALT(KC_DOT), LALT(KC_SLSH), + + TO(0), KC_TRNS, + KC_TRNS, TO(0) + ) +}; + +// https://docs.qmk.fm/#/feature_key_overrides?id=creating-key-overrides +// All layers are QWERTY layers (0, 1, 2) +#define QWERTY_LAYERS ~0 + +// QWERTY: alt ; = enter, shift+alt ; = noop +const key_override_t semicolon_key_alt_override = ko_make_with_layers_and_negmods(MOD_MASK_ALT, KC_SCLN, KC_ENTER, QWERTY_LAYERS, MOD_MASK_SHIFT); +const key_override_t semicolon_key_alt_shifted_override = ko_make_with_layers(MOD_MASK_SA, KC_SCLN, KC_NO, QWERTY_LAYERS); + +// QWERTY: alt p = backspace, shift+alt p = noop +const key_override_t p_key_alt_override = ko_make_with_layers_and_negmods(MOD_MASK_ALT, KC_P, KC_BSPC, QWERTY_LAYERS, MOD_MASK_SHIFT); +const key_override_t p_key_alt_shifted_override = ko_make_with_layers(MOD_MASK_SA, KC_P, KC_NO, QWERTY_LAYERS); + +// QWERTY: alt / = delete word, shift+alt / = noop +const key_override_t slsh_key_alt_override = ko_make_with_layers_and_negmods(MOD_MASK_ALT, KC_SLSH, LALT(KC_BSPC), QWERTY_LAYERS, MOD_MASK_SHIFT); +const key_override_t slsh_key_alt_shifted_override = ko_make_with_layers(MOD_MASK_SA, KC_SLSH, KC_NO, QWERTY_LAYERS); + +// Alt+key on QWERTY layer 0 outputs symbols (from old layer 1) +// Top row +const key_override_t q_key_alt_override = ko_make_with_layers_and_negmods(MOD_MASK_ALT, KC_Q, KC_ESC, QWERTY_LAYERS, MOD_MASK_SHIFT); +const key_override_t w_key_alt_override = ko_make_with_layers_and_negmods(MOD_MASK_ALT, KC_W, KC_AT, QWERTY_LAYERS, MOD_MASK_CSG); +const key_override_t e_key_alt_override = ko_make_with_layers_and_negmods(MOD_MASK_ALT, KC_E, KC_UK_HASH, QWERTY_LAYERS, MOD_MASK_CSG); +const key_override_t r_key_alt_override = ko_make_with_layers_and_negmods(MOD_MASK_ALT, KC_R, KC_DOLLAR, QWERTY_LAYERS, MOD_MASK_CSG); +const key_override_t t_key_alt_override = ko_make_with_layers_and_negmods(MOD_MASK_ALT, KC_T, KC_PERCENT, QWERTY_LAYERS, MOD_MASK_CSG); +const key_override_t y_key_alt_override = ko_make_with_layers_and_negmods(MOD_MASK_ALT, KC_Y, KC_CIRCUMFLEX, QWERTY_LAYERS, MOD_MASK_CSG); +const key_override_t u_key_alt_override = ko_make_with_layers_and_negmods(MOD_MASK_ALT, KC_U, KC_AMPERSAND, QWERTY_LAYERS, MOD_MASK_CSG); +const key_override_t i_key_alt_override = ko_make_with_layers_and_negmods(MOD_MASK_ALT, KC_I, KC_ASTERISK, QWERTY_LAYERS, MOD_MASK_CSG); +const key_override_t o_key_alt_override = ko_make_with_layers_and_negmods(MOD_MASK_ALT, KC_O, KC_MINUS, QWERTY_LAYERS, MOD_MASK_SHIFT); + +// Middle row +const key_override_t a_key_alt_override = ko_make_with_layers_and_negmods(MOD_MASK_ALT, KC_A, KC_TAB, QWERTY_LAYERS, MOD_MASK_SHIFT); +const key_override_t s_key_alt_override = ko_make_with_layers_and_negmods(MOD_MASK_ALT, KC_S, KC_GRAVE, QWERTY_LAYERS, MOD_MASK_SHIFT); +// D, F, J, K handled in process_record_user() due to mod-tap interference +const key_override_t g_key_alt_override = ko_make_with_layers_and_negmods(MOD_MASK_ALT, KC_G, KC_NO, QWERTY_LAYERS, MOD_MASK_SHIFT); +const key_override_t h_key_alt_override = ko_make_with_layers_and_negmods(MOD_MASK_ALT, KC_H, KC_BACKSLASH, QWERTY_LAYERS, MOD_MASK_SHIFT); +const key_override_t l_key_alt_override = ko_make_with_layers_and_negmods(MOD_MASK_ALT, KC_L, KC_RBRC, QWERTY_LAYERS, MOD_MASK_SHIFT); + +// Bottom row +const key_override_t z_key_alt_override = ko_make_with_layers_and_negmods(MOD_MASK_ALT, KC_Z, KC_TILDE, QWERTY_LAYERS, MOD_MASK_CSG); +const key_override_t x_key_alt_override = ko_make_with_layers_and_negmods(MOD_MASK_ALT, KC_X, KC_MINUS, QWERTY_LAYERS, MOD_MASK_SHIFT); +const key_override_t c_key_alt_override = ko_make_with_layers_and_negmods(MOD_MASK_ALT, KC_C, KC_PLUS, QWERTY_LAYERS, MOD_MASK_CSG); +const key_override_t v_key_alt_override = ko_make_with_layers_and_negmods(MOD_MASK_ALT, KC_V, KC_EQUAL, QWERTY_LAYERS, MOD_MASK_SHIFT); +const key_override_t b_key_alt_override = ko_make_with_layers_and_negmods(MOD_MASK_ALT, KC_B, KC_UNDERSCORE, QWERTY_LAYERS, MOD_MASK_CSG); +const key_override_t m_key_alt_override = ko_make_with_layers_and_negmods(MOD_MASK_ALT, KC_M, KC_LPRN, QWERTY_LAYERS, MOD_MASK_CSG); +const key_override_t dot_key_alt_override = ko_make_with_layers_and_negmods(MOD_MASK_ALT, KC_DOT, KC_RPRN, QWERTY_LAYERS, MOD_MASK_CSG); + +// Shift+Alt+key on QWERTY layer 0 (shifted symbols from old layer 1) +// Top row +const key_override_t q_key_shift_alt_override = ko_make_with_layers(MOD_MASK_SA, KC_Q, KC_NO, QWERTY_LAYERS); +const key_override_t w_key_shift_alt_override = ko_make_with_layers(MOD_MASK_SA, KC_W, KC_EURO, QWERTY_LAYERS); +const key_override_t e_key_shift_alt_override = ko_make_with_layers(MOD_MASK_SA, KC_E, KC_NO, QWERTY_LAYERS); +const key_override_t r_key_shift_alt_override = ko_make_with_layers(MOD_MASK_SA, KC_R, KC_UK_POUND, QWERTY_LAYERS); +const key_override_t t_key_shift_alt_override = ko_make_with_layers(MOD_MASK_SA, KC_T, KC_NO, QWERTY_LAYERS); +const key_override_t y_key_shift_alt_override = ko_make_with_layers(MOD_MASK_SA, KC_Y, KC_NO, QWERTY_LAYERS); +const key_override_t u_key_shift_alt_override = ko_make_with_layers(MOD_MASK_SA, KC_U, KC_NO, QWERTY_LAYERS); +const key_override_t i_key_shift_alt_override = ko_make_with_layers(MOD_MASK_SA, KC_I, KC_NO, QWERTY_LAYERS); +const key_override_t o_key_shift_alt_override = ko_make_with_layers(MOD_MASK_SA, KC_O, KC_NO, QWERTY_LAYERS); +const key_override_t p_key_shift_alt_override = ko_make_with_layers(MOD_MASK_SA, KC_P, KC_NO, QWERTY_LAYERS); + +// Middle row +const key_override_t a_key_shift_alt_override = ko_make_with_layers(MOD_MASK_SA, KC_A, KC_NO, QWERTY_LAYERS); +const key_override_t s_key_shift_alt_override = ko_make_with_layers(MOD_MASK_SA, KC_S, KC_NO, QWERTY_LAYERS); +// D, F, J, K handled in process_record_user() due to mod-tap interference +const key_override_t g_key_shift_alt_override = ko_make_with_layers(MOD_MASK_SA, KC_G, KC_NO, QWERTY_LAYERS); +const key_override_t h_key_shift_alt_override = ko_make_with_layers(MOD_MASK_SA, KC_H, KC_NO, QWERTY_LAYERS); +const key_override_t l_key_shift_alt_override = ko_make_with_layers(MOD_MASK_SA, KC_L, KC_RCBR, QWERTY_LAYERS); +const key_override_t scln_key_shift_alt_override = ko_make_with_layers(MOD_MASK_SA, KC_SCLN, KC_NO, QWERTY_LAYERS); + +// Bottom row +const key_override_t z_key_shift_alt_override = ko_make_with_layers(MOD_MASK_SA, KC_Z, KC_NO, QWERTY_LAYERS); +const key_override_t x_key_shift_alt_override = ko_make_with_layers(MOD_MASK_SA, KC_X, KC_DOUBLE_QUOTE_OPEN, QWERTY_LAYERS); +const key_override_t c_key_shift_alt_override = ko_make_with_layers(MOD_MASK_SA, KC_C, KC_SINGLE_QUOTE_OPEN, QWERTY_LAYERS); +const key_override_t v_key_shift_alt_override = ko_make_with_layers(MOD_MASK_SA, KC_V, KC_SINGLE_QUOTE_CLOSE, QWERTY_LAYERS); +const key_override_t b_key_shift_alt_override = ko_make_with_layers(MOD_MASK_SA, KC_B, KC_DOUBLE_QUOTE_CLOSE, QWERTY_LAYERS); +const key_override_t n_key_shift_alt_override = ko_make_with_layers(MOD_MASK_SA, KC_N, KC_NO, QWERTY_LAYERS); +const key_override_t m_key_shift_alt_override = ko_make_with_layers(MOD_MASK_SA, KC_M, KC_LABK, QWERTY_LAYERS); +const key_override_t comma_key_shift_alt_override = ko_make_with_layers(MOD_MASK_SA, KC_COMMA, KC_NO, QWERTY_LAYERS); +const key_override_t dot_key_shift_alt_override = ko_make_with_layers(MOD_MASK_SA, KC_DOT, KC_RABK, QWERTY_LAYERS); +const key_override_t slsh_key_shift_alt_override = ko_make_with_layers(MOD_MASK_SA, KC_SLSH, KC_NO, QWERTY_LAYERS); + +const key_override_t delete_key_override = ko_make_basic(MOD_MASK_SHIFT, KC_BSPC, KC_DEL); +const key_override_t period_key_override = ko_make_basic(MOD_MASK_SHIFT, KC_DOT, KC_COMM); +const key_override_t repeat_key_override = ko_make_basic(MOD_MASK_SHIFT, QK_REPEAT_KEY, QK_ALT_REPEAT_KEY); +const key_override_t lparen_key_override = ko_make_basic(MOD_MASK_SHIFT, KC_LPRN, KC_LABK); +const key_override_t rparen_key_override = ko_make_basic(MOD_MASK_SHIFT, KC_RPRN, KC_RABK); +const key_override_t minus_key_override = ko_make_basic(MOD_MASK_SHIFT, KC_MINUS, KC_DOUBLE_QUOTE_OPEN); +const key_override_t plus_key_override = ko_make_basic(MOD_MASK_SHIFT, KC_PLUS, KC_SINGLE_QUOTE_OPEN); +const key_override_t equal_key_override = ko_make_basic(MOD_MASK_SHIFT, KC_EQUAL, KC_SINGLE_QUOTE_CLOSE); +const key_override_t underscore_key_override = ko_make_basic(MOD_MASK_SHIFT, KC_UNDERSCORE, KC_DOUBLE_QUOTE_CLOSE); +const key_override_t dollar_key_override = ko_make_basic(MOD_MASK_SHIFT, KC_DOLLAR, KC_UK_POUND); +const key_override_t at_key_override = ko_make_basic(MOD_MASK_SHIFT, KC_AT, KC_EURO); +// Alt+keypad number keys act as FN keys +const key_override_t kp_one_key_override = ko_make_basic(MOD_MASK_ALT, KC_KP_1, KC_F1); +const key_override_t kp_two_key_override = ko_make_basic(MOD_MASK_ALT, KC_KP_2, KC_F2); +const key_override_t kp_three_key_override = ko_make_basic(MOD_MASK_ALT, KC_KP_3, KC_F3); +const key_override_t kp_four_key_override = ko_make_basic(MOD_MASK_ALT, KC_KP_4, KC_F4); +const key_override_t kp_five_key_override = ko_make_basic(MOD_MASK_ALT, KC_KP_5, KC_F5); +const key_override_t kp_six_key_override = ko_make_basic(MOD_MASK_ALT, KC_KP_6, KC_F6); +const key_override_t kp_seven_key_override = ko_make_basic(MOD_MASK_ALT, KC_KP_7, KC_F7); +const key_override_t kp_eight_key_override = ko_make_basic(MOD_MASK_ALT, KC_KP_8, KC_F8); +const key_override_t kp_nine_key_override = ko_make_basic(MOD_MASK_ALT, KC_KP_9, KC_F9); +const key_override_t kp_zero_key_override = ko_make_basic(MOD_MASK_ALT, KC_KP_0, KC_F10); + +// This globally defines all key overrides to be used +const key_override_t *key_overrides[] = { + &semicolon_key_alt_override, + &semicolon_key_alt_shifted_override, + &p_key_alt_override, + &p_key_alt_shifted_override, + &slsh_key_alt_override, + &slsh_key_alt_shifted_override, + // QWERTY Alt+key overrides + &q_key_alt_override, + &w_key_alt_override, + &e_key_alt_override, + &r_key_alt_override, + &t_key_alt_override, + &y_key_alt_override, + &u_key_alt_override, + &i_key_alt_override, + &o_key_alt_override, + &a_key_alt_override, + &s_key_alt_override, + // D, F, J, K handled in process_record_user() + &g_key_alt_override, + &h_key_alt_override, + &l_key_alt_override, + &z_key_alt_override, + &x_key_alt_override, + &c_key_alt_override, + &v_key_alt_override, + &b_key_alt_override, + &m_key_alt_override, + &dot_key_alt_override, + // QWERTY Shift+Alt vacant overrides + &q_key_shift_alt_override, + &w_key_shift_alt_override, + &e_key_shift_alt_override, + &r_key_shift_alt_override, + &t_key_shift_alt_override, + &y_key_shift_alt_override, + &u_key_shift_alt_override, + &i_key_shift_alt_override, + &o_key_shift_alt_override, + &p_key_shift_alt_override, + &a_key_shift_alt_override, + &s_key_shift_alt_override, + // D, F, J, K handled in process_record_user() + &g_key_shift_alt_override, + &h_key_shift_alt_override, + &l_key_shift_alt_override, + &scln_key_shift_alt_override, + &z_key_shift_alt_override, + &x_key_shift_alt_override, + &c_key_shift_alt_override, + &v_key_shift_alt_override, + &b_key_shift_alt_override, + &n_key_shift_alt_override, + &m_key_shift_alt_override, + &comma_key_shift_alt_override, + &dot_key_shift_alt_override, + &slsh_key_shift_alt_override, + &delete_key_override, + &period_key_override, + &repeat_key_override, + &lparen_key_override, + &rparen_key_override, + &minus_key_override, + &plus_key_override, + &equal_key_override, + &underscore_key_override, + &dollar_key_override, + &at_key_override, + &kp_one_key_override, + &kp_two_key_override, + &kp_three_key_override, + &kp_four_key_override, + &kp_five_key_override, + &kp_six_key_override, + &kp_seven_key_override, + &kp_eight_key_override, + &kp_nine_key_override, + &kp_zero_key_override, + NULL // Null terminate the array of overrides! +}; + +const uint16_t PROGMEM qwerty_combo[] = {KC_ESC, KC_TAB, KC_BSPC, COMBO_END}; +combo_t key_combos[] = { + COMBO(qwerty_combo, TO(0)) +}; + +#if defined(ENCODER_ENABLE) && defined(ENCODER_MAP_ENABLE) +const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][NUM_DIRECTIONS] = { + +}; +#endif // defined(ENCODER_ENABLE) && defined(ENCODER_MAP_ENABLE) + +// If this value is greater than 100, the keyboard +// won't work on iOS devices. (Default value is 500) +#define USB_MAX_POWER_CONSUMPTION 100 + +// Custom handling for Alt+homerow mod-tap keys +// Key overrides don't work with mod-tap keys, so we handle them manually +bool process_record_user(uint16_t keycode, keyrecord_t *record) { + // Check which modifiers are active (including one-shot modifiers) + uint8_t mods = get_mods(); + uint8_t oneshot_mods = get_oneshot_mods(); + uint8_t all_mods = mods | oneshot_mods; + + bool alt_held = (all_mods & MOD_MASK_ALT); + bool shift_held = (all_mods & MOD_MASK_SHIFT); + bool only_alt = alt_held && !shift_held && !(all_mods & MOD_MASK_CG); // Alt only, no Shift/Ctrl/GUI + + if (record->event.pressed) { + // Handle Alt+homerow mod-tap keys + if (only_alt) { + uint8_t temp_mods = get_mods(); + + switch(keycode) { + case MT(MOD_LGUI, KC_D): // Alt+D → ' + del_mods(MOD_MASK_ALT); // Clear Alt temporarily + del_oneshot_mods(MOD_MASK_ALT); // Clear one-shot Alt (consume it) + tap_code16(KC_QUOTE); // Send ' + set_last_keycode(KC_QUOTE); + set_last_mods(0); + set_mods(temp_mods); // Restore regular mods only + return false; + case MT(MOD_LCTL, KC_F): // Alt+F → " + del_mods(MOD_MASK_ALT); + del_oneshot_mods(MOD_MASK_ALT); + tap_code16(KC_DQUO); // Send " + set_last_keycode(KC_QUOTE); + set_last_mods(MOD_BIT(KC_LSFT)); + set_mods(temp_mods); + return false; + case MT(MOD_RCTL, KC_J): // Alt+J → [ + del_mods(MOD_MASK_ALT); + del_oneshot_mods(MOD_MASK_ALT); + tap_code16(KC_LBRC); // Send [ + set_last_keycode(KC_LBRC); + set_last_mods(0); + set_mods(temp_mods); + return false; + case MT(MOD_RGUI, KC_K): // Alt+K → | + del_mods(MOD_MASK_ALT); + del_oneshot_mods(MOD_MASK_ALT); + tap_code16(KC_PIPE); // Send | + set_last_keycode(KC_BACKSLASH); + set_last_mods(MOD_BIT(KC_LSFT)); + set_mods(temp_mods); + return false; + } + + // Handle Alt+key repeat behavior for non-homerow keys + // Key overrides happen after repeat key tracking, so we manually + // set what repeat should remember (the overridden output, not Alt+key) + switch(keycode) { + case KC_Q: // Alt+Q → Esc + set_last_keycode(KC_ESC); + set_last_mods(0); + break; + case KC_W: // Alt+W → @ + set_last_keycode(KC_2); + set_last_mods(MOD_BIT(KC_LSFT)); + break; + case KC_E: // Alt+E → # (UK keyboard: Alt+3) + set_last_keycode(KC_3); + set_last_mods(MOD_BIT(KC_LALT)); + break; + case KC_R: // Alt+R → $ + set_last_keycode(KC_4); + set_last_mods(MOD_BIT(KC_LSFT)); + break; + case KC_T: // Alt+T → % + set_last_keycode(KC_5); + set_last_mods(MOD_BIT(KC_LSFT)); + break; + case KC_Y: // Alt+Y → ^ + set_last_keycode(KC_6); + set_last_mods(MOD_BIT(KC_LSFT)); + break; + case KC_U: // Alt+U → & + set_last_keycode(KC_7); + set_last_mods(MOD_BIT(KC_LSFT)); + break; + case KC_I: // Alt+I → * + set_last_keycode(KC_8); + set_last_mods(MOD_BIT(KC_LSFT)); + break; + case KC_O: // Alt+O → - + case KC_X: // Alt+X → - + set_last_keycode(KC_MINUS); + set_last_mods(0); + break; + case KC_P: // Alt+P → Backspace + set_last_keycode(KC_BSPC); + set_last_mods(0); + break; + case KC_A: // Alt+A → Tab + set_last_keycode(KC_TAB); + set_last_mods(0); + break; + case KC_S: // Alt+S → ` + set_last_keycode(KC_GRAVE); + set_last_mods(0); + break; + case KC_H: // Alt+H → backslash + set_last_keycode(KC_BACKSLASH); + set_last_mods(0); + break; + case KC_L: // Alt+L → ] + set_last_keycode(KC_RBRC); + set_last_mods(0); + break; + case KC_Z: // Alt+Z → ~ + set_last_keycode(KC_GRAVE); + set_last_mods(MOD_BIT(KC_LSFT)); + break; + case KC_C: // Alt+C → + + set_last_keycode(KC_EQUAL); + set_last_mods(MOD_BIT(KC_LSFT)); + break; + case KC_V: // Alt+V → = + set_last_keycode(KC_EQUAL); + set_last_mods(0); + break; + case KC_B: // Alt+B → _ + set_last_keycode(KC_MINUS); + set_last_mods(MOD_BIT(KC_LSFT)); + break; + case KC_M: // Alt+M → ( + set_last_keycode(KC_9); + set_last_mods(MOD_BIT(KC_LSFT)); + break; + case KC_DOT: // Alt+. → ) + set_last_keycode(KC_0); + set_last_mods(MOD_BIT(KC_LSFT)); + break; + case KC_SCLN: // Alt+; → Enter + set_last_keycode(KC_ENTER); + set_last_mods(0); + break; + case KC_SLSH: // Alt+/ → delete word (Alt+Backspace) + set_last_keycode(KC_BSPC); + set_last_mods(MOD_BIT(KC_LALT)); + break; + } + } + + // Handle Shift+Alt+homerow mod-tap keys + if (alt_held && shift_held) { + uint8_t temp_mods = get_mods(); + + switch(keycode) { + case MT(MOD_RCTL, KC_J): // Shift+Alt+J → { + del_mods(MOD_MASK_ALT | MOD_MASK_SHIFT); // Clear Alt+Shift temporarily + del_oneshot_mods(MOD_MASK_ALT | MOD_MASK_SHIFT); // Consume one-shot mods + tap_code16(KC_LCBR); // Send { + set_last_keycode(KC_LBRC); + set_last_mods(MOD_BIT(KC_LSFT)); + set_mods(temp_mods); // Restore regular mods only + return false; + case MT(MOD_RGUI, KC_K): // Shift+Alt+K → ! + del_mods(MOD_MASK_ALT | MOD_MASK_SHIFT); + del_oneshot_mods(MOD_MASK_ALT | MOD_MASK_SHIFT); + tap_code16(KC_EXCLAIM); // Send ! + set_last_keycode(KC_1); + set_last_mods(MOD_BIT(KC_LSFT)); + set_mods(temp_mods); + return false; + case MT(MOD_LGUI, KC_D): + case MT(MOD_LCTL, KC_F): + return false; // Block D, F with Shift+Alt (no symbol assigned) + } + + // Handle Shift+Alt+key repeat behavior for non-homerow keys + switch(keycode) { + case KC_W: // Shift+Alt+W → € (Alt+2 on macOS) + set_last_keycode(KC_2); + set_last_mods(MOD_BIT(KC_LALT)); + break; + case KC_R: // Shift+Alt+R → £ + set_last_keycode(KC_3); + set_last_mods(MOD_BIT(KC_LSFT)); + break; + case KC_L: // Shift+Alt+L → } + set_last_keycode(KC_RBRC); + set_last_mods(MOD_BIT(KC_LSFT)); + break; + case KC_X: // Shift+Alt+X → " (left double quote: Alt+[) + set_last_keycode(KC_LEFT_BRACKET); + set_last_mods(MOD_BIT(KC_LALT)); + break; + case KC_C: // Shift+Alt+C → ' (left single quote: Alt+]) + set_last_keycode(KC_RIGHT_BRACKET); + set_last_mods(MOD_BIT(KC_LALT)); + break; + case KC_V: // Shift+Alt+V → ' (right single quote: Alt+Shift+]) + set_last_keycode(KC_RIGHT_BRACKET); + set_last_mods(MOD_BIT(KC_LALT) | MOD_BIT(KC_LSFT)); + break; + case KC_B: // Shift+Alt+B → " (right double quote: Alt+Shift+[) + set_last_keycode(KC_LEFT_BRACKET); + set_last_mods(MOD_BIT(KC_LALT) | MOD_BIT(KC_LSFT)); + break; + case KC_M: // Shift+Alt+M → < + set_last_keycode(KC_COMMA); + set_last_mods(MOD_BIT(KC_LSFT)); + break; + case KC_DOT: // Shift+Alt+. → > + set_last_keycode(KC_DOT); + set_last_mods(MOD_BIT(KC_LSFT)); + break; + } + } + } + + return true; // Continue normal processing +} + +// Define handedness for Chordal Hold using layout array +// For Ferris Sweep (split keyboard): left half = 'L', right half = 'R' +const char chordal_hold_layout[MATRIX_ROWS][MATRIX_COLS] PROGMEM = + LAYOUT_split_3x5_2( + 'L', 'L', 'L', 'L', 'L', 'R', 'R', 'R', 'R', 'R', + 'L', 'L', 'L', 'L', 'L', 'R', 'R', 'R', 'R', 'R', + 'L', 'L', 'L', 'L', 'L', 'R', 'R', 'R', 'R', 'R', + 'L', 'L', 'R', 'R' + ); diff --git a/keyboards/ferris/sweep/keymaps/qwerty/keymap.json b/keyboards/ferris/sweep/keymaps/qwerty/keymap.json deleted file mode 100644 index 0d081e4d..00000000 --- a/keyboards/ferris/sweep/keymaps/qwerty/keymap.json +++ /dev/null @@ -1,106 +0,0 @@ -{ "version": 1, - "notes": "My awesome keymap", - "documentation": "\"This file is a QMK Configurator export. You can import this at . It can also be used directly with QMK's source code.\n\nTo setup your QMK environment check out the tutorial: \n\nYou can convert this file to a keymap.c using this command: `qmk json2c {keymap}`\n\nYou can compile this keymap using this command: `qmk compile {keymap}`\"\n", - "keyboard": "ferris/0_1", - "keymap": "default", - "layout": "LAYOUT_split_3x5_2", - "layers": [ - ["KC_Q" , "KC_W" , "KC_E" , "KC_R" , "KC_T", - "KC_Y" , "KC_U" , "KC_I" , "KC_O" , "KC_P", - - "LSFT_T(KC_A)", "LT(5,KC_S)" , "LT(1,KC_D)" , "LT(3,KC_F)" , "KC_G", - "KC_H" , "LT(4,KC_J)" , "LT(2,KC_K)" , "LT(6,KC_L)" , "LSFT_T(KC_SCLN)", - - "KC_Z" , "LCTL_T(KC_X)", "LALT_T(KC_C)" , "KC_V" , "KC_B", - "KC_N" , "KC_M" , "LALT_T(KC_COMM)", "LCTL_T(KC_DOT)", "KC_SLSH", - - "KC_P0" , "KC_BSPC", - "LT(7,KC_SPC)", "KC_P1" - ], - ["KC_TRNS" , "KC_TRNS" , "KC_TRNS" , "KC_TRNS" , "KC_TRNS", - "KC_TRNS" , "MS_BTN1" , "MS_WHLU" , "MS_BTN2" , "KC_TRNS", - - "KC_TRNS" , "MS_BTN2" , "KC_NO" , "MS_BTN1" , "KC_TRNS", - "KC_TRNS" , "MS_LEFT" , "MS_DOWN" , "MS_UP" , "MS_RGHT", - - "KC_TRNS" , "KC_TRNS" , "KC_TRNS" , "KC_TRNS" , "KC_TRNS", - "KC_TRNS" , "MS_WHLL" , "MS_WHLD" , "MS_WHLR" , "KC_TRNS", - - "KC_TRNS" , "KC_TRNS", - "KC_TRNS" , "KC_TRNS" - ], - ["KC_TRNS" , "KC_TRNS" , "KC_PGUP" , "KC_TRNS" , "KC_TRNS", - "KC_TRNS" , "KC_TRNS" , "KC_TRNS" , "KC_TRNS" , "KC_TRNS", - - "KC_LEFT" , "KC_UP" , "KC_DOWN" , "KC_RGHT" , "KC_TRNS", - "KC_TRNS" , "KC_LGUI" , "KC_NO" , "LCTL(KC_LALT)" , "LCA(KC_LSFT)", - - "KC_TRNS" , "KC_HOME" , "KC_PGDN" , "KC_END" , "KC_TRNS", - "KC_TRNS" , "KC_TRNS" , "KC_TRNS" , "KC_TRNS" , "KC_TRNS", - - "KC_TRNS" , "KC_TRNS", - "KC_TRNS" , "KC_TRNS" - ], - ["KC_TRNS" , "KC_TRNS" , "KC_TRNS" , "KC_TRNS" , "KC_TRNS", - "KC_TRNS" , "KC_UNDS" , "KC_PIPE" , "KC_QUOT" , "KC_TRNS", - - "KC_CIRC" , "KC_ASTR" , "KC_AMPR" , "KC_NO" , "KC_TRNS", - "KC_HASH" , "KC_TILD" , "KC_SLSH" , "KC_DQUO" , "KC_DLR", - - "KC_TRNS" , "KC_TRNS" , "KC_TRNS" , "KC_TRNS" , "KC_TRNS", - "KC_TRNS" , "KC_MINS" , "KC_BSLS" , "KC_GRV" , "KC_TRNS", - - "RM_PREV" , "KC_TRNS", - "KC_TRNS" , "RM_NEXT" - ], - ["KC_TRNS" , "KC_COLN" , "KC_LT" , "KC_GT" , "KC_SCLN", - "KC_TRNS" , "KC_TRNS" , "KC_TRNS" , "KC_TRNS" , "KC_TRNS", - - "KC_LCBR" , "KC_RCBR" , "KC_LPRN" , "KC_RPRN" , "KC_AT", - "KC_TRNS" , "KC_NO" , "KC_EQL" , "KC_PLUS" , "KC_PERC", - - "KC_TRNS" , "KC_EXLM" , "KC_LBRC" , "KC_RBRC" , "KC_TRNS", - "KC_TRNS" , "KC_TRNS" , "KC_TRNS" , "KC_TRNS" , "KC_TRNS", - - "KC_VOLD" , "KC_TRNS", - "KC_TRNS" , "KC_VOLU" - ], - ["KC_TRNS" , "KC_TRNS" , "KC_TRNS" , "KC_TRNS" , "KC_TRNS", - "KC_TRNS" , "KC_F7" , "KC_F8" , "KC_F9" , "KC_F10", - - "KC_TRNS" , "KC_NO" , "LCTL(KC_LALT)" , "KC_TRNS" , "KC_TRNS", - "KC_TRNS" , "KC_F4" , "KC_F5" , "KC_F6" , "KC_F11", - - "KC_TRNS" , "KC_TRNS" , "KC_TRNS" , "KC_TRNS" , "KC_TRNS", - "KC_TRNS" , "KC_F1" , "KC_F2" , "KC_F3" , "KC_F12", - - "KC_TRNS" , "KC_TRNS", - "KC_TRNS" , "KC_TRNS" - ], - ["KC_PSLS" , "KC_7" , "KC_8" , "KC_9" , "KC_PPLS", - "KC_TRNS" , "KC_TRNS" , "KC_TRNS" , "KC_TRNS" , "KC_TRNS", - - "KC_0" , "KC_1" , "KC_2" , "KC_3" , "KC_PMNS", - "KC_TRNS" , "KC_TRNS" , "KC_TRNS" , "KC_NO" , "KC_TRNS", - - "KC_PAST" , "KC_4" , "KC_5" , "KC_6" , "KC_PEQL", - "KC_TRNS" , "KC_TRNS" , "KC_TRNS" , "KC_TRNS" , "KC_TRNS", - - "KC_TRNS" , "KC_TRNS", - "KC_TRNS" , "KC_TRNS" - ], - ["KC_TRNS" , "KC_TRNS" , "KC_COLN" , "KC_ESC" , "KC_TRNS", - "KC_TRNS" , "KC_TRNS" , "KC_TRNS" , "KC_TRNS" , "KC_DEL", - - "KC_TRNS" , "KC_PERC" , "KC_SLSH" , "KC_ENT" , "KC_TRNS", - "DF(1)" , "KC_LGUI" , "KC_TRNS" , "KC_TRNS" , "KC_TRNS", - - "KC_TRNS" , "KC_TRNS" , "KC_TRNS" , "KC_EXLM" , "KC_TRNS", - "DF(0)" , "KC_TRNS" , "RALT_T(KC_COMM)", "RCTL_T(KC_DOT)", "QK_BOOT", - - "KC_TRNS" , "KC_TAB", - "KC_NO" , "KC_TRNS" - ] - ], - "author": "@pierrec83" -} diff --git a/keyboards/ferris/sweep/keymaps/qwerty/readme.md b/keyboards/ferris/sweep/keymaps/qwerty/readme.md index aa7ba6d1..43dbb477 100644 --- a/keyboards/ferris/sweep/keymaps/qwerty/readme.md +++ b/keyboards/ferris/sweep/keymaps/qwerty/readme.md @@ -1,122 +1,59 @@ -A usable default keymap for the Ferris keyboard -=============================================== +# QWERTY Keymap for Ferris Sweep -Keymaps in general are quite personal, so it is difficult to come up with a default that will suit every user. +A personal QWERTY keymap optimized for programming and macOS usage. -This keymap makes heavy use of keys behaving differently when tapped and held, so that all the keys one may need remain accessible despite the low number of thumb keys. +## Layers -It comes with a number of layers to give access to most of the keys one may need on a keyboard. It is not meant to be the best possible keymap, but rather a good base on which to build a keymap that works for you. +### Layer 0: Base (QWERTY) -This is not the only way to make 34 keys a comfortable typing experience, but it is one way to do so. If you don't already know of a better way, this may be as good a starting point as any :) +Standard QWERTY layout with: +- Homerow mods (D, F, J, K) +- One-shot modifiers on thumbs (Shift, Alt) +- Layer toggle to Nav layer +- Repeat key -Note that this keymap was built from the perspective that it is OK to take a steep learning curve if it results in a keymap that is easier to use in the long run. This means that it may take more effort to learn this keymap than some alternatives. "Easy to use" was assessed against the workflow of the author, so your mileage may vary on some of the details. +### Layer 1: Numbers and Navigation -What do all these layers do? ----------------------------- +- Keypad numbers (0-9) +- Arrow keys (Left, Down, Up, Right) +- Browser navigation (Cmd+[, Ctrl+Shift+Tab, Ctrl+Tab, Cmd+]) +- Period key for decimal input +- Backspace, Tab, Enter, Esc -### Layer 0: Base layer +### Layer 2: Alt-Symbols -![Layer 0](https://i.imgur.com/HjNHUPL.png) +Special macOS symbols accessed via Alt+key combinations (rarely used as a layer). -On tapping the keys, our base layer is qwerty with space on the right homing thumb and backspace on the left homing thumb. +## Key Configuration Notes -In this layer, the non-homing-thumb positions have 0 and 1. I recommend modifying this to some frequently accessed shortcut such as copy/paste, previous/next tab or anything that makes most sense in your own workflow. O and 1 are place-holders and make it easy to troubleshoot that all keys are working properly before soldering in the switches. -The reason I recommend convenience shortcuts instead of more commonly used keys like tab or meta is that unhoming of the thumbs was a frequent source of typos for me when I used more than one thumb key frequently in the context of typing. +### Chordal Hold Behavior -Despite being missing on this layer, "meta", "tab", "esc" and such are accessible from any other layer: see Layer 7. +Chordal Hold prevents same-hand chords from activating modifiers: +- D (left) + F (left) = "df" (no Cmd) +- K (right) + F (left) = Cmd+F (opposite hands) -The behaviour of some keys differ when held: -* Both homing pinkies behave as shift. -* Both bottom-row ring fingers behave as ctrl. -* Both bottom-row middle fingers behave as alt. +Note: Chordal Hold only affects fast typing. Holding a homerow mod past the tapping term (200ms) without pressing another key will activate the modifier. -* The homing left ring finger gives access to the Function keys layer -* The homing right ring finger gives access to the Numbers layer -* The homing left middle finger gives access to the Mouse layer -* The homing right middle finger gives access to the Navigation layer -* The homing left index finger gives access to the Right symbols layer -* The homing right index finger gives access to the Left symbols layer -* The homing right thumb gives access to the Always accessible layer +### Cmd+Alt+Key "Melody" Behavior -### Layer 1: Mouse +Due to one-shot modifier timing, Cmd+Alt+key combinations require a specific order: +1. Press and hold homerow mod (Cmd) +2. Press and hold Alt thumb key +3. Press the target key -![Layer 1](https://i.imgur.com/0fvTuB9.png) +Reversing the order (Alt first, then Cmd) may not work as expected. -Layer 1 is a mouse layer: it can be used one-handed or two-handed. The most common way to use it is two handed, with left and right click on the homerow of the left hand and directions on the homerow of the right hand. -Scrolling is available on the right hand with mid finger up and down for vertical scroll and index and ring finger down for horizontal scroll. -On the right hand, left click and right click are also available with index and ring finger up to allow one handed operation. This can be particularly handy when enabling the mouse layer permanently (no need to hold the left middle finger), which can be done from Layer 7. +## Build -Note that thanks to the transparency, shift, ctrl and alt are all accessible on the left hand while operating the mouse. +To compile the keymap: -### Layer 2: Navigation +```bash +qmk compile -kb ferris/sweep -km qwerty +``` -![Layer 2](https://i.imgur.com/ZquQJRq.png) +And to flash it: -The navigation layer somewhat mirrors the mouse layer. It is accessed by holding the right middle finger and gives access to arrow keys on the left homerow. Page up and down, Home and End mirror the vertical scrolling and horizontal scrolling on the mouse layer. +```bash +qmk flash -kb ferris/sweep -km qwerty +``` -On the right hand, in addition to ctrl and alt which are available through transparency, ctrl + alt, ctrl + alt + shift and meta are accessible on the homerow to enable common shortcuts in some window managers. This part is quite workflow dependent, so make sure to adapt it to your own workflow as appropriate. - -### Layer 3: Right symbols - -![Layer 3](https://i.imgur.com/9tLAUqG.png) - -When holding down the left index, one may access about half of the symbols. The pinkies store `^` and `$` symbols that represent begin and end in vim. The left homerow hosts `*` and `&`, symbols which are related in the way that they represent some form of indirection in programming languages such as rust. On the right hand, most symbols used when navigating the command line are stored together, organized by columns of related symbols. - -### Layer 4: Left symbols - -![Layer 4](https://i.imgur.com/CkjUSW6.png) - -When holding down the right index, one may access the other symbols. On the left hand, most of the different brackets are laid out. The most frequent ones (round brackets and curly brackets) get a spot on the homerow. The rest of the layer hosts the remaining symbols that are easier to access here than on any other layers. - -### Layer 5: Function keys - -![Layer 5](https://i.imgur.com/fWgVqc4.png) - -By holding down the left ring finger, one may access the function keys, roughly in a numpad layout. -This means that alt+F4 is easy to type, with F4 being on the homerow. -There is a shortcut for ctrl+alt on the left hand to enable convenient switching between virtual terminals on Linux. - -### Layer 6: Numbers - -![Layer 6](https://i.imgur.com/S8gq9Kj.png) - -The number layer is accessed by holding the right ring finger. It hosts the numbers and some duplicated symbols that are commonly accessed next to numbers, such as mathematical operators. -The number are layed out similarly to a numpad, but with the middle row and the homerow swapped so that the most used numbers: 0, 1, 2 and 3 are all available in homing positions. - -### Layer 7: Always accessible - -![Layer 7](https://i.imgur.com/twqBeBb.png) - -Layer 7 is accessed by holding the right homing thumb down. Because this position is left transparent from every other layer, this layer is always accessible. -It gives access to some essential keys that would typically be accessed on a thumb cluster or pinkies, such as meta, enter, tab, esc and delete. - -As the layer hosting esc, we duplicated some symbols here to allow for fast navigation in vim. For instance, esc, :, w, q can be done in a single roll. - -Where is the keymap.c? ----------------------- - -The keymap.c file is not published to the repository. It is generated from `keymap.json` by the build system. - -This avoids duplicating information and allow users to edit their keymap from the qmk configurator web interface. - -How do I edit and update the keymap? ------------------------------------- - -The `keymap.json` file is generated from the qmk configurator interface and formatted for better readability in the context of the Ferris keyboard. - -To edit it, you may: -* Edit it directly from a text editor. -* Edit it from the qmk configurator. - -If you decide to use the latter workflow, here are the steps to follow: - -* From the qmk configurator, hit the "import QMK keymap json file" button (it has a drawing with an up arrow on it). -* Browse to the location of your keymap (for example, `/keyboards/ferris/keymaps/default/keymap.json`) -* Perform any modification to the keymap in the web UI -* Export the keymap to your downloads folder, by hitting the "Export QMK keymap json file" button (it has a drawing with a down arrow on it) -* Override your original keymap with the output of formatting the exported keymap by running a command such as this one from the root of your qmk repo: - ``` - ./keyboards/handwired/ferris/keymaps/json2crab.py --input /default.json > ./keyboards/handwired/ferris/keymaps/default/keymap.json - ``` - Note that you may first need to make json2crab executable by using `chmod +x` on it. - Also note that you may then want to remove the exported keymap from your dowload directory. diff --git a/keyboards/ferris/sweep/keymaps/qwerty/rules.mk b/keyboards/ferris/sweep/keymaps/qwerty/rules.mk new file mode 100644 index 00000000..a082130e --- /dev/null +++ b/keyboards/ferris/sweep/keymaps/qwerty/rules.mk @@ -0,0 +1,4 @@ +KEY_OVERRIDE_ENABLE = yes +REPEAT_KEY_ENABLE = yes +CAPS_WORD_ENABLE = yes +COMBO_ENABLE = yes