diff options
Diffstat (limited to 'quantum')
56 files changed, 2348 insertions, 885 deletions
| diff --git a/quantum/bootmagic/bootmagic.h b/quantum/bootmagic/bootmagic.h new file mode 100644 index 0000000000..959750178d --- /dev/null +++ b/quantum/bootmagic/bootmagic.h @@ -0,0 +1,24 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 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 <http://www.gnu.org/licenses/>. + */ +#pragma once + +#if defined(BOOTMAGIC_ENABLE) +#    include "bootmagic_full.h" +#elif defined(BOOTMAGIC_LITE) +#    include "bootmagic_lite.h" +#endif + +void bootmagic(void); diff --git a/quantum/bootmagic/bootmagic_full.c b/quantum/bootmagic/bootmagic_full.c new file mode 100644 index 0000000000..a7a0dcfcb2 --- /dev/null +++ b/quantum/bootmagic/bootmagic_full.c @@ -0,0 +1,147 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 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 <http://www.gnu.org/licenses/>. + */ +#include <stdint.h> +#include <stdbool.h> +#include "wait.h" +#include "matrix.h" +#include "bootloader.h" +#include "debug.h" +#include "keymap.h" +#include "host.h" +#include "action_layer.h" +#include "eeconfig.h" +#include "bootmagic.h" + +/** \brief Scan Keycode + * + * FIXME: needs doc + */ +static bool scan_keycode(uint8_t keycode) { +    for (uint8_t r = 0; r < MATRIX_ROWS; r++) { +        matrix_row_t matrix_row = matrix_get_row(r); +        for (uint8_t c = 0; c < MATRIX_COLS; c++) { +            if (matrix_row & ((matrix_row_t)1 << c)) { +                if (keycode == keymap_key_to_keycode(0, (keypos_t){.row = r, .col = c})) { +                    return true; +                } +            } +        } +    } +    return false; +} + +/** \brief Bootmagic Scan Keycode + * + * FIXME: needs doc + */ +static bool bootmagic_scan_keycode(uint8_t keycode) { +    if (!scan_keycode(BOOTMAGIC_KEY_SALT)) return false; + +    return scan_keycode(keycode); +} + +void bootmagic(void) { +    /* do scans in case of bounce */ +    print("bootmagic scan: ... "); +    uint8_t scan = 100; +    while (scan--) { +        matrix_scan(); +        wait_ms(10); +    } +    print("done.\n"); + +    /* bootmagic skip */ +    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SKIP)) { +        return; +    } + +    /* eeconfig clear */ +    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_EEPROM_CLEAR)) { +        eeconfig_init(); +    } + +    /* bootloader */ +    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_BOOTLOADER)) { +        bootloader_jump(); +    } + +    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEBUG_ENABLE)) { +        if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEBUG_MATRIX)) { +            debug_config.matrix = !debug_config.matrix; +        } else if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEBUG_KEYBOARD)) { +            debug_config.keyboard = !debug_config.keyboard; +        } else if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEBUG_MOUSE)) { +            debug_config.mouse = !debug_config.mouse; +        } else { +            debug_config.enable = !debug_config.enable; +        } +    } +    eeconfig_update_debug(debug_config.raw); + +    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SWAP_CONTROL_CAPSLOCK)) { +        keymap_config.swap_control_capslock = !keymap_config.swap_control_capslock; +    } +    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_CAPSLOCK_TO_CONTROL)) { +        keymap_config.capslock_to_control = !keymap_config.capslock_to_control; +    } +    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SWAP_LALT_LGUI)) { +        keymap_config.swap_lalt_lgui = !keymap_config.swap_lalt_lgui; +    } +    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SWAP_RALT_RGUI)) { +        keymap_config.swap_ralt_rgui = !keymap_config.swap_ralt_rgui; +    } +    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_NO_GUI)) { +        keymap_config.no_gui = !keymap_config.no_gui; +    } +    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SWAP_GRAVE_ESC)) { +        keymap_config.swap_grave_esc = !keymap_config.swap_grave_esc; +    } +    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SWAP_BACKSLASH_BACKSPACE)) { +        keymap_config.swap_backslash_backspace = !keymap_config.swap_backslash_backspace; +    } +    if (bootmagic_scan_keycode(BOOTMAGIC_HOST_NKRO)) { +        keymap_config.nkro = !keymap_config.nkro; +    } +    eeconfig_update_keymap(keymap_config.raw); + +    /* default layer */ +    uint8_t default_layer = 0; +    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_0)) { +        default_layer |= (1 << 0); +    } else if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_1)) { +        default_layer |= (1 << 1); +    } else if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_2)) { +        default_layer |= (1 << 2); +    } else if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_3)) { +        default_layer |= (1 << 3); +    } else if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_4)) { +        default_layer |= (1 << 4); +    } else if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_5)) { +        default_layer |= (1 << 5); +    } else if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_6)) { +        default_layer |= (1 << 6); +    } else if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_7)) { +        default_layer |= (1 << 7); +    } +    eeconfig_update_default_layer(default_layer); + +    /* EE_HANDS handedness */ +    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_EE_HANDS_LEFT)) { +        eeconfig_update_handedness(true); +    } else if (bootmagic_scan_keycode(BOOTMAGIC_KEY_EE_HANDS_RIGHT)) { +        eeconfig_update_handedness(false); +    } +} diff --git a/quantum/bootmagic/bootmagic_full.h b/quantum/bootmagic/bootmagic_full.h new file mode 100644 index 0000000000..28f914c1b6 --- /dev/null +++ b/quantum/bootmagic/bootmagic_full.h @@ -0,0 +1,115 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 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 <http://www.gnu.org/licenses/>. + */ + +#pragma once + +/* FIXME: Add special doxygen comments for defines here. */ + +/* bootmagic salt key */ +#ifndef BOOTMAGIC_KEY_SALT +#    define BOOTMAGIC_KEY_SALT KC_SPACE +#endif + +/* skip bootmagic and eeconfig */ +#ifndef BOOTMAGIC_KEY_SKIP +#    define BOOTMAGIC_KEY_SKIP KC_ESC +#endif + +/* eeprom clear */ +#ifndef BOOTMAGIC_KEY_EEPROM_CLEAR +#    define BOOTMAGIC_KEY_EEPROM_CLEAR KC_BSPACE +#endif + +/* kick up bootloader */ +#ifndef BOOTMAGIC_KEY_BOOTLOADER +#    define BOOTMAGIC_KEY_BOOTLOADER KC_B +#endif + +/* debug enable */ +#ifndef BOOTMAGIC_KEY_DEBUG_ENABLE +#    define BOOTMAGIC_KEY_DEBUG_ENABLE KC_D +#endif +#ifndef BOOTMAGIC_KEY_DEBUG_MATRIX +#    define BOOTMAGIC_KEY_DEBUG_MATRIX KC_X +#endif +#ifndef BOOTMAGIC_KEY_DEBUG_KEYBOARD +#    define BOOTMAGIC_KEY_DEBUG_KEYBOARD KC_K +#endif +#ifndef BOOTMAGIC_KEY_DEBUG_MOUSE +#    define BOOTMAGIC_KEY_DEBUG_MOUSE KC_M +#endif +#ifndef BOOTMAGIC_KEY_EE_HANDS_LEFT +#    define BOOTMAGIC_KEY_EE_HANDS_LEFT KC_L +#endif +#ifndef BOOTMAGIC_KEY_EE_HANDS_RIGHT +#    define BOOTMAGIC_KEY_EE_HANDS_RIGHT KC_R +#endif + +/* + * keymap config + */ +#ifndef BOOTMAGIC_KEY_SWAP_CONTROL_CAPSLOCK +#    define BOOTMAGIC_KEY_SWAP_CONTROL_CAPSLOCK KC_LCTRL +#endif +#ifndef BOOTMAGIC_KEY_CAPSLOCK_TO_CONTROL +#    define BOOTMAGIC_KEY_CAPSLOCK_TO_CONTROL KC_CAPSLOCK +#endif +#ifndef BOOTMAGIC_KEY_SWAP_LALT_LGUI +#    define BOOTMAGIC_KEY_SWAP_LALT_LGUI KC_LALT +#endif +#ifndef BOOTMAGIC_KEY_SWAP_RALT_RGUI +#    define BOOTMAGIC_KEY_SWAP_RALT_RGUI KC_RALT +#endif +#ifndef BOOTMAGIC_KEY_NO_GUI +#    define BOOTMAGIC_KEY_NO_GUI KC_LGUI +#endif +#ifndef BOOTMAGIC_KEY_SWAP_GRAVE_ESC +#    define BOOTMAGIC_KEY_SWAP_GRAVE_ESC KC_GRAVE +#endif +#ifndef BOOTMAGIC_KEY_SWAP_BACKSLASH_BACKSPACE +#    define BOOTMAGIC_KEY_SWAP_BACKSLASH_BACKSPACE KC_BSLASH +#endif +#ifndef BOOTMAGIC_HOST_NKRO +#    define BOOTMAGIC_HOST_NKRO KC_N +#endif + +/* + * change default layer + */ +#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_0 +#    define BOOTMAGIC_KEY_DEFAULT_LAYER_0 KC_0 +#endif +#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_1 +#    define BOOTMAGIC_KEY_DEFAULT_LAYER_1 KC_1 +#endif +#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_2 +#    define BOOTMAGIC_KEY_DEFAULT_LAYER_2 KC_2 +#endif +#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_3 +#    define BOOTMAGIC_KEY_DEFAULT_LAYER_3 KC_3 +#endif +#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_4 +#    define BOOTMAGIC_KEY_DEFAULT_LAYER_4 KC_4 +#endif +#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_5 +#    define BOOTMAGIC_KEY_DEFAULT_LAYER_5 KC_5 +#endif +#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_6 +#    define BOOTMAGIC_KEY_DEFAULT_LAYER_6 KC_6 +#endif +#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_7 +#    define BOOTMAGIC_KEY_DEFAULT_LAYER_7 KC_7 +#endif
\ No newline at end of file diff --git a/quantum/bootmagic/bootmagic_lite.c b/quantum/bootmagic/bootmagic_lite.c new file mode 100644 index 0000000000..9cbdcb0bbd --- /dev/null +++ b/quantum/bootmagic/bootmagic_lite.c @@ -0,0 +1,66 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 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 <http://www.gnu.org/licenses/>. + */ +#include "quantum.h" + +/** \brief Reset eeprom + * + * ...just incase someone wants to only change the eeprom behaviour + */ +__attribute__((weak)) void bootmagic_lite_reset_eeprom(void) { +#if defined(VIA_ENABLE) +    via_eeprom_reset(); +#else +    eeconfig_disable(); +#endif +} + +/** \brief The lite version of TMK's bootmagic based on Wilba. + * + *  100% less potential for accidentally making the keyboard do stupid things. + */ +__attribute__((weak)) void bootmagic_lite(void) { +    // We need multiple scans because debouncing can't be turned off. +    matrix_scan(); +#if defined(DEBOUNCE) && DEBOUNCE > 0 +    wait_ms(DEBOUNCE * 2); +#else +    wait_ms(30); +#endif +    matrix_scan(); + +    // If the configured key (commonly Esc) is held down on power up, +    // reset the EEPROM valid state and jump to bootloader. +    // This isn't very generalized, but we need something that doesn't +    // rely on user's keymaps in firmware or EEPROM. +    uint8_t row = BOOTMAGIC_LITE_ROW; +    uint8_t col = BOOTMAGIC_LITE_COLUMN; + +#if defined(SPLIT_KEYBOARD) && defined(BOOTMAGIC_LITE_ROW_RIGHT) && defined(BOOTMAGIC_LITE_COLUMN_RIGHT) +    if (!is_keyboard_left()) { +        row = BOOTMAGIC_LITE_ROW_RIGHT; +        col = BOOTMAGIC_LITE_COLUMN_RIGHT; +    } +#endif + +    if (matrix_get_row(row) & (1 << col)) { +        bootmagic_lite_reset_eeprom(); + +        // Jump to bootloader. +        bootloader_jump(); +    } +} + +void bootmagic(void) { bootmagic_lite(); } diff --git a/quantum/bootmagic/bootmagic_lite.h b/quantum/bootmagic/bootmagic_lite.h new file mode 100644 index 0000000000..17777e6b4a --- /dev/null +++ b/quantum/bootmagic/bootmagic_lite.h @@ -0,0 +1,25 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 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 <http://www.gnu.org/licenses/>. + */ +#pragma once + +#ifndef BOOTMAGIC_LITE_COLUMN +#    define BOOTMAGIC_LITE_COLUMN 0 +#endif +#ifndef BOOTMAGIC_LITE_ROW +#    define BOOTMAGIC_LITE_ROW 0 +#endif + +void bootmagic_lite(void); diff --git a/quantum/bootmagic/magic.c b/quantum/bootmagic/magic.c new file mode 100644 index 0000000000..f1cb11c395 --- /dev/null +++ b/quantum/bootmagic/magic.c @@ -0,0 +1,54 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 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 <http://www.gnu.org/licenses/>. + */ +#include <stdint.h> +#include <stdbool.h> +#include "wait.h" +#include "matrix.h" +#include "bootloader.h" +#include "debug.h" +#include "keymap.h" +#include "host.h" +#include "action_layer.h" +#include "eeconfig.h" +#include "bootmagic.h" + +keymap_config_t keymap_config; + +__attribute__((weak)) void bootmagic(void) {} + +/** \brief Magic + * + * FIXME: Needs doc + */ +void magic(void) { +    /* check signature */ +    if (!eeconfig_is_enabled()) { +        eeconfig_init(); +    } + +    /* init globals */ +    debug_config.raw  = eeconfig_read_debug(); +    keymap_config.raw = eeconfig_read_keymap(); + +    bootmagic(); + +    /* read here just incase bootmagic process changed its value */ +    layer_state_t default_layer = (layer_state_t)eeconfig_read_default_layer(); +    default_layer_set(default_layer); + +    /* Also initialize layer state to trigger callback functions for layer_state */ +    layer_state_set_kb((layer_state_t)layer_state); +} diff --git a/quantum/bootmagic/magic.h b/quantum/bootmagic/magic.h new file mode 100644 index 0000000000..2c3969b85c --- /dev/null +++ b/quantum/bootmagic/magic.h @@ -0,0 +1,18 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 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 <http://www.gnu.org/licenses/>. + */ +#pragma once + +void magic(void); diff --git a/quantum/config_common.h b/quantum/config_common.h index d93477b27e..661609ef2a 100644 --- a/quantum/config_common.h +++ b/quantum/config_common.h @@ -24,4 +24,7 @@  #define COL2ROW 0  #define ROW2COL 1 +// Deprecated alias - avoid using +#define KEYMAP LAYOUT +  #include "song_list.h" diff --git a/quantum/keycode_config.h b/quantum/keycode_config.h index f878168c5f..d7e334fdc8 100644 --- a/quantum/keycode_config.h +++ b/quantum/keycode_config.h @@ -37,6 +37,7 @@ typedef union {          bool nkro : 1;          bool swap_lctl_lgui : 1;          bool swap_rctl_rgui : 1; +        bool oneshot_disable : 1;      };  } keymap_config_t; diff --git a/quantum/led_matrix.c b/quantum/led_matrix.c index 4f1f06c7ac..d612fbfa9d 100644 --- a/quantum/led_matrix.c +++ b/quantum/led_matrix.c @@ -17,79 +17,143 @@   * along with this program.  If not, see <http://www.gnu.org/licenses/>.   */ -#include <stdint.h> -#include <stdbool.h> -#include "quantum.h"  #include "led_matrix.h"  #include "progmem.h"  #include "config.h"  #include "eeprom.h"  #include <string.h>  #include <math.h> +#include "led_tables.h" -led_eeconfig_t led_matrix_eeconfig; +#include <lib/lib8tion/lib8tion.h> -#ifndef MAX -#    define MAX(X, Y) ((X) > (Y) ? (X) : (Y)) +#ifndef LED_MATRIX_CENTER +const led_point_t k_led_matrix_center = {112, 32}; +#else +const led_point_t k_led_matrix_center = LED_MATRIX_CENTER;  #endif -#ifndef MIN -#    define MIN(a, b) ((a) < (b) ? (a) : (b)) +// Generic effect runners +#include "led_matrix_runners/effect_runner_dx_dy_dist.h" +#include "led_matrix_runners/effect_runner_dx_dy.h" +#include "led_matrix_runners/effect_runner_i.h" +#include "led_matrix_runners/effect_runner_sin_cos_i.h" +#include "led_matrix_runners/effect_runner_reactive.h" +#include "led_matrix_runners/effect_runner_reactive_splash.h" + +// ------------------------------------------ +// -----Begin led effect includes macros----- +#define LED_MATRIX_EFFECT(name) +#define LED_MATRIX_CUSTOM_EFFECT_IMPLS + +#include "led_matrix_animations/led_matrix_effects.inc" +#ifdef LED_MATRIX_CUSTOM_KB +#    include "led_matrix_kb.inc"  #endif +#ifdef LED_MATRIX_CUSTOM_USER +#    include "led_matrix_user.inc" +#endif + +#undef LED_MATRIX_CUSTOM_EFFECT_IMPLS +#undef LED_MATRIX_EFFECT +// -----End led effect includes macros------- +// ------------------------------------------ -#ifndef LED_DISABLE_AFTER_TIMEOUT -#    define LED_DISABLE_AFTER_TIMEOUT 0 +#if defined(LED_DISABLE_AFTER_TIMEOUT) && !defined(LED_DISABLE_TIMEOUT) +#    define LED_DISABLE_TIMEOUT (LED_DISABLE_AFTER_TIMEOUT * 1200UL)  #endif -#ifndef LED_DISABLE_WHEN_USB_SUSPENDED -#    define LED_DISABLE_WHEN_USB_SUSPENDED false +#ifndef LED_DISABLE_TIMEOUT +#    define LED_DISABLE_TIMEOUT 0  #endif -#ifndef EECONFIG_LED_MATRIX -#    define EECONFIG_LED_MATRIX EECONFIG_RGBLIGHT +#if LED_DISABLE_WHEN_USB_SUSPENDED == false +#    undef LED_DISABLE_WHEN_USB_SUSPENDED  #endif -#if !defined(LED_MATRIX_MAXIMUM_BRIGHTNESS) || LED_MATRIX_MAXIMUM_BRIGHTNESS > 255 -#    define LED_MATRIX_MAXIMUM_BRIGHTNESS 255 +#if !defined(LED_MATRIX_MAXIMUM_BRIGHTNESS) || LED_MATRIX_MAXIMUM_BRIGHTNESS > UINT8_MAX +#    undef LED_MATRIX_MAXIMUM_BRIGHTNESS +#    define LED_MATRIX_MAXIMUM_BRIGHTNESS UINT8_MAX  #endif -bool g_suspend_state = false; +#if !defined(LED_MATRIX_VAL_STEP) +#    define LED_MATRIX_VAL_STEP 8 +#endif -// Global tick at 20 Hz -uint32_t g_tick = 0; +#if !defined(LED_MATRIX_SPD_STEP) +#    define LED_MATRIX_SPD_STEP 16 +#endif -// Ticks since this key was last hit. -uint8_t g_key_hit[DRIVER_LED_TOTAL]; +#if !defined(LED_MATRIX_STARTUP_MODE) +#    define LED_MATRIX_STARTUP_MODE LED_MATRIX_SOLID +#endif -// Ticks since any key was last hit. -uint32_t g_any_key_hit = 0; +#if !defined(LED_MATRIX_STARTUP_VAL) +#    define LED_MATRIX_STARTUP_VAL LED_MATRIX_MAXIMUM_BRIGHTNESS +#endif -uint32_t eeconfig_read_led_matrix(void) { return eeprom_read_dword(EECONFIG_LED_MATRIX); } +#if !defined(LED_MATRIX_STARTUP_SPD) +#    define LED_MATRIX_STARTUP_SPD UINT8_MAX / 2 +#endif -void eeconfig_update_led_matrix(uint32_t config_value) { eeprom_update_dword(EECONFIG_LED_MATRIX, config_value); } +// globals +led_eeconfig_t led_matrix_eeconfig;  // TODO: would like to prefix this with g_ for global consistancy, do this in another pr +uint32_t       g_led_timer; +#ifdef LED_MATRIX_FRAMEBUFFER_EFFECTS +uint8_t g_led_frame_buffer[MATRIX_ROWS][MATRIX_COLS] = {{0}}; +#endif  // LED_MATRIX_FRAMEBUFFER_EFFECTS +#ifdef LED_MATRIX_KEYREACTIVE_ENABLED +last_hit_t g_last_hit_tracker; +#endif  // LED_MATRIX_KEYREACTIVE_ENABLED + +// internals +static bool            suspend_state     = false; +static uint8_t         led_last_enable   = UINT8_MAX; +static uint8_t         led_last_effect   = UINT8_MAX; +static effect_params_t led_effect_params = {0, LED_FLAG_ALL, false}; +static led_task_states led_task_state    = SYNCING; +#if LED_DISABLE_TIMEOUT > 0 +static uint32_t led_anykey_timer; +#endif  // LED_DISABLE_TIMEOUT > 0 + +// double buffers +static uint32_t led_timer_buffer; +#ifdef LED_MATRIX_KEYREACTIVE_ENABLED +static last_hit_t last_hit_buffer; +#endif  // LED_MATRIX_KEYREACTIVE_ENABLED + +// split led matrix +#if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) +const uint8_t k_led_matrix_split[2] = LED_MATRIX_SPLIT; +#endif + +void eeconfig_read_led_matrix(void) { eeprom_read_block(&led_matrix_eeconfig, EECONFIG_LED_MATRIX, sizeof(led_matrix_eeconfig)); } + +void eeconfig_update_led_matrix(void) { eeprom_update_block(&led_matrix_eeconfig, EECONFIG_LED_MATRIX, sizeof(led_matrix_eeconfig)); }  void eeconfig_update_led_matrix_default(void) {      dprintf("eeconfig_update_led_matrix_default\n");      led_matrix_eeconfig.enable = 1; -    led_matrix_eeconfig.mode   = LED_MATRIX_UNIFORM_BRIGHTNESS; -    led_matrix_eeconfig.val    = 128; -    led_matrix_eeconfig.speed  = 0; -    eeconfig_update_led_matrix(led_matrix_eeconfig.raw); +    led_matrix_eeconfig.mode   = LED_MATRIX_STARTUP_MODE; +    led_matrix_eeconfig.val    = LED_MATRIX_STARTUP_VAL; +    led_matrix_eeconfig.speed  = LED_MATRIX_STARTUP_SPD; +    led_matrix_eeconfig.flags  = LED_FLAG_ALL; +    eeconfig_update_led_matrix();  }  void eeconfig_debug_led_matrix(void) { -    dprintf("led_matrix_eeconfig eeprom\n"); +    dprintf("led_matrix_eeconfig EEPROM\n");      dprintf("led_matrix_eeconfig.enable = %d\n", led_matrix_eeconfig.enable);      dprintf("led_matrix_eeconfig.mode = %d\n", led_matrix_eeconfig.mode);      dprintf("led_matrix_eeconfig.val = %d\n", led_matrix_eeconfig.val);      dprintf("led_matrix_eeconfig.speed = %d\n", led_matrix_eeconfig.speed); +    dprintf("led_matrix_eeconfig.flags = %d\n", led_matrix_eeconfig.flags);  } -uint8_t g_last_led_hit[LED_HITS_TO_REMEMBER] = {255}; -uint8_t g_last_led_count                     = 0; +__attribute__((weak)) uint8_t led_matrix_map_row_column_to_led_kb(uint8_t row, uint8_t column, uint8_t *led_i) { return 0; } -uint8_t map_row_column_to_led(uint8_t row, uint8_t column, uint8_t *led_i) { -    uint8_t led_count = 0; +uint8_t led_matrix_map_row_column_to_led(uint8_t row, uint8_t column, uint8_t *led_i) { +    uint8_t led_count = led_matrix_map_row_column_to_led_kb(row, column, led_i);      uint8_t led_index = g_led_config.matrix_co[row][column];      if (led_index != NO_LED) {          led_i[led_count] = led_index; @@ -100,88 +164,235 @@ uint8_t map_row_column_to_led(uint8_t row, uint8_t column, uint8_t *led_i) {  void led_matrix_update_pwm_buffers(void) { led_matrix_driver.flush(); } -void led_matrix_set_index_value(int index, uint8_t value) { led_matrix_driver.set_value(index, value); } - -void led_matrix_set_index_value_all(uint8_t value) { led_matrix_driver.set_value_all(value); } - -bool process_led_matrix(uint16_t keycode, keyrecord_t *record) { -    if (record->event.pressed) { -        uint8_t led[8]; -        uint8_t led_count = map_row_column_to_led(record->event.key.row, record->event.key.col, led); -        if (led_count > 0) { -            for (uint8_t i = LED_HITS_TO_REMEMBER; i > 1; i--) { -                g_last_led_hit[i - 1] = g_last_led_hit[i - 2]; -            } -            g_last_led_hit[0] = led[0]; -            g_last_led_count  = MIN(LED_HITS_TO_REMEMBER, g_last_led_count + 1); -        } -        for (uint8_t i = 0; i < led_count; i++) g_key_hit[led[i]] = 0; -        g_any_key_hit = 0; -    } else { -#ifdef LED_MATRIX_KEYRELEASES -        uint8_t led[8]; -        uint8_t led_count = map_row_column_to_led(record->event.key.row, record->event.key.col, led); -        for (uint8_t i = 0; i < led_count; i++) g_key_hit[led[i]] = 255; +void led_matrix_set_value(int index, uint8_t value) { +#if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) +    if (!is_keyboard_left() && index >= k_led_matrix_split[0]) +#    ifdef USE_CIE1931_CURVE +        led_matrix_driver.set_value(index - k_led_matrix_split[0], pgm_read_byte(&CIE1931_CURVE[value])); +#    else +        led_matrix_driver.set_value(index - k_led_matrix_split[0], value); +#    endif +    else if (is_keyboard_left() && index < k_led_matrix_split[0]) +#endif +#ifdef USE_CIE1931_CURVE +        led_matrix_driver.set_value(index, pgm_read_byte(&CIE1931_CURVE[value])); +#else +    led_matrix_driver.set_value(index, value); +#endif +} -        g_any_key_hit = 255; +void led_matrix_set_value_all(uint8_t value) { +#if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) +    for (uint8_t i = 0; i < DRIVER_LED_TOTAL; i++) led_matrix_set_value(i, value); +#else +#    ifdef USE_CIE1931_CURVE +    led_matrix_driver.set_value_all(pgm_read_byte(&CIE1931_CURVE[value])); +#    else +    led_matrix_driver.set_value_all(value); +#    endif  #endif -    } -    return true;  } -void led_matrix_set_suspend_state(bool state) { g_suspend_state = state; } +void process_led_matrix(uint8_t row, uint8_t col, bool pressed) { +#ifndef LED_MATRIX_SPLIT +    if (!is_keyboard_master()) return; +#endif +#if LED_DISABLE_TIMEOUT > 0 +    led_anykey_timer = 0; +#endif  // LED_DISABLE_TIMEOUT > 0 -// All LEDs off -void led_matrix_all_off(void) { led_matrix_set_index_value_all(0); } +#ifdef LED_MATRIX_KEYREACTIVE_ENABLED +    uint8_t led[LED_HITS_TO_REMEMBER]; +    uint8_t led_count = 0; -// Uniform brightness -void led_matrix_uniform_brightness(void) { led_matrix_set_index_value_all(LED_MATRIX_MAXIMUM_BRIGHTNESS / BACKLIGHT_LEVELS * led_matrix_eeconfig.val); } +#    if defined(LED_MATRIX_KEYRELEASES) +    if (!pressed) +#    elif defined(LED_MATRIX_KEYPRESSES) +    if (pressed) +#    endif  // defined(LED_MATRIX_KEYRELEASES) +    { +        led_count = led_matrix_map_row_column_to_led(row, col, led); +    } -void led_matrix_custom(void) {} +    if (last_hit_buffer.count + led_count > LED_HITS_TO_REMEMBER) { +        memcpy(&last_hit_buffer.x[0], &last_hit_buffer.x[led_count], LED_HITS_TO_REMEMBER - led_count); +        memcpy(&last_hit_buffer.y[0], &last_hit_buffer.y[led_count], LED_HITS_TO_REMEMBER - led_count); +        memcpy(&last_hit_buffer.tick[0], &last_hit_buffer.tick[led_count], (LED_HITS_TO_REMEMBER - led_count) * 2);  // 16 bit +        memcpy(&last_hit_buffer.index[0], &last_hit_buffer.index[led_count], LED_HITS_TO_REMEMBER - led_count); +        last_hit_buffer.count--; +    } -void led_matrix_task(void) { -    if (!led_matrix_eeconfig.enable) { -        led_matrix_all_off(); -        led_matrix_indicators(); -        return; +    for (uint8_t i = 0; i < led_count; i++) { +        uint8_t index                = last_hit_buffer.count; +        last_hit_buffer.x[index]     = g_led_config.point[led[i]].x; +        last_hit_buffer.y[index]     = g_led_config.point[led[i]].y; +        last_hit_buffer.index[index] = led[i]; +        last_hit_buffer.tick[index]  = 0; +        last_hit_buffer.count++;      } +#endif  // LED_MATRIX_KEYREACTIVE_ENABLED -    g_tick++; +#if defined(LED_MATRIX_FRAMEBUFFER_EFFECTS) && !defined(DISABLE_LED_MATRIX_TYPING_HEATMAP) +    if (led_matrix_eeconfig.mode == LED_MATRIX_TYPING_HEATMAP) { +        process_led_matrix_typing_heatmap(row, col); +    } +#endif  // defined(LED_MATRIX_FRAMEBUFFER_EFFECTS) && !defined(DISABLE_LED_MATRIX_TYPING_HEATMAP) +} -    if (g_any_key_hit < 0xFFFFFFFF) { -        g_any_key_hit++; +static bool led_matrix_none(effect_params_t *params) { +    if (!params->init) { +        return false;      } -    for (int led = 0; led < DRIVER_LED_TOTAL; led++) { -        if (g_key_hit[led] < 255) { -            if (g_key_hit[led] == 254) g_last_led_count = MAX(g_last_led_count - 1, 0); -            g_key_hit[led]++; +    led_matrix_set_value_all(0); +    return false; +} + +static void led_task_timers(void) { +#if defined(LED_MATRIX_KEYREACTIVE_ENABLED) || LED_DISABLE_TIMEOUT > 0 +    uint32_t deltaTime = sync_timer_elapsed32(led_timer_buffer); +#endif  // defined(LED_MATRIX_KEYREACTIVE_ENABLED) || LED_DISABLE_TIMEOUT > 0 +    led_timer_buffer = sync_timer_read32(); + +    // Update double buffer timers +#if LED_DISABLE_TIMEOUT > 0 +    if (led_anykey_timer < UINT32_MAX) { +        if (UINT32_MAX - deltaTime < led_anykey_timer) { +            led_anykey_timer = UINT32_MAX; +        } else { +            led_anykey_timer += deltaTime;          }      } +#endif  // LED_DISABLE_TIMEOUT > 0 + +    // Update double buffer last hit timers +#ifdef LED_MATRIX_KEYREACTIVE_ENABLED +    uint8_t count = last_hit_buffer.count; +    for (uint8_t i = 0; i < count; ++i) { +        if (UINT16_MAX - deltaTime < last_hit_buffer.tick[i]) { +            last_hit_buffer.count--; +            continue; +        } +        last_hit_buffer.tick[i] += deltaTime; +    } +#endif  // LED_MATRIX_KEYREACTIVE_ENABLED +} -    // Ideally we would also stop sending zeros to the LED driver PWM buffers -    // while suspended and just do a software shutdown. This is a cheap hack for now. -    bool    suspend_backlight = ((g_suspend_state && LED_DISABLE_WHEN_USB_SUSPENDED) || (LED_DISABLE_AFTER_TIMEOUT > 0 && g_any_key_hit > LED_DISABLE_AFTER_TIMEOUT * 60 * 20)); -    uint8_t effect            = suspend_backlight ? 0 : led_matrix_eeconfig.mode; +static void led_task_sync(void) { +    // next task +    if (sync_timer_elapsed32(g_led_timer) >= LED_MATRIX_LED_FLUSH_LIMIT) led_task_state = STARTING; +} + +static void led_task_start(void) { +    // reset iter +    led_effect_params.iter = 0; + +    // update double buffers +    g_led_timer = led_timer_buffer; +#ifdef LED_MATRIX_KEYREACTIVE_ENABLED +    g_last_hit_tracker = last_hit_buffer; +#endif  // LED_MATRIX_KEYREACTIVE_ENABLED + +    // next task +    led_task_state = RENDERING; +} + +static void led_task_render(uint8_t effect) { +    bool rendering         = false; +    led_effect_params.init = (effect != led_last_effect) || (led_matrix_eeconfig.enable != led_last_enable); +    if (led_effect_params.flags != led_matrix_eeconfig.flags) { +        led_effect_params.flags = led_matrix_eeconfig.flags; +        led_matrix_set_value_all(0); +    } -    // this gets ticked at 20 Hz.      // each effect can opt to do calculations      // and/or request PWM buffer updates.      switch (effect) { -        case LED_MATRIX_UNIFORM_BRIGHTNESS: -            led_matrix_uniform_brightness(); +        case LED_MATRIX_NONE: +            rendering = led_matrix_none(&led_effect_params);              break; -        default: -            led_matrix_custom(); + +// --------------------------------------------- +// -----Begin led effect switch case macros----- +#define LED_MATRIX_EFFECT(name, ...)          \ +    case LED_MATRIX_##name:                   \ +        rendering = name(&led_effect_params); \ +        break; +#include "led_matrix_animations/led_matrix_effects.inc" +#undef LED_MATRIX_EFFECT + +#if defined(LED_MATRIX_CUSTOM_KB) || defined(LED_MATRIX_CUSTOM_USER) +#    define LED_MATRIX_EFFECT(name, ...)          \ +        case LED_MATRIX_CUSTOM_##name:            \ +            rendering = name(&led_effect_params); \              break; +#    ifdef LED_MATRIX_CUSTOM_KB +#        include "led_matrix_kb.inc" +#    endif +#    ifdef LED_MATRIX_CUSTOM_USER +#        include "led_matrix_user.inc" +#    endif +#    undef LED_MATRIX_EFFECT +#endif +            // -----End led effect switch case macros------- +            // ---------------------------------------------      } -    if (!suspend_backlight) { -        led_matrix_indicators(); +    led_effect_params.iter++; + +    // next task +    if (!rendering) { +        led_task_state = FLUSHING; +        if (!led_effect_params.init && effect == LED_MATRIX_NONE) { +            // We only need to flush once if we are LED_MATRIX_NONE +            led_task_state = SYNCING; +        }      } +} + +static void led_task_flush(uint8_t effect) { +    // update last trackers after the first full render so we can init over several frames +    led_last_effect = effect; +    led_last_enable = led_matrix_eeconfig.enable; + +    // update pwm buffers +    led_matrix_update_pwm_buffers(); -    // Tell the LED driver to update its state -    led_matrix_driver.flush(); +    // next task +    led_task_state = SYNCING; +} + +void led_matrix_task(void) { +    led_task_timers(); + +    // Ideally we would also stop sending zeros to the LED driver PWM buffers +    // while suspended and just do a software shutdown. This is a cheap hack for now. +    bool suspend_backlight = suspend_state || +#if LED_DISABLE_TIMEOUT > 0 +                             (led_anykey_timer > (uint32_t)LED_DISABLE_TIMEOUT) || +#endif  // LED_DISABLE_TIMEOUT > 0 +                             false; + +    uint8_t effect = suspend_backlight || !led_matrix_eeconfig.enable ? 0 : led_matrix_eeconfig.mode; + +    switch (led_task_state) { +        case STARTING: +            led_task_start(); +            break; +        case RENDERING: +            led_task_render(effect); +            if (effect) { +                led_matrix_indicators(); +                led_matrix_indicators_advanced(&led_effect_params); +            } +            break; +        case FLUSHING: +            led_task_flush(effect); +            break; +        case SYNCING: +            led_task_sync(); +            break; +    }  }  void led_matrix_indicators(void) { @@ -193,33 +404,42 @@ __attribute__((weak)) void led_matrix_indicators_kb(void) {}  __attribute__((weak)) void led_matrix_indicators_user(void) {} -// void led_matrix_set_indicator_index(uint8_t *index, uint8_t row, uint8_t column) -// { -//  if (row >= MATRIX_ROWS) -//  { -//      // Special value, 255=none, 254=all -//      *index = row; -//  } -//  else -//  { -//      // This needs updated to something like -//      // uint8_t led[8]; -//      // uint8_t led_count = map_row_column_to_led(row, column, led); -//      // for(uint8_t i = 0; i < led_count; i++) -//      map_row_column_to_led(row, column, index); -//  } -// } +void led_matrix_indicators_advanced(effect_params_t *params) { +    /* special handling is needed for "params->iter", since it's already been incremented. +     * Could move the invocations to led_task_render, but then it's missing a few checks +     * and not sure which would be better. Otherwise, this should be called from +     * led_task_render, right before the iter++ line. +     */ +#if defined(LED_MATRIX_LED_PROCESS_LIMIT) && LED_MATRIX_LED_PROCESS_LIMIT > 0 && LED_MATRIX_LED_PROCESS_LIMIT < DRIVER_LED_TOTAL +    uint8_t min = LED_MATRIX_LED_PROCESS_LIMIT * (params->iter - 1); +    uint8_t max = min + LED_MATRIX_LED_PROCESS_LIMIT; +    if (max > DRIVER_LED_TOTAL) max = DRIVER_LED_TOTAL; +#else +    uint8_t min = 0; +    uint8_t max = DRIVER_LED_TOTAL; +#endif +    led_matrix_indicators_advanced_kb(min, max); +    led_matrix_indicators_advanced_user(min, max); +} + +__attribute__((weak)) void led_matrix_indicators_advanced_kb(uint8_t led_min, uint8_t led_max) {} + +__attribute__((weak)) void led_matrix_indicators_advanced_user(uint8_t led_min, uint8_t led_max) {}  void led_matrix_init(void) {      led_matrix_driver.init(); -    // Wait half a second for the driver to finish initializing -    wait_ms(500); +#ifdef LED_MATRIX_KEYREACTIVE_ENABLED +    g_last_hit_tracker.count = 0; +    for (uint8_t i = 0; i < LED_HITS_TO_REMEMBER; ++i) { +        g_last_hit_tracker.tick[i] = UINT16_MAX; +    } -    // clear the key hits -    for (int led = 0; led < DRIVER_LED_TOTAL; led++) { -        g_key_hit[led] = 255; +    last_hit_buffer.count = 0; +    for (uint8_t i = 0; i < LED_HITS_TO_REMEMBER; ++i) { +        last_hit_buffer.tick[i] = UINT16_MAX;      } +#endif  // LED_MATRIX_KEYREACTIVE_ENABLED      if (!eeconfig_is_enabled()) {          dprintf("led_matrix_init_drivers eeconfig is not enabled.\n"); @@ -227,122 +447,137 @@ void led_matrix_init(void) {          eeconfig_update_led_matrix_default();      } -    led_matrix_eeconfig.raw = eeconfig_read_led_matrix(); - +    eeconfig_read_led_matrix();      if (!led_matrix_eeconfig.mode) {          dprintf("led_matrix_init_drivers led_matrix_eeconfig.mode = 0. Write default values to EEPROM.\n");          eeconfig_update_led_matrix_default(); -        led_matrix_eeconfig.raw = eeconfig_read_led_matrix();      } -      eeconfig_debug_led_matrix();  // display current eeprom values  } -// Deals with the messy details of incrementing an integer -static uint8_t increment(uint8_t value, uint8_t step, uint8_t min, uint8_t max) { -    int16_t new_value = value; -    new_value += step; -    return MIN(MAX(new_value, min), max); +void led_matrix_set_suspend_state(bool state) { +#ifdef LED_DISABLE_WHEN_USB_SUSPENDED +    if (state) { +        led_matrix_set_value_all(0);  // turn off all LEDs when suspending +    } +    suspend_state = state; +#endif  } -static uint8_t decrement(uint8_t value, uint8_t step, uint8_t min, uint8_t max) { -    int16_t new_value = value; -    new_value -= step; -    return MIN(MAX(new_value, min), max); -} +bool led_matrix_get_suspend_state(void) { return suspend_state; } -// void *backlight_get_custom_key_value_eeprom_address(uint8_t led) { -//     // 3 bytes per value -//     return EECONFIG_LED_MATRIX + (led * 3); -// } - -// void backlight_get_key_value(uint8_t led, uint8_t *value) { -//     void *address = backlight_get_custom_key_value_eeprom_address(led); -//     value = eeprom_read_byte(address); -// } - -// void backlight_set_key_value(uint8_t row, uint8_t column, uint8_t value) { -//     uint8_t led[8]; -//     uint8_t led_count = map_row_column_to_led(row, column, led); -//     for(uint8_t i = 0; i < led_count; i++) { -//         if (led[i] < DRIVER_LED_TOTAL) { -//             void *address = backlight_get_custom_key_value_eeprom_address(led[i]); -//             eeprom_update_byte(address, value); -//         } -//     } -// } - -uint32_t led_matrix_get_tick(void) { return g_tick; } - -void led_matrix_toggle(void) { +void led_matrix_toggle_eeprom_helper(bool write_to_eeprom) {      led_matrix_eeconfig.enable ^= 1; -    eeconfig_update_led_matrix(led_matrix_eeconfig.raw); +    led_task_state = STARTING; +    if (write_to_eeprom) { +        eeconfig_update_led_matrix(); +    } +    dprintf("led matrix toggle [%s]: led_matrix_eeconfig.enable = %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.enable);  } +void led_matrix_toggle_noeeprom(void) { led_matrix_toggle_eeprom_helper(false); } +void led_matrix_toggle(void) { led_matrix_toggle_eeprom_helper(true); }  void led_matrix_enable(void) { -    led_matrix_eeconfig.enable = 1; -    eeconfig_update_led_matrix(led_matrix_eeconfig.raw); +    led_matrix_enable_noeeprom(); +    eeconfig_update_led_matrix();  } -void led_matrix_enable_noeeprom(void) { led_matrix_eeconfig.enable = 1; } +void led_matrix_enable_noeeprom(void) { +    if (!led_matrix_eeconfig.enable) led_task_state = STARTING; +    led_matrix_eeconfig.enable = 1; +}  void led_matrix_disable(void) { +    led_matrix_disable_noeeprom(); +    eeconfig_update_led_matrix(); +} + +void led_matrix_disable_noeeprom(void) { +    if (led_matrix_eeconfig.enable) led_task_state = STARTING;      led_matrix_eeconfig.enable = 0; -    eeconfig_update_led_matrix(led_matrix_eeconfig.raw);  } -void led_matrix_disable_noeeprom(void) { led_matrix_eeconfig.enable = 0; } +uint8_t led_matrix_is_enabled(void) { return led_matrix_eeconfig.enable; } -void led_matrix_step(void) { -    led_matrix_eeconfig.mode++; -    if (led_matrix_eeconfig.mode >= LED_MATRIX_EFFECT_MAX) { -        led_matrix_eeconfig.mode = 1; +void led_matrix_mode_eeprom_helper(uint8_t mode, bool write_to_eeprom) { +    if (!led_matrix_eeconfig.enable) { +        return;      } -    eeconfig_update_led_matrix(led_matrix_eeconfig.raw); -} - -void led_matrix_step_reverse(void) { -    led_matrix_eeconfig.mode--; -    if (led_matrix_eeconfig.mode < 1) { +    if (mode < 1) { +        led_matrix_eeconfig.mode = 1; +    } else if (mode >= LED_MATRIX_EFFECT_MAX) {          led_matrix_eeconfig.mode = LED_MATRIX_EFFECT_MAX - 1; +    } else { +        led_matrix_eeconfig.mode = mode; +    } +    led_task_state = STARTING; +    if (write_to_eeprom) { +        eeconfig_update_led_matrix();      } -    eeconfig_update_led_matrix(led_matrix_eeconfig.raw); +    dprintf("led matrix mode [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.mode);  } +void led_matrix_mode_noeeprom(uint8_t mode) { led_matrix_mode_eeprom_helper(mode, false); } +void led_matrix_mode(uint8_t mode) { led_matrix_mode_eeprom_helper(mode, true); } -void led_matrix_increase_val(void) { -    led_matrix_eeconfig.val = increment(led_matrix_eeconfig.val, 8, 0, LED_MATRIX_MAXIMUM_BRIGHTNESS); -    eeconfig_update_led_matrix(led_matrix_eeconfig.raw); -} +uint8_t led_matrix_get_mode(void) { return led_matrix_eeconfig.mode; } -void led_matrix_decrease_val(void) { -    led_matrix_eeconfig.val = decrement(led_matrix_eeconfig.val, 8, 0, LED_MATRIX_MAXIMUM_BRIGHTNESS); -    eeconfig_update_led_matrix(led_matrix_eeconfig.raw); +void led_matrix_step_helper(bool write_to_eeprom) { +    uint8_t mode = led_matrix_eeconfig.mode + 1; +    led_matrix_mode_eeprom_helper((mode < LED_MATRIX_EFFECT_MAX) ? mode : 1, write_to_eeprom);  } +void led_matrix_step_noeeprom(void) { led_matrix_step_helper(false); } +void led_matrix_step(void) { led_matrix_step_helper(true); } -void led_matrix_increase_speed(void) { -    led_matrix_eeconfig.speed = increment(led_matrix_eeconfig.speed, 1, 0, 3); -    eeconfig_update_led_matrix(led_matrix_eeconfig.raw);  // EECONFIG needs to be increased to support this +void led_matrix_step_reverse_helper(bool write_to_eeprom) { +    uint8_t mode = led_matrix_eeconfig.mode - 1; +    led_matrix_mode_eeprom_helper((mode < 1) ? LED_MATRIX_EFFECT_MAX - 1 : mode, write_to_eeprom);  } +void led_matrix_step_reverse_noeeprom(void) { led_matrix_step_reverse_helper(false); } +void led_matrix_step_reverse(void) { led_matrix_step_reverse_helper(true); } -void led_matrix_decrease_speed(void) { -    led_matrix_eeconfig.speed = decrement(led_matrix_eeconfig.speed, 1, 0, 3); -    eeconfig_update_led_matrix(led_matrix_eeconfig.raw);  // EECONFIG needs to be increased to support this +void led_matrix_set_val_eeprom_helper(uint8_t val, bool write_to_eeprom) { +    if (!led_matrix_eeconfig.enable) { +        return; +    } +    led_matrix_eeconfig.val = (val > LED_MATRIX_MAXIMUM_BRIGHTNESS) ? LED_MATRIX_MAXIMUM_BRIGHTNESS : val; +    if (write_to_eeprom) { +        eeconfig_update_led_matrix(); +    } +    dprintf("led matrix set val [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.val);  } +void led_matrix_set_val_noeeprom(uint8_t val) { led_matrix_set_val_eeprom_helper(val, false); } +void led_matrix_set_val(uint8_t val) { led_matrix_set_val_eeprom_helper(val, true); } -void led_matrix_mode(uint8_t mode, bool eeprom_write) { -    led_matrix_eeconfig.mode = mode; -    if (eeprom_write) { -        eeconfig_update_led_matrix(led_matrix_eeconfig.raw); +uint8_t led_matrix_get_val(void) { return led_matrix_eeconfig.val; } + +void led_matrix_increase_val_helper(bool write_to_eeprom) { led_matrix_set_val_eeprom_helper(qadd8(led_matrix_eeconfig.val, LED_MATRIX_VAL_STEP), write_to_eeprom); } +void led_matrix_increase_val_noeeprom(void) { led_matrix_increase_val_helper(false); } +void led_matrix_increase_val(void) { led_matrix_increase_val_helper(true); } + +void led_matrix_decrease_val_helper(bool write_to_eeprom) { led_matrix_set_val_eeprom_helper(qsub8(led_matrix_eeconfig.val, LED_MATRIX_VAL_STEP), write_to_eeprom); } +void led_matrix_decrease_val_noeeprom(void) { led_matrix_decrease_val_helper(false); } +void led_matrix_decrease_val(void) { led_matrix_decrease_val_helper(true); } + +void led_matrix_set_speed_eeprom_helper(uint8_t speed, bool write_to_eeprom) { +    led_matrix_eeconfig.speed = speed; +    if (write_to_eeprom) { +        eeconfig_update_led_matrix();      } +    dprintf("led matrix set speed [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.speed);  } +void led_matrix_set_speed_noeeprom(uint8_t speed) { led_matrix_set_speed_eeprom_helper(speed, false); } +void led_matrix_set_speed(uint8_t speed) { led_matrix_set_speed_eeprom_helper(speed, true); } -uint8_t led_matrix_get_mode(void) { return led_matrix_eeconfig.mode; } +uint8_t led_matrix_get_speed(void) { return led_matrix_eeconfig.speed; } -void led_matrix_set_value_noeeprom(uint8_t val) { led_matrix_eeconfig.val = val; } +void led_matrix_increase_speed_helper(bool write_to_eeprom) { led_matrix_set_speed_eeprom_helper(qadd8(led_matrix_eeconfig.speed, LED_MATRIX_SPD_STEP), write_to_eeprom); } +void led_matrix_increase_speed_noeeprom(void) { led_matrix_increase_speed_helper(false); } +void led_matrix_increase_speed(void) { led_matrix_increase_speed_helper(true); } -void led_matrix_set_value(uint8_t val) { -    led_matrix_set_value_noeeprom(val); -    eeconfig_update_led_matrix(led_matrix_eeconfig.raw); -} +void led_matrix_decrease_speed_helper(bool write_to_eeprom) { led_matrix_set_speed_eeprom_helper(qsub8(led_matrix_eeconfig.speed, LED_MATRIX_SPD_STEP), write_to_eeprom); } +void led_matrix_decrease_speed_noeeprom(void) { led_matrix_decrease_speed_helper(false); } +void led_matrix_decrease_speed(void) { led_matrix_decrease_speed_helper(true); } + +led_flags_t led_matrix_get_flags(void) { return led_matrix_eeconfig.flags; } -void backlight_set(uint8_t val) { led_matrix_set_value(val); } +void led_matrix_set_flags(led_flags_t flags) { led_matrix_eeconfig.flags = flags; } diff --git a/quantum/led_matrix.h b/quantum/led_matrix.h index 85bae43c15..0984de73b3 100644 --- a/quantum/led_matrix.h +++ b/quantum/led_matrix.h @@ -19,61 +19,120 @@  #pragma once +#include <stdint.h> +#include <stdbool.h>  #include "led_matrix_types.h" +#include "quantum.h" -#ifndef BACKLIGHT_ENABLE -#    error You must define BACKLIGHT_ENABLE with LED_MATRIX_ENABLE +#ifdef IS31FL3731 +#    include "is31fl3731-simple.h"  #endif +#ifndef LED_MATRIX_LED_FLUSH_LIMIT +#    define LED_MATRIX_LED_FLUSH_LIMIT 16 +#endif + +#ifndef LED_MATRIX_LED_PROCESS_LIMIT +#    define LED_MATRIX_LED_PROCESS_LIMIT (DRIVER_LED_TOTAL + 4) / 5 +#endif + +#if defined(LED_MATRIX_LED_PROCESS_LIMIT) && LED_MATRIX_LED_PROCESS_LIMIT > 0 && LED_MATRIX_LED_PROCESS_LIMIT < DRIVER_LED_TOTAL +#    define LED_MATRIX_USE_LIMITS(min, max)                        \ +        uint8_t min = LED_MATRIX_LED_PROCESS_LIMIT * params->iter; \ +        uint8_t max = min + LED_MATRIX_LED_PROCESS_LIMIT;          \ +        if (max > DRIVER_LED_TOTAL) max = DRIVER_LED_TOTAL; +#else +#    define LED_MATRIX_USE_LIMITS(min, max) \ +        uint8_t min = 0;                    \ +        uint8_t max = DRIVER_LED_TOTAL; +#endif + +#define LED_MATRIX_TEST_LED_FLAGS() \ +    if (!HAS_ANY_FLAGS(g_led_config.flags[i], params->flags)) continue +  enum led_matrix_effects { -    LED_MATRIX_UNIFORM_BRIGHTNESS = 1, -    // All new effects go above this line +    LED_MATRIX_NONE = 0, + +// -------------------------------------- +// -----Begin led effect enum macros----- +#define LED_MATRIX_EFFECT(name, ...) LED_MATRIX_##name, +#include "led_matrix_animations/led_matrix_effects.inc" +#undef LED_MATRIX_EFFECT + +#if defined(LED_MATRIX_CUSTOM_KB) || defined(LED_MATRIX_CUSTOM_USER) +#    define LED_MATRIX_EFFECT(name, ...) LED_MATRIX_CUSTOM_##name, +#    ifdef LED_MATRIX_CUSTOM_KB +#        include "led_matrix_kb.inc" +#    endif +#    ifdef LED_MATRIX_CUSTOM_USER +#        include "led_matrix_user.inc" +#    endif +#    undef LED_MATRIX_EFFECT +#endif +    // -------------------------------------- +    // -----End led effect enum macros------- +      LED_MATRIX_EFFECT_MAX  }; -void led_matrix_set_index_value(int index, uint8_t value); -void led_matrix_set_index_value_all(uint8_t value); +void eeconfig_update_led_matrix_default(void); +void eeconfig_update_led_matrix(void); +void eeconfig_debug_led_matrix(void); + +uint8_t led_matrix_map_row_column_to_led_kb(uint8_t row, uint8_t column, uint8_t *led_i); +uint8_t led_matrix_map_row_column_to_led(uint8_t row, uint8_t column, uint8_t *led_i); + +void led_matrix_set_value(int index, uint8_t value); +void led_matrix_set_value_all(uint8_t value); + +void process_led_matrix(uint8_t row, uint8_t col, bool pressed); + +void led_matrix_task(void);  // This runs after another backlight effect and replaces -// colors already set +// values already set  void led_matrix_indicators(void);  void led_matrix_indicators_kb(void);  void led_matrix_indicators_user(void); -void led_matrix_init(void); -void led_matrix_setup_drivers(void); - -void led_matrix_set_suspend_state(bool state); -void led_matrix_set_indicator_state(uint8_t state); +void led_matrix_indicators_advanced(effect_params_t *params); +void led_matrix_indicators_advanced_kb(uint8_t led_min, uint8_t led_max); +void led_matrix_indicators_advanced_user(uint8_t led_min, uint8_t led_max); -void led_matrix_task(void); +void led_matrix_init(void); -// This should not be called from an interrupt -// (eg. from a timer interrupt). -// Call this while idle (in between matrix scans). -// If the buffer is dirty, it will update the driver with the buffer. -void led_matrix_update_pwm_buffers(void); - -bool process_led_matrix(uint16_t keycode, keyrecord_t *record); - -uint32_t led_matrix_get_tick(void); - -void    led_matrix_toggle(void); -void    led_matrix_enable(void); -void    led_matrix_enable_noeeprom(void); -void    led_matrix_disable(void); -void    led_matrix_disable_noeeprom(void); -void    led_matrix_step(void); -void    led_matrix_step_reverse(void); -void    led_matrix_increase_val(void); -void    led_matrix_decrease_val(void); -void    led_matrix_increase_speed(void); -void    led_matrix_decrease_speed(void); -void    led_matrix_mode(uint8_t mode, bool eeprom_write); -void    led_matrix_mode_noeeprom(uint8_t mode); -uint8_t led_matrix_get_mode(void); -void    led_matrix_set_value(uint8_t mode); -void    led_matrix_set_value_noeeprom(uint8_t mode); +void        led_matrix_set_suspend_state(bool state); +bool        led_matrix_get_suspend_state(void); +void        led_matrix_toggle(void); +void        led_matrix_toggle_noeeprom(void); +void        led_matrix_enable(void); +void        led_matrix_enable_noeeprom(void); +void        led_matrix_disable(void); +void        led_matrix_disable_noeeprom(void); +uint8_t     led_matrix_is_enabled(void); +void        led_matrix_mode(uint8_t mode); +void        led_matrix_mode_noeeprom(uint8_t mode); +uint8_t     led_matrix_get_mode(void); +void        led_matrix_step(void); +void        led_matrix_step_noeeprom(void); +void        led_matrix_step_reverse(void); +void        led_matrix_step_reverse_noeeprom(void); +void        led_matrix_set_val(uint8_t val); +void        led_matrix_set_val_noeeprom(uint8_t val); +uint8_t     led_matrix_get_val(void); +void        led_matrix_increase_val(void); +void        led_matrix_increase_val_noeeprom(void); +void        led_matrix_decrease_val(void); +void        led_matrix_decrease_val_noeeprom(void); +void        led_matrix_set_speed(uint8_t speed); +void        led_matrix_set_speed_noeeprom(uint8_t speed); +uint8_t     led_matrix_get_speed(void); +void        led_matrix_increase_speed(void); +void        led_matrix_increase_speed_noeeprom(void); +void        led_matrix_decrease_speed(void); +void        led_matrix_decrease_speed_noeeprom(void); +led_flags_t led_matrix_get_flags(void); +void        led_matrix_set_flags(led_flags_t flags);  typedef struct {      /* Perform any initialisation required for the other driver functions to work. */ @@ -91,4 +150,11 @@ extern const led_matrix_driver_t led_matrix_driver;  extern led_eeconfig_t led_matrix_eeconfig; +extern uint32_t     g_led_timer;  extern led_config_t g_led_config; +#ifdef LED_MATRIX_KEYREACTIVE_ENABLED +extern last_hit_t g_last_hit_tracker; +#endif +#ifdef LED_MATRIX_FRAMEBUFFER_EFFECTS +extern uint8_t g_led_frame_buffer[MATRIX_ROWS][MATRIX_COLS]; +#endif diff --git a/quantum/led_matrix_animations/alpha_mods_anim.h b/quantum/led_matrix_animations/alpha_mods_anim.h new file mode 100644 index 0000000000..a4638fde69 --- /dev/null +++ b/quantum/led_matrix_animations/alpha_mods_anim.h @@ -0,0 +1,24 @@ +#ifndef DISABLE_LED_MATRIX_ALPHAS_MODS +LED_MATRIX_EFFECT(ALPHAS_MODS) +#    ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS + +// alphas = val1, mods = val2 +bool ALPHAS_MODS(effect_params_t* params) { +    LED_MATRIX_USE_LIMITS(led_min, led_max); + +    uint8_t val1 = led_matrix_eeconfig.val; +    uint8_t val2 = val1 + led_matrix_eeconfig.speed; + +    for (uint8_t i = led_min; i < led_max; i++) { +        LED_MATRIX_TEST_LED_FLAGS(); +        if (HAS_FLAGS(g_led_config.flags[i], LED_FLAG_MODIFIER)) { +            led_matrix_set_value(i, val2); +        } else { +            led_matrix_set_value(i, val1); +        } +    } +    return led_max < DRIVER_LED_TOTAL; +} + +#    endif  // LED_MATRIX_CUSTOM_EFFECT_IMPLS +#endif      // DISABLE_LED_MATRIX_ALPHAS_MODS diff --git a/quantum/led_matrix_animations/band_anim.h b/quantum/led_matrix_animations/band_anim.h new file mode 100644 index 0000000000..4a2b746a76 --- /dev/null +++ b/quantum/led_matrix_animations/band_anim.h @@ -0,0 +1,15 @@ +#ifndef DISABLE_LED_MATRIX_BAND +LED_MATRIX_EFFECT(BAND) +#    ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS + +static uint8_t BAND_math(uint8_t val, uint8_t i, uint8_t time) { +    int16_t v = val - abs(scale8(g_led_config.point[i].x, 228) + 28 - time) * 8; +    return scale8(v < 0 ? 0 : v, val); +} + +bool BAND(effect_params_t* params) { +    return effect_runner_i(params, &BAND_math); +} + +#    endif  // LED_MATRIX_CUSTOM_EFFECT_IMPLS +#endif      // DISABLE_LED_MATRIX_BAND diff --git a/quantum/led_matrix_animations/band_pinwheel_anim.h b/quantum/led_matrix_animations/band_pinwheel_anim.h new file mode 100644 index 0000000000..9836320d2a --- /dev/null +++ b/quantum/led_matrix_animations/band_pinwheel_anim.h @@ -0,0 +1,14 @@ +#ifndef DISABLE_LED_MATRIX_BAND_PINWHEEL +LED_MATRIX_EFFECT(BAND_PINWHEEL) +#    ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS + +static uint8_t BAND_PINWHEEL_math(uint8_t val, int16_t dx, int16_t dy, uint8_t time) { +    return scale8(val - time - atan2_8(dy, dx) * 3, val); +} + +bool BAND_PINWHEEL(effect_params_t* params) { +    return effect_runner_dx_dy(params, &BAND_PINWHEEL_math); +} + +#    endif  // LED_MATRIX_CUSTOM_EFFECT_IMPLS +#endif      // DISABLE_LED_MATRIX_BAND_PINWHEEL diff --git a/quantum/led_matrix_animations/band_spiral_anim.h b/quantum/led_matrix_animations/band_spiral_anim.h new file mode 100644 index 0000000000..be17c03aad --- /dev/null +++ b/quantum/led_matrix_animations/band_spiral_anim.h @@ -0,0 +1,14 @@ +#ifndef DISABLE_LED_MATRIX_BAND_SPIRAL +LED_MATRIX_EFFECT(BAND_SPIRAL) +#    ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS + +static uint8_t BAND_SPIRAL_math(uint8_t val, int16_t dx, int16_t dy, uint8_t dist, uint8_t time) { +    return scale8(val + dist - time - atan2_8(dy, dx), val); +} + +bool BAND_SPIRAL(effect_params_t* params) { +    return effect_runner_dx_dy_dist(params, &BAND_SPIRAL_math); +} + +#    endif  // LED_MATRIX_CUSTOM_EFFECT_IMPLS +#endif      // DISABLE_LED_MATRIX_BAND_SPIRAL diff --git a/quantum/led_matrix_animations/breathing_anim.h b/quantum/led_matrix_animations/breathing_anim.h new file mode 100644 index 0000000000..4f49f50690 --- /dev/null +++ b/quantum/led_matrix_animations/breathing_anim.h @@ -0,0 +1,19 @@ +#ifndef DISABLE_LED_MATRIX_BREATHING +LED_MATRIX_EFFECT(BREATHING) +#    ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS + +bool BREATHING(effect_params_t* params) { +    LED_MATRIX_USE_LIMITS(led_min, led_max); + +    uint8_t  val  = led_matrix_eeconfig.val; +    uint16_t time = scale16by8(g_led_timer, led_matrix_eeconfig.speed / 8); +    val           = scale8(abs8(sin8(time) - 128) * 2, val); +    for (uint8_t i = led_min; i < led_max; i++) { +        LED_MATRIX_TEST_LED_FLAGS(); +        led_matrix_set_value(i, val); +    } +    return led_max < DRIVER_LED_TOTAL; +} + +#    endif  // LED_MATRIX_CUSTOM_EFFECT_IMPLS +#endif      // DISABLE_LED_MATRIX_BREATHING diff --git a/quantum/led_matrix_animations/cycle_left_right_anim.h b/quantum/led_matrix_animations/cycle_left_right_anim.h new file mode 100644 index 0000000000..404fda26f5 --- /dev/null +++ b/quantum/led_matrix_animations/cycle_left_right_anim.h @@ -0,0 +1,14 @@ +#ifndef DISABLE_LED_MATRIX_CYCLE_LEFT_RIGHT +LED_MATRIX_EFFECT(CYCLE_LEFT_RIGHT) +#    ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS + +static uint8_t CYCLE_LEFT_RIGHT_math(uint8_t val, uint8_t i, uint8_t time) { +    return scale8(g_led_config.point[i].x - time, val); +} + +bool CYCLE_LEFT_RIGHT(effect_params_t* params) { +    return effect_runner_i(params, &CYCLE_LEFT_RIGHT_math); +} + +#    endif  // LED_MATRIX_CUSTOM_EFFECT_IMPLS +#endif      // DISABLE_LED_MATRIX_CYCLE_LEFT_RIGHT diff --git a/quantum/led_matrix_animations/cycle_out_in_anim.h b/quantum/led_matrix_animations/cycle_out_in_anim.h new file mode 100644 index 0000000000..3f5fc5b187 --- /dev/null +++ b/quantum/led_matrix_animations/cycle_out_in_anim.h @@ -0,0 +1,14 @@ +#ifndef DISABLE_LED_MATRIX_CYCLE_OUT_IN +LED_MATRIX_EFFECT(CYCLE_OUT_IN) +#    ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS + +static uint8_t CYCLE_OUT_IN_math(uint8_t val, int16_t dx, int16_t dy, uint8_t dist, uint8_t time) { +    return scale8(3 * dist / 2 + time, val); +} + +bool CYCLE_OUT_IN(effect_params_t* params) { +    return effect_runner_dx_dy_dist(params, &CYCLE_OUT_IN_math); +} + +#    endif  // LED_MATRIX_CUSTOM_EFFECT_IMPLS +#endif      // DISABLE_LED_MATRIX_CYCLE_OUT_IN diff --git a/quantum/led_matrix_animations/cycle_up_down_anim.h b/quantum/led_matrix_animations/cycle_up_down_anim.h new file mode 100644 index 0000000000..25fc211b17 --- /dev/null +++ b/quantum/led_matrix_animations/cycle_up_down_anim.h @@ -0,0 +1,14 @@ +#ifndef DISABLE_LED_MATRIX_CYCLE_UP_DOWN +LED_MATRIX_EFFECT(CYCLE_UP_DOWN) +#    ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS + +static uint8_t CYCLE_UP_DOWN_math(uint8_t val, uint8_t i, uint8_t time) { +    return scale8(g_led_config.point[i].y - time, val); +} + +bool CYCLE_UP_DOWN(effect_params_t* params) { +    return effect_runner_i(params, &CYCLE_UP_DOWN_math); +} + +#    endif  // LED_MATRIX_CUSTOM_EFFECT_IMPLS +#endif      // DISABLE_LED_MATRIX_CYCLE_UP_DOWN diff --git a/quantum/led_matrix_animations/dual_beacon_anim.h b/quantum/led_matrix_animations/dual_beacon_anim.h new file mode 100644 index 0000000000..1fa1df1395 --- /dev/null +++ b/quantum/led_matrix_animations/dual_beacon_anim.h @@ -0,0 +1,14 @@ +#ifndef DISABLE_LED_MATRIX_DUAL_BEACON +LED_MATRIX_EFFECT(DUAL_BEACON) +#    ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS + +static uint8_t DUAL_BEACON_math(uint8_t val, int8_t sin, int8_t cos, uint8_t i, uint8_t time) { +    return scale8(((g_led_config.point[i].y - k_led_matrix_center.y) * cos + (g_led_config.point[i].x - k_led_matrix_center.x) * sin) / 128, val); +} + +bool DUAL_BEACON(effect_params_t* params) { +    return effect_runner_sin_cos_i(params, &DUAL_BEACON_math); +} + +#    endif  // LED_MATRIX_CUSTOM_EFFECT_IMPLS +#endif      // DISABLE_LED_MATRIX_DUAL_BEACON diff --git a/quantum/led_matrix_animations/led_matrix_effects.inc b/quantum/led_matrix_animations/led_matrix_effects.inc new file mode 100644 index 0000000000..67237c5683 --- /dev/null +++ b/quantum/led_matrix_animations/led_matrix_effects.inc @@ -0,0 +1,18 @@ +// Add your new core led matrix effect here, order determins enum order, requires "led_matrix_animations/ directory +#include "led_matrix_animations/solid_anim.h" +#include "led_matrix_animations/alpha_mods_anim.h" +#include "led_matrix_animations/breathing_anim.h" +#include "led_matrix_animations/band_anim.h" +#include "led_matrix_animations/band_pinwheel_anim.h" +#include "led_matrix_animations/band_spiral_anim.h" +#include "led_matrix_animations/cycle_left_right_anim.h" +#include "led_matrix_animations/cycle_up_down_anim.h" +#include "led_matrix_animations/cycle_out_in_anim.h" +#include "led_matrix_animations/dual_beacon_anim.h" +#include "led_matrix_animations/solid_reactive_simple_anim.h" +#include "led_matrix_animations/solid_reactive_wide.h" +#include "led_matrix_animations/solid_reactive_cross.h" +#include "led_matrix_animations/solid_reactive_nexus.h" +#include "led_matrix_animations/solid_splash_anim.h" +#include "led_matrix_animations/wave_left_right_anim.h" +#include "led_matrix_animations/wave_up_down_anim.h" diff --git a/quantum/led_matrix_animations/solid_anim.h b/quantum/led_matrix_animations/solid_anim.h new file mode 100644 index 0000000000..4c9e43c581 --- /dev/null +++ b/quantum/led_matrix_animations/solid_anim.h @@ -0,0 +1,15 @@ +LED_MATRIX_EFFECT(SOLID) +#ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS + +bool SOLID(effect_params_t* params) { +    LED_MATRIX_USE_LIMITS(led_min, led_max); + +    uint8_t val = led_matrix_eeconfig.val; +    for (uint8_t i = led_min; i < led_max; i++) { +        LED_MATRIX_TEST_LED_FLAGS(); +        led_matrix_set_value(i, val); +    } +    return led_max < DRIVER_LED_TOTAL; +} + +#endif  // LED_MATRIX_CUSTOM_EFFECT_IMPLS diff --git a/quantum/led_matrix_animations/solid_reactive_cross.h b/quantum/led_matrix_animations/solid_reactive_cross.h new file mode 100644 index 0000000000..a50d1fc629 --- /dev/null +++ b/quantum/led_matrix_animations/solid_reactive_cross.h @@ -0,0 +1,39 @@ +#ifdef LED_MATRIX_KEYREACTIVE_ENABLED +#    if !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_CROSS) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTICROSS) + +#        ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_CROSS +LED_MATRIX_EFFECT(SOLID_REACTIVE_CROSS) +#        endif + +#        ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTICROSS +LED_MATRIX_EFFECT(SOLID_REACTIVE_MULTICROSS) +#        endif + +#        ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS + +static uint8_t SOLID_REACTIVE_CROSS_math(uint8_t val, int16_t dx, int16_t dy, uint8_t dist, uint16_t tick) { +    uint16_t effect = tick + dist; +    dx              = dx < 0 ? dx * -1 : dx; +    dy              = dy < 0 ? dy * -1 : dy; +    dx              = dx * 16 > 255 ? 255 : dx * 16; +    dy              = dy * 16 > 255 ? 255 : dy * 16; +    effect += dx > dy ? dy : dx; +    if (effect > 255) effect = 255; +    return qadd8(val, 255 - effect); +} + +#            ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_CROSS +bool SOLID_REACTIVE_CROSS(effect_params_t* params) { +    return effect_runner_reactive_splash(qsub8(g_last_hit_tracker.count, 1), params, &SOLID_REACTIVE_CROSS_math); +} +#            endif + +#            ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTICROSS +bool SOLID_REACTIVE_MULTICROSS(effect_params_t* params) { +    return effect_runner_reactive_splash(0, params, &SOLID_REACTIVE_CROSS_math); +} +#            endif + +#        endif  // LED_MATRIX_CUSTOM_EFFECT_IMPLS +#    endif      // !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_CROSS) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTICROSS) +#endif          // LED_MATRIX_KEYREACTIVE_ENABLED diff --git a/quantum/led_matrix_animations/solid_reactive_nexus.h b/quantum/led_matrix_animations/solid_reactive_nexus.h new file mode 100644 index 0000000000..4638aac5a4 --- /dev/null +++ b/quantum/led_matrix_animations/solid_reactive_nexus.h @@ -0,0 +1,36 @@ +#ifdef LED_MATRIX_KEYREACTIVE_ENABLED +#    if !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_NEXUS) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTINEXUS) + +#        ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_NEXUS +LED_MATRIX_EFFECT(SOLID_REACTIVE_NEXUS) +#        endif + +#        ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTINEXUS +LED_MATRIX_EFFECT(SOLID_REACTIVE_MULTINEXUS) +#        endif + +#        ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS + +static uint8_t SOLID_REACTIVE_NEXUS_math(uint8_t val, int16_t dx, int16_t dy, uint8_t dist, uint16_t tick) { +    uint16_t effect = tick - dist; +    if (effect > 255) effect = 255; +    if (dist > 72) effect = 255; +    if ((dx > 8 || dx < -8) && (dy > 8 || dy < -8)) effect = 255; +    return qadd8(val, 255 - effect); +} + +#            ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_NEXUS +bool SOLID_REACTIVE_NEXUS(effect_params_t* params) { +    return effect_runner_reactive_splash(qsub8(g_last_hit_tracker.count, 1), params, &SOLID_REACTIVE_NEXUS_math); +} +#            endif + +#            ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTINEXUS +bool SOLID_REACTIVE_MULTINEXUS(effect_params_t* params) { +    return effect_runner_reactive_splash(0, params, &SOLID_REACTIVE_NEXUS_math); +} +#            endif + +#        endif  // LED_MATRIX_CUSTOM_EFFECT_IMPLS +#    endif      // !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_NEXUS) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTINEXUS) +#endif          // LED_MATRIX_KEYREACTIVE_ENABLED diff --git a/quantum/led_matrix_animations/solid_reactive_simple_anim.h b/quantum/led_matrix_animations/solid_reactive_simple_anim.h new file mode 100644 index 0000000000..e1166a4fb6 --- /dev/null +++ b/quantum/led_matrix_animations/solid_reactive_simple_anim.h @@ -0,0 +1,16 @@ +#ifdef LED_MATRIX_KEYREACTIVE_ENABLED +#    ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_SIMPLE +LED_MATRIX_EFFECT(SOLID_REACTIVE_SIMPLE) +#        ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS + +static uint8_t SOLID_REACTIVE_SIMPLE_math(uint8_t val, uint16_t offset) { +    return scale8(255 - offset, val); +} + +bool SOLID_REACTIVE_SIMPLE(effect_params_t* params) { +    return effect_runner_reactive(params, &SOLID_REACTIVE_SIMPLE_math); +} + +#        endif  // LED_MATRIX_CUSTOM_EFFECT_IMPLS +#    endif      // DISABLE_LED_MATRIX_SOLID_REACTIVE_SIMPLE +#endif          // LED_MATRIX_KEYREACTIVE_ENABLED diff --git a/quantum/led_matrix_animations/solid_reactive_wide.h b/quantum/led_matrix_animations/solid_reactive_wide.h new file mode 100644 index 0000000000..4bcaba331e --- /dev/null +++ b/quantum/led_matrix_animations/solid_reactive_wide.h @@ -0,0 +1,34 @@ +#ifdef LED_MATRIX_KEYREACTIVE_ENABLED +#    if !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_WIDE) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTIWIDE) + +#        ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_WIDE +LED_MATRIX_EFFECT(SOLID_REACTIVE_WIDE) +#        endif + +#        ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTIWIDE +LED_MATRIX_EFFECT(SOLID_REACTIVE_MULTIWIDE) +#        endif + +#        ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS + +static uint8_t SOLID_REACTIVE_WIDE_math(uint8_t val, int16_t dx, int16_t dy, uint8_t dist, uint16_t tick) { +    uint16_t effect = tick + dist * 5; +    if (effect > 255) effect = 255; +    return qadd8(val, 255 - effect); +} + +#            ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_WIDE +bool SOLID_REACTIVE_WIDE(effect_params_t* params) { +    return effect_runner_reactive_splash(qsub8(g_last_hit_tracker.count, 1), params, &SOLID_REACTIVE_WIDE_math); +} +#            endif + +#            ifndef DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTIWIDE +bool SOLID_REACTIVE_MULTIWIDE(effect_params_t* params) { +    return effect_runner_reactive_splash(0, params, &SOLID_REACTIVE_WIDE_math); +} +#            endif + +#        endif  // LED_MATRIX_CUSTOM_EFFECT_IMPLS +#    endif      // !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_WIDE) || !defined(DISABLE_LED_MATRIX_SOLID_REACTIVE_MULTIWIDE) +#endif          // LED_MATRIX_KEYREACTIVE_ENABLED diff --git a/quantum/led_matrix_animations/solid_splash_anim.h b/quantum/led_matrix_animations/solid_splash_anim.h new file mode 100644 index 0000000000..3e9046640e --- /dev/null +++ b/quantum/led_matrix_animations/solid_splash_anim.h @@ -0,0 +1,34 @@ +#ifdef LED_MATRIX_KEYREACTIVE_ENABLED +#    if !defined(DISABLE_LED_MATRIX_SOLID_SPLASH) || !defined(DISABLE_LED_MATRIX_SOLID_MULTISPLASH) + +#        ifndef DISABLE_LED_MATRIX_SOLID_SPLASH +LED_MATRIX_EFFECT(SOLID_SPLASH) +#        endif + +#        ifndef DISABLE_LED_MATRIX_SOLID_MULTISPLASH +LED_MATRIX_EFFECT(SOLID_MULTISPLASH) +#        endif + +#        ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS + +uint8_t SOLID_SPLASH_math(uint8_t val, int16_t dx, int16_t dy, uint8_t dist, uint16_t tick) { +    uint16_t effect = tick - dist; +    if (effect > 255) effect = 255; +    return qadd8(val, 255 - effect); +} + +#            ifndef DISABLE_LED_MATRIX_SOLID_SPLASH +bool SOLID_SPLASH(effect_params_t* params) { +    return effect_runner_reactive_splash(qsub8(g_last_hit_tracker.count, 1), params, &SOLID_SPLASH_math); +} +#            endif + +#            ifndef DISABLE_LED_MATRIX_SOLID_MULTISPLASH +bool SOLID_MULTISPLASH(effect_params_t* params) { +    return effect_runner_reactive_splash(0, params, &SOLID_SPLASH_math); +} +#            endif + +#        endif  // LED_MATRIX_CUSTOM_EFFECT_IMPLS +#    endif      // !defined(DISABLE_LED_MATRIX_SPLASH) && !defined(DISABLE_LED_MATRIX_MULTISPLASH) +#endif          // LED_MATRIX_KEYREACTIVE_ENABLED diff --git a/quantum/led_matrix_animations/wave_left_right_anim.h b/quantum/led_matrix_animations/wave_left_right_anim.h new file mode 100644 index 0000000000..d547c72cee --- /dev/null +++ b/quantum/led_matrix_animations/wave_left_right_anim.h @@ -0,0 +1,14 @@ +#ifndef DISABLE_LED_MATRIX_WAVE_LEFT_RIGHT +LED_MATRIX_EFFECT(WAVE_LEFT_RIGHT) +#    ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS + +static uint8_t WAVE_LEFT_RIGHT_math(uint8_t val, uint8_t i, uint8_t time) { +    return scale8(sin8(g_led_config.point[i].x - time), val); +} + +bool WAVE_LEFT_RIGHT(effect_params_t* params) { +    return effect_runner_i(params, &WAVE_LEFT_RIGHT_math); +} + +#    endif  // LED_MATRIX_CUSTOM_EFFECT_IMPLS +#endif      // DISABLE_LED_MATRIX_WAVE_LEFT_RIGHT diff --git a/quantum/led_matrix_animations/wave_up_down_anim.h b/quantum/led_matrix_animations/wave_up_down_anim.h new file mode 100644 index 0000000000..b68ff9bbc6 --- /dev/null +++ b/quantum/led_matrix_animations/wave_up_down_anim.h @@ -0,0 +1,14 @@ +#ifndef DISABLE_LED_MATRIX_WAVE_UP_DOWN +LED_MATRIX_EFFECT(WAVE_UP_DOWN) +#    ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS + +static uint8_t WAVE_UP_DOWN_math(uint8_t val, uint8_t i, uint8_t time) { +    return scale8(sin8(g_led_config.point[i].y - time), val); +} + +bool WAVE_UP_DOWN(effect_params_t* params) { +    return effect_runner_i(params, &WAVE_UP_DOWN_math); +} + +#    endif  // LED_MATRIX_CUSTOM_EFFECT_IMPLS +#endif      // DISABLE_LED_MATRIX_WAVE_UP_DOWN diff --git a/quantum/led_matrix_drivers.c b/quantum/led_matrix_drivers.c index eddf3f2863..370c5e6853 100644 --- a/quantum/led_matrix_drivers.c +++ b/quantum/led_matrix_drivers.c @@ -15,9 +15,6 @@   * along with this program.  If not, see <http://www.gnu.org/licenses/>.   */ -#include <stdint.h> -#include <stdbool.h> -#include "quantum.h"  #include "led_matrix.h"  /* Each driver needs to define a struct: @@ -30,10 +27,6 @@  #if defined(IS31FL3731) || defined(IS31FL3733) -#    if defined(IS31FL3731) -#        include "is31fl3731-simple.h" -#    endif -  #    include "i2c_master.h"  static void init(void) { diff --git a/quantum/led_matrix_runners/effect_runner_dx_dy.h b/quantum/led_matrix_runners/effect_runner_dx_dy.h new file mode 100644 index 0000000000..ef97631b90 --- /dev/null +++ b/quantum/led_matrix_runners/effect_runner_dx_dy.h @@ -0,0 +1,16 @@ +#pragma once + +typedef uint8_t (*dx_dy_f)(uint8_t val, int16_t dx, int16_t dy, uint8_t time); + +bool effect_runner_dx_dy(effect_params_t* params, dx_dy_f effect_func) { +    LED_MATRIX_USE_LIMITS(led_min, led_max); + +    uint8_t time = scale16by8(g_led_timer, led_matrix_eeconfig.speed / 2); +    for (uint8_t i = led_min; i < led_max; i++) { +        LED_MATRIX_TEST_LED_FLAGS(); +        int16_t dx = g_led_config.point[i].x - k_led_matrix_center.x; +        int16_t dy = g_led_config.point[i].y - k_led_matrix_center.y; +        led_matrix_set_value(i, effect_func(led_matrix_eeconfig.val, dx, dy, time)); +    } +    return led_max < DRIVER_LED_TOTAL; +} diff --git a/quantum/led_matrix_runners/effect_runner_dx_dy_dist.h b/quantum/led_matrix_runners/effect_runner_dx_dy_dist.h new file mode 100644 index 0000000000..5ef5938be0 --- /dev/null +++ b/quantum/led_matrix_runners/effect_runner_dx_dy_dist.h @@ -0,0 +1,17 @@ +#pragma once + +typedef uint8_t (*dx_dy_dist_f)(uint8_t val, int16_t dx, int16_t dy, uint8_t dist, uint8_t time); + +bool effect_runner_dx_dy_dist(effect_params_t* params, dx_dy_dist_f effect_func) { +    LED_MATRIX_USE_LIMITS(led_min, led_max); + +    uint8_t time = scale16by8(g_led_timer, led_matrix_eeconfig.speed / 2); +    for (uint8_t i = led_min; i < led_max; i++) { +        LED_MATRIX_TEST_LED_FLAGS(); +        int16_t dx   = g_led_config.point[i].x - k_led_matrix_center.x; +        int16_t dy   = g_led_config.point[i].y - k_led_matrix_center.y; +        uint8_t dist = sqrt16(dx * dx + dy * dy); +        led_matrix_set_value(i, effect_func(led_matrix_eeconfig.val, dx, dy, dist, time)); +    } +    return led_max < DRIVER_LED_TOTAL; +} diff --git a/quantum/led_matrix_runners/effect_runner_i.h b/quantum/led_matrix_runners/effect_runner_i.h new file mode 100644 index 0000000000..b3015759be --- /dev/null +++ b/quantum/led_matrix_runners/effect_runner_i.h @@ -0,0 +1,14 @@ +#pragma once + +typedef uint8_t (*i_f)(uint8_t val, uint8_t i, uint8_t time); + +bool effect_runner_i(effect_params_t* params, i_f effect_func) { +    LED_MATRIX_USE_LIMITS(led_min, led_max); + +    uint8_t time = scale16by8(g_led_timer, led_matrix_eeconfig.speed / 4); +    for (uint8_t i = led_min; i < led_max; i++) { +        LED_MATRIX_TEST_LED_FLAGS(); +        led_matrix_set_value(i, effect_func(led_matrix_eeconfig.val, i, time)); +    } +    return led_max < DRIVER_LED_TOTAL; +} diff --git a/quantum/led_matrix_runners/effect_runner_reactive.h b/quantum/led_matrix_runners/effect_runner_reactive.h new file mode 100644 index 0000000000..4369ea8c49 --- /dev/null +++ b/quantum/led_matrix_runners/effect_runner_reactive.h @@ -0,0 +1,28 @@ +#pragma once + +#ifdef LED_MATRIX_KEYREACTIVE_ENABLED + +typedef uint8_t (*reactive_f)(uint8_t val, uint16_t offset); + +bool effect_runner_reactive(effect_params_t* params, reactive_f effect_func) { +    LED_MATRIX_USE_LIMITS(led_min, led_max); + +    uint16_t max_tick = 65535 / led_matrix_eeconfig.speed; +    for (uint8_t i = led_min; i < led_max; i++) { +        LED_MATRIX_TEST_LED_FLAGS(); +        uint16_t tick = max_tick; +        // Reverse search to find most recent key hit +        for (int8_t j = g_last_hit_tracker.count - 1; j >= 0; j--) { +            if (g_last_hit_tracker.index[j] == i && g_last_hit_tracker.tick[j] < tick) { +                tick = g_last_hit_tracker.tick[j]; +                break; +            } +        } + +        uint16_t offset = scale16by8(tick, led_matrix_eeconfig.speed); +        led_matrix_set_value(i, effect_func(led_matrix_eeconfig.val, offset)); +    } +    return led_max < DRIVER_LED_TOTAL; +} + +#endif  // LED_MATRIX_KEYREACTIVE_ENABLED diff --git a/quantum/led_matrix_runners/effect_runner_reactive_splash.h b/quantum/led_matrix_runners/effect_runner_reactive_splash.h new file mode 100644 index 0000000000..d6eb9731ee --- /dev/null +++ b/quantum/led_matrix_runners/effect_runner_reactive_splash.h @@ -0,0 +1,26 @@ +#pragma once + +#ifdef LED_MATRIX_KEYREACTIVE_ENABLED + +typedef uint8_t (*reactive_splash_f)(uint8_t val, int16_t dx, int16_t dy, uint8_t dist, uint16_t tick); + +bool effect_runner_reactive_splash(uint8_t start, effect_params_t* params, reactive_splash_f effect_func) { +    LED_MATRIX_USE_LIMITS(led_min, led_max); + +    uint8_t count = g_last_hit_tracker.count; +    for (uint8_t i = led_min; i < led_max; i++) { +        LED_MATRIX_TEST_LED_FLAGS(); +        uint8_t val = 0; +        for (uint8_t j = start; j < count; j++) { +            int16_t  dx   = g_led_config.point[i].x - g_last_hit_tracker.x[j]; +            int16_t  dy   = g_led_config.point[i].y - g_last_hit_tracker.y[j]; +            uint8_t  dist = sqrt16(dx * dx + dy * dy); +            uint16_t tick = scale16by8(g_last_hit_tracker.tick[j], led_matrix_eeconfig.speed); +            val           = effect_func(val, dx, dy, dist, tick); +        } +        led_matrix_set_value(i, scale8(val, led_matrix_eeconfig.val)); +    } +    return led_max < DRIVER_LED_TOTAL; +} + +#endif  // LED_MATRIX_KEYREACTIVE_ENABLED diff --git a/quantum/led_matrix_runners/effect_runner_sin_cos_i.h b/quantum/led_matrix_runners/effect_runner_sin_cos_i.h new file mode 100644 index 0000000000..4a5219abd1 --- /dev/null +++ b/quantum/led_matrix_runners/effect_runner_sin_cos_i.h @@ -0,0 +1,16 @@ +#pragma once + +typedef uint8_t (*sin_cos_i_f)(uint8_t val, int8_t sin, int8_t cos, uint8_t i, uint8_t time); + +bool effect_runner_sin_cos_i(effect_params_t* params, sin_cos_i_f effect_func) { +    LED_MATRIX_USE_LIMITS(led_min, led_max); + +    uint16_t time      = scale16by8(g_led_timer, led_matrix_eeconfig.speed / 4); +    int8_t   cos_value = cos8(time) - 128; +    int8_t   sin_value = sin8(time) - 128; +    for (uint8_t i = led_min; i < led_max; i++) { +        LED_MATRIX_TEST_LED_FLAGS(); +        led_matrix_set_value(i, effect_func(led_matrix_eeconfig.val, cos_value, sin_value, i, time)); +    } +    return led_max < DRIVER_LED_TOTAL; +} diff --git a/quantum/led_matrix_types.h b/quantum/led_matrix_types.h index 669b67042b..61cdbd9b8e 100644 --- a/quantum/led_matrix_types.h +++ b/quantum/led_matrix_types.h @@ -29,15 +29,42 @@  #    pragma pack(push, 1)  #endif +#if defined(LED_MATRIX_KEYPRESSES) || defined(LED_MATRIX_KEYRELEASES) +#    define LED_MATRIX_KEYREACTIVE_ENABLED +#endif +  // Last led hit  #ifndef LED_HITS_TO_REMEMBER  #    define LED_HITS_TO_REMEMBER 8  #endif  // LED_HITS_TO_REMEMBER +#ifdef LED_MATRIX_KEYREACTIVE_ENABLED +typedef struct PACKED { +    uint8_t  count; +    uint8_t  x[LED_HITS_TO_REMEMBER]; +    uint8_t  y[LED_HITS_TO_REMEMBER]; +    uint8_t  index[LED_HITS_TO_REMEMBER]; +    uint16_t tick[LED_HITS_TO_REMEMBER]; +} last_hit_t; +#endif  // LED_MATRIX_KEYREACTIVE_ENABLED + +typedef enum led_task_states { STARTING, RENDERING, FLUSHING, SYNCING } led_task_states; + +typedef uint8_t led_flags_t; + +typedef struct PACKED { +    uint8_t     iter; +    led_flags_t flags; +    bool        init; +} effect_params_t; +  typedef struct PACKED {      uint8_t x;      uint8_t y; -} point_t; +} led_point_t; + +#define HAS_FLAGS(bits, flags) ((bits & flags) == flags) +#define HAS_ANY_FLAGS(bits, flags) ((bits & flags) != 0x00)  #define LED_FLAG_ALL 0xFF  #define LED_FLAG_NONE 0x00 @@ -48,19 +75,20 @@ typedef struct PACKED {  #define NO_LED 255  typedef struct PACKED { -    uint8_t matrix_co[MATRIX_ROWS][MATRIX_COLS]; -    point_t point[DRIVER_LED_TOTAL]; -    uint8_t flags[DRIVER_LED_TOTAL]; +    uint8_t     matrix_co[MATRIX_ROWS][MATRIX_COLS]; +    led_point_t point[DRIVER_LED_TOTAL]; +    uint8_t     flags[DRIVER_LED_TOTAL];  } led_config_t;  typedef union {      uint32_t raw;      struct PACKED { -        uint8_t  enable : 2; -        uint8_t  mode : 6; -        uint16_t reserved; -        uint8_t  val; -        uint8_t  speed;  // EECONFIG needs to be increased to support this +        uint8_t     enable : 2; +        uint8_t     mode : 6; +        uint16_t    reserved; +        uint8_t     val; +        uint8_t     speed;  // EECONFIG needs to be increased to support this +        led_flags_t flags;      };  } led_eeconfig_t; diff --git a/quantum/matrix.h b/quantum/matrix.h index ce57010a47..3fe691aaee 100644 --- a/quantum/matrix.h +++ b/quantum/matrix.h @@ -74,6 +74,11 @@ void matrix_scan_kb(void);  void matrix_init_user(void);  void matrix_scan_user(void); +#ifdef SPLIT_KEYBOARD +void matrix_slave_scan_kb(void); +void matrix_slave_scan_user(void); +#endif +  #ifdef __cplusplus  }  #endif diff --git a/quantum/mcu_selection.mk b/quantum/mcu_selection.mk index f7329fc4d9..9268c4522e 100644 --- a/quantum/mcu_selection.mk +++ b/quantum/mcu_selection.mk @@ -81,6 +81,33 @@ ifneq ($(findstring MK20DX256, $(MCU)),)    BOARD ?= PJRC_TEENSY_3_1  endif +ifneq ($(findstring MK66F18, $(MCU)),) +  # Cortex version +  MCU = cortex-m4 + +  # ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7 +  ARMV = 7 + +  ## chip/board settings +  # - the next two should match the directories in +  #   <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES) +  MCU_FAMILY = KINETIS +  MCU_SERIES = MK66F18 + +  # Linker script to use +  # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/ +  #   or <keyboard_dir>/ld/ +  MCU_LDSCRIPT ?= MK66FX1M0 + +  # Startup code to use +  #  - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/ +  MCU_STARTUP ?= MK66F18 + +  # Board: it should exist either in <chibios>/os/hal/boards/, +  # <keyboard_dir>/boards/, or drivers/boards/ +  BOARD ?= PJRC_TEENSY_3_6 +endif +  ifneq ($(findstring STM32F042, $(MCU)),)    # Cortex version    MCU = cortex-m0 @@ -112,6 +139,9 @@ ifneq ($(findstring STM32F042, $(MCU)),)    # Options to pass to dfu-util when flashing    DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave    DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 + +  # UF2 settings +  UF2_FAMILY ?= STM32F0  endif  ifneq ($(findstring STM32F072, $(MCU)),) @@ -145,6 +175,9 @@ ifneq ($(findstring STM32F072, $(MCU)),)    # Options to pass to dfu-util when flashing    DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave    DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 + +  # UF2 settings +  UF2_FAMILY ?= STM32F0  endif  ifneq ($(findstring STM32F103, $(MCU)),) @@ -178,6 +211,9 @@ ifneq ($(findstring STM32F103, $(MCU)),)    # Options to pass to dfu-util when flashing    DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave    DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 + +  # UF2 settings +  UF2_FAMILY ?= STM32F1  endif  ifneq ($(findstring STM32F303, $(MCU)),) @@ -211,6 +247,9 @@ ifneq ($(findstring STM32F303, $(MCU)),)    # Options to pass to dfu-util when flashing    DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave    DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 + +  # UF2 settings +  UF2_FAMILY ?= STM32F3  endif  ifneq ($(findstring STM32F401, $(MCU)),) @@ -244,6 +283,9 @@ ifneq ($(findstring STM32F401, $(MCU)),)    # Options to pass to dfu-util when flashing    DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave    DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 + +  # UF2 settings +  UF2_FAMILY ?= STM32F4  endif  ifneq ($(findstring STM32F411, $(MCU)),) @@ -262,7 +304,12 @@ ifneq ($(findstring STM32F411, $(MCU)),)    # Linker script to use    # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/    #   or <keyboard_dir>/ld/ -  MCU_LDSCRIPT ?= STM32F411xE +  ifeq ($(strip $(BOOTLOADER)), tinyuf2) +    MCU_LDSCRIPT ?= STM32F411xE_tinyuf2 +    FIRMWARE_FORMAT ?= uf2 +  else +    MCU_LDSCRIPT ?= STM32F411xE +  endif    # Startup code to use    #  - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/ @@ -277,6 +324,43 @@ ifneq ($(findstring STM32F411, $(MCU)),)    # Options to pass to dfu-util when flashing    DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave    DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 + +  # UF2 settings +  UF2_FAMILY ?= STM32F4 +endif + +ifneq ($(findstring STM32F446, $(MCU)),) +  # Cortex version +  MCU = cortex-m4 + +  # ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7 +  ARMV = 7 + +  ## chip/board settings +  # - the next two should match the directories in +  #   <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES) +  MCU_FAMILY = STM32 +  MCU_SERIES = STM32F4xx + +  # Linker script to use +  # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/ +  #   or <chibios>/os/common/startup/ARMCMx/compilers/GCC/ld/ +  #   or <keyboard_dir>/ld/ +  MCU_LDSCRIPT ?= STM32F446xE + +  # Startup code to use +  #  - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/ +  MCU_STARTUP ?= stm32f4xx + +  # Board: it should exist either in <chibios>/os/hal/boards/, +  # <keyboard_dir>/boards/, or drivers/boards/ +  BOARD ?= GENERIC_STM32_F446XE + +  USE_FPU ?= yes + +  # Options to pass to dfu-util when flashing +  DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave +  DFU_SUFFIX_ARGS ?= -v 0483 -p DF11  endif  ifneq ($(findstring STM32G431, $(MCU)),) @@ -310,6 +394,9 @@ ifneq ($(findstring STM32G431, $(MCU)),)    # Options to pass to dfu-util when flashing    DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave    DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 + +  # UF2 settings +  UF2_FAMILY ?= STM32G4  endif  ifneq ($(findstring STM32G474, $(MCU)),) @@ -343,6 +430,47 @@ ifneq ($(findstring STM32G474, $(MCU)),)    # Options to pass to dfu-util when flashing    DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave    DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 + +  # UF2 settings +  UF2_FAMILY ?= STM32G4 +endif + +ifneq (,$(filter $(MCU),STM32L433 STM32L443)) +  # Cortex version +  MCU = cortex-m4 + +  # ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7 +  ARMV = 7 + +  ## chip/board settings +  # - the next two should match the directories in +  #   <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES) +  MCU_FAMILY = STM32 +  MCU_SERIES = STM32L4xx + +  # Linker script to use +  # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/ +  #   or <keyboard_dir>/ld/ +  MCU_LDSCRIPT ?= STM32L432xC + +  # Startup code to use +  #  - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/ +  MCU_STARTUP ?= stm32l4xx + +  # Board: it should exist either in <chibios>/os/hal/boards/, +  # <keyboard_dir>/boards/, or drivers/boards/ +  BOARD ?= GENERIC_STM32_L433XC + +  PLATFORM_NAME ?= platform_l432 + +  USE_FPU ?= yes + +  # Options to pass to dfu-util when flashing +  DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave +  DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 + +  # UF2 settings +  UF2_FAMILY ?= STM32L4  endif  ifneq (,$(filter $(MCU),at90usb162 atmega16u2 atmega32u2 atmega16u4 atmega32u4 at90usb646 at90usb647 at90usb1286 at90usb1287)) diff --git a/quantum/process_keycode/process_auto_shift.c b/quantum/process_keycode/process_auto_shift.c index bf359e994d..51b0efdb47 100644 --- a/quantum/process_keycode/process_auto_shift.c +++ b/quantum/process_keycode/process_auto_shift.c @@ -216,7 +216,18 @@ bool process_auto_shift(uint16_t keycode, keyrecord_t *record) {  #    endif          }      } +    if (get_auto_shifted_key(keycode, record)) { +        if (record->event.pressed) { +            return autoshift_press(keycode, now, record); +        } else { +            autoshift_end(keycode, now, false); +            return false; +        } +    } +    return true; +} +__attribute__((weak)) bool get_auto_shifted_key(uint16_t keycode, keyrecord_t *record) {      switch (keycode) {  #    ifndef NO_AUTO_SHIFT_ALPHA          case KC_A ... KC_Z: @@ -229,14 +240,9 @@ bool process_auto_shift(uint16_t keycode, keyrecord_t *record) {          case KC_MINUS ... KC_SLASH:          case KC_NONUS_BSLASH:  #    endif -            if (record->event.pressed) { -                return autoshift_press(keycode, now, record); -            } else { -                autoshift_end(keycode, now, false); -                return false; -            } +            return true;      } -    return true; +    return false;  }  #endif diff --git a/quantum/process_keycode/process_auto_shift.h b/quantum/process_keycode/process_auto_shift.h index 5b2718f11c..00a9ab036f 100644 --- a/quantum/process_keycode/process_auto_shift.h +++ b/quantum/process_keycode/process_auto_shift.h @@ -31,3 +31,4 @@ bool     get_autoshift_state(void);  uint16_t get_autoshift_timeout(void);  void     set_autoshift_timeout(uint16_t timeout);  void     autoshift_matrix_scan(void); +bool     get_auto_shifted_key(uint16_t keycode, keyrecord_t *record); diff --git a/quantum/process_keycode/process_backlight.c b/quantum/process_keycode/process_backlight.c index 4d12f6813a..8b70339a55 100644 --- a/quantum/process_keycode/process_backlight.c +++ b/quantum/process_keycode/process_backlight.c @@ -16,11 +16,35 @@  #include "process_backlight.h" -#include "backlight.h" +#ifdef LED_MATRIX_ENABLE +#    include "led_matrix.h" +#else +#    include "backlight.h" +#endif  bool process_backlight(uint16_t keycode, keyrecord_t *record) {      if (record->event.pressed) {          switch (keycode) { +#ifdef LED_MATRIX_ENABLE +            case BL_ON: +                led_matrix_enable(); +                return false; +            case BL_OFF: +                led_matrix_disable(); +                return false; +            case BL_DEC: +                led_matrix_decrease_val(); +                return false; +            case BL_INC: +                led_matrix_increase_val(); +                return false; +            case BL_TOGG: +                led_matrix_toggle(); +                return false; +            case BL_STEP: +                led_matrix_step(); +                return false; +#else              case BL_ON:                  backlight_level(BACKLIGHT_LEVELS);                  return false; @@ -39,10 +63,11 @@ bool process_backlight(uint16_t keycode, keyrecord_t *record) {              case BL_STEP:                  backlight_step();                  return false; -#ifdef BACKLIGHT_BREATHING +#    ifdef BACKLIGHT_BREATHING              case BL_BRTG:                  backlight_toggle_breathing();                  return false; +#    endif  #endif          }      } diff --git a/quantum/process_keycode/process_leader.c b/quantum/process_keycode/process_leader.c index 58a615d85a..cf63f25141 100644 --- a/quantum/process_keycode/process_leader.c +++ b/quantum/process_keycode/process_leader.c @@ -49,7 +49,10 @@ bool process_leader(uint16_t keycode, keyrecord_t *record) {      // Leader key set-up      if (record->event.pressed) {          if (leading) { -            if (timer_elapsed(leader_time) < LEADER_TIMEOUT) { +#    ifndef LEADER_NO_TIMEOUT +            if (timer_elapsed(leader_time) < LEADER_TIMEOUT) +#    endif  // LEADER_NO_TIMEOUT +            {  #    ifndef LEADER_KEY_STRICT_KEY_PROCESSING                  if ((keycode >= QK_MOD_TAP && keycode <= QK_MOD_TAP_MAX) || (keycode >= QK_LAYER_TAP && keycode <= QK_LAYER_TAP_MAX)) {                      keycode = keycode & 0xFF; diff --git a/quantum/process_keycode/process_leader.h b/quantum/process_keycode/process_leader.h index 9844f27a1b..f3fe14a432 100644 --- a/quantum/process_keycode/process_leader.h +++ b/quantum/process_keycode/process_leader.h @@ -35,4 +35,9 @@ void qk_leader_start(void);      extern uint16_t leader_time;        \      extern uint16_t leader_sequence[5]; \      extern uint8_t  leader_sequence_size -#define LEADER_DICTIONARY() if (leading && timer_elapsed(leader_time) > LEADER_TIMEOUT) + +#ifdef LEADER_NO_TIMEOUT +#    define LEADER_DICTIONARY() if (leading && leader_sequence_size > 0 && timer_elapsed(leader_time) > LEADER_TIMEOUT) +#else +#    define LEADER_DICTIONARY() if (leading && timer_elapsed(leader_time) > LEADER_TIMEOUT) +#endif diff --git a/quantum/process_keycode/process_rgb.c b/quantum/process_keycode/process_rgb.c index 5dd8e7809d..167c0c03c9 100644 --- a/quantum/process_keycode/process_rgb.c +++ b/quantum/process_keycode/process_rgb.c @@ -207,6 +207,11 @@ bool process_rgb(const uint16_t keycode, const keyrecord_t *record) {                  rgblight_mode(RGBLIGHT_MODE_RGB_TEST);  #endif                  return false; +            case RGB_MODE_TWINKLE: +#if defined(RGBLIGHT_ENABLE) && !defined(RGBLIGHT_DISABLE_KEYCODES) && defined(RGBLIGHT_EFFECT_TWINKLE) +                handleKeycodeRGBMode(RGBLIGHT_MODE_TWINKLE, RGBLIGHT_MODE_TWINKLE_end); +#endif +                return false;          }      } diff --git a/quantum/quantum.c b/quantum/quantum.c index b40b40544a..8ccdb774bd 100644 --- a/quantum/quantum.c +++ b/quantum/quantum.c @@ -15,6 +15,7 @@   */  #include "quantum.h" +#include "magic.h"  #ifdef BLUETOOTH_ENABLE  #    include "outputselect.h" @@ -233,7 +234,7 @@ bool process_record_quantum(keyrecord_t *record) {  #ifdef AUDIO_ENABLE              process_audio(keycode, record) &&  #endif -#ifdef BACKLIGHT_ENABLE +#if defined(BACKLIGHT_ENABLE) || defined(LED_MATRIX_ENABLE)              process_backlight(keycode, record) &&  #endif  #ifdef STENO_ENABLE @@ -318,6 +319,17 @@ bool process_record_quantum(keyrecord_t *record) {                  set_output(OUTPUT_BLUETOOTH);                  return false;  #endif +#ifndef NO_ACTION_ONESHOT +            case ONESHOT_TOGGLE: +                oneshot_toggle(); +                break; +            case ONESHOT_ENABLE: +                oneshot_enable(); +                break; +            case ONESHOT_DISABLE: +                oneshot_disable(); +                break; +#endif          }      } @@ -341,26 +353,20 @@ layer_state_t update_tri_layer_state(layer_state_t state, uint8_t layer1, uint8_  void update_tri_layer(uint8_t layer1, uint8_t layer2, uint8_t layer3) { layer_state_set(update_tri_layer_state(layer_state, layer1, layer2, layer3)); }  void matrix_init_quantum() { -#ifdef BOOTMAGIC_LITE -    bootmagic_lite(); -#endif -    if (!eeconfig_is_enabled()) { -        eeconfig_init(); -    } +    magic();  #if defined(LED_NUM_LOCK_PIN) || defined(LED_CAPS_LOCK_PIN) || defined(LED_SCROLL_LOCK_PIN) || defined(LED_COMPOSE_PIN) || defined(LED_KANA_PIN)      // TODO: remove calls to led_init_ports from keyboards and remove ifdef      led_init_ports();  #endif  #ifdef BACKLIGHT_ENABLE -#    ifdef LED_MATRIX_ENABLE -    led_matrix_init(); -#    else      backlight_init_ports(); -#    endif  #endif  #ifdef AUDIO_ENABLE      audio_init();  #endif +#ifdef LED_MATRIX_ENABLE +    led_matrix_init(); +#endif  #ifdef RGB_MATRIX_ENABLE      rgb_matrix_init();  #endif diff --git a/quantum/quantum.h b/quantum/quantum.h index e24a4c43a3..fe6bf310aa 100644 --- a/quantum/quantum.h +++ b/quantum/quantum.h @@ -30,11 +30,11 @@  #include "keymap.h"  #ifdef BACKLIGHT_ENABLE -#    ifdef LED_MATRIX_ENABLE -#        include "led_matrix.h" -#    else -#        include "backlight.h" -#    endif +#    include "backlight.h" +#endif + +#ifdef LED_MATRIX_ENABLE +#    include "led_matrix.h"  #endif  #if defined(RGBLIGHT_ENABLE) @@ -52,6 +52,7 @@  #include "action_layer.h"  #include "eeconfig.h"  #include "bootloader.h" +#include "bootmagic.h"  #include "timer.h"  #include "sync_timer.h"  #include "config_common.h" @@ -97,7 +98,7 @@ extern layer_state_t layer_state;  #    include "process_music.h"  #endif -#ifdef BACKLIGHT_ENABLE +#if defined(BACKLIGHT_ENABLE) || defined(LED_MATRIX_ENABLE)  #    include "process_backlight.h"  #endif @@ -199,39 +200,6 @@ extern layer_state_t layer_state;  #    include "usbpd.h"  #endif -// Function substitutions to ease GPIO manipulation -#if defined(__AVR__) - -/*   The AVR series GPIOs have a one clock read delay for changes in the digital input signal. - *   But here's more margin to make it two clocks. */ -#    if !defined(GPIO_INPUT_PIN_DELAY) -#        define GPIO_INPUT_PIN_DELAY 2 -#    endif -#    define waitInputPinDelay() wait_cpuclock(GPIO_INPUT_PIN_DELAY) - -#elif defined(__ARMEL__) || defined(__ARMEB__) - -/* For GPIOs on ARM-based MCUs, the input pins are sampled by the clock of the bus - * to which the GPIO is connected. - * The connected buses differ depending on the various series of MCUs. - * And since the instruction execution clock of the CPU and the bus clock of GPIO are different, - * there is a delay of several clocks to read the change of the input signal. - * - * Define this delay with the GPIO_INPUT_PIN_DELAY macro. - * If the GPIO_INPUT_PIN_DELAY macro is not defined, the following default values will be used. - * (A fairly large value of 0.25 microseconds is set.) - */ -#    if !defined(GPIO_INPUT_PIN_DELAY) -#        if defined(STM32_SYSCLK) -#            define GPIO_INPUT_PIN_DELAY (STM32_SYSCLK / 1000000L / 4) -#        elif defined(KINETIS_SYSCLK_FREQUENCY) -#            define GPIO_INPUT_PIN_DELAY (KINETIS_SYSCLK_FREQUENCY / 1000000L / 4) -#        endif -#    endif -#    define waitInputPinDelay() wait_cpuclock(GPIO_INPUT_PIN_DELAY) - -#endif -  // For tri-layer  void          update_tri_layer(uint8_t layer1, uint8_t layer2, uint8_t layer3);  layer_state_t update_tri_layer_state(layer_state_t state, uint8_t layer1, uint8_t layer2, uint8_t layer3); @@ -256,15 +224,6 @@ bool     process_record_user(uint16_t keycode, keyrecord_t *record);  void     post_process_record_kb(uint16_t keycode, keyrecord_t *record);  void     post_process_record_user(uint16_t keycode, keyrecord_t *record); -#ifndef BOOTMAGIC_LITE_COLUMN -#    define BOOTMAGIC_LITE_COLUMN 0 -#endif -#ifndef BOOTMAGIC_LITE_ROW -#    define BOOTMAGIC_LITE_ROW 0 -#endif - -void bootmagic_lite(void); -  void reset_keyboard(void);  void startup_user(void); diff --git a/quantum/quantum_keycodes.h b/quantum/quantum_keycodes.h index e49f8dcdaa..26021598a1 100644 --- a/quantum/quantum_keycodes.h +++ b/quantum/quantum_keycodes.h @@ -16,19 +16,7 @@  #pragma once -#if defined(SEQUENCER_ENABLE) -#    include "sequencer.h" -#endif - -#ifndef MIDI_ENABLE_STRICT -#    define MIDI_ENABLE_STRICT 0 -#endif - -#if !MIDI_ENABLE_STRICT || (defined(MIDI_ENABLE) && defined(MIDI_ADVANCED)) -#    ifndef MIDI_TONE_KEYCODE_OCTAVES -#        define MIDI_TONE_KEYCODE_OCTAVES 3 -#    endif -#endif +#include "sequencer.h"  // Fillers to make layering more clear  #define _______ KC_TRNS @@ -67,6 +55,8 @@ enum quantum_keycodes {      QK_ONE_SHOT_LAYER_MAX   = 0x54FF,      QK_ONE_SHOT_MOD         = 0x5500,      QK_ONE_SHOT_MOD_MAX     = 0x55FF, +    QK_SWAP_HANDS           = 0x5600, +    QK_SWAP_HANDS_MAX       = 0x56FF,      QK_TAP_DANCE            = 0x5700,      QK_TAP_DANCE_MAX        = 0x57FF,      QK_LAYER_TAP_TOGGLE     = 0x5800, @@ -77,507 +67,458 @@ enum quantum_keycodes {      QK_STENO_BOLT           = 0x5A30,      QK_STENO_GEMINI         = 0x5A31,      QK_STENO_MAX            = 0x5A3F, -    QK_SWAP_HANDS           = 0x5B00, -    QK_SWAP_HANDS_MAX       = 0x5BFF, -    QK_MOD_TAP              = 0x6000, -    QK_MOD_TAP_MAX          = 0x7FFF, -    QK_UNICODE              = 0x8000, -    QK_UNICODE_MAX          = 0xFFFF, -    QK_UNICODEMAP           = 0x8000, -    QK_UNICODEMAP_MAX       = 0xBFFF, -    QK_UNICODEMAP_PAIR      = 0xC000, -    QK_UNICODEMAP_PAIR_MAX  = 0xFFFF, +    // 0x5C00 - 0x5FFF are reserved, see below +    QK_MOD_TAP             = 0x6000, +    QK_MOD_TAP_MAX         = 0x7FFF, +    QK_UNICODE             = 0x8000, +    QK_UNICODE_MAX         = 0xFFFF, +    QK_UNICODEMAP          = 0x8000, +    QK_UNICODEMAP_MAX      = 0xBFFF, +    QK_UNICODEMAP_PAIR     = 0xC000, +    QK_UNICODEMAP_PAIR_MAX = 0xFFFF,      // Loose keycodes - to be used directly      RESET = 0x5C00, -    DEBUG, -    MAGIC_SWAP_CONTROL_CAPSLOCK, -    MAGIC_CAPSLOCK_TO_CONTROL, -    MAGIC_SWAP_LALT_LGUI, -    MAGIC_SWAP_RALT_RGUI, -    MAGIC_NO_GUI, -    MAGIC_SWAP_GRAVE_ESC, -    MAGIC_SWAP_BACKSLASH_BACKSPACE, -    MAGIC_HOST_NKRO, -    MAGIC_SWAP_ALT_GUI, -    MAGIC_UNSWAP_CONTROL_CAPSLOCK, -    MAGIC_UNCAPSLOCK_TO_CONTROL, -    MAGIC_UNSWAP_LALT_LGUI, -    MAGIC_UNSWAP_RALT_RGUI, -    MAGIC_UNNO_GUI, -    MAGIC_UNSWAP_GRAVE_ESC, -    MAGIC_UNSWAP_BACKSLASH_BACKSPACE, -    MAGIC_UNHOST_NKRO, -    MAGIC_UNSWAP_ALT_GUI, -    MAGIC_TOGGLE_NKRO, -    MAGIC_TOGGLE_ALT_GUI, -    GRAVE_ESC, - -// Leader key -#ifdef LEADER_ENABLE -    KC_LEAD, -#endif - -// Auto Shift setup -#ifndef AUTO_SHIFT_NO_SETUP -    KC_ASUP, -    KC_ASDN, -    KC_ASRP, -#endif -    KC_ASTG, -    KC_ASON, -    KC_ASOFF, - -    // Audio on/off/toggle -    AU_ON, -    AU_OFF, -    AU_TOG, - -    // Faux clicky as part of main audio feature -    CLICKY_TOGGLE, -    CLICKY_ENABLE, -    CLICKY_DISABLE, -    CLICKY_UP, -    CLICKY_DOWN, -    CLICKY_RESET, - -    // Music mode on/off/toggle -    MU_ON, -    MU_OFF, -    MU_TOG, - -    // Music mode cycle -    MU_MOD, - -    // Music voice iterate -    MUV_IN, -    MUV_DE, - -// Midi -#if !MIDI_ENABLE_STRICT || (defined(MIDI_ENABLE) && defined(MIDI_BASIC)) -    MI_ON, -    MI_OFF, -    MI_TOG, -#endif - -#if !MIDI_ENABLE_STRICT || (defined(MIDI_ENABLE) && defined(MIDI_ADVANCED)) -    MIDI_TONE_MIN, - -#    if !MIDI_ENABLE_STRICT || MIDI_TONE_KEYCODE_OCTAVES > 0 -    MI_C = MIDI_TONE_MIN, -    MI_Cs, +    DEBUG,  // 5C01 + +    // Magic +    MAGIC_SWAP_CONTROL_CAPSLOCK,       // 5C02 +    MAGIC_CAPSLOCK_TO_CONTROL,         // 5C03 +    MAGIC_SWAP_LALT_LGUI,              // 5C04 +    MAGIC_SWAP_RALT_RGUI,              // 5C05 +    MAGIC_NO_GUI,                      // 5C06 +    MAGIC_SWAP_GRAVE_ESC,              // 5C07 +    MAGIC_SWAP_BACKSLASH_BACKSPACE,    // 5C08 +    MAGIC_HOST_NKRO,                   // 5C09 +    MAGIC_SWAP_ALT_GUI,                // 5C0A +    MAGIC_UNSWAP_CONTROL_CAPSLOCK,     // 5C0B +    MAGIC_UNCAPSLOCK_TO_CONTROL,       // 5C0C +    MAGIC_UNSWAP_LALT_LGUI,            // 5C0D +    MAGIC_UNSWAP_RALT_RGUI,            // 5C0E +    MAGIC_UNNO_GUI,                    // 5C0F +    MAGIC_UNSWAP_GRAVE_ESC,            // 5C10 +    MAGIC_UNSWAP_BACKSLASH_BACKSPACE,  // 5C11 +    MAGIC_UNHOST_NKRO,                 // 5C12 +    MAGIC_UNSWAP_ALT_GUI,              // 5C13 +    MAGIC_TOGGLE_NKRO,                 // 5C14 +    MAGIC_TOGGLE_ALT_GUI,              // 5C15 + +    // Grave Escape +    GRAVE_ESC,  // 5C16 + +    // Auto Shift +    KC_ASUP,   // 5C17 +    KC_ASDN,   // 5C18 +    KC_ASRP,   // 5C19 +    KC_ASTG,   // 5C1A +    KC_ASON,   // 5C1B +    KC_ASOFF,  // 5C1C + +    // Audio +    AU_ON,   // 5C1D +    AU_OFF,  // 5C1E +    AU_TOG,  // 5C1F + +    // Audio Clicky +    CLICKY_TOGGLE,   // 5C20 +    CLICKY_ENABLE,   // 5C21 +    CLICKY_DISABLE,  // 5C22 +    CLICKY_UP,       // 5C23 +    CLICKY_DOWN,     // 5C24 +    CLICKY_RESET,    // 5C25 + +    // Music mode +    MU_ON,   // 5C26 +    MU_OFF,  // 5C27 +    MU_TOG,  // 5C28 +    MU_MOD,  // 5C29 +    MUV_IN,  // 5C2A +    MUV_DE,  // 5C2B + +    // MIDI +    MI_ON,   // 5C2C +    MI_OFF,  // 5C2D +    MI_TOG,  // 5C2E + +    MI_C,   // 5C2F +    MI_Cs,  // 5C30      MI_Db = MI_Cs, -    MI_D, -    MI_Ds, +    MI_D,   // 5C31 +    MI_Ds,  // 5C32      MI_Eb = MI_Ds, -    MI_E, -    MI_F, -    MI_Fs, +    MI_E,   // 5C33 +    MI_F,   // 5C34 +    MI_Fs,  // 5C35      MI_Gb = MI_Fs, -    MI_G, -    MI_Gs, +    MI_G,   // 5C36 +    MI_Gs,  // 5C37      MI_Ab = MI_Gs, -    MI_A, -    MI_As, +    MI_A,   // 5C38 +    MI_As,  // 5C39      MI_Bb = MI_As, -    MI_B, -#    endif +    MI_B,  // 5C3A -#    if !MIDI_ENABLE_STRICT || MIDI_TONE_KEYCODE_OCTAVES > 1 -    MI_C_1, -    MI_Cs_1, +    MI_C_1,   // 5C3B +    MI_Cs_1,  // 5C3C      MI_Db_1 = MI_Cs_1, -    MI_D_1, -    MI_Ds_1, +    MI_D_1,   // 5C3D +    MI_Ds_1,  // 5C3E      MI_Eb_1 = MI_Ds_1, -    MI_E_1, -    MI_F_1, -    MI_Fs_1, +    MI_E_1,   // 5C3F +    MI_F_1,   // 5C40 +    MI_Fs_1,  // 5C41      MI_Gb_1 = MI_Fs_1, -    MI_G_1, -    MI_Gs_1, +    MI_G_1,   // 5C42 +    MI_Gs_1,  // 5C43      MI_Ab_1 = MI_Gs_1, -    MI_A_1, -    MI_As_1, +    MI_A_1,   // 5C44 +    MI_As_1,  // 5C45      MI_Bb_1 = MI_As_1, -    MI_B_1, -#    endif +    MI_B_1,  // 5C46 -#    if !MIDI_ENABLE_STRICT || MIDI_TONE_KEYCODE_OCTAVES > 2 -    MI_C_2, -    MI_Cs_2, +    MI_C_2,   // 5C47 +    MI_Cs_2,  // 5C48      MI_Db_2 = MI_Cs_2, -    MI_D_2, -    MI_Ds_2, +    MI_D_2,   // 5C49 +    MI_Ds_2,  // 5C4A      MI_Eb_2 = MI_Ds_2, -    MI_E_2, -    MI_F_2, -    MI_Fs_2, +    MI_E_2,   // 5C4B +    MI_F_2,   // 5C4C +    MI_Fs_2,  // 5C4D      MI_Gb_2 = MI_Fs_2, -    MI_G_2, -    MI_Gs_2, +    MI_G_2,   // 5C4E +    MI_Gs_2,  // 5C4F      MI_Ab_2 = MI_Gs_2, -    MI_A_2, -    MI_As_2, +    MI_A_2,   // 5C50 +    MI_As_2,  // 5C51      MI_Bb_2 = MI_As_2, -    MI_B_2, -#    endif +    MI_B_2,  // 5C52 -#    if !MIDI_ENABLE_STRICT || MIDI_TONE_KEYCODE_OCTAVES > 3 -    MI_C_3, -    MI_Cs_3, +    MI_C_3,   // 5C53 +    MI_Cs_3,  // 5C54      MI_Db_3 = MI_Cs_3, -    MI_D_3, -    MI_Ds_3, +    MI_D_3,   // 5C55 +    MI_Ds_3,  // 5C56      MI_Eb_3 = MI_Ds_3, -    MI_E_3, -    MI_F_3, -    MI_Fs_3, +    MI_E_3,   // 5C57 +    MI_F_3,   // 5C58 +    MI_Fs_3,  // 5C59      MI_Gb_3 = MI_Fs_3, -    MI_G_3, -    MI_Gs_3, +    MI_G_3,   // 5C5A +    MI_Gs_3,  // 5C5B      MI_Ab_3 = MI_Gs_3, -    MI_A_3, -    MI_As_3, +    MI_A_3,   // 5C5C +    MI_As_3,  // 5C5D      MI_Bb_3 = MI_As_3, -    MI_B_3, -#    endif +    MI_B_3,  // 5C5E -#    if !MIDI_ENABLE_STRICT || MIDI_TONE_KEYCODE_OCTAVES > 4 -    MI_C_4, -    MI_Cs_4, +    MI_C_4,   // 5C5F +    MI_Cs_4,  // 5C60      MI_Db_4 = MI_Cs_4, -    MI_D_4, -    MI_Ds_4, +    MI_D_4,   // 5C61 +    MI_Ds_4,  // 5C62      MI_Eb_4 = MI_Ds_4, -    MI_E_4, -    MI_F_4, -    MI_Fs_4, +    MI_E_4,   // 5C63 +    MI_F_4,   // 5C64 +    MI_Fs_4,  // 5C65      MI_Gb_4 = MI_Fs_4, -    MI_G_4, -    MI_Gs_4, +    MI_G_4,   // 5C66 +    MI_Gs_4,  // 5C67      MI_Ab_4 = MI_Gs_4, -    MI_A_4, -    MI_As_4, +    MI_A_4,   // 5C68 +    MI_As_4,  // 5C69      MI_Bb_4 = MI_As_4, -    MI_B_4, -#    endif +    MI_B_4,  // 5C6A -#    if !MIDI_ENABLE_STRICT || MIDI_TONE_KEYCODE_OCTAVES > 5 -    MI_C_5, -    MI_Cs_5, +    MI_C_5,   // 5C6B +    MI_Cs_5,  // 5C6C      MI_Db_5 = MI_Cs_5, -    MI_D_5, -    MI_Ds_5, +    MI_D_5,   // 5C6D +    MI_Ds_5,  // 5C6E      MI_Eb_5 = MI_Ds_5, -    MI_E_5, -    MI_F_5, -    MI_Fs_5, +    MI_E_5,   // 5C6F +    MI_F_5,   // 5C70 +    MI_Fs_5,  // 5C71      MI_Gb_5 = MI_Fs_5, -    MI_G_5, -    MI_Gs_5, +    MI_G_5,   // 5C72 +    MI_Gs_5,  // 5C73      MI_Ab_5 = MI_Gs_5, -    MI_A_5, -    MI_As_5, +    MI_A_5,   // 5C74 +    MI_As_5,  // 5C75      MI_Bb_5 = MI_As_5, -    MI_B_5, -#    endif - -#    if !MIDI_ENABLE_STRICT || MIDI_TONE_KEYCODE_OCTAVES > 5 -    MIDI_TONE_MAX = MI_B_5, -#    elif MIDI_TONE_KEYCODE_OCTAVES > 4 -    MIDI_TONE_MAX = MI_B_4, -#    elif MIDI_TONE_KEYCODE_OCTAVES > 3 -    MIDI_TONE_MAX = MI_B_3, -#    elif MIDI_TONE_KEYCODE_OCTAVES > 2 -    MIDI_TONE_MAX = MI_B_2, -#    elif MIDI_TONE_KEYCODE_OCTAVES > 1 -    MIDI_TONE_MAX = MI_B_1, -#    elif MIDI_TONE_KEYCODE_OCTAVES > 0 -    MIDI_TONE_MAX = MI_B, -#    endif - -    MIDI_OCTAVE_MIN, -    MI_OCT_N2 = MIDI_OCTAVE_MIN, -    MI_OCT_N1, -    MI_OCT_0, -    MI_OCT_1, -    MI_OCT_2, -    MI_OCT_3, -    MI_OCT_4, -    MI_OCT_5, -    MI_OCT_6, -    MI_OCT_7, -    MIDI_OCTAVE_MAX = MI_OCT_7, -    MI_OCTD,  // octave down -    MI_OCTU,  // octave up - -    MIDI_TRANSPOSE_MIN, -    MI_TRNS_N6 = MIDI_TRANSPOSE_MIN, -    MI_TRNS_N5, -    MI_TRNS_N4, -    MI_TRNS_N3, -    MI_TRNS_N2, -    MI_TRNS_N1, -    MI_TRNS_0, -    MI_TRNS_1, -    MI_TRNS_2, -    MI_TRNS_3, -    MI_TRNS_4, -    MI_TRNS_5, -    MI_TRNS_6, -    MIDI_TRANSPOSE_MAX = MI_TRNS_6, -    MI_TRNSD,  // transpose down -    MI_TRNSU,  // transpose up - -    MIDI_VELOCITY_MIN, -    MI_VEL_0 = MIDI_VELOCITY_MIN, -#    ifdef VIA_ENABLE -    MI_VEL_1 = MIDI_VELOCITY_MIN, -#    else -    MI_VEL_1, -#    endif -    MI_VEL_2, -    MI_VEL_3, -    MI_VEL_4, -    MI_VEL_5, -    MI_VEL_6, -    MI_VEL_7, -    MI_VEL_8, -    MI_VEL_9, -    MI_VEL_10, -    MIDI_VELOCITY_MAX = MI_VEL_10, -    MI_VELD,  // velocity down -    MI_VELU,  // velocity up - -    MIDI_CHANNEL_MIN, -    MI_CH1 = MIDI_CHANNEL_MIN, -    MI_CH2, -    MI_CH3, -    MI_CH4, -    MI_CH5, -    MI_CH6, -    MI_CH7, -    MI_CH8, -    MI_CH9, -    MI_CH10, -    MI_CH11, -    MI_CH12, -    MI_CH13, -    MI_CH14, -    MI_CH15, -    MI_CH16, -    MIDI_CHANNEL_MAX = MI_CH16, -    MI_CHD,  // previous channel -    MI_CHU,  // next channel - -    MI_ALLOFF,  // all notes off - -    MI_SUS,   // sustain -    MI_PORT,  // portamento -    MI_SOST,  // sostenuto -    MI_SOFT,  // soft pedal -    MI_LEG,   // legato - -    MI_MOD,    // modulation -    MI_MODSD,  // decrease modulation speed -    MI_MODSU,  // increase modulation speed - -    MI_BENDD,  // Bend down -    MI_BENDU,  // Bend up -#endif         // MIDI_ADVANCED - -    // Backlight functionality -    BL_ON, -    BL_OFF, -    BL_DEC, -    BL_INC, -    BL_TOGG, -    BL_STEP, -    BL_BRTG, - -    // RGB functionality -    RGB_TOG, -    RGB_MODE_FORWARD, -    RGB_MODE_REVERSE, -    RGB_HUI, -    RGB_HUD, -    RGB_SAI, -    RGB_SAD, -    RGB_VAI, -    RGB_VAD, -    RGB_SPI, -    RGB_SPD, -    RGB_MODE_PLAIN, -    RGB_MODE_BREATHE, -    RGB_MODE_RAINBOW, -    RGB_MODE_SWIRL, -    RGB_MODE_SNAKE, -    RGB_MODE_KNIGHT, -    RGB_MODE_XMAS, -    RGB_MODE_GRADIENT, -    RGB_MODE_RGBTEST, - -    // Momentum matching toggle -    VLK_TOG, - -    // Left shift, open paren -    KC_LSPO, - -    // Right shift, close paren -    KC_RSPC, - -    // Shift, Enter -    KC_SFTENT, - -    // Printing -    PRINT_ON, -    PRINT_OFF, - -    // output selection -    OUT_AUTO, -    OUT_USB, -#ifdef BLUETOOTH_ENABLE -    OUT_BT, -#endif - -#ifdef KEY_LOCK_ENABLE -    KC_LOCK, +    MI_B_5,  // 5C76 + +    MI_OCT_N2,  // 5C77 +    MI_OCT_N1,  // 5C78 +    MI_OCT_0,   // 5C79 +    MI_OCT_1,   // 5C7A +    MI_OCT_2,   // 5C7B +    MI_OCT_3,   // 5C7C +    MI_OCT_4,   // 5C7D +    MI_OCT_5,   // 5C7E +    MI_OCT_6,   // 5C7F +    MI_OCT_7,   // 5C80 +    MI_OCTD,    // 5C81 +    MI_OCTU,    // 5C82 + +    MI_TRNS_N6,  // 5C83 +    MI_TRNS_N5,  // 5C84 +    MI_TRNS_N4,  // 5C85 +    MI_TRNS_N3,  // 5C86 +    MI_TRNS_N2,  // 5C87 +    MI_TRNS_N1,  // 5C88 +    MI_TRNS_0,   // 5C89 +    MI_TRNS_1,   // 5C8A +    MI_TRNS_2,   // 5C8B +    MI_TRNS_3,   // 5C8C +    MI_TRNS_4,   // 5C8D +    MI_TRNS_5,   // 5C8E +    MI_TRNS_6,   // 5C8F +    MI_TRNSD,    // 5C90 +    MI_TRNSU,    // 5C91 + +    MI_VEL_0,  // 5C92 +#ifdef VIA_ENABLE +    MI_VEL_1 = MI_VEL_0, +#else +    MI_VEL_1,  // 5C93  #endif - -#ifdef TERMINAL_ENABLE -    TERM_ON, -    TERM_OFF, -#endif - -    EEPROM_RESET, - -    UNICODE_MODE_FORWARD, -    UNICODE_MODE_REVERSE, -    UNICODE_MODE_MAC, -    UNICODE_MODE_LNX, -    UNICODE_MODE_WIN, -    UNICODE_MODE_BSD, -    UNICODE_MODE_WINC, - -    HPT_ON, -    HPT_OFF, -    HPT_TOG, -    HPT_RST, -    HPT_FBK, -    HPT_BUZ, -    HPT_MODI, -    HPT_MODD, -    HPT_CONT, -    HPT_CONI, -    HPT_COND, -    HPT_DWLI, -    HPT_DWLD, - -    // Left control, open paren -    KC_LCPO, - -    // Right control, close paren -    KC_RCPC, - -    // Left control, open paren -    KC_LAPO, - -    // Right control, close paren -    KC_RAPC, - -    CMB_ON, -    CMB_OFF, -    CMB_TOG, - -    MAGIC_SWAP_LCTL_LGUI, -    MAGIC_SWAP_RCTL_RGUI, -    MAGIC_UNSWAP_LCTL_LGUI, -    MAGIC_UNSWAP_RCTL_RGUI, -    MAGIC_SWAP_CTL_GUI, -    MAGIC_UNSWAP_CTL_GUI, -    MAGIC_TOGGLE_CTL_GUI, -    MAGIC_EE_HANDS_LEFT, -    MAGIC_EE_HANDS_RIGHT, +    MI_VEL_2,   // 5C94 +    MI_VEL_3,   // 5C95 +    MI_VEL_4,   // 5C96 +    MI_VEL_5,   // 5C97 +    MI_VEL_6,   // 5C98 +    MI_VEL_7,   // 5C99 +    MI_VEL_8,   // 5C9A +    MI_VEL_9,   // 5C9B +    MI_VEL_10,  // 5C9C +    MI_VELD,    // 5C9D +    MI_VELU,    // 5C9E + +    MI_CH1,   // 5C9F +    MI_CH2,   // 5CA0 +    MI_CH3,   // 5CA1 +    MI_CH4,   // 5CA2 +    MI_CH5,   // 5CA3 +    MI_CH6,   // 5CA4 +    MI_CH7,   // 5CA5 +    MI_CH8,   // 5CA6 +    MI_CH9,   // 5CA7 +    MI_CH10,  // 5CA8 +    MI_CH11,  // 5CA9 +    MI_CH12,  // 5CAA +    MI_CH13,  // 5CAB +    MI_CH14,  // 5CAC +    MI_CH15,  // 5CAD +    MI_CH16,  // 5CAE +    MI_CHD,   // 5CAF +    MI_CHU,   // 5CB0 + +    MI_ALLOFF,  // 5CB1 + +    MI_SUS,   // 5CB2 +    MI_PORT,  // 5CB3 +    MI_SOST,  // 5CB4 +    MI_SOFT,  // 5CB5 +    MI_LEG,   // 5CB6 + +    MI_MOD,    // 5CB7 +    MI_MODSD,  // 5CB8 +    MI_MODSU,  // 5CB9 + +    MI_BENDD,  // 5CBA +    MI_BENDU,  // 5CBB + +    // Backlight +    BL_ON,    // 5CBC +    BL_OFF,   // 5CBD +    BL_DEC,   // 5CBE +    BL_INC,   // 5CBF +    BL_TOGG,  // 5CC0 +    BL_STEP,  // 5CC1 +    BL_BRTG,  // 5CC2 + +    // RGB underglow/matrix +    RGB_TOG,            // 5CC3 +    RGB_MODE_FORWARD,   // 5CC4 +    RGB_MODE_REVERSE,   // 5CC5 +    RGB_HUI,            // 5CC6 +    RGB_HUD,            // 5CC7 +    RGB_SAI,            // 5CC8 +    RGB_SAD,            // 5CC9 +    RGB_VAI,            // 5CCA +    RGB_VAD,            // 5CCB +    RGB_SPI,            // 5CCC +    RGB_SPD,            // 5CCD +    RGB_MODE_PLAIN,     // 5CCE +    RGB_MODE_BREATHE,   // 5CCF +    RGB_MODE_RAINBOW,   // 5CD0 +    RGB_MODE_SWIRL,     // 5CD1 +    RGB_MODE_SNAKE,     // 5CD2 +    RGB_MODE_KNIGHT,    // 5CD3 +    RGB_MODE_XMAS,      // 5CD4 +    RGB_MODE_GRADIENT,  // 5CD5 +    RGB_MODE_RGBTEST,   // 5CD6 + +    // Velocikey +    VLK_TOG,  // 5CD7 + +    // Space Cadet +    KC_LSPO,    // 5CD8 +    KC_RSPC,    // 5CD9 +    KC_SFTENT,  // 5CDA + +    // Thermal Printer +    PRINT_ON,   // 5CDB +    PRINT_OFF,  // 5CDC + +    // Bluetooth: output selection +    OUT_AUTO,  // 5CDD +    OUT_USB,   // 5CDE + +    // Clear EEPROM +    EEPROM_RESET,  // 5CDF + +    // Unicode +    UNICODE_MODE_FORWARD,  // 5CE0 +    UNICODE_MODE_REVERSE,  // 5CE1 +    UNICODE_MODE_MAC,      // 5CE2 +    UNICODE_MODE_LNX,      // 5CE3 +    UNICODE_MODE_WIN,      // 5CE4 +    UNICODE_MODE_BSD,      // 5CE5 +    UNICODE_MODE_WINC,     // 5CE6 + +    // Haptic +    HPT_ON,    // 5CE7 +    HPT_OFF,   // 5CE8 +    HPT_TOG,   // 5CE9 +    HPT_RST,   // 5CEA +    HPT_FBK,   // 5CEB +    HPT_BUZ,   // 5CEC +    HPT_MODI,  // 5CED +    HPT_MODD,  // 5CEE +    HPT_CONT,  // 5CEF +    HPT_CONI,  // 5CF0 +    HPT_COND,  // 5CF1 +    HPT_DWLI,  // 5CF2 +    HPT_DWLD,  // 5CF3 + +    // Space Cadet (continued) +    KC_LCPO,  // 5CF4 +    KC_RCPC,  // 5CF5 +    KC_LAPO,  // 5CF6 +    KC_RAPC,  // 5CF7 + +    // Combos +    CMB_ON,   // 5CF8 +    CMB_OFF,  // 5CF9 +    CMB_TOG,  // 5CFA + +    // Magic (continued) +    MAGIC_SWAP_LCTL_LGUI,    // 5CFB +    MAGIC_SWAP_RCTL_RGUI,    // 5CFC +    MAGIC_UNSWAP_LCTL_LGUI,  // 5CFD +    MAGIC_UNSWAP_RCTL_RGUI,  // 5CFE +    MAGIC_SWAP_CTL_GUI,      // 5CFF +    MAGIC_UNSWAP_CTL_GUI,    // 5D00 +    MAGIC_TOGGLE_CTL_GUI,    // 5D01 +    MAGIC_EE_HANDS_LEFT,     // 5D02 +    MAGIC_EE_HANDS_RIGHT,    // 5D03      // Dynamic Macros -    DYN_REC_START1, -    DYN_REC_START2, -    DYN_REC_STOP, -    DYN_MACRO_PLAY1, -    DYN_MACRO_PLAY2, - -    JS_BUTTON0, -    JS_BUTTON_MIN = JS_BUTTON0, -    JS_BUTTON1, -    JS_BUTTON2, -    JS_BUTTON3, -    JS_BUTTON4, -    JS_BUTTON5, -    JS_BUTTON6, -    JS_BUTTON7, -    JS_BUTTON8, -    JS_BUTTON9, -    JS_BUTTON10, -    JS_BUTTON11, -    JS_BUTTON12, -    JS_BUTTON13, -    JS_BUTTON14, -    JS_BUTTON15, -    JS_BUTTON16, -    JS_BUTTON17, -    JS_BUTTON18, -    JS_BUTTON19, -    JS_BUTTON20, -    JS_BUTTON21, -    JS_BUTTON22, -    JS_BUTTON23, -    JS_BUTTON24, -    JS_BUTTON25, -    JS_BUTTON26, -    JS_BUTTON27, -    JS_BUTTON28, -    JS_BUTTON29, -    JS_BUTTON30, -    JS_BUTTON31, -    JS_BUTTON_MAX = JS_BUTTON31, - -#if defined(SEQUENCER_ENABLE) -    SQ_ON, -    SQ_OFF, -    SQ_TOG, - -    SQ_TMPD,  // Decrease tempo -    SQ_TMPU,  // Increase tempo +    DYN_REC_START1,   // 5D04 +    DYN_REC_START2,   // 5D05 +    DYN_REC_STOP,     // 5D06 +    DYN_MACRO_PLAY1,  // 5D07 +    DYN_MACRO_PLAY2,  // 5D08 + +    // Joystick +    JS_BUTTON0,   // 5D09 +    JS_BUTTON1,   // 5D0A +    JS_BUTTON2,   // 5D0B +    JS_BUTTON3,   // 5D0C +    JS_BUTTON4,   // 5D0D +    JS_BUTTON5,   // 5D0E +    JS_BUTTON6,   // 5D0F +    JS_BUTTON7,   // 5D10 +    JS_BUTTON8,   // 5D11 +    JS_BUTTON9,   // 5D12 +    JS_BUTTON10,  // 5D13 +    JS_BUTTON11,  // 5D14 +    JS_BUTTON12,  // 5D15 +    JS_BUTTON13,  // 5D16 +    JS_BUTTON14,  // 5D17 +    JS_BUTTON15,  // 5D18 +    JS_BUTTON16,  // 5D19 +    JS_BUTTON17,  // 5D1A +    JS_BUTTON18,  // 5D1B +    JS_BUTTON19,  // 5D1C +    JS_BUTTON20,  // 5D1D +    JS_BUTTON21,  // 5D1E +    JS_BUTTON22,  // 5D1F +    JS_BUTTON23,  // 5D20 +    JS_BUTTON24,  // 5D21 +    JS_BUTTON25,  // 5D22 +    JS_BUTTON26,  // 5D23 +    JS_BUTTON27,  // 5D24 +    JS_BUTTON28,  // 5D25 +    JS_BUTTON29,  // 5D26 +    JS_BUTTON30,  // 5D27 +    JS_BUTTON31,  // 5D28 + +    // Leader Key +    KC_LEAD,  // 5D29 + +    // Bluetooth: output selection (continued) +    OUT_BT,  // 5D2A + +    // Lock Key +    KC_LOCK,  // 5D2B + +    // Terminal +    TERM_ON,   // 5D2C +    TERM_OFF,  // 5D2D + +    // Sequencer +    SQ_ON,   // 5D2E +    SQ_OFF,  // 5D2F +    SQ_TOG,  // 5D30 + +    SQ_TMPD,  // 5D31 +    SQ_TMPU,  // 5D32 + +    SQ_RESD,  // 5D33 +    SQ_RESU,  // 5D34 + +    SQ_SALL,  // 5D35 +    SQ_SCLR,  // 5D36 + +    SEQUENCER_STEP_MIN,  // 5D37 +    SEQUENCER_STEP_MAX = SEQUENCER_STEP_MIN + SEQUENCER_STEPS,      SEQUENCER_RESOLUTION_MIN,      SEQUENCER_RESOLUTION_MAX = SEQUENCER_RESOLUTION_MIN + SEQUENCER_RESOLUTIONS, -    SQ_RESD,  // Decrease resolution -    SQ_RESU,  // Increase resolution - -    SQ_SALL,  // All steps on -    SQ_SCLR,  // All steps off -    SEQUENCER_STEP_MIN, -    SEQUENCER_STEP_MAX = SEQUENCER_STEP_MIN + SEQUENCER_STEPS,      SEQUENCER_TRACK_MIN,      SEQUENCER_TRACK_MAX = SEQUENCER_TRACK_MIN + SEQUENCER_TRACKS, -/** - * Helpers to assign a keycode to a step, a resolution, or a track. - * Falls back to NOOP if n is out of range. - */ -#    define SQ_S(n) (n < SEQUENCER_STEPS ? SEQUENCER_STEP_MIN + n : XXXXXXX) -#    define SQ_R(n) (n < SEQUENCER_RESOLUTIONS ? SEQUENCER_RESOLUTION_MIN + n : XXXXXXX) -#    define SQ_T(n) (n < SEQUENCER_TRACKS ? SEQUENCER_TRACK_MIN + n : XXXXXXX) +#define SQ_S(n) (n < SEQUENCER_STEPS ? SEQUENCER_STEP_MIN + n : KC_NO) +#define SQ_R(n) (n < SEQUENCER_RESOLUTIONS ? SEQUENCER_RESOLUTION_MIN + n : KC_NO) +#define SQ_T(n) (n < SEQUENCER_TRACKS ? SEQUENCER_TRACK_MIN + n : KC_NO) -#endif +    // One Shot +    ONESHOT_ENABLE, +    ONESHOT_DISABLE, +    ONESHOT_TOGGLE, + +    // RGB underglow/matrix (continued) +    RGB_MODE_TWINKLE, -    // always leave at the end +    // Start of custom keycode range for keyboards and keymaps - always leave at the end      SAFE_RANGE  }; -// Ability to use mods in layouts +// Keycode modifiers & aliases  #define LCTL(kc) (QK_LCTL | (kc))  #define LSFT(kc) (QK_LSFT | (kc))  #define LALT(kc) (QK_LALT | (kc)) @@ -609,11 +550,7 @@ enum quantum_keycodes {  #define MOD_HYPR 0xF  #define MOD_MEH 0x7 -// Aliases for shifted symbols -// Each key has a 4-letter code, and some have longer aliases too. -// While the long aliases are descriptive, the 4-letter codes -// make for nicer grid layouts (everything lines up), and are -// the preferred style for Quantum. +// US ANSI shifted keycode aliases  #define KC_TILD LSFT(KC_GRV)  // ~  #define KC_TILDE KC_TILD @@ -680,18 +617,15 @@ enum quantum_keycodes {  #define KC_DELT KC_DELETE  // Del key (four letter code) -// Alias for function layers than expand past FN31 -#define FUNC(kc) (QK_FUNCTION | (kc)) - -// Aliases +// Modified keycode aliases  #define C(kc) LCTL(kc)  #define S(kc) LSFT(kc)  #define A(kc) LALT(kc)  #define G(kc) LGUI(kc) -#define F(kc) FUNC(kc) +// Deprecated - do not use +#define F(kc) (QK_FUNCTION | (kc))  #define M(kc) (QK_MACRO | (kc)) -  #define MACROTAP(kc) (QK_MACRO | (FUNC_TAP << 8) | (kc))  #define MACRODOWN(...) (record->event.pressed ? MACRO(__VA_ARGS__) : MACRO_NONE) @@ -699,19 +633,21 @@ enum quantum_keycodes {  #define EEP_RST EEPROM_RESET +// Audio Clicky aliases  #define CK_TOGG CLICKY_TOGGLE  #define CK_RST CLICKY_RESET  #define CK_UP CLICKY_UP  #define CK_DOWN CLICKY_DOWN  #define CK_ON CLICKY_ENABLE  #define CK_OFF CLICKY_DISABLE +// Fauxclicky (deprecated) redirects to Audio Clicky  #define FC_ON CLICKY_ENABLE  #define FC_OFF CLICKY_DISABLE  #define FC_TOGG CLICKY_TOGGLE +// RGB aliases  #define RGB_MOD RGB_MODE_FORWARD  #define RGB_RMOD RGB_MODE_REVERSE -  #define RGB_M_P RGB_MODE_PLAIN  #define RGB_M_B RGB_MODE_BREATHE  #define RGB_M_R RGB_MODE_RAINBOW @@ -721,10 +657,9 @@ enum quantum_keycodes {  #define RGB_M_X RGB_MODE_XMAS  #define RGB_M_G RGB_MODE_GRADIENT  #define RGB_M_T RGB_MODE_RGBTEST +#define RGB_M_TW RGB_MODE_TWINKLE -// L-ayer, T-ap - 256 keycode max, 16 layer max -#define LT(layer, kc) (QK_LAYER_TAP | (((layer)&0xF) << 8) | ((kc)&0xFF)) - +// Magic aliases  #define CL_SWAP MAGIC_SWAP_CONTROL_CAPSLOCK  #define CL_NORM MAGIC_UNSWAP_CONTROL_CAPSLOCK  #define CL_CTRL MAGIC_CAPSLOCK_TO_CONTROL @@ -793,6 +728,9 @@ enum quantum_keycodes {  // Layer tap-toggle  #define TT(layer) (QK_LAYER_TAP_TOGGLE | ((layer)&0xFF)) +// L-ayer, T-ap - 256 keycode max, 16 layer max +#define LT(layer, kc) (QK_LAYER_TAP | (((layer)&0xF) << 8) | ((kc)&0xFF)) +  // M-od, T-ap - 256 keycode max  #define MT(mod, kc) (QK_MOD_TAP | (((mod)&0x1F) << 8) | ((kc)&0xFF)) @@ -842,6 +780,7 @@ enum quantum_keycodes {  #define KC_HYPR HYPR(KC_NO)  #define KC_MEH MEH(KC_NO) +// Unicode aliases  // UNICODE_ENABLE - Allows Unicode input up to 0x7FFF  #define UC(c) (QK_UNICODE | (c))  // UNICODEMAP_ENABLE - Allows Unicode input up to 0x10FFFF, requires unicode_map @@ -859,6 +798,7 @@ enum quantum_keycodes {  #define UC_M_BS UNICODE_MODE_BSD  #define UC_M_WC UNICODE_MODE_WINC +// Swap Hands  #define SH_T(kc) (QK_SWAP_HANDS | (kc))  #define SH_TG (QK_SWAP_HANDS | OP_SH_TOGGLE)  #define SH_TT (QK_SWAP_HANDS | OP_SH_TAP_TOGGLE) @@ -868,9 +808,30 @@ enum quantum_keycodes {  #define SH_ON (QK_SWAP_HANDS | OP_SH_ON)  #define SH_OFF (QK_SWAP_HANDS | OP_SH_OFF) +// MIDI aliases +#define MIDI_TONE_MIN MI_C +#define MIDI_TONE_MAX MI_B_5 +#define MIDI_OCTAVE_MIN MI_OCT_N2 +#define MIDI_OCTAVE_MAX MI_OCT_7 +#define MIDI_TRANSPOSE_MIN MI_TRNS_N6 +#define MIDI_TRANSPOSE_MAX MI_TRNS_6 +#define MIDI_VELOCITY_MIN MI_VEL_0 +#define MIDI_VELOCITY_MAX MI_VEL_10 +#define MIDI_CHANNEL_MIN MI_CH1 +#define MIDI_CHANNEL_MAX MI_CH16 +  // Dynamic Macros aliases  #define DM_REC1 DYN_REC_START1  #define DM_REC2 DYN_REC_START2  #define DM_RSTP DYN_REC_STOP  #define DM_PLY1 DYN_MACRO_PLAY1  #define DM_PLY2 DYN_MACRO_PLAY2 + +// Joystick aliases +#define JS_BUTTON_MIN JS_BUTTON0 +#define JS_BUTTON_MAX JS_BUTTON31 + +// One Shot aliases +#define OS_TOGG ONESHOT_TOGGLE +#define OS_ON ONESHOT_ENABLE +#define OS_OFF ONESHOT_DISABLE diff --git a/quantum/rgb_matrix.c b/quantum/rgb_matrix.c index ec17b4d72c..e716c6aad3 100644 --- a/quantum/rgb_matrix.c +++ b/quantum/rgb_matrix.c @@ -26,9 +26,9 @@  #include <lib/lib8tion/lib8tion.h>  #ifndef RGB_MATRIX_CENTER -const point_t k_rgb_matrix_center = {112, 32}; +const led_point_t k_rgb_matrix_center = {112, 32};  #else -const point_t k_rgb_matrix_center = RGB_MATRIX_CENTER; +const led_point_t k_rgb_matrix_center = RGB_MATRIX_CENTER;  #endif  __attribute__((weak)) RGB rgb_matrix_hsv_to_rgb(HSV hsv) { return hsv_to_rgb(hsv); } @@ -67,8 +67,8 @@ __attribute__((weak)) RGB rgb_matrix_hsv_to_rgb(HSV hsv) { return hsv_to_rgb(hsv  #    define RGB_DISABLE_TIMEOUT 0  #endif -#ifndef RGB_DISABLE_WHEN_USB_SUSPENDED -#    define RGB_DISABLE_WHEN_USB_SUSPENDED false +#if RGB_DISABLE_WHEN_USB_SUSPENDED == false +#    undef RGB_DISABLE_WHEN_USB_SUSPENDED  #endif  #if !defined(RGB_MATRIX_MAXIMUM_BRIGHTNESS) || RGB_MATRIX_MAXIMUM_BRIGHTNESS > UINT8_MAX @@ -118,7 +118,6 @@ __attribute__((weak)) RGB rgb_matrix_hsv_to_rgb(HSV hsv) { return hsv_to_rgb(hsv  #endif  // globals -bool         g_suspend_state = false;  rgb_config_t rgb_matrix_config;  // TODO: would like to prefix this with g_ for global consistancy, do this in another pr  uint32_t     g_rgb_timer;  #ifdef RGB_MATRIX_FRAMEBUFFER_EFFECTS @@ -129,9 +128,10 @@ last_hit_t g_last_hit_tracker;  #endif  // RGB_MATRIX_KEYREACTIVE_ENABLED  // internals +static bool            suspend_state     = false;  static uint8_t         rgb_last_enable   = UINT8_MAX;  static uint8_t         rgb_last_effect   = UINT8_MAX; -static effect_params_t rgb_effect_params = {0, 0xFF}; +static effect_params_t rgb_effect_params = {0, LED_FLAG_ALL, false};  static rgb_task_states rgb_task_state    = SYNCING;  #if RGB_DISABLE_TIMEOUT > 0  static uint32_t rgb_anykey_timer; @@ -143,6 +143,11 @@ static uint32_t rgb_timer_buffer;  static last_hit_t last_hit_buffer;  #endif  // RGB_MATRIX_KEYREACTIVE_ENABLED +// split rgb matrix +#if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) +const uint8_t k_rgb_matrix_split[2] = RGB_MATRIX_SPLIT; +#endif +  void eeconfig_read_rgb_matrix(void) { eeprom_read_block(&rgb_matrix_config, EECONFIG_RGB_MATRIX, sizeof(rgb_matrix_config)); }  void eeconfig_update_rgb_matrix(void) { eeprom_update_block(&rgb_matrix_config, EECONFIG_RGB_MATRIX, sizeof(rgb_matrix_config)); } @@ -153,6 +158,7 @@ void eeconfig_update_rgb_matrix_default(void) {      rgb_matrix_config.mode   = RGB_MATRIX_STARTUP_MODE;      rgb_matrix_config.hsv    = (HSV){RGB_MATRIX_STARTUP_HUE, RGB_MATRIX_STARTUP_SAT, RGB_MATRIX_STARTUP_VAL};      rgb_matrix_config.speed  = RGB_MATRIX_STARTUP_SPD; +    rgb_matrix_config.flags  = LED_FLAG_ALL;      eeconfig_update_rgb_matrix();  } @@ -164,6 +170,7 @@ void eeconfig_debug_rgb_matrix(void) {      dprintf("rgb_matrix_config.hsv.s = %d\n", rgb_matrix_config.hsv.s);      dprintf("rgb_matrix_config.hsv.v = %d\n", rgb_matrix_config.hsv.v);      dprintf("rgb_matrix_config.speed = %d\n", rgb_matrix_config.speed); +    dprintf("rgb_matrix_config.flags = %d\n", rgb_matrix_config.flags);  }  __attribute__((weak)) uint8_t rgb_matrix_map_row_column_to_led_kb(uint8_t row, uint8_t column, uint8_t *led_i) { return 0; } @@ -180,9 +187,22 @@ uint8_t rgb_matrix_map_row_column_to_led(uint8_t row, uint8_t column, uint8_t *l  void rgb_matrix_update_pwm_buffers(void) { rgb_matrix_driver.flush(); } -void rgb_matrix_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) { rgb_matrix_driver.set_color(index, red, green, blue); } +void rgb_matrix_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) { +#if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) +    if (!is_keyboard_left() && index >= k_rgb_matrix_split[0]) +        rgb_matrix_driver.set_color(index - k_rgb_matrix_split[0], red, green, blue); +    else if (is_keyboard_left() && index < k_rgb_matrix_split[0]) +#endif +        rgb_matrix_driver.set_color(index, red, green, blue); +} -void rgb_matrix_set_color_all(uint8_t red, uint8_t green, uint8_t blue) { rgb_matrix_driver.set_color_all(red, green, blue); } +void rgb_matrix_set_color_all(uint8_t red, uint8_t green, uint8_t blue) { +#if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) +    for (uint8_t i = 0; i < DRIVER_LED_TOTAL; i++) rgb_matrix_set_color(i, red, green, blue); +#else +    rgb_matrix_driver.set_color_all(red, green, blue); +#endif +}  void process_rgb_matrix(uint8_t row, uint8_t col, bool pressed) {  #ifndef RGB_MATRIX_SPLIT @@ -315,6 +335,10 @@ static void rgb_task_start(void) {  static void rgb_task_render(uint8_t effect) {      bool rendering         = false;      rgb_effect_params.init = (effect != rgb_last_effect) || (rgb_matrix_config.enable != rgb_last_enable); +    if (rgb_effect_params.flags != rgb_matrix_config.flags) { +        rgb_effect_params.flags = rgb_matrix_config.flags; +        rgb_matrix_set_color_all(0, 0, 0); +    }      // each effect can opt to do calculations      // and/or request PWM buffer updates. @@ -385,14 +409,11 @@ void rgb_matrix_task(void) {      // Ideally we would also stop sending zeros to the LED driver PWM buffers      // while suspended and just do a software shutdown. This is a cheap hack for now. -    bool suspend_backlight = -#if RGB_DISABLE_WHEN_USB_SUSPENDED == true -        g_suspend_state || -#endif  // RGB_DISABLE_WHEN_USB_SUSPENDED == true +    bool suspend_backlight = suspend_state ||  #if RGB_DISABLE_TIMEOUT > 0 -        (rgb_anykey_timer > (uint32_t)RGB_DISABLE_TIMEOUT) || +                             (rgb_anykey_timer > (uint32_t)RGB_DISABLE_TIMEOUT) ||  #endif  // RGB_DISABLE_TIMEOUT > 0 -        false; +                             false;      uint8_t effect = suspend_backlight || !rgb_matrix_config.enable ? 0 : rgb_matrix_config.mode; @@ -477,13 +498,15 @@ void rgb_matrix_init(void) {  }  void rgb_matrix_set_suspend_state(bool state) { -    if (RGB_DISABLE_WHEN_USB_SUSPENDED && state) { +#ifdef RGB_DISABLE_WHEN_USB_SUSPENDED +    if (state) {          rgb_matrix_set_color_all(0, 0, 0);  // turn off all LEDs when suspending      } -    g_suspend_state = state; +    suspend_state = state; +#endif  } -bool rgb_matrix_get_suspend_state(void) { return g_suspend_state; } +bool rgb_matrix_get_suspend_state(void) { return suspend_state; }  void rgb_matrix_toggle_eeprom_helper(bool write_to_eeprom) {      rgb_matrix_config.enable ^= 1; @@ -618,6 +641,6 @@ void rgb_matrix_decrease_speed_helper(bool write_to_eeprom) { rgb_matrix_set_spe  void rgb_matrix_decrease_speed_noeeprom(void) { rgb_matrix_decrease_speed_helper(false); }  void rgb_matrix_decrease_speed(void) { rgb_matrix_decrease_speed_helper(true); } -led_flags_t rgb_matrix_get_flags(void) { return rgb_effect_params.flags; } +led_flags_t rgb_matrix_get_flags(void) { return rgb_matrix_config.flags; } -void rgb_matrix_set_flags(led_flags_t flags) { rgb_effect_params.flags = flags; } +void rgb_matrix_set_flags(led_flags_t flags) { rgb_matrix_config.flags = flags; } diff --git a/quantum/rgb_matrix.h b/quantum/rgb_matrix.h index bb8bcfab68..a615b8422c 100644 --- a/quantum/rgb_matrix.h +++ b/quantum/rgb_matrix.h @@ -216,7 +216,6 @@ extern const rgb_matrix_driver_t rgb_matrix_driver;  extern rgb_config_t rgb_matrix_config; -extern bool         g_suspend_state;  extern uint32_t     g_rgb_timer;  extern led_config_t g_led_config;  #ifdef RGB_MATRIX_KEYREACTIVE_ENABLED diff --git a/quantum/rgb_matrix_types.h b/quantum/rgb_matrix_types.h index 7b8171fb23..df575d6577 100644 --- a/quantum/rgb_matrix_types.h +++ b/quantum/rgb_matrix_types.h @@ -62,7 +62,7 @@ typedef struct PACKED {  typedef struct PACKED {      uint8_t x;      uint8_t y; -} point_t; +} led_point_t;  #define HAS_FLAGS(bits, flags) ((bits & flags) == flags)  #define HAS_ANY_FLAGS(bits, flags) ((bits & flags) != 0x00) @@ -77,18 +77,19 @@ typedef struct PACKED {  #define NO_LED 255  typedef struct PACKED { -    uint8_t matrix_co[MATRIX_ROWS][MATRIX_COLS]; -    point_t point[DRIVER_LED_TOTAL]; -    uint8_t flags[DRIVER_LED_TOTAL]; +    uint8_t     matrix_co[MATRIX_ROWS][MATRIX_COLS]; +    led_point_t point[DRIVER_LED_TOTAL]; +    uint8_t     flags[DRIVER_LED_TOTAL];  } led_config_t;  typedef union {      uint32_t raw;      struct PACKED { -        uint8_t enable : 2; -        uint8_t mode : 6; -        HSV     hsv; -        uint8_t speed;  // EECONFIG needs to be increased to support this +        uint8_t     enable : 2; +        uint8_t     mode : 6; +        HSV         hsv; +        uint8_t     speed;  // EECONFIG needs to be increased to support this +        led_flags_t flags;      };  } rgb_config_t; diff --git a/quantum/split_common/matrix.c b/quantum/split_common/matrix.c index d6636b886a..f8de17809d 100644 --- a/quantum/split_common/matrix.c +++ b/quantum/split_common/matrix.c @@ -43,6 +43,7 @@ extern matrix_row_t matrix[MATRIX_ROWS];      // debounced values  uint8_t thisHand, thatHand;  // user-defined overridable functions +__attribute__((weak)) void matrix_slave_scan_kb(void) { matrix_slave_scan_user(); }  __attribute__((weak)) void matrix_slave_scan_user(void) {}  static inline void setPinOutput_writeLow(pin_t pin) { @@ -284,7 +285,7 @@ bool matrix_post_scan(void) {      } else {          transport_slave(matrix + thatHand, matrix + thisHand); -        matrix_slave_scan_user(); +        matrix_slave_scan_kb();      }      return changed; diff --git a/quantum/split_common/split_util.c b/quantum/split_common/split_util.c index 2ae44e6e15..9e75e19ce0 100644 --- a/quantum/split_common/split_util.c +++ b/quantum/split_common/split_util.c @@ -1,3 +1,18 @@ +/* Copyright 2021 QMK + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 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 <http://www.gnu.org/licenses/>. + */  #include "split_util.h"  #include "matrix.h"  #include "keyboard.h" @@ -6,14 +21,7 @@  #include "transport.h"  #include "quantum.h"  #include "wait.h" - -#ifdef PROTOCOL_LUFA -#    include <LUFA/Drivers/USB/USB.h> -#endif - -#ifdef PROTOCOL_VUSB -#    include <usbdrv/usbdrv.h> -#endif +#include "usb_util.h"  #ifdef EE_HANDS  #    include "eeconfig.h" @@ -31,56 +39,21 @@  #    define SPLIT_USB_TIMEOUT_POLL 10  #endif -#ifdef PROTOCOL_CHIBIOS -#    define SPLIT_USB_DETECT  // Force this on for now -#endif -  volatile bool isLeftHand = true;  #if defined(SPLIT_USB_DETECT) -#    if defined(PROTOCOL_LUFA) -static inline bool usbHasActiveConnection(void) { return USB_Device_IsAddressSet(); } -static inline void usbDisable(void) { -    USB_Disable(); -    USB_DeviceState = DEVICE_STATE_Unattached; -} -#    elif defined(PROTOCOL_CHIBIOS) -static inline bool usbHasActiveConnection(void) { return usbGetDriverStateI(&USBD1) == USB_ACTIVE; } -static inline void usbDisable(void) { usbStop(&USBD1); } -#    elif defined(PROTOCOL_VUSB) -static inline bool usbHasActiveConnection(void) { -    usbPoll(); -    return usbConfiguration; -} -static inline void usbDisable(void) { usbDeviceDisconnect(); } -#    else -static inline bool usbHasActiveConnection(void) { return true; } -static inline void usbDisable(void) {} -#    endif - -bool usbIsActive(void) { +static bool usbIsActive(void) {      for (uint8_t i = 0; i < (SPLIT_USB_TIMEOUT / SPLIT_USB_TIMEOUT_POLL); i++) {          // This will return true if a USB connection has been established -        if (usbHasActiveConnection()) { +        if (usb_connected_state()) {              return true;          }          wait_ms(SPLIT_USB_TIMEOUT_POLL);      } - -    // Avoid NO_USB_STARTUP_CHECK - Disable USB as the previous checks seem to enable it somehow -    usbDisable(); -      return false;  } -#elif defined(PROTOCOL_LUFA) && defined(OTGPADE) -static inline bool usbIsActive(void) { -    USB_OTGPAD_On();  // enables VBUS pad -    wait_us(5); - -    return USB_VBUS_GetStatus();  // checks state of VBUS -}  #else -static inline bool usbIsActive(void) { return true; } +static inline bool usbIsActive(void) { return usb_vbus_state(); }  #endif  #ifdef SPLIT_HAND_MATRIX_GRID @@ -126,6 +99,11 @@ __attribute__((weak)) bool is_keyboard_master(void) {      // only check once, as this is called often      if (usbstate == UNKNOWN) {          usbstate = usbIsActive() ? MASTER : SLAVE; + +        // Avoid NO_USB_STARTUP_CHECK - Disable USB as the previous checks seem to enable it somehow +        if (usbstate == SLAVE) { +            usb_disable(); +        }      }      return (usbstate == MASTER); diff --git a/quantum/split_common/transport.c b/quantum/split_common/transport.c index 61b61ea08c..9b3f70ed06 100644 --- a/quantum/split_common/transport.c +++ b/quantum/split_common/transport.c @@ -22,6 +22,13 @@ static pin_t encoders_pad[] = ENCODERS_PAD_A;  #    define NUMBER_OF_ENCODERS (sizeof(encoders_pad) / sizeof(pin_t))  #endif +#if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) +#    include "led_matrix.h" +#endif +#if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) +#    include "rgb_matrix.h" +#endif +  #if defined(USE_I2C)  #    include "i2c_master.h" @@ -54,6 +61,14 @@ typedef struct _I2C_slave_buffer_t {  #    ifdef WPM_ENABLE      uint8_t current_wpm;  #    endif +#    if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) +    led_eeconfig_t led_matrix; +    bool           led_suspend_state; +#    endif +#    if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) +    rgb_config_t rgb_matrix; +    bool         rgb_suspend_state; +#    endif  } I2C_slave_buffer_t;  static I2C_slave_buffer_t *const i2c_buffer = (I2C_slave_buffer_t *)i2c_slave_reg; @@ -68,6 +83,10 @@ static I2C_slave_buffer_t *const i2c_buffer = (I2C_slave_buffer_t *)i2c_slave_re  #    define I2C_RGB_START offsetof(I2C_slave_buffer_t, rgblight_sync)  #    define I2C_ENCODER_START offsetof(I2C_slave_buffer_t, encoder_state)  #    define I2C_WPM_START offsetof(I2C_slave_buffer_t, current_wpm) +#    define I2C_LED_MATRIX_START offsetof(I2C_slave_buffer_t, led_matrix) +#    define I2C_LED_SUSPEND_START offsetof(I2C_slave_buffer_t, led_suspend_state) +#    define I2C_RGB_MATRIX_START offsetof(I2C_slave_buffer_t, rgb_matrix) +#    define I2C_RGB_SUSPEND_START offsetof(I2C_slave_buffer_t, rgb_suspend_state)  #    define TIMEOUT 100 @@ -141,6 +160,17 @@ bool transport_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[])  #        endif  #    endif +#    if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) +    i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_LED_MATRIX_START, (void *)led_matrix_eeconfig, sizeof(i2c_buffer->led_matrix), TIMEOUT); +    bool suspend_state = led_matrix_get_suspend_state(); +    i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_LED_SUSPEND_START, (void *)suspend_state, sizeof(i2c_buffer->led_suspend_state), TIMEOUT); +#    endif +#    if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) +    i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_RGB_MATRIX_START, (void *)rgb_matrix_config, sizeof(i2c_buffer->rgb_matrix), TIMEOUT); +    bool suspend_state = rgb_matrix_get_suspend_state(); +    i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_RGB_SUSPEND_START, (void *)suspend_state, sizeof(i2c_buffer->rgb_suspend_state), TIMEOUT); +#    endif +  #    ifndef DISABLE_SYNC_TIMER      i2c_buffer->sync_timer = sync_timer_read32() + SYNC_TIMER_OFFSET;      i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_SYNC_TIME_START, (void *)&i2c_buffer->sync_timer, sizeof(i2c_buffer->sync_timer), TIMEOUT); @@ -186,6 +216,15 @@ void transport_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[])      set_oneshot_mods(i2c_buffer->oneshot_mods);  #        endif  #    endif + +#    if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) +    memcpy((void *)i2c_buffer->led_matrix, (void *)led_matrix_eeconfig, sizeof(i2c_buffer->led_matrix)); +    led_matrix_set_suspend_state(i2c_buffer->led_suspend_state); +#    endif +#    if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) +    memcpy((void *)i2c_buffer->rgb_matrix, (void *)rgb_matrix_config, sizeof(i2c_buffer->rgb_matrix)); +    rgb_matrix_set_suspend_state(i2c_buffer->rgb_suspend_state); +#    endif  }  void transport_master_init(void) { i2c_init(); } @@ -208,23 +247,31 @@ typedef struct _Serial_s2m_buffer_t {  typedef struct _Serial_m2s_buffer_t {  #    ifdef SPLIT_MODS_ENABLE -    uint8_t      real_mods; -    uint8_t      weak_mods; +    uint8_t        real_mods; +    uint8_t        weak_mods;  #        ifndef NO_ACTION_ONESHOT -    uint8_t      oneshot_mods; +    uint8_t        oneshot_mods;  #        endif  #    endif  #    ifndef DISABLE_SYNC_TIMER -    uint32_t     sync_timer; +    uint32_t       sync_timer;  #    endif  #    ifdef SPLIT_TRANSPORT_MIRROR -    matrix_row_t mmatrix[ROWS_PER_HAND]; +    matrix_row_t   mmatrix[ROWS_PER_HAND];  #    endif  #    ifdef BACKLIGHT_ENABLE -    uint8_t      backlight_level; +    uint8_t        backlight_level;  #    endif  #    ifdef WPM_ENABLE -    uint8_t      current_wpm; +    uint8_t        current_wpm; +#    endif +#    if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) +    led_eeconfig_t led_matrix; +    bool           led_suspend_state; +#    endif +#    if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) +    rgb_config_t   rgb_matrix; +    bool           rgb_suspend_state;  #    endif  } Serial_m2s_buffer_t; @@ -333,18 +380,28 @@ bool transport_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[])  #    ifdef WPM_ENABLE      // Write wpm to slave -    serial_m2s_buffer.current_wpm  = get_current_wpm(); +    serial_m2s_buffer.current_wpm       = get_current_wpm();  #    endif  #    ifdef SPLIT_MODS_ENABLE -    serial_m2s_buffer.real_mods    = get_mods(); -    serial_m2s_buffer.weak_mods    = get_weak_mods(); +    serial_m2s_buffer.real_mods         = get_mods(); +    serial_m2s_buffer.weak_mods         = get_weak_mods();  #        ifndef NO_ACTION_ONESHOT -    serial_m2s_buffer.oneshot_mods = get_oneshot_mods(); +    serial_m2s_buffer.oneshot_mods      = get_oneshot_mods();  #        endif  #    endif + +#    if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) +    serial_m2s_buffer.led_matrix        = led_matrix_econfig; +    serial_m2s_buffer.led_suspend_state = led_matrix_get_suspend_state(); +#    endif +#    if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) +    serial_m2s_buffer.rgb_matrix        = rgb_matrix_config; +    serial_m2s_buffer.rgb_suspend_state = rgb_matrix_get_suspend_state(); +#    endif +  #    ifndef DISABLE_SYNC_TIMER -    serial_m2s_buffer.sync_timer   = sync_timer_read32() + SYNC_TIMER_OFFSET; +    serial_m2s_buffer.sync_timer        = sync_timer_read32() + SYNC_TIMER_OFFSET;  #    endif      return true;  } @@ -381,6 +438,15 @@ void transport_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[])      set_oneshot_mods(serial_m2s_buffer.oneshot_mods);  #        endif  #    endif + +#    if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT) +    led_matrix_eeconfig = serial_m2s_buffer.led_matrix; +    led_matrix_set_suspend_state(serial_m2s_buffer.led_suspend_state); +#    endif +#    if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT) +    rgb_matrix_config = serial_m2s_buffer.rgb_matrix; +    rgb_matrix_set_suspend_state(serial_m2s_buffer.rgb_suspend_state); +#    endif  }  #endif diff --git a/quantum/wpm.c b/quantum/wpm.c index da30bd252c..bec419a48e 100644 --- a/quantum/wpm.c +++ b/quantum/wpm.c @@ -19,11 +19,10 @@  // WPM Stuff  static uint8_t  current_wpm = 0; -static uint8_t  latest_wpm  = 0;  static uint16_t wpm_timer   = 0;  // This smoothing is 40 keystrokes -static const float wpm_smoothing = 0.0487; +static const float wpm_smoothing = WPM_SMOOTHING;  void set_current_wpm(uint8_t new_wpm) { current_wpm = new_wpm; } @@ -46,19 +45,46 @@ __attribute__((weak)) bool wpm_keycode_user(uint16_t keycode) {      return false;  } +#ifdef WPM_ALLOW_COUNT_REGRESSION +__attribute__((weak)) uint8_t wpm_regress_count(uint16_t keycode) { +    bool weak_modded = (keycode >= QK_LCTL && keycode < QK_LSFT) || (keycode >= QK_RCTL && keycode < QK_RSFT); + +    if ((keycode >= QK_MOD_TAP && keycode <= QK_MOD_TAP_MAX) || (keycode >= QK_LAYER_TAP && keycode <= QK_LAYER_TAP_MAX) || (keycode >= QK_MODS && keycode <= QK_MODS_MAX)) { +        keycode = keycode & 0xFF; +    } else if (keycode > 0xFF) { +        keycode = 0; +    } +    if (keycode == KC_DEL || keycode == KC_BSPC) { +        if (((get_mods() | get_oneshot_mods()) & MOD_MASK_CTRL) || weak_modded) { +            return WPM_ESTIMATED_WORD_SIZE; +        } else { +            return 1; +        } +    } else { +        return 0; +    } +} +#endif +  void update_wpm(uint16_t keycode) {      if (wpm_keycode(keycode)) {          if (wpm_timer > 0) { -            latest_wpm  = 60000 / timer_elapsed(wpm_timer) / 5; -            current_wpm = (latest_wpm - current_wpm) * wpm_smoothing + current_wpm; +            current_wpm += ((60000 / timer_elapsed(wpm_timer) / WPM_ESTIMATED_WORD_SIZE) - current_wpm) * wpm_smoothing;          }          wpm_timer = timer_read();      } +#ifdef WPM_ALLOW_COUNT_REGRESSION +    uint8_t regress = wpm_regress_count(keycode); +    if (regress) { +        current_wpm -= regress; +        wpm_timer = timer_read(); +    } +#endif  }  void decay_wpm(void) {      if (timer_elapsed(wpm_timer) > 1000) { -        current_wpm = (0 - current_wpm) * wpm_smoothing + current_wpm; -        wpm_timer   = timer_read(); +        current_wpm += (-current_wpm) * wpm_smoothing; +        wpm_timer = timer_read();      }  } diff --git a/quantum/wpm.h b/quantum/wpm.h index 15ab4ffcd1..4af52d2b98 100644 --- a/quantum/wpm.h +++ b/quantum/wpm.h @@ -19,10 +19,21 @@  #include "quantum.h" +#ifndef WPM_ESTIMATED_WORD_SIZE +#    define WPM_ESTIMATED_WORD_SIZE 5 +#endif +#ifndef WPM_SMOOTHING +#    define WPM_SMOOTHING 0.0487 +#endif +  bool wpm_keycode(uint16_t keycode);  bool wpm_keycode_kb(uint16_t keycode);  bool wpm_keycode_user(uint16_t keycode); +#ifdef WPM_ALLOW_COUNT_REGRESSION +uint8_t wpm_regress_count(uint16_t keycode); +#endif +  void    set_current_wpm(uint8_t);  uint8_t get_current_wpm(void);  void    update_wpm(uint16_t); | 
