* Change how desktop commands work * Add DST_MOD_MASK as a config option * DST_RMV → DST_REM * Add melody96:konstantin keymap * Update custom SEND_STRING * Move feature flags from userspace into keyboard rules * Use "Vo-", "Vo+" instead of "VoD", "VoU" in keymap comments * Add RGB controls and numpad Unicode to Melody96 keymap * Add RGB_SET keycode to Melody96 and RGB files to userspace * Generate UNICODE and UNICODEMAP constants using macros * Avoid collisions with X_* send string constants * Use two spaces before inline comments * Add _keymap versions of other custom Quantum functions Not added: eeconfig_update_keymap, eeconfig_read_keymap * Switch to UNICODEMAP in keyboard rules * Make toggle_numpad a nested function in process_record_user * Set Melody96 underglow color to Godspeed blue on EEPROM reset * Remove most _keymap and _user definitions in userspace Some keyboards misuse _user functions by defining them in the base files instead of the corresponding _kb functions (especially led_set_user and matrix_init_user). Until this is fixed (#5148), I've removed definitions in my userspace that could cause linking collisions. * Update GODSPEED_BLUE values and RGB mode keys * Add GODSPEED_YELLOW color * Set preferred intervals for rgblight effects * Update tap dance function names * Replace td_lshift_fn with generic td_mod_layer, add TD_RCTL_FN Move TD_FN_RCTL after TD_RCTL_FN * Replace td_fn_rctrl with generic td_layer_mod * Add blank lines, prefer explicit initialization * ACTION_TAP_DANCE_DOUBLE_MODS → ACTION_TAP_DANCE_DOUBLE_MOD * Update Godspeed colors * Add media controls to Melody96 keymap * Add SysRq, Break combos and other keys to Melody96 keymappull/5368/head
@ -1,2 +1,11 @@ | |||
BOOTMAGIC_ENABLE = no | |||
COMMAND_ENABLE = yes | |||
CONSOLE_ENABLE = yes | |||
EXTRAKEY_ENABLE = yes | |||
MOUSEKEY_ENABLE = yes | |||
NKRO_ENABLE = yes | |||
TAP_DANCE_ENABLE = yes | |||
UNICODEMAP_ENABLE = yes | |||
BACKLIGHT_ENABLE = no | |||
RGBLIGHT_ENABLE = no |
@ -0,0 +1,3 @@ | |||
#pragma once | |||
#define LAYER_FN |
@ -0,0 +1,78 @@ | |||
#include QMK_KEYBOARD_H | |||
#include "konstantin.h" | |||
static const hsv_t *colors[] = { &GODSPEED_BLUE, &GODSPEED_YELLOW }; | |||
static size_t cnum = sizeof colors / sizeof *colors; | |||
static size_t cidx = 0; | |||
void eeconfig_init_keymap(void) { | |||
rgblight_sethsv(colors[cidx]->h, colors[cidx]->s, colors[cidx]->v); | |||
} | |||
enum keycodes_keymap { | |||
RGB_SET = RANGE_KEYMAP, | |||
}; | |||
bool process_record_keymap(uint16_t keycode, keyrecord_t *record) { | |||
switch (keycode) { | |||
case RGB_SET: | |||
if (record->event.pressed) { | |||
cidx = (cidx + 1) % cnum; | |||
rgblight_sethsv(colors[cidx]->h, colors[cidx]->s, colors[cidx]->v); | |||
} | |||
return false; | |||
default: | |||
return true; | |||
} | |||
} | |||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | |||
/* Base layer | |||
* ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐ | |||
* │Esc│F1 │F2 │F3 │F4 │F5 │F6 │F7 │F8 │F9 │F10│F11│F12│PSc│Ins│Hom│End│PgU│PgD│ | |||
* ├───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┤ | |||
* │ ` │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ - │ = │ \ │Del│NLk│P/ │P* │P- │ | |||
* ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴───┼───┼───┼───┼───┤ | |||
* │ Tab │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │ [ │ ] │Bspc │P7 │P8 │P9 │ │ | |||
* ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┼───┼───┼───┤P+ │ | |||
* │FnCaps│ A │ S │ D │ F │ G │ H │ J │ K │ L │ ; │ ' │ Enter │P4 │P5 │P6 │ │ | |||
* ├────┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────┬───┼───┼───┼───┼───┤ | |||
* │LSft│RAG│ Z │ X │ C │ V │ B │ N │ M │ , │ . │ / │RShift│ ↑ │P1 │P2 │P3 │ │ | |||
* ├────┼───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┴┬──┴──┬───┼───┼───┼───┼───┤PEn│ | |||
* │LCtl│LGui│LAlt│ Space │RAlGu│RCtrl│ ← │ ↓ │ → │P0 │P. │ │ | |||
* └────┴────┴────┴────────────────────────┴─────┴─────┴───┴───┴───┴───┴───┴───┘ | |||
*/ | |||
[L_BASE] = 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_F12, KC_PSCR, KC_INS, KC_HOME, KC_END, KC_PGUP, KC_PGDN, | |||
KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSLS, KC_DEL, KC_NLCK, KC_PSLS, KC_PAST, KC_PMNS, | |||
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSPC, KC_P7, KC_P8, KC_P9, XXXXXXX, | |||
FN_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT, KC_P4, KC_P5, KC_P6, KC_PPLS, | |||
KC_LSFT, RAL_RGU, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_UP, KC_P1, KC_P2, KC_P3, XXXXXXX, | |||
KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, RAL_RGU, XXXXXXX, KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT, KC_P0, KC_PDOT, KC_PENT | |||
), | |||
/* Function layer | |||
* ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐ | |||
* │ │ │ │ │ │ │ │ │ │ │ │ │ │Sys│SLk│Pau│Brk│Top│Btm│ | |||
* ├───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┤ | |||
* │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │RTg│ ÷ │ × │ − │ | |||
* ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴───┼───┼───┼───┼───┤ | |||
* │ M4 │M2 │M↑ │M1 │M3 │M5 │ │UCM│ │Stp│Ply│Prv│Nxt│Clear│RH+│RS+│RV+│ │ | |||
* ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┼───┼───┼───┤RSt│ | |||
* │ │M← │M↓ │M→ │MW↑│ │ │ │ │ │ │ │ │RH-│RS-│RV-│ │ | |||
* ├────┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────┬───┼───┼───┼───┼───┤ | |||
* │ │ │MA0│MA2│MW←│MW→│ │ │ │Vo-│Vo+│Mut│ │PgU│RMR│RMS│RMB│ │ | |||
* ├────┼───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┴┬──┴──┬───┼───┼───┼───┼───┤RMP│ | |||
* │ │DtPR│DtNA│ MW↓ │ │ App │Hom│PgD│End│RM-│RM+│ │ | |||
* └────┴────┴────┴────────────────────────┴─────┴─────┴───┴───┴───┴───┴───┴───┘ | |||
*/ | |||
[L_FN] = LAYOUT( \ | |||
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_SYSR, KC_SLCK, KC_PAUS, KC_BRK, TOP, BOTTOM, | |||
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, RGB_TOG, DIVIDE, TIMES, MINUS, | |||
KC_BTN4, KC_BTN2, KC_MS_U, KC_BTN1, KC_BTN3, KC_BTN5, _______, UC_MOD, _______, KC_MSTP, KC_MPLY, KC_MPRV, KC_MNXT, CLEAR, RGB_HUI, RGB_SAI, RGB_VAI, XXXXXXX, | |||
_______, KC_MS_L, KC_MS_D, KC_MS_R, KC_WH_U, _______, _______, _______, _______, _______, _______, _______, _______, RGB_HUD, RGB_SAD, RGB_VAD, RGB_SET, | |||
_______, _______, KC_ACL0, KC_ACL2, KC_WH_L, KC_WH_R, _______, _______, _______, KC_VOLD, KC_VOLU, KC_MUTE, _______, KC_PGUP, RGB_M_R, RGB_M_SN,RGB_M_B, XXXXXXX, | |||
_______, DST_P_R, DST_N_A, KC_WH_D, _______, XXXXXXX, KC_APP, KC_HOME, KC_PGDN, KC_END, RGB_RMOD,RGB_MOD, RGB_M_P | |||
), | |||
}; |
@ -0,0 +1,10 @@ | |||
BOOTMAGIC_ENABLE = no | |||
COMMAND_ENABLE = yes | |||
CONSOLE_ENABLE = no | |||
EXTRAKEY_ENABLE = yes | |||
MOUSEKEY_ENABLE = yes | |||
NKRO_ENABLE = yes | |||
TAP_DANCE_ENABLE = yes | |||
UNICODEMAP_ENABLE = yes | |||
BACKLIGHT_ENABLE = no |
@ -1,2 +1,11 @@ | |||
BOOTMAGIC_ENABLE = no | |||
COMMAND_ENABLE = yes | |||
CONSOLE_ENABLE = yes | |||
EXTRAKEY_ENABLE = yes | |||
MOUSEKEY_ENABLE = yes | |||
NKRO_ENABLE = yes | |||
TAP_DANCE_ENABLE = yes | |||
UNICODEMAP_ENABLE = yes | |||
BACKLIGHT_ENABLE = no | |||
VISUALIZER_ENABLE = no |
@ -0,0 +1,24 @@ | |||
#include "rgb.h" | |||
#ifdef RGBLIGHT_EFFECT_BREATHING | |||
const uint8_t RGBLED_BREATHING_INTERVALS[] PROGMEM = {20, 30, 5, 10}; | |||
#endif | |||
#ifdef RGBLIGHT_EFFECT_RAINBOW_MOOD | |||
const uint8_t RGBLED_RAINBOW_MOOD_INTERVALS[] PROGMEM = {20, 50, 100}; | |||
#endif | |||
#ifdef RGBLIGHT_EFFECT_RAINBOW_SWIRL | |||
const uint8_t RGBLED_RAINBOW_SWIRL_INTERVALS[] PROGMEM = {20, 50, 100}; | |||
#endif | |||
#ifdef RGBLIGHT_EFFECT_SNAKE | |||
const uint8_t RGBLED_SNAKE_INTERVALS[] PROGMEM = {20, 50, 100}; | |||
#endif | |||
#ifdef RGBLIGHT_EFFECT_KNIGHT | |||
const uint8_t RGBLED_KNIGHT_INTERVALS[] PROGMEM = {20, 50, 100}; | |||
#endif | |||
const hsv_t GODSPEED_BLUE = { .h = 280, .s = 68, .v = RGBLIGHT_LIMIT_VAL }; | |||
const hsv_t GODSPEED_YELLOW = { .h = 38, .s = 153, .v = RGBLIGHT_LIMIT_VAL }; |
@ -0,0 +1,18 @@ | |||
#pragma once | |||
#include "quantum.h" | |||
typedef struct { | |||
uint16_t h; // 0–360 | |||
uint8_t s; // 0–255 | |||
uint8_t v; // 0–255 | |||
} hsv_t; | |||
typedef struct { | |||
uint8_t r; // 0–255 | |||
uint8_t g; // 0–255 | |||
uint8_t b; // 0–255 | |||
} rgb_t; | |||
extern const hsv_t GODSPEED_BLUE; | |||
extern const hsv_t GODSPEED_YELLOW; |
@ -1,15 +1,12 @@ | |||
BOOTMAGIC_ENABLE = no | |||
COMMAND_ENABLE = yes | |||
CONSOLE_ENABLE = yes | |||
EXTRAKEY_ENABLE = yes | |||
MOUSEKEY_ENABLE = yes | |||
NKRO_ENABLE = yes | |||
TAP_DANCE_ENABLE = yes | |||
UNICODE_ENABLE = yes | |||
SRC += konstantin.c | |||
ifneq (,$(filter yes,$(RGBLIGHT_ENABLE) $(RGB_MATRIX_ENABLE))) # if either is yes | |||
SRC += rgb.c | |||
endif | |||
ifeq ($(strip $(TAP_DANCE_ENABLE)), yes) | |||
SRC += tap_dance.c | |||
endif | |||
ifneq (,$(filter yes,$(UNICODE_ENABLE) $(UNICODEMAP_ENABLE))) # if either is yes | |||
SRC += unicode.c | |||
endif | |||
EXTRAFLAGS += -flto |
@ -1,93 +1,117 @@ | |||
#include "tap_dance.h" | |||
#include "konstantin.h" | |||
#define ACTION_TAP_DANCE_DOUBLE_MODS(mod1, mod2) { \ | |||
.fn = { td_double_mods_each, NULL, td_double_mods_reset }, \ | |||
.user_data = &(qk_tap_dance_pair_t){ mod1, mod2 }, \ | |||
#define ACTION_TAP_DANCE_DOUBLE_MOD(mod1, mod2) { \ | |||
.fn = { td_double_mod_each, NULL, td_double_mod_reset }, \ | |||
.user_data = &(qk_tap_dance_pair_t){ mod1, mod2 }, \ | |||
} | |||
void td_double_mods_each(qk_tap_dance_state_t *state, void *user_data) { | |||
qk_tap_dance_pair_t *mods = (qk_tap_dance_pair_t *)user_data; | |||
void td_double_mod_each(qk_tap_dance_state_t *state, void *user_data) { | |||
qk_tap_dance_pair_t *data = (qk_tap_dance_pair_t *)user_data; | |||
// Single tap → mod1, double tap → mod2, triple tap etc. → mod1+mod2 | |||
if (state->count == 1 || state->count == 3) { | |||
register_code(mods->kc1); | |||
register_code(data->kc1); | |||
} else if (state->count == 2) { | |||
unregister_code(mods->kc1); | |||
register_code(mods->kc2); | |||
unregister_code(data->kc1); | |||
register_code(data->kc2); | |||
} | |||
// Prevent tap dance from sending kc1 and kc2 as weak mods | |||
state->weak_mods &= ~(MOD_BIT(mods->kc1) | MOD_BIT(mods->kc2)); | |||
// Prevent tap dance from sending the mods as weak mods | |||
state->weak_mods &= ~(MOD_BIT(data->kc1) | MOD_BIT(data->kc2)); | |||
} | |||
void td_double_mods_reset(qk_tap_dance_state_t *state, void *user_data) { | |||
qk_tap_dance_pair_t *mods = (qk_tap_dance_pair_t *)user_data; | |||
void td_double_mod_reset(qk_tap_dance_state_t *state, void *user_data) { | |||
qk_tap_dance_pair_t *data = (qk_tap_dance_pair_t *)user_data; | |||
if (state->count == 1 || state->count >= 3) { | |||
unregister_code(mods->kc1); | |||
unregister_code(data->kc1); | |||
} | |||
if (state->count >= 2) { | |||
unregister_code(mods->kc2); | |||
unregister_code(data->kc2); | |||
} | |||
} | |||
struct { | |||
bool fn_on; // Layer state when tap dance started | |||
bool started; | |||
} td_fn_rctrl_data; | |||
void td_fn_rctrl_each(qk_tap_dance_state_t *state, void *user_data) { | |||
if (!td_fn_rctrl_data.started) { | |||
td_fn_rctrl_data.fn_on = IS_LAYER_ON(L_FN); | |||
td_fn_rctrl_data.started = true; | |||
#define ACTION_TAP_DANCE_MOD_LAYER(mod, layer) { \ | |||
.fn = { td_mod_layer_each, NULL, td_mod_layer_reset }, \ | |||
.user_data = &(qk_tap_dance_dual_role_t){ mod, layer }, \ | |||
} | |||
// Single tap → Fn, double tap → RCtrl, triple tap etc. → Fn+RCtrl | |||
void td_mod_layer_each(qk_tap_dance_state_t *state, void *user_data) { | |||
qk_tap_dance_dual_role_t *data = (qk_tap_dance_dual_role_t *)user_data; | |||
// Single tap → mod, double tap → layer, triple tap etc. → mod+layer | |||
if (state->count == 1 || state->count == 3) { | |||
layer_on(L_FN); | |||
register_code(data->kc); | |||
} else if (state->count == 2) { | |||
if (!td_fn_rctrl_data.fn_on) { | |||
layer_off(L_FN); | |||
} | |||
register_code(KC_RCTL); | |||
unregister_code(data->kc); | |||
// Prevent tap dance from sending the mod as a weak mod | |||
state->weak_mods &= ~MOD_BIT(data->kc); | |||
layer_on(data->layer); | |||
} | |||
} | |||
void td_fn_rctrl_reset(qk_tap_dance_state_t *state, void *user_data) { | |||
if ((state->count == 1 || state->count >= 3) && !td_fn_rctrl_data.fn_on) { | |||
layer_off(L_FN); | |||
void td_mod_layer_reset(qk_tap_dance_state_t *state, void *user_data) { | |||
qk_tap_dance_dual_role_t *data = (qk_tap_dance_dual_role_t *)user_data; | |||
if (state->count == 1 || state->count >= 3) { | |||
unregister_code(data->kc); | |||
} | |||
if (state->count >= 2) { | |||
unregister_code(KC_RCTL); | |||
layer_off(data->layer); | |||
} | |||
td_fn_rctrl_data.started = false; | |||
} | |||
void td_lsft_fn_each(qk_tap_dance_state_t *state, void *user_data) { | |||
// Single tap → LShift, double tap → Fn, triple tap etc. → Fn+LShift | |||
#define ACTION_TAP_DANCE_LAYER_MOD(layer, mod) { \ | |||
.fn = { td_layer_mod_each, NULL, td_layer_mod_reset }, \ | |||
.user_data = &(qk_tap_dance_layer_mod_t){ layer, mod, 0, 0 }, \ | |||
} | |||
typedef struct { | |||
uint8_t layer; | |||
uint16_t kc; | |||
bool layer_on; // Layer state when tap dance started | |||
bool started; | |||
} qk_tap_dance_layer_mod_t; | |||
void td_layer_mod_each(qk_tap_dance_state_t *state, void *user_data) { | |||
qk_tap_dance_layer_mod_t *data = (qk_tap_dance_layer_mod_t *)user_data; | |||
if (!data->started) { | |||
data->layer_on = IS_LAYER_ON(data->layer); | |||
data->started = true; | |||
} | |||
// Single tap → layer, double tap → mod, triple tap etc. → layer+mod | |||
if (state->count == 1 || state->count == 3) { | |||
register_code(KC_LSFT); | |||
layer_on(data->layer); | |||
} else if (state->count == 2) { | |||
unregister_code(KC_LSFT); | |||
// Prevent tap dance from sending LShift as a weak mod | |||
state->weak_mods &= ~MOD_BIT(KC_LSFT); | |||
layer_on(L_FN); | |||
if (!data->layer_on) { | |||
layer_off(data->layer); | |||
} | |||
register_code(data->kc); | |||
} | |||
} | |||
void td_lsft_fn_reset(qk_tap_dance_state_t *state, void *user_data) { | |||
if (state->count == 1 || state->count >= 3) { | |||
unregister_code(KC_LSFT); | |||
void td_layer_mod_reset(qk_tap_dance_state_t *state, void *user_data) { | |||
qk_tap_dance_layer_mod_t *data = (qk_tap_dance_layer_mod_t *)user_data; | |||
if ((state->count == 1 || state->count >= 3) && !data->layer_on) { | |||
layer_off(data->layer); | |||
} | |||
if (state->count >= 2) { | |||
layer_off(L_FN); | |||
unregister_code(data->kc); | |||
} | |||
data->started = false; | |||
} | |||
qk_tap_dance_action_t tap_dance_actions[] = { | |||
[TD_DESKTOP] = ACTION_TAP_DANCE_DOUBLE(LCTL(LGUI(KC_D)), LCTL(LGUI(KC_F4))), // Add/close virtual desktop | |||
[TD_DST_A_R] = ACTION_TAP_DANCE_DOUBLE(DST_ADD, DST_REM), | |||
[TD_RAL_LAL] = ACTION_TAP_DANCE_DOUBLE_MODS(KC_RALT, KC_LALT), | |||
[TD_RAL_RGU] = ACTION_TAP_DANCE_DOUBLE_MODS(KC_RALT, KC_RGUI), | |||
[TD_RCT_RSF] = ACTION_TAP_DANCE_DOUBLE_MODS(KC_RCTL, KC_RSFT), | |||
[TD_RAL_LAL] = ACTION_TAP_DANCE_DOUBLE_MOD(KC_RALT, KC_LALT), | |||
[TD_RAL_RGU] = ACTION_TAP_DANCE_DOUBLE_MOD(KC_RALT, KC_RGUI), | |||
[TD_RCT_RSF] = ACTION_TAP_DANCE_DOUBLE_MOD(KC_RCTL, KC_RSFT), | |||
[TD_FN_RCTL] = ACTION_TAP_DANCE_FN_ADVANCED(td_fn_rctrl_each, NULL, td_fn_rctrl_reset), | |||
[TD_LSFT_FN] = ACTION_TAP_DANCE_FN_ADVANCED(td_lsft_fn_each, NULL, td_lsft_fn_reset), | |||
[TD_LSFT_FN] = ACTION_TAP_DANCE_MOD_LAYER(KC_LSFT, L_FN), | |||
[TD_RCTL_FN] = ACTION_TAP_DANCE_MOD_LAYER(KC_RCTL, L_FN), | |||
[TD_FN_RCTL] = ACTION_TAP_DANCE_LAYER_MOD(L_FN, KC_RCTL), | |||
}; |
@ -0,0 +1,7 @@ | |||
#include "unicode.h" | |||
#ifdef UNICODEMAP_ENABLE | |||
const uint32_t PROGMEM unicode_map[] = { | |||
FOREACH_UNICODE(UCM_ENTRY) | |||
}; | |||
#endif |