diff options
Diffstat (limited to 'quantum')
60 files changed, 2441 insertions, 918 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..f3d4bc896e 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) { @@ -53,16 +46,28 @@ static void init(void) { # endif # else # ifdef LED_DRIVER_ADDR_1 - IS31FL3733_init(LED_DRIVER_ADDR_1, 0); +# ifndef LED_DRIVER_SYNC_1 +# define LED_DRIVER_SYNC_1 0 +# endif + IS31FL3733_init(LED_DRIVER_ADDR_1, LED_DRIVER_SYNC_1); # endif # ifdef LED_DRIVER_ADDR_2 - IS31FL3733_init(LED_DRIVER_ADDR_2, 0); +# ifndef LED_DRIVER_SYNC_2 +# define LED_DRIVER_SYNC_2 0 +# endif + IS31FL3733_init(LED_DRIVER_ADDR_2, LED_DRIVER_SYNC_2); # endif # ifdef LED_DRIVER_ADDR_3 - IS31FL3733_init(LED_DRIVER_ADDR_3, 0); +# ifndef LED_DRIVER_SYNC_3 +# define LED_DRIVER_SYNC_3 0 +# endif + IS31FL3733_init(LED_DRIVER_ADDR_3, LED_DRIVER_SYNC_3); # endif # ifdef LED_DRIVER_ADDR_4 - IS31FL3733_init(LED_DRIVER_ADDR_4, 0); +# ifndef LED_DRIVER_SYNC_4 +# define LED_DRIVER_SYNC_4 0 +# endif + IS31FL3733_init(LED_DRIVER_ADDR_4, LED_DRIVER_SYNC_4); # endif # endif @@ -140,7 +145,7 @@ const led_matrix_driver_t led_matrix_driver = { .set_value = IS31FL3731_set_value, .set_value_all = IS31FL3731_set_value_all, # else - .set_value = IS31FL3733_set_value, + .set_value = IS31FL3733_set_value, .set_value_all = IS31FL3733_set_value_all, # endif }; 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.c b/quantum/matrix.c index c027b7bf27..34d6af2e6d 100644 --- a/quantum/matrix.c +++ b/quantum/matrix.c @@ -116,9 +116,7 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) // Unselect row unselect_row(current_row); - if (current_row + 1 < MATRIX_ROWS) { - matrix_output_unselect_delay(); // wait for row signal to go HIGH - } + matrix_output_unselect_delay(); // wait for all Col signals to go HIGH // If the row has changed, store the row and return the changed flag. if (current_matrix[current_row] != current_row_value) { @@ -178,9 +176,7 @@ static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) // Unselect col unselect_col(current_col); - if (current_col + 1 < MATRIX_COLS) { - matrix_output_unselect_delay(); // wait for col signal to go HIGH - } + matrix_output_unselect_delay(); // wait for all Row signals to go HIGH return matrix_changed; } 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_drivers.c b/quantum/rgb_matrix_drivers.c index 2978e7bed9..a4db86d196 100644 --- a/quantum/rgb_matrix_drivers.c +++ b/quantum/rgb_matrix_drivers.c @@ -41,7 +41,28 @@ static void init(void) { IS31FL3731_init(DRIVER_ADDR_4); # endif # elif defined(IS31FL3733) - IS31FL3733_init(DRIVER_ADDR_1, 0); +# ifndef DRIVER_SYNC_1 +# define DRIVER_SYNC_1 0 +# endif + IS31FL3733_init(DRIVER_ADDR_1, DRIVER_SYNC_1); +# if defined DRIVER_ADDR_2 && (DRIVER_ADDR_1 != DRIVER_ADDR_2) +# ifndef DRIVER_SYNC_2 +# define DRIVER_SYNC_2 0 +# endif + IS31FL3733_init(DRIVER_ADDR_2, DRIVER_SYNC_2); +# endif +# ifdef DRIVER_ADDR_3 +# ifndef DRIVER_SYNC_3 +# define DRIVER_SYNC_3 0 +# endif + IS31FL3733_init(DRIVER_ADDR_3, DRIVER_SYNC_3); +# endif +# ifdef DRIVER_ADDR_4 +# ifndef DRIVER_SYNC_4 +# define DRIVER_SYNC_4 0 +# endif + IS31FL3733_init(DRIVER_ADDR_4, DRIVER_SYNC_4); +# endif # elif defined(IS31FL3737) IS31FL3737_init(DRIVER_ADDR_1); # else @@ -74,7 +95,15 @@ static void init(void) { # endif # elif defined(IS31FL3733) IS31FL3733_update_led_control_registers(DRIVER_ADDR_1, 0); +# ifdef DRIVER_ADDR_2 IS31FL3733_update_led_control_registers(DRIVER_ADDR_2, 1); +# endif +# ifdef DRIVER_ADDR_3 + IS31FL3733_update_led_control_registers(DRIVER_ADDR_3, 2); +# endif +# ifdef DRIVER_ADDR_4 + IS31FL3733_update_led_control_registers(DRIVER_ADDR_4, 3); +# endif # elif defined(IS31FL3737) IS31FL3737_update_led_control_registers(DRIVER_ADDR_1, DRIVER_ADDR_2); # else @@ -105,13 +134,21 @@ const rgb_matrix_driver_t rgb_matrix_driver = { # elif defined(IS31FL3733) static void flush(void) { IS31FL3733_update_pwm_buffers(DRIVER_ADDR_1, 0); +# ifdef DRIVER_ADDR_2 IS31FL3733_update_pwm_buffers(DRIVER_ADDR_2, 1); +# endif +# ifdef DRIVER_ADDR_3 + IS31FL3733_update_pwm_buffers(DRIVER_ADDR_3, 2); +# endif +# ifdef DRIVER_ADDR_4 + IS31FL3733_update_pwm_buffers(DRIVER_ADDR_4, 3); +# endif } const rgb_matrix_driver_t rgb_matrix_driver = { - .init = init, - .flush = flush, - .set_color = IS31FL3733_set_color, + .init = init, + .flush = flush, + .set_color = IS31FL3733_set_color, .set_color_all = IS31FL3733_set_color_all, }; # elif defined(IS31FL3737) 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/rgblight.c b/quantum/rgblight.c index 119d3eab21..e4c4d555e5 100644 --- a/quantum/rgblight.c +++ b/quantum/rgblight.c @@ -722,23 +722,41 @@ static void rgblight_layers_write(void) { } # ifdef RGBLIGHT_LAYER_BLINK -rgblight_layer_mask_t _blinked_layer_mask = 0; -static uint16_t _blink_timer; +rgblight_layer_mask_t _blinking_layer_mask = 0; +static uint16_t _repeat_timer; +static uint8_t _times_remaining; +static uint16_t _dur; void rgblight_blink_layer(uint8_t layer, uint16_t duration_ms) { + rgblight_blink_layer_repeat(layer, duration_ms, 1); +} + +void rgblight_blink_layer_repeat(uint8_t layer, uint16_t duration_ms, uint8_t times) { + _times_remaining = times * 2; + _dur = duration_ms; + rgblight_set_layer_state(layer, true); - _blinked_layer_mask |= (rgblight_layer_mask_t)1 << layer; - _blink_timer = sync_timer_read() + duration_ms; + _times_remaining--; + _blinking_layer_mask |= (rgblight_layer_mask_t)1 << layer; + _repeat_timer = sync_timer_read() + duration_ms; } -void rgblight_unblink_layers(void) { - if (_blinked_layer_mask != 0 && timer_expired(sync_timer_read(), _blink_timer)) { +void rgblight_blink_layer_repeat_helper(void) { + if (_blinking_layer_mask != 0 && timer_expired(sync_timer_read(), _repeat_timer)) { for (uint8_t layer = 0; layer < RGBLIGHT_MAX_LAYERS; layer++) { - if ((_blinked_layer_mask & (rgblight_layer_mask_t)1 << layer) != 0) { - rgblight_set_layer_state(layer, false); + if ((_blinking_layer_mask & (rgblight_layer_mask_t)1 << layer) != 0 && _times_remaining > 0) { + if (_times_remaining % 2 == 1) { + rgblight_set_layer_state(layer, false); + } else { + rgblight_set_layer_state(layer, true); + } + _times_remaining--; + _repeat_timer = sync_timer_read() + _dur; } } - _blinked_layer_mask = 0; + if (_times_remaining <= 0) { + _blinking_layer_mask = 0; + } } } # endif @@ -755,8 +773,8 @@ void rgblight_suspend(void) { # ifdef RGBLIGHT_LAYER_BLINK // make sure any layer blinks don't come back after suspend - rgblight_status.enabled_layer_mask &= ~_blinked_layer_mask; - _blinked_layer_mask = 0; + rgblight_status.enabled_layer_mask &= ~_blinking_layer_mask; + _blinking_layer_mask = 0; # endif rgblight_disable_noeeprom(); @@ -1030,7 +1048,7 @@ void rgblight_task(void) { } # ifdef RGBLIGHT_LAYER_BLINK - rgblight_unblink_layers(); + rgblight_blink_layer_repeat_helper(); # endif } diff --git a/quantum/rgblight.h b/quantum/rgblight.h index 6fb3ab9380..bec2c66955 100644 --- a/quantum/rgblight.h +++ b/quantum/rgblight.h @@ -222,6 +222,7 @@ extern const rgblight_segment_t *const *rgblight_layers; # ifdef RGBLIGHT_LAYER_BLINK # define RGBLIGHT_USE_TIMER void rgblight_blink_layer(uint8_t layer, uint16_t duration_ms); +void rgblight_blink_layer_repeat(uint8_t layer, uint16_t duration_ms, uint8_t times); # endif # endif diff --git a/quantum/split_common/matrix.c b/quantum/split_common/matrix.c index d6636b886a..039e7d9773 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) { @@ -129,9 +130,7 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) // Unselect row unselect_row(current_row); - if (current_row + 1 < MATRIX_ROWS) { - matrix_output_unselect_delay(); // wait for row signal to go HIGH - } + matrix_output_unselect_delay(); // wait for all Col signals to go HIGH // If the row has changed, store the row and return the changed flag. if (current_matrix[current_row] != current_row_value) { @@ -191,9 +190,7 @@ static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) // Unselect col unselect_col(current_col); - if (current_col + 1 < MATRIX_COLS) { - matrix_output_unselect_delay(); // wait for col signal to go HIGH - } + matrix_output_unselect_delay(); // wait for all Row signals to go HIGH return matrix_changed; } @@ -284,7 +281,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..bf942c5260 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_eeconfig; + 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); |