From 4a10d45422edaff16e9b96aa7a250ab578a8f9a4 Mon Sep 17 00:00:00 2001 From: Andre Brait Date: Mon, 3 Jul 2023 21:22:26 +0200 Subject: [PATCH] [Keymap] Update andrebrait keymap for GMMK Pro (#21133) --- .../pro/rev1/ansi/keymaps/andrebrait/config.h | 58 ++ .../pro/rev1/ansi/keymaps/andrebrait/keymap.c | 613 ++++++++++++------ .../rev1/ansi/keymaps/andrebrait/readme.md | 16 +- .../pro/rev1/ansi/keymaps/andrebrait/rules.mk | 22 +- 4 files changed, 498 insertions(+), 211 deletions(-) diff --git a/keyboards/gmmk/pro/rev1/ansi/keymaps/andrebrait/config.h b/keyboards/gmmk/pro/rev1/ansi/keymaps/andrebrait/config.h index 5dda6f15bc5e..08eade43c877 100644 --- a/keyboards/gmmk/pro/rev1/ansi/keymaps/andrebrait/config.h +++ b/keyboards/gmmk/pro/rev1/ansi/keymaps/andrebrait/config.h @@ -20,3 +20,61 @@ #define RGB_MATRIX_TIMEOUT 1200000 // 20 minutes (20 * 60 * 1000ms) #define RGB_DISABLE_WHEN_USB_SUSPENDED #endif + +// Setting DEBOUNCE to 8 to be a little conservative due to issues with Glorious' proprietary hot-swap sockets +#ifdef DEBOUNCE + #undef DEBOUNCE +#endif +#define DEBOUNCE 8 + +// RGB Matrix Animation modes. Explicitly enabled +// For full list of effects, see: +// https://docs.qmk.fm/#/feature_rgb_matrix?id=rgb-matrix-effects +// #define ENABLE_RGB_MATRIX_ALPHAS_MODS +// #define ENABLE_RGB_MATRIX_GRADIENT_UP_DOWN +// #define ENABLE_RGB_MATRIX_GRADIENT_LEFT_RIGHT +#define ENABLE_RGB_MATRIX_BREATHING +// #define ENABLE_RGB_MATRIX_BAND_SAT +// #define ENABLE_RGB_MATRIX_BAND_VAL +// #define ENABLE_RGB_MATRIX_BAND_PINWHEEL_SAT +// #define ENABLE_RGB_MATRIX_BAND_PINWHEEL_VAL +// #define ENABLE_RGB_MATRIX_BAND_SPIRAL_SAT +#define ENABLE_RGB_MATRIX_BAND_SPIRAL_VAL +#define ENABLE_RGB_MATRIX_CYCLE_ALL +#define ENABLE_RGB_MATRIX_CYCLE_LEFT_RIGHT +#define ENABLE_RGB_MATRIX_CYCLE_UP_DOWN +#define ENABLE_RGB_MATRIX_RAINBOW_MOVING_CHEVRON +#define ENABLE_RGB_MATRIX_CYCLE_OUT_IN +#define ENABLE_RGB_MATRIX_CYCLE_OUT_IN_DUAL +#define ENABLE_RGB_MATRIX_CYCLE_PINWHEEL +#define ENABLE_RGB_MATRIX_CYCLE_SPIRAL +#define ENABLE_RGB_MATRIX_DUAL_BEACON +#define ENABLE_RGB_MATRIX_RAINBOW_BEACON +// #define ENABLE_RGB_MATRIX_RAINBOW_PINWHEELS +// #define ENABLE_RGB_MATRIX_RAINDROPS +#define ENABLE_RGB_MATRIX_JELLYBEAN_RAINDROPS +// #define ENABLE_RGB_MATRIX_HUE_BREATHING +// #define ENABLE_RGB_MATRIX_HUE_PENDULUM +// #define ENABLE_RGB_MATRIX_HUE_WAVE +#define ENABLE_RGB_MATRIX_PIXEL_RAIN +// #define ENABLE_RGB_MATRIX_PIXEL_FLOW +// #define ENABLE_RGB_MATRIX_PIXEL_FRACTAL +// enabled only if RGB_MATRIX_FRAMEBUFFER_EFFECTS is defined +#define ENABLE_RGB_MATRIX_TYPING_HEATMAP +#define ENABLE_RGB_MATRIX_DIGITAL_RAIN +// enabled only of RGB_MATRIX_KEYPRESSES or RGB_MATRIX_KEYRELEASES is defined +#define ENABLE_RGB_MATRIX_SOLID_REACTIVE_SIMPLE +// #define ENABLE_RGB_MATRIX_SOLID_REACTIVE +// #define ENABLE_RGB_MATRIX_SOLID_REACTIVE_WIDE +#define ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTIWIDE +// #define ENABLE_RGB_MATRIX_SOLID_REACTIVE_CROSS +// #define ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTICROSS +// #define ENABLE_RGB_MATRIX_SOLID_REACTIVE_NEXUS +#define ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTINEXUS +#define ENABLE_RGB_MATRIX_SPLASH +// #define ENABLE_RGB_MATRIX_MULTISPLASH +#define ENABLE_RGB_MATRIX_SOLID_SPLASH +#define ENABLE_RGB_MATRIX_SOLID_MULTISPLASH + +#define RGB_MATRIX_KEYPRESSES +#define RGB_MATRIX_FRAMEBUFFER_EFFECTS diff --git a/keyboards/gmmk/pro/rev1/ansi/keymaps/andrebrait/keymap.c b/keyboards/gmmk/pro/rev1/ansi/keymaps/andrebrait/keymap.c index f803b44abbd0..6c467ff63653 100644 --- a/keyboards/gmmk/pro/rev1/ansi/keymaps/andrebrait/keymap.c +++ b/keyboards/gmmk/pro/rev1/ansi/keymaps/andrebrait/keymap.c @@ -24,16 +24,22 @@ enum layers { MAC_FN }; -#define KC_TASK LGUI(KC_TAB) -#define KC_FLXP LGUI(KC_E) -#define TO_WINB TO(WIN_BASE) -#define TO_MACB TO(MAC_BASE) -#define MO_WINF MO(WIN_FN) -#define MO_MACF MO(MAC_FN) +enum custom_keycodes { + CMDQ_TOG = QK_KB_2 // TECH DEBT: Starts at QK_KB_2 to maintain ordering with VIA definitions. See #19884. Revert to QK_KB_0 when VIA catches up with QMK. +}; + +#define KC_TASK LWIN(KC_TAB) // Open Task Manager +#define KC_FLXP LWIN(KC_E) // Open File Explorer +#define DF_WINB DF(WIN_BASE) // Switch to WIN_BASE layer +#define MO_WINF MO(WIN_FN) // Toggle to WIN_FN layer +#define DF_MACB DF(MAC_BASE) // Switch to MAX_BASE layer +#define MO_MACF MO(MAC_FN) // Toggle to MAC_FN layer // clang-format off const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { +// The GMMK Pro default layout is: +// // ESC F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 Del Rotary(Play/Pause) // ~ 1 2 3 4 5 6 7 8 9 0 - (=) BackSpc Home // Tab Q W E R T Y U I O P [ ] \ PgUp @@ -55,133 +61,249 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { // Press Fn+N to toggle between 6KRO and NKRO. This setting is persisted to the EEPROM and thus persists between restarts. // // RGB and function keys are inspired by the Keychron Q1 layouts instead of using the default keys. - // - // KC_PAUS/KC_BRMU and KC_SCRL/KC_BRMD are aliases for the same keys, but their names reflect better the function in each layout. + // To clean the EEPROM, hold the ESC key while connecting the keyboard. + [WIN_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_DEL, KC_MUTE, - 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_BSPC, KC_HOME, - 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_BSLS, KC_PGUP, - KC_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_PGDN, + 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_MUTE, + 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_BSPC, KC_INS, + 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_BSLS, KC_DEL, + KC_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_HOME, KC_LSFT, 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_END, - KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, MO_WINF, KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT + KC_LCTL, KC_LWIN, KC_LALT, KC_SPC, KC_RALT, MO_WINF, KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT ), [WIN_FN] = LAYOUT( - _______, KC_BRID, KC_BRIU, KC_TASK, KC_FLXP, KC_MPRV, KC_MNXT, KC_MPLY, KC_MSTP, KC_MUTE, KC_VOLD, KC_VOLU, XXXXXXX, KC_INS, XXXXXXX, - XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC_PSCR, - RGB_TOG, RGB_MOD, RGB_VAI, RGB_HUI, RGB_SAI, RGB_SPI, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, QK_BOOT, KC_PAUS, - TO_MACB, RGB_RMOD, RGB_VAD, RGB_HUD, RGB_SAD, RGB_SPD, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC_SCRL, - _______, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, NK_TOGG, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, - _______, _______, _______, XXXXXXX, _______, _______, _______, XXXXXXX, XXXXXXX, XXXXXXX + EE_CLR, KC_BRID, KC_BRIU, KC_TASK, KC_FLXP, RGB_VAD, RGB_VAI, KC_MPRV, KC_MPLY, KC_MNXT, KC_MUTE, KC_VOLD, KC_VOLU, XXXXXXX, XXXXXXX, + XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC_PAUS, + RGB_TOG, RGB_MOD, RGB_HUI, RGB_SAI, RGB_SPI, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, QK_BOOT, KC_SCRL, + DF_MACB, RGB_RMOD, RGB_HUD, RGB_SAD, RGB_SPD, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC_PGUP, + XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, NK_TOGG, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC_PGDN, + XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX ), [MAC_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_DEL, KC_MUTE, - 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_BSPC, KC_HOME, - 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_BSLS, KC_PGUP, - KC_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_PGDN, + 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_MUTE, + 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_BSPC, KC_INS, + 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_BSLS, KC_DEL, + KC_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_HOME, KC_LSFT, 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_END, - KC_LCTL, KC_LALT, KC_LGUI, KC_SPC, KC_RALT, MO_MACF, KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT + KC_LCTL, KC_LOPT, KC_LCMD, KC_SPC, KC_RCMD, MO_MACF, KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT ), [MAC_FN] = LAYOUT( - _______, KC_BRID, KC_BRIU, KC_MCTL, KC_LPAD, KC_MPRV, KC_MNXT, KC_MPLY, KC_MSTP, KC_MUTE, KC_VOLD, KC_VOLU, XXXXXXX, KC_INS, XXXXXXX, - XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC_PSCR, - RGB_TOG, RGB_MOD, RGB_VAI, RGB_HUI, RGB_SAI, RGB_SPI, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, QK_BOOT, KC_BRMU, - TO_WINB, RGB_RMOD, RGB_VAD, RGB_HUD, RGB_SAD, RGB_SPD, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC_BRMD, - _______, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, NK_TOGG, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, - _______, _______, _______, XXXXXXX, _______, _______, _______, XXXXXXX, XXXXXXX, XXXXXXX + EE_CLR, KC_BRID, KC_BRIU, KC_MCTL, KC_LPAD, RGB_VAD, RGB_VAI, KC_MPRV, KC_MPLY, KC_MNXT, KC_MUTE, KC_VOLD, KC_VOLU, XXXXXXX, XXXXXXX, + XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC_BRMU, + RGB_TOG, RGB_MOD, RGB_HUI, RGB_SAI, RGB_SPI, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, QK_BOOT, KC_BRMD, + DF_WINB, RGB_RMOD, RGB_HUD, RGB_SAD, RGB_SPD, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC_PGUP, + XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, NK_TOGG, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC_PGDN, + XXXXXXX, XXXXXXX, CMDQ_TOG, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX ) }; // clang-format on -#ifdef RGB_MATRIX_ENABLE +#ifdef ENCODER_MAP_ENABLE +const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][2] = { + [WIN_BASE] = { ENCODER_CCW_CW(KC_VOLD, KC_VOLU) }, + [WIN_FN] = { ENCODER_CCW_CW(XXXXXXX, XXXXXXX) }, + [MAC_BASE] = { ENCODER_CCW_CW(KC_VOLD, KC_VOLU) }, + [MAC_FN] = { ENCODER_CCW_CW(XXXXXXX, XXXXXXX) }, +}; +#endif -/* Renaming those to make the purpose on this keymap clearer */ -#define LED_FLAG_CAPS LED_FLAG_NONE -#define LED_FLAG_EFFECTS LED_FLAG_INDICATOR +/* To record user preferences */ +typedef union { + uint32_t raw; // set to 32-bit of size + struct { + bool rgb_enabled :1; // Artificial RGB ON/OFF flag (1 bit) + bool cmd_q_delay_enabled :1; // Toggle CMD+Q delay (1 bit) + }; +} user_config_t; +user_config_t user_config; -static void set_rgb_caps_leds(void); +/* Delayed keypresses variables and functions */ +static uint16_t delayed_press_delay = 0; +static uint16_t delayed_press_keycode = KC_NO; +static uint16_t delayed_press_start_time = 0; +static uint16_t delayed_press_sent_keycode = KC_NO; +static void start_delayed_press(const uint16_t delay, const uint16_t keycode); +static bool is_any_delayed_press_pending(void); +static bool is_delayed_press_pending(const uint16_t keycode); +static bool is_delayed_press_sent(const uint16_t keycode); +static void mark_delayed_press_sent(void); +static void mark_delayed_release_sent(void); +static void cancel_delayed_press(void); -static uint16_t effect_started_time = 0; -static uint8_t r_effect = 0x0, g_effect = 0x0, b_effect = 0x0; -static void start_effects(void); +/* CMD+Q delay */ +#ifndef CMD_Q_DELAY + #define CMD_Q_DELAY 1000 +#endif +#if CMD_Q_DELAY <= 0 || CMD_Q_DELAY >= UINT16_MAX / 2 + #error "CMD_Q_DELAY must be a positive integer smaller than UINT16_MAX / 2" +#endif -/* The interval time in ms */ -#ifndef EFFECTS_TIME - #define EFFECTS_TIME 2000 +#define MIN(x, y) (((x) < (y)) ? (x) : (y)) +#define MAX(x, y) (((x) > (y)) ? (x) : (y)) + +#ifdef RGB_MATRIX_ENABLE + +#define CAPS_LOCK_COLOR RGB_RED +#define WIN_BASE_COLOR RGB_BLUE +#define WIN_FN_COLOR RGB_BLUE +#define MAC_BASE_COLOR RGB_WHITE +#define MAC_FN_COLOR RGB_WHITE +#define UNKNOWN_LAYER_COLOR RGB_PINK + +/* The maximum effects duration */ +#ifndef EFFECTS_DURATION + #define EFFECTS_DURATION 2000 #endif -#ifndef EFFECTS_INTERVAL - #define EFFECTS_INTERVAL 250 +#if EFFECTS_DURATION <= 0 || EFFECTS_DURATION >= UINT16_MAX / 2 + #error "EFFECTS_DURATION must be a positive integer smaller than UINT16_MAX / 2" #endif -#if EFFECTS_TIME <= 0 || EFFECTS_TIME >= 32767 - #error "EFFECTS_TIME must be a positive integer smaller than 32767" +/* The interval for the flashing effect */ +#ifndef FLASHING_EFFECT_INTERVAL + #define FLASHING_EFFECT_INTERVAL 250 #endif -#if EFFECTS_INTERVAL <= 0 || EFFECTS_INTERVAL >= 32767 - #error "EFFECTS_INTERVAL must be a positive integer smaller than 32767" +#if FLASHING_EFFECT_INTERVAL <= 0 || FLASHING_EFFECT_INTERVAL >= UINT16_MAX / 2 + #error "FLASHING_EFFECT_INTERVAL must be a positive integer smaller than UINT16_MAX / 2" #endif -#define effect_red() r_effect = 0xFF, g_effect = 0x0, b_effect = 0x0 -#define effect_green() r_effect = 0x0, g_effect = 0xFF, b_effect = 0x0 -#define effect_blue() r_effect = 0x0, g_effect = 0x0, b_effect = 0xFF -#define effect_white() r_effect = 0xFF, g_effect = 0xFF, b_effect = 0xFF -static uint8_t previous_effect_layer = 255; +static void set_rgb_layer_winfn(void); +static void set_rgb_layer_macfn(void); -layer_state_t layer_state_set_user(layer_state_t state) { - uint8_t current_layer = get_highest_layer(state); - switch (current_layer) { - case WIN_BASE: - if (previous_effect_layer != current_layer) { - previous_effect_layer = current_layer; - effect_blue(); - start_effects(); - } - break; - case MAC_BASE: - if (previous_effect_layer != current_layer) { - previous_effect_layer = current_layer; - effect_white(); - start_effects(); - } - break; - } - return state; +/* Effects functions */ +static float flashing_effect(const uint16_t delta_time); +static float static_effect(const uint16_t delta_time); +static float increasing_effect(const uint16_t delta_time); + +/* Effect variables and functions */ +static uint16_t effect_started_time = 0; +static uint16_t effect_max_duration = EFFECTS_DURATION; +static uint8_t effect_r = 0x0, effect_g = 0x0, effect_b = 0x0; +static float (*effect_multiplier)(const uint16_t) = static_effect; +static void start_effects( + const uint16_t max_duration, + const uint8_t r_color, + const uint8_t g_color, + const uint8_t b_color, + const float (*multiplier)(const uint16_t)); +static void stop_effects(void); + +/* Delayed keypresses variables with RGB variant */ +static void start_delayed_press_with_effects( + const uint16_t delay, + const uint16_t keycode, + const uint8_t r_color, + const uint8_t g_color, + const uint8_t b_color); + +#endif // RGB_MATRIX_ENABLE + +void eeconfig_init_user(void) { // EEPROM is getting reset! + user_config.raw = 0; + user_config.rgb_enabled = true; // We want this enabled by default + user_config.cmd_q_delay_enabled = true; // We want this enabled by default + eeconfig_update_user(user_config.raw); // Write default value to EEPROM now } -bool led_update_user(led_t led_state) { - if (led_state.caps_lock) { - if (!rgb_matrix_is_enabled()) { - /* Turn ON the RGB Matrix for CAPS LOCK */ - rgb_matrix_set_flags(LED_FLAG_CAPS); - rgb_matrix_enable(); - } - } else if (rgb_matrix_get_flags() == LED_FLAG_CAPS) { - /* RGB Matrix was only ON because of CAPS LOCK. Turn it OFF. */ +void keyboard_post_init_user(void) { + #ifdef RGB_MATRIX_ENABLE + // Enable the RGB matrix, if not enabled + if (!rgb_matrix_is_enabled()) { + rgb_matrix_enable(); + } + // Set the flags to ALL, if not already set + if (rgb_matrix_get_flags() != LED_FLAG_ALL) { rgb_matrix_set_flags(LED_FLAG_ALL); - rgb_matrix_disable(); } - return true; + #endif + + // Read the user config from EEPROM + user_config.raw = eeconfig_read_user(); } -#endif // RGB_MATRIX_ENABLE +void matrix_scan_user(void) { + if (is_any_delayed_press_pending()) { + if (sync_timer_elapsed(delayed_press_start_time) > delayed_press_delay) { + register_code(delayed_press_keycode); + mark_delayed_press_sent(); + } + } +} bool process_record_user(uint16_t keycode, keyrecord_t *record) { + if (is_delayed_press_sent(keycode)) { + if (!record->event.pressed) { + /* Send key-up event and clear the keycode and stop processing */ + unregister_code(keycode); + mark_delayed_release_sent(); + return false; + } + } else if (is_delayed_press_pending(keycode)) { + if (!record->event.pressed) { + /* Cancel the pending press and stop processing */ + cancel_delayed_press(); + return false; + } + } else if (is_any_delayed_press_pending()) { + /* Cancel the pending press and resume processing */ + cancel_delayed_press(); + } switch (keycode) { - #ifdef RGB_MATRIX_ENABLE - #ifdef NKRO_ENABLE + case QK_DEF_LAYER ... QK_DEF_LAYER_MAX: + if (record->event.pressed) { + /* Set the default layout on the EEPROM, let the default layer change callback handle the rest */ + set_single_persistent_default_layer(QK_DEF_LAYER_GET_LAYER(keycode)); + } + return false; + case CMDQ_TOG: + if (record->event.pressed) { + if (user_config.cmd_q_delay_enabled) { + /* Turning delay OFF */ + #ifdef RGB_MATRIX_ENABLE + start_effects(EFFECTS_DURATION, RGB_RED, flashing_effect); + #endif + } else { + /* Turning delay ON */ + #ifdef RGB_MATRIX_ENABLE + start_effects(EFFECTS_DURATION, RGB_GREEN, flashing_effect); + #endif + } + user_config.cmd_q_delay_enabled = !user_config.cmd_q_delay_enabled; + eeconfig_update_user(user_config.raw); + } + return false; + case KC_Q: + if (user_config.cmd_q_delay_enabled) { + if (layer_state_is(MAC_BASE)) { + const uint8_t mods = get_mods(); + if (mods == MOD_BIT(KC_LCMD) || mods == MOD_BIT(KC_RCMD)) { + if (record->event.pressed) { + #ifdef RGB_MATRIX_ENABLE + start_delayed_press_with_effects(CMD_Q_DELAY, KC_Q, RGB_ORANGE); + #else + start_delayed_press(CMD_Q_DELAY, KC_Q); + #endif + } + return false; + } + } + } + break; + #ifdef RGB_MATRIX_ENABLE + #ifdef NKRO_ENABLE case NK_TOGG: if (record->event.pressed) { if (keymap_config.nkro) { /* Turning NKRO OFF */ - effect_red(); + start_effects(EFFECTS_DURATION, RGB_RED, flashing_effect); } else { /* Turning NKRO ON */ - effect_green(); + start_effects(EFFECTS_DURATION, RGB_GREEN, flashing_effect); } - start_effects(); } break; - #endif // NKRO_ENABLE + #endif // NKRO_ENABLE case RGB_MOD: case RGB_RMOD: case RGB_HUI: @@ -192,99 +314,171 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) { case RGB_VAD: case RGB_SPI: case RGB_SPD: - if (record->event.pressed) { - if (rgb_matrix_get_flags() != LED_FLAG_ALL) { - /* Ignore changes to RGB settings while only it's supposed to be OFF */ - return false; // Skip all further processing of this key - } + if (!user_config.rgb_enabled) { + /* Ignore changes to RGB settings while only it's supposed to be OFF */ + return false; // Skip all further processing of this key } break; case RGB_TOG: if (record->event.pressed) { - if (rgb_matrix_is_enabled()) { - switch (rgb_matrix_get_flags()) { - case LED_FLAG_EFFECTS: - case LED_FLAG_CAPS: - /* Turned ON because of EFFECTS or CAPS, is actually OFF */ - /* Change to LED_FLAG_ALL to signal it's really ON */ - rgb_matrix_set_flags(LED_FLAG_ALL); - /* Will be re-enabled by the processing of the toggle */ - rgb_matrix_disable_noeeprom(); - break; - case LED_FLAG_ALL: - /* Is actually ON */ - if (effect_started_time > 0) { - /* Signal EFFECTS */ - rgb_matrix_set_flags(LED_FLAG_EFFECTS); - /* Will be re-enabled by the processing of the toggle */ - rgb_matrix_disable_noeeprom(); - } else - if (host_keyboard_led_state().caps_lock) { - /* Signal CAPS */ - rgb_matrix_set_flags(LED_FLAG_CAPS); - /* Will be re-enabled by the processing of the toggle */ - rgb_matrix_disable_noeeprom(); - } - break; - } - } + user_config.rgb_enabled = !user_config.rgb_enabled; + eeconfig_update_user(user_config.raw); } - break; - #endif // RGB_MATRIX_ENABLE + return false; + #endif // RGB_MATRIX_ENABLE } return true; } +static void start_delayed_press(const uint16_t delay, const uint16_t keycode) { + delayed_press_delay = delay; + delayed_press_keycode = keycode; + delayed_press_start_time = sync_timer_read(); + delayed_press_sent_keycode = KC_NO; +} + +static bool is_any_delayed_press_pending(void) { + return delayed_press_start_time > 0 && delayed_press_keycode != KC_NO; +} + +static bool is_delayed_press_pending(const uint16_t keycode) { + return delayed_press_start_time > 0 && delayed_press_keycode == keycode; +} + +static bool is_delayed_press_sent(const uint16_t keycode) { + return delayed_press_sent_keycode != KC_NO && delayed_press_sent_keycode == keycode; +} + +static void mark_delayed_press_sent(void) { + delayed_press_sent_keycode = delayed_press_keycode; + cancel_delayed_press(); +} + +static void mark_delayed_release_sent(void) { + delayed_press_sent_keycode = KC_NO; +} + +static void cancel_delayed_press(void) { + delayed_press_delay = 0; + delayed_press_keycode = KC_NO; + delayed_press_start_time = 0; + #ifdef RGB_MATRIX_ENABLE + stop_effects(); + #endif +} + #ifdef RGB_MATRIX_ENABLE + +static void start_delayed_press_with_effects( + const uint16_t delay, + const uint16_t keycode, + const uint8_t r_color, + const uint8_t g_color, + const uint8_t b_color) { + start_delayed_press(delay, keycode); + start_effects(delay, r_color, g_color, b_color, increasing_effect); +} + +/* +Effects when switching layers +*/ + +static uint8_t previous_layer = UINT8_MAX; + +layer_state_t default_layer_state_set_user(layer_state_t state) { + const uint8_t current_layer = get_highest_layer(state); + if (previous_layer != current_layer) { + // For some reason, setting the default layer alone doesn't change it fully + layer_move(current_layer); + switch (current_layer) { + case WIN_BASE: + start_effects(EFFECTS_DURATION, WIN_BASE_COLOR, flashing_effect); + break; + case MAC_BASE: + start_effects(EFFECTS_DURATION, MAC_BASE_COLOR, flashing_effect); + break; + default: + // This should not ever happen, but let's display something if it does! + start_effects(EFFECTS_DURATION, UNKNOWN_LAYER_COLOR, static_effect); + break; + } + previous_layer = current_layer; + } + return state; +} + +static void start_effects( + const uint16_t max_duration, + const uint8_t r_color, + const uint8_t g_color, + const uint8_t b_color, + const float (*multiplier)(const uint16_t)) { + effect_r = r_color; + effect_g = g_color; + effect_b = b_color; + effect_multiplier = multiplier; + effect_max_duration = max_duration; + effect_started_time = sync_timer_read(); +} + +static void stop_effects(void) { + effect_r = 0x0; + effect_g = 0x0; + effect_b = 0x0; + effect_multiplier = static_effect; + effect_max_duration = EFFECTS_DURATION; + effect_started_time = 0; +} + +static float flashing_effect(const uint16_t delta_time) { + return ((delta_time / FLASHING_EFFECT_INTERVAL) + 1) & 0x01; +} + +static float static_effect(const uint16_t delta_time) { + return 1.0; +} + +static float increasing_effect(const uint16_t delta_time) { + return MAX(0.0, MIN(1.0, ((float) delta_time) / effect_max_duration)); +} + bool rgb_matrix_indicators_user(void) { if (effect_started_time > 0) { - /* Render blinking EFFECTS */ - const uint16_t deltaTime = sync_timer_elapsed(effect_started_time); - if (deltaTime <= EFFECTS_TIME) { - const uint8_t led_state = ((deltaTime / EFFECTS_INTERVAL) + 1) & 0x01; - const uint8_t val_r = led_state * r_effect; - const uint8_t val_g = led_state * g_effect; - const uint8_t val_b = led_state * b_effect; + const uint16_t delta_time = sync_timer_elapsed(effect_started_time); + if (delta_time <= effect_max_duration) { + /* Render effect */ + const float multiplier = effect_multiplier(delta_time); + const uint8_t val_r = multiplier * effect_r; + const uint8_t val_g = multiplier * effect_g; + const uint8_t val_b = multiplier * effect_b; rgb_matrix_set_color_all(val_r, val_g, val_b); - if (host_keyboard_led_state().caps_lock) { - set_rgb_caps_leds(); - } return false; } else { - /* EFFECTS duration is finished */ - effect_started_time = 0; - if (rgb_matrix_get_flags() == LED_FLAG_EFFECTS) { - /* It was turned ON because of EFFECTS */ - if (host_keyboard_led_state().caps_lock) { - /* CAPS is still ON. Demote to CAPS */ - rgb_matrix_set_flags(LED_FLAG_CAPS); - } else { - /* There is nothing else keeping RGB enabled. Reset flags and turn if off. */ - rgb_matrix_set_flags(LED_FLAG_ALL); - rgb_matrix_disable_noeeprom(); - } - } + /* Effect duration is finished */ + stop_effects(); } } - if (rgb_matrix_get_flags() == LED_FLAG_CAPS) { - rgb_matrix_set_color_all(0x0, 0x0, 0x0); - } if (host_keyboard_led_state().caps_lock) { - set_rgb_caps_leds(); + rgb_matrix_set_color_all(CAPS_LOCK_COLOR); + } else if (!user_config.rgb_enabled) { + rgb_matrix_set_color_all(RGB_OFF); } - return false; -} - -static void start_effects(void) { - effect_started_time = sync_timer_read(); - if (!rgb_matrix_is_enabled()) { - /* Turn it ON, signal the cause (EFFECTS) */ - rgb_matrix_set_flags(LED_FLAG_EFFECTS); - rgb_matrix_enable_noeeprom(); - } else if (rgb_matrix_get_flags() == LED_FLAG_CAPS) { - /* It's already ON, promote the cause from CAPS to EFFECTS */ - rgb_matrix_set_flags(LED_FLAG_EFFECTS); + switch (get_highest_layer(layer_state)) { + case WIN_BASE: + case MAC_BASE: + break; + case WIN_FN: + set_rgb_layer_winfn(); + return false; + case MAC_FN: + set_rgb_layer_macfn(); + return false; + default: + // This should never happen, but if it does, let's display something! + rgb_matrix_set_color_all(UNKNOWN_LAYER_COLOR); + return false; } + return true; } // RGB led number layout, function of the key @@ -298,38 +492,69 @@ static void start_effects(void) { // 87, led 07 88, led 18 // 91, led 08 92, led 19 -static void set_rgb_caps_leds(void) { - rgb_matrix_set_color(0, 0xFF, 0x0, 0x0); // ESC - rgb_matrix_set_color(6, 0xFF, 0x0, 0x0); // F1 - rgb_matrix_set_color(12, 0xFF, 0x0, 0x0); // F2 - rgb_matrix_set_color(18, 0xFF, 0x0, 0x0); // F3 - rgb_matrix_set_color(23, 0xFF, 0x0, 0x0); // F4 - rgb_matrix_set_color(28, 0xFF, 0x0, 0x0); // F5 - rgb_matrix_set_color(34, 0xFF, 0x0, 0x0); // F6 - rgb_matrix_set_color(39, 0xFF, 0x0, 0x0); // F7 - rgb_matrix_set_color(44, 0xFF, 0x0, 0x0); // F8 - rgb_matrix_set_color(50, 0xFF, 0x0, 0x0); // F9 - rgb_matrix_set_color(56, 0xFF, 0x0, 0x0); // F10 - rgb_matrix_set_color(61, 0xFF, 0x0, 0x0); // F11 - rgb_matrix_set_color(66, 0xFF, 0x0, 0x0); // F12 - rgb_matrix_set_color(69, 0xFF, 0x0, 0x0); // Prt - rgb_matrix_set_color(67, 0xFF, 0x0, 0x0); // Left side LED 1 - rgb_matrix_set_color(68, 0xFF, 0x0, 0x0); // Right side LED 1 - rgb_matrix_set_color(70, 0xFF, 0x0, 0x0); // Left side LED 2 - rgb_matrix_set_color(71, 0xFF, 0x0, 0x0); // Right side LED 2 - rgb_matrix_set_color(73, 0xFF, 0x0, 0x0); // Left side LED 3 - rgb_matrix_set_color(74, 0xFF, 0x0, 0x0); // Right side LED 3 - rgb_matrix_set_color(76, 0xFF, 0x0, 0x0); // Left side LED 4 - rgb_matrix_set_color(77, 0xFF, 0x0, 0x0); // Right side LED 4 - rgb_matrix_set_color(80, 0xFF, 0x0, 0x0); // Left side LED 5 - rgb_matrix_set_color(81, 0xFF, 0x0, 0x0); // Right side LED 5 - rgb_matrix_set_color(83, 0xFF, 0x0, 0x0); // Left side LED 6 - rgb_matrix_set_color(84, 0xFF, 0x0, 0x0); // Right side LED 6 - rgb_matrix_set_color(87, 0xFF, 0x0, 0x0); // Left side LED 7 - rgb_matrix_set_color(88, 0xFF, 0x0, 0x0); // Right side LED 7 - rgb_matrix_set_color(91, 0xFF, 0x0, 0x0); // Left side LED 8 - rgb_matrix_set_color(92, 0xFF, 0x0, 0x0); // Right side LED 8 - rgb_matrix_set_color(3, 0xFF, 0x0, 0x0); // CAPS LED +static void set_rgb_layer_winfn(void) { + rgb_matrix_set_color(0, WIN_FN_COLOR); + rgb_matrix_set_color(6, WIN_FN_COLOR); + rgb_matrix_set_color(12, WIN_FN_COLOR); + rgb_matrix_set_color(18, WIN_FN_COLOR); + rgb_matrix_set_color(23, WIN_FN_COLOR); + rgb_matrix_set_color(28, WIN_FN_COLOR); + rgb_matrix_set_color(34, WIN_FN_COLOR); + rgb_matrix_set_color(39, WIN_FN_COLOR); + rgb_matrix_set_color(44, WIN_FN_COLOR); + rgb_matrix_set_color(50, WIN_FN_COLOR); + rgb_matrix_set_color(56, WIN_FN_COLOR); + rgb_matrix_set_color(61, WIN_FN_COLOR); + rgb_matrix_set_color(66, WIN_FN_COLOR); + rgb_matrix_set_color(2, WIN_FN_COLOR); + rgb_matrix_set_color(3, WIN_FN_COLOR); + rgb_matrix_set_color(8, WIN_FN_COLOR); + rgb_matrix_set_color(9, WIN_FN_COLOR); + rgb_matrix_set_color(14, WIN_FN_COLOR); + rgb_matrix_set_color(15, WIN_FN_COLOR); + rgb_matrix_set_color(20, WIN_FN_COLOR); + rgb_matrix_set_color(21, WIN_FN_COLOR); + rgb_matrix_set_color(25, WIN_FN_COLOR); + rgb_matrix_set_color(26, WIN_FN_COLOR); + rgb_matrix_set_color(38, WIN_FN_COLOR); + rgb_matrix_set_color(93, WIN_FN_COLOR); + rgb_matrix_set_color(72, WIN_FN_COLOR); + rgb_matrix_set_color(75, WIN_FN_COLOR); + rgb_matrix_set_color(86, WIN_FN_COLOR); + rgb_matrix_set_color(82, WIN_FN_COLOR); +} + +static void set_rgb_layer_macfn(void) { + rgb_matrix_set_color(0, MAC_FN_COLOR); + rgb_matrix_set_color(6, MAC_FN_COLOR); + rgb_matrix_set_color(12, MAC_FN_COLOR); + rgb_matrix_set_color(18, MAC_FN_COLOR); + rgb_matrix_set_color(23, MAC_FN_COLOR); + rgb_matrix_set_color(28, MAC_FN_COLOR); + rgb_matrix_set_color(34, MAC_FN_COLOR); + rgb_matrix_set_color(39, MAC_FN_COLOR); + rgb_matrix_set_color(44, MAC_FN_COLOR); + rgb_matrix_set_color(50, MAC_FN_COLOR); + rgb_matrix_set_color(56, MAC_FN_COLOR); + rgb_matrix_set_color(61, MAC_FN_COLOR); + rgb_matrix_set_color(66, MAC_FN_COLOR); + rgb_matrix_set_color(2, MAC_FN_COLOR); + rgb_matrix_set_color(3, MAC_FN_COLOR); + rgb_matrix_set_color(8, MAC_FN_COLOR); + rgb_matrix_set_color(9, MAC_FN_COLOR); + rgb_matrix_set_color(14, MAC_FN_COLOR); + rgb_matrix_set_color(15, MAC_FN_COLOR); + rgb_matrix_set_color(20, MAC_FN_COLOR); + rgb_matrix_set_color(21, MAC_FN_COLOR); + rgb_matrix_set_color(25, MAC_FN_COLOR); + rgb_matrix_set_color(26, MAC_FN_COLOR); + rgb_matrix_set_color(38, MAC_FN_COLOR); + rgb_matrix_set_color(93, MAC_FN_COLOR); + rgb_matrix_set_color(72, MAC_FN_COLOR); + rgb_matrix_set_color(75, MAC_FN_COLOR); + rgb_matrix_set_color(86, MAC_FN_COLOR); + rgb_matrix_set_color(82, MAC_FN_COLOR); + rgb_matrix_set_color(17, MAC_FN_COLOR); } #endif // RGB_MATRIX_ENABLE diff --git a/keyboards/gmmk/pro/rev1/ansi/keymaps/andrebrait/readme.md b/keyboards/gmmk/pro/rev1/ansi/keymaps/andrebrait/readme.md index b080f02c6b35..2b21bd2821f7 100644 --- a/keyboards/gmmk/pro/rev1/ansi/keymaps/andrebrait/readme.md +++ b/keyboards/gmmk/pro/rev1/ansi/keymaps/andrebrait/readme.md @@ -7,15 +7,23 @@ The differences are as follows: - Dedicated MacOS and Windows/Linux layers - Switching between them by pressing Fn + CAPS LOCK +- VIA support - Disabled Mouse Keys (to fix issues with KVM switches and also because they're not used here anyway) - RGB turns off after 20 minutes of inactivity - RGB turns off when USB is suspended - Layer 0: - - Print Screen (default) -> Delete - - Delete (default) -> Home + - Delete -> Insert + - Page Up -> Delete + - Page Down -> Home - Layer 1 (accessed by pressing Fn): - - Fn + Delete -> Insert - - Fn + Home -> Print Screen + - Fn + Insert -> Pause + - Fn + Delete -> Scroll Lock + - Fn + Esc -> Clear EEPROM + - Fn + (Left) CMD (macOS layout) -> Toggle the CMD + Q delay + +On the Mac layer, pressing CMD + Q will not immediately send the combination.\ +There's a configurable delay (defaults to 1 second) to send it.\ +This is done mainly to prevent hitting CMD + Q by mistake when alternating between applications with CMD + Tab. This keymap also includes CAPS LOCK ON indicator.\ All left and right side LEDs, and the Caps key LED will turn solid red while CAPS LOCK is ON. diff --git a/keyboards/gmmk/pro/rev1/ansi/keymaps/andrebrait/rules.mk b/keyboards/gmmk/pro/rev1/ansi/keymaps/andrebrait/rules.mk index d5942a2e904d..d095a6015482 100644 --- a/keyboards/gmmk/pro/rev1/ansi/keymaps/andrebrait/rules.mk +++ b/keyboards/gmmk/pro/rev1/ansi/keymaps/andrebrait/rules.mk @@ -3,21 +3,17 @@ # Disabling MouseKey because it breaks my KVM switch MOUSEKEY_ENABLE = no -# Cherry MX-style switches and diodes are not susceptible to noise, no need for noise-resistant algorithms. -# This significantly reduces latency. -# -# The matrix scan frequency seems to be around 1820 Hz, so even sym_defer_g would perform ok, -# but the "defer" part would mean we would wait DEBOUNCE ms before sending any events. -# Using "asym_eager_defer_pk" does not seem to benefit us in anything. -# The GMMK Pro has more then enough system resources for a per-key algorithm. -# Using an "eager" algorithm leads to extremely low latency while also reducing the chances of chattering -# due to it's "post-event" debouncing (of sorts). -# -# I have observed zero chattering or double-keypress issues on my Gateron Yellow switches. -# Most chattering issues on the GMMK Pro seem to be related to its proprietary hot-swap sockets anyway. -DEBOUNCE_TYPE = sym_eager_pk +# Ensure sym_defer_g is used. +# It seems sym_defer_pk results in significant chattering, even with an 8ms debounce time. +DEBOUNCE_TYPE = sym_defer_g # Useful for debugging # CONSOLE_ENABLE = yes # DEBUG_MATRIX_SCAN_RATE_ENABLE = yes # DEBUG_MATRIX_SCAN_RATE = yes + +# Encoder Map support +ENCODER_MAP_ENABLE = yes + +# Enables VIA +VIA_ENABLE = yes