From cd92946f492bf13e09c6a5e6d24dcc4bbc523e6a Mon Sep 17 00:00:00 2001 From: Sébastien Dailly Date: Tue, 19 Dec 2023 21:44:34 +0100 Subject: Added the qmk firmware for sofle keyboard --- qmk/keyboards/sofle_choc/keymaps/custom/config.h | 45 ++++ qmk/keyboards/sofle_choc/keymaps/custom/keycodes.c | 78 +++++++ qmk/keyboards/sofle_choc/keymaps/custom/keycodes.h | 28 +++ qmk/keyboards/sofle_choc/keymaps/custom/keymap.c | 68 +++++++ .../sofle_choc/keymaps/custom/quad_tapdance.c | 226 +++++++++++++++++++++ .../sofle_choc/keymaps/custom/quad_tapdance.h | 30 +++ qmk/keyboards/sofle_choc/keymaps/custom/rules.mk | 6 + 7 files changed, 481 insertions(+) create mode 100644 qmk/keyboards/sofle_choc/keymaps/custom/config.h create mode 100644 qmk/keyboards/sofle_choc/keymaps/custom/keycodes.c create mode 100644 qmk/keyboards/sofle_choc/keymaps/custom/keycodes.h create mode 100644 qmk/keyboards/sofle_choc/keymaps/custom/keymap.c create mode 100644 qmk/keyboards/sofle_choc/keymaps/custom/quad_tapdance.c create mode 100644 qmk/keyboards/sofle_choc/keymaps/custom/quad_tapdance.h create mode 100644 qmk/keyboards/sofle_choc/keymaps/custom/rules.mk (limited to 'qmk/keyboards/sofle_choc') diff --git a/qmk/keyboards/sofle_choc/keymaps/custom/config.h b/qmk/keyboards/sofle_choc/keymaps/custom/config.h new file mode 100644 index 0000000..9a89fd8 --- /dev/null +++ b/qmk/keyboards/sofle_choc/keymaps/custom/config.h @@ -0,0 +1,45 @@ +/* Copyright 2023 Brian Low + * + * 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 + +// Enabling this option changes the startup behavior to listen for an +// active USB communication to delegate which part is master and which +// is slave. With this option enabled and theres’s USB communication, +// then that half assumes it is the master, otherwise it assumes it +// is the slave. +// +// I've found this helps with some ProMicros where the slave does not boot +#define SPLIT_USB_DETECT + +#define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended +#define SPLIT_TRANSPORT_MIRROR // If LED_MATRIX_KEYPRESSES or LED_MATRIX_KEYRELEASES is enabled, you also will want to enable SPLIT_TRANSPORT_MIRROR +#define RGB_MATRIX_MAXIMUM_BRIGHTNESS 100 // limits maximum brightness of LEDs (max 255). Higher may cause the controller to crash. + + + +#define RP2040_BOOTLOADER_DOUBLE_TAP_RESET // Activates the double-tap behavior +#define RP2040_BOOTLOADER_DOUBLE_TAP_RESET_TIMEOUT 200U // Timeout window in ms in which the double tap can occur. +#define RP2040_BOOTLOADER_DOUBLE_TAP_RESET_LED D5 // Specify an optional status LED by GPIO number which blinks when entering the bootloader + +#define TAPPING_TERM 200 + +// Movihy the tap-hold configuration for helping with some tap-dance keys. +// The behavior with double-tap (like c/ç) and mod-tap is to wait the delay for +// the tap-dance before reporting the key to send. +// If I release the MOD-TAP key before, the modifier is not applied and the +// host receive a sequence of two keys, which is not what I want. +//#define PERMISSIVE_HOLD +//#define HOLD_ON_OTHER_KEY_PRESS diff --git a/qmk/keyboards/sofle_choc/keymaps/custom/keycodes.c b/qmk/keyboards/sofle_choc/keymaps/custom/keycodes.c new file mode 100644 index 0000000..e0f8994 --- /dev/null +++ b/qmk/keyboards/sofle_choc/keymaps/custom/keycodes.c @@ -0,0 +1,78 @@ +#include QMK_KEYBOARD_H +#include "keymap_bepo.h" +#include "keycodes.h" + +/* + * Rules and modifier to apply over the keycodes. This includes the keys + * redefinitions and the keys to include in the caps_word mecanism. + * + * All thoses update are working over the custom keys declared in `keycodes.h` + */ + +/* + * This function need to be declared after the key definition, including the + * tapdance keys because I need to reference the keycode here if I want to + * include them in the caps_word mecanism. + */ +bool caps_word_press_user(uint16_t keycode) { + switch (keycode) { + // Keycodes that continue Caps Word, with shift applied. + case KC_A ... KC_Z: + case KC_1 ... KC_0: + case KC_MINS: + case KEY_C: // Add also the tapdance keys here. + case KEY_W: + case KEY_E: + case BP_Z: // Additionals keys from the bepo layout. + case BP_M: + case BP_G: + case BP_H: + case BP_N: + add_weak_mods(MOD_BIT(KC_LSFT)); // Apply shift to next key. + return true; + + // Keycodes that continue Caps Word, without shifting. + case KC_BSPC: + case KC_DEL: + return true; + case KC_SPACE: + // The space key is used in order to generate the _ symbol, + // I check which modifier is applied, it’s ok when it’s ALT + return get_mods() & MOD_MASK_ALT; + + default: + return false; // Deactivate Caps Word. + } +} + +// +// Override the symbol ° and replace it by ` +// The symbol is still available in the symbol layer with the key just below. +// +const key_override_t perc_key_override = + ko_make_basic(MOD_MASK_SHIFT, KEY_PRC, LSFT(BP_PERC)); + +// +// I don’t care of the mapping CTRL+Ç and using the mod_tap does not work well +// when I type too fast because of tap-dance, so I remap the pattern here. +// +const key_override_t c_key_override = + ko_make_basic(MOD_MASK_CTRL, KEY_C, LCTL(BP_C)); + +// Same here, I override the key W with CTRL because the tapdance activate the +// caps_word which does not make sense here. +const key_override_t w_key_override = + ko_make_basic(MOD_MASK_CTRL, KEY_W, LCTL(BP_W)); + +const key_override_t e_key_override = + ko_make_basic(MOD_MASK_CTRL, KEY_E, RCTL(BP_E)); + + +// This globally defines all key overrides to be used +const key_override_t **key_overrides = (const key_override_t *[]){ + &perc_key_override, + &c_key_override, + &w_key_override, + &e_key_override, + NULL +}; diff --git a/qmk/keyboards/sofle_choc/keymaps/custom/keycodes.h b/qmk/keyboards/sofle_choc/keymaps/custom/keycodes.h new file mode 100644 index 0000000..9837769 --- /dev/null +++ b/qmk/keyboards/sofle_choc/keymaps/custom/keycodes.h @@ -0,0 +1,28 @@ +#pragma once + +enum { + // Custom key for defining the tapdance allowing to transform C into Ç + TD_C_CCED, + // Transform the key W into SHIFT or CAPSLOCK + TD_W_CAPSLOCK, + // Transform the key E into È + TD_E_EE, + TD_PRC, + TD_LAYER_SYMB, + TD_LSFT, +}; + +#define _BASE 0 +#define LAYER_SYMBOLS 1 + +#define MENU LGUI(BP_I) +#define KEY_C TD(TD_C_CCED) +#define KEY_W TD(TD_W_CAPSLOCK) +#define KEY_PRC TD(TD_PRC) +#define LT_SFT TD(TD_LSFT) +#define AL_ENT MT(MOD_RALT, KC_ENT) +#define AL_SPC MT(MOD_LALT, KC_SPC) +#define KEY_E TD(TD_E_EE) +#define KEY_T MT(MOD_RCTL, BP_T) +#define KEY_INS MT(MOD_RGUI, KC_INS) + diff --git a/qmk/keyboards/sofle_choc/keymaps/custom/keymap.c b/qmk/keyboards/sofle_choc/keymaps/custom/keymap.c new file mode 100644 index 0000000..fb1ba89 --- /dev/null +++ b/qmk/keyboards/sofle_choc/keymaps/custom/keymap.c @@ -0,0 +1,68 @@ +/* Copyright 2023 Brian Low + * + * 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 QMK_KEYBOARD_H +#include "keymap_bepo.h" +#include "keycodes.h" + + +#define LY_SYMBOL TD(TD_LAYER_SYMB) + + +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { +/* + * BÉPO + * ,-----------------------------------------. ,-----------------------------------------. + * | ` | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | ° | + * |------+------+------+------+------+------| |------+------+------+------+------+------| + * | ESC | B | É | P | O | È | | ! | V | D | L | J | Z | + * |------+------+------+------+------+------| |------+------+------+------+------+------| + * | Tab | A | U | I | EÈ | ; |-------. ,-------| CÇ | T | S | R | N | M | + * |------+------+------+------+------+------| Mute | | Pause |------+------+------+------+------+------| + * |LShift| À | Y | X | : | K |-------| |-------| ? | Q | G | H | F | W | + * `-----------------------------------------/ / \ \-----------------------------------------' + * | LCTL | LGUI | LCMD | Layer| / Space / \Enter \ | Layer| RCMD | RGUI | RCTL | + * | | | | dwn |/ LALT / \ RALT \ | up | | | | + * `-----------------------------------' '------''---------------------------' + */ + +[_BASE] = LAYOUT( + KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KEY_PRC, + BP_DLR, BP_B, BP_EACU, BP_P, BP_O, KC_BSPC, BP_DCIR, BP_V, BP_D, BP_L, BP_J, BP_Z, + KC_TAB, BP_A, BP_U, BP_I, KEY_E, BP_COMM, KEY_C, KEY_T, BP_S, BP_R, BP_N, BP_M, + LT_SFT, BP_AGRV,BP_Y, BP_X, BP_DOT, KC_B, KC_MUTE, KC_MPLY,BP_QUOT, BP_Q, BP_G, BP_H, BP_F, KEY_W, + KC_LCTL, KC_LGUI, KC_BSPC, LY_SYMBOL,AL_SPC, AL_ENT, LY_SYMBOL,MENU, KEY_INS, KC_RCTL +), + +// In the number layout, I keep the mod-tap modifiers applies to the middle letters : +// +#define KEY_5 MT(MOD_LCTL, KC_P5) +#define KEY_DOWN MT(MOD_RCTL, KC_DOWN) + +[LAYER_SYMBOLS] = LAYOUT( + KC_ESC, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, + KC_NO, KC_NO, KC_NO, KC_P7, KC_P8, KC_P9, KC_HOME, KC_UP, KC_END, KC_NO, KC_NO, S(BP_EQL), + KC_TAB, KC_NO, KC_NO, KC_P4, KEY_5, KC_P6, KC_LEFT, KEY_DOWN, KC_RIGHT,KC_NO, KC_NO, KC_NO, + LT_SFT, KC_NO, KC_P0, KC_P1, KC_P2, KC_P3, KC_MUTE, KC_MPLY,KC_PGUP, KC_NO, KC_PGDN, KC_NO, KC_NO, KC_RIGHT_SHIFT, + KC_LCTL, KC_LGUI, KC_BSPC, LY_SYMBOL,AL_SPC, AL_ENT, LY_SYMBOL,KC_NO, KC_RGUI, KC_RCTL +), +}; + +#if defined(ENCODER_MAP_ENABLE) +const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][NUM_DIRECTIONS] = { + [_BASE] = { ENCODER_CCW_CW(KC_VOLD, KC_VOLU), ENCODER_CCW_CW(KC_MS_WH_UP, KC_MS_WH_DOWN) }, + [LAYER_SYMBOLS] = { ENCODER_CCW_CW(KC_VOLD, KC_VOLU), ENCODER_CCW_CW(KC_MS_WH_UP, KC_MS_WH_DOWN) }, +}; +#endif diff --git a/qmk/keyboards/sofle_choc/keymaps/custom/quad_tapdance.c b/qmk/keyboards/sofle_choc/keymaps/custom/quad_tapdance.c new file mode 100644 index 0000000..9978315 --- /dev/null +++ b/qmk/keyboards/sofle_choc/keymaps/custom/quad_tapdance.c @@ -0,0 +1,226 @@ +/* Return an integer that corresponds to what kind of tap dance should be executed. + * + * How to figure out tap dance state: interrupted and pressed. + * + * Interrupted: If the state of a dance is "interrupted", that means that another key has been hit + * under the tapping term. This is typically indicitive that you are trying to "tap" the key. + * + * Pressed: Whether or not the key is still being pressed. If this value is true, that means the tapping term + * has ended, but the key is still being pressed down. This generally means the key is being "held". + * + * One thing that is currenlty not possible with qmk software in regards to tap dance is to mimic the "permissive hold" + * feature. In general, advanced tap dances do not work well if they are used with commonly typed letters. + * For example "A". Tap dances are best used on non-letter keys that are not hit while typing letters. + * + * Good places to put an advanced tap dance: + * z,q,x,j,k,v,b, any function key, home/end, comma, semi-colon + * + * Criteria for "good placement" of a tap dance key: + * Not a key that is hit frequently in a sentence + * Not a key that is used frequently to double tap, for example 'tab' is often double tapped in a terminal, or + * in a web form. So 'tab' would be a poor choice for a tap dance. + * Letters used in common words as a double. For example 'p' in 'pepper'. If a tap dance function existed on the + * letter 'p', the word 'pepper' would be quite frustating to type. + * + * For the third point, there does exist the 'TD_DOUBLE_SINGLE_TAP', however this is not fully tested + * + */ + +#include QMK_KEYBOARD_H +#include "keymap_bepo.h" +#include "quad_tapdance.h" +#include "keycodes.h" + +td_state_t cur_dance(tap_dance_state_t *state) { + if (state->count == 1) { + if (!state->pressed) return TD_SINGLE_TAP; + // Key has not been interrupted, but the key is still held. Means you want to send a 'HOLD'. + else return TD_SINGLE_HOLD; + } else if (state->count == 2) { + // TD_DOUBLE_SINGLE_TAP is to distinguish between typing "pepper", and actually wanting a double tap + // action when hitting 'pp'. Suggested use case for this return value is when you want to send two + // keystrokes of the key, and not the 'double tap' action/macro. + if (state->interrupted) return TD_DOUBLE_SINGLE_TAP; + else if (state->pressed) return TD_DOUBLE_HOLD; + else return TD_DOUBLE_TAP; + } + + // Assumes no one is trying to type the same letter three times (at least not quickly). + // If your tap dance key is 'KC_W', and you want to type "www." quickly - then you will need to add + // an exception here to return a 'TD_TRIPLE_SINGLE_TAP', and define that enum just like 'TD_DOUBLE_SINGLE_TAP' + if (state->count == 3) { + if (state->interrupted || !state->pressed) return TD_TRIPLE_TAP; + else return TD_TRIPLE_HOLD; + } else return TD_UNKNOWN; +} + +// +// Definition for the key W. +// +// The main usage is to send the letter W when pressed, but the key is also +// used to activate the SHIFT mode when pressed. +// +// If the key is double tapped, it will also switch into the caps_word mode. +// + +static td_tap_t w_tap_state = { + .is_press_action = true, + .state = TD_NONE +}; + +void w_finished(tap_dance_state_t *state, void *user_data) { + w_tap_state.state = cur_dance(state); + switch (w_tap_state.state) { + case TD_SINGLE_TAP: register_code(BP_W); break; + case TD_SINGLE_HOLD: register_code(KC_RIGHT_SHIFT); break; + case TD_DOUBLE_TAP: caps_word_on(); break; + case TD_DOUBLE_SINGLE_TAP: tap_code(BP_W); register_code(BP_W); break; + default: break; + } +} + +void w_reset(tap_dance_state_t *state, void *user_data) { + switch (w_tap_state.state) { + case TD_SINGLE_TAP: unregister_code(BP_W); break; + case TD_SINGLE_HOLD: unregister_code(KC_RIGHT_SHIFT); break; + case TD_DOUBLE_SINGLE_TAP: unregister_code(BP_W); break; + default: break; + } + w_tap_state.state = TD_NONE; +} + +// +// Definition for the layer key +// +// The only one usage is to activate the layer over the keyboard, but there is +// two way of doing it: +// +// The first mode, when hold, is to activate the layer as long as the key is pressed. +// The second one is to switch in the layer mode when double tapped, in this +// mode, you can go back into the normal layer by a single press on the key. +// +static td_tap_t ql_tap_state = { + .is_press_action = true, + .state = TD_NONE +}; + +// Functions that control what our tap dance key does +void ql_finished(tap_dance_state_t *state, void *user_data) { + ql_tap_state.state = cur_dance(state); + switch (ql_tap_state.state) { + // Remove the layer with a single tap, this way I always have a key to remove the + // the layer, without knowing the previous state I had. + case TD_SINGLE_TAP: layer_off(LAYER_SYMBOLS); break; + case TD_SINGLE_HOLD: layer_on(LAYER_SYMBOLS); break; + case TD_DOUBLE_TAP: layer_invert(LAYER_SYMBOLS); break; + default: break; + } +} + +void ql_reset(tap_dance_state_t *state, void *user_data) { + // If the key was held down and now is released then switch off the layer + if (ql_tap_state.state == TD_SINGLE_HOLD) { + layer_off(LAYER_SYMBOLS); + } + ql_tap_state.state = TD_NONE; +} + +// +// Definiton for the key DEL. +// The main usage of the key is to activate the LShift when hold. But the key +// can also be used to send the DEL keycode. +// +// As I do not want to send the DEL keycode by mistake, I’ve configured the key +// to do it on double-tap. If you hold the key after a double tap, the DELETE +// code will be repeated again until the key is released. +// +// On a single press, the key will just remove the CAPSLOCK state if active. +// +static td_tap_t lshift_tap_state = { + .is_press_action = true, + .state = TD_NONE +}; + +// Functions that control what our tap dance key does +void lshift_finished(tap_dance_state_t *state, void *user_data) { + lshift_tap_state.state = cur_dance(state); + switch (lshift_tap_state.state) { + // Remove the layer with a single tap, this way I always have a key to remove the + // the layer, without knowing the previous state I had. + case TD_SINGLE_HOLD: register_code(KC_LEFT_SHIFT); break; + case TD_DOUBLE_TAP: + case TD_DOUBLE_HOLD: + register_code(KC_DELETE); break; + case TD_SINGLE_TAP: + if (host_keyboard_led_state().caps_lock) + register_code(KC_CAPS_LOCK); + break; + default: break; + } +} + +void lshift_reset(tap_dance_state_t *state, void *user_data) { + switch (lshift_tap_state.state) { + case TD_SINGLE_HOLD: unregister_code(KC_LEFT_SHIFT); break; + case TD_DOUBLE_TAP: + case TD_DOUBLE_HOLD: + unregister_code(KC_DELETE); break; + case TD_SINGLE_TAP: + if (host_keyboard_led_state().caps_lock) + unregister_code(KC_CAPS_LOCK); + break; + default: break; + } + lshift_tap_state.state = TD_NONE; +} + +// Definition for the key E +// This key can transform into LEFT CONTROL when hold, but can also transform into È when double tapped. +static td_tap_t e_tap_state = { + .is_press_action = true, + .state = TD_NONE +}; + +// Functions that control what our tap dance key does +void e_finished(tap_dance_state_t *state, void *user_data) { + e_tap_state.state = cur_dance(state); + switch (e_tap_state.state) { + // Remove the layer with a single tap, this way I always have a key to remove the + // the layer, without knowing the previous state I had. + case TD_SINGLE_HOLD: register_code(KC_LEFT_CTRL); break; + case TD_DOUBLE_TAP: + register_code(BP_EGRV); break; + case TD_SINGLE_TAP: + register_code(BP_E); break; + break; + default: break; + } +} + +void e_reset(tap_dance_state_t *state, void *user_data) { + switch (e_tap_state.state) { + case TD_SINGLE_HOLD: unregister_code(KC_LEFT_CTRL); break; + case TD_DOUBLE_TAP: + unregister_code(BP_EGRV); break; + case TD_SINGLE_TAP: + unregister_code(BP_E); break; + break; + default: break; + } + e_tap_state.state = TD_NONE; +} + + + +// +// Declare the tapdance table here. +// +tap_dance_action_t tap_dance_actions[] = { + [TD_C_CCED] = ACTION_TAP_DANCE_DOUBLE(BP_C, BP_CCED), + [TD_PRC] = ACTION_TAP_DANCE_DOUBLE(BP_EQL, BP_PERC), + [TD_W_CAPSLOCK] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, w_finished, w_reset), + [TD_LAYER_SYMB] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, ql_finished, ql_reset), + [TD_LSFT] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, lshift_finished, lshift_reset), + [TD_E_EE] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, e_finished, e_reset), +}; + diff --git a/qmk/keyboards/sofle_choc/keymaps/custom/quad_tapdance.h b/qmk/keyboards/sofle_choc/keymaps/custom/quad_tapdance.h new file mode 100644 index 0000000..87da433 --- /dev/null +++ b/qmk/keyboards/sofle_choc/keymaps/custom/quad_tapdance.h @@ -0,0 +1,30 @@ +#pragma once + +typedef enum { + TD_NONE, + TD_UNKNOWN, + TD_SINGLE_TAP, + TD_SINGLE_HOLD, + TD_DOUBLE_TAP, + TD_DOUBLE_HOLD, + TD_DOUBLE_SINGLE_TAP, // Send two single taps + TD_TRIPLE_TAP, + TD_TRIPLE_HOLD +} td_state_t; + +typedef struct { + bool is_press_action; + td_state_t state; +} td_tap_t; + +td_state_t cur_dance(tap_dance_state_t *state); + +// For the x tap dance. Put it here so it can be used in any keymap +void w_finished(tap_dance_state_t *state, void *user_data); +void w_reset(tap_dance_state_t *state, void *user_data); + +void ql_finished(tap_dance_state_t *state, void *user_data); +void ql_reset(tap_dance_state_t *state, void *user_data); + +void lshift_finished(tap_dance_state_t *state, void *user_data); +void lshift_reset(tap_dance_state_t *state, void *user_data); diff --git a/qmk/keyboards/sofle_choc/keymaps/custom/rules.mk b/qmk/keyboards/sofle_choc/keymaps/custom/rules.mk new file mode 100644 index 0000000..5edfedd --- /dev/null +++ b/qmk/keyboards/sofle_choc/keymaps/custom/rules.mk @@ -0,0 +1,6 @@ +ENCODER_MAP_ENABLE = yes +SPLIT_KEYBOARD = yes +TAP_DANCE_ENABLE = yes +CAPS_WORD_ENABLE = yes +KEY_OVERRIDE_ENABLE = yes +SRC += quad_tapdance.c keycodes.c -- cgit v1.2.3