Merge tag '0.13.13' into firmware_21

This commit is contained in:
Drashna Jael're
2021-07-08 21:16:31 -07:00
177 changed files with 5485 additions and 1649 deletions
+21 -3
View File
@@ -17,11 +17,16 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "quantum.h"
#include "backlight.h"
#include "eeprom.h"
#include "eeconfig.h"
#include "debug.h"
backlight_config_t backlight_config;
#ifndef BACKLIGHT_DEFAULT_LEVEL
# define BACKLIGHT_DEFAULT_LEVEL BACKLIGHT_LEVELS
#endif
#ifdef BACKLIGHT_BREATHING
// TODO: migrate to backlight_config_t
static uint8_t breathing_period = BREATHING_PERIOD;
@@ -35,6 +40,7 @@ void backlight_init(void) {
/* check signature */
if (!eeconfig_is_enabled()) {
eeconfig_init();
eeconfig_update_backlight_default();
}
backlight_config.raw = eeconfig_read_backlight();
if (backlight_config.level > BACKLIGHT_LEVELS) {
@@ -152,11 +158,23 @@ void backlight_level(uint8_t level) {
eeconfig_update_backlight(backlight_config.raw);
}
/** \brief Update current backlight state to EEPROM
*
*/
uint8_t eeconfig_read_backlight(void) { return eeprom_read_byte(EECONFIG_BACKLIGHT); }
void eeconfig_update_backlight(uint8_t val) { eeprom_update_byte(EECONFIG_BACKLIGHT, val); }
void eeconfig_update_backlight_current(void) { eeconfig_update_backlight(backlight_config.raw); }
void eeconfig_update_backlight_default(void) {
backlight_config.enable = 1;
#ifdef BACKLIGHT_DEFAULT_BREATHING
backlight_config.breathing = 1;
#else
backlight_config.breathing = 0;
#endif
backlight_config.level = BACKLIGHT_DEFAULT_LEVEL;
eeconfig_update_backlight(backlight_config.raw);
}
/** \brief Get backlight level
*
* FIXME: needs doc
+4
View File
@@ -55,7 +55,11 @@ void backlight_decrease(void);
void backlight_level_noeeprom(uint8_t level);
void backlight_level(uint8_t level);
uint8_t get_backlight_level(void);
uint8_t eeconfig_read_backlight(void);
void eeconfig_update_backlight(uint8_t val);
void eeconfig_update_backlight_current(void);
void eeconfig_update_backlight_default(void);
// implementation specific
void backlight_init_ports(void);
+24
View File
@@ -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);
+147
View File
@@ -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);
}
}
+115
View File
@@ -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
+66
View File
@@ -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(); }
+25
View File
@@ -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);
+54
View File
@@ -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);
}
+18
View File
@@ -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);
+3
View File
@@ -24,4 +24,7 @@
#define COL2ROW 0
#define ROW2COL 1
// Deprecated alias - avoid using
#define KEYMAP LAYOUT
#include "song_list.h"
+5 -5
View File
@@ -59,9 +59,9 @@ static uint8_t thisHand, thatHand;
static uint8_t encoder_value[NUMBER_OF_ENCODERS] = {0};
#endif
__attribute__((weak)) void encoder_update_user(int8_t index, bool clockwise) {}
__attribute__((weak)) bool encoder_update_user(uint8_t index, bool clockwise) { return true; }
__attribute__((weak)) void encoder_update_kb(int8_t index, bool clockwise) { encoder_update_user(index, clockwise); }
__attribute__((weak)) bool encoder_update_kb(uint8_t index, bool clockwise) { return encoder_update_user(index, clockwise); }
void encoder_init(void) {
#if defined(SPLIT_KEYBOARD) && defined(ENCODERS_PAD_A_RIGHT) && defined(ENCODERS_PAD_B_RIGHT)
@@ -94,14 +94,14 @@ void encoder_init(void) {
#endif
}
static bool encoder_update(int8_t index, uint8_t state) {
static bool encoder_update(uint8_t index, uint8_t state) {
bool changed = false;
uint8_t i = index;
#ifdef ENCODER_RESOLUTIONS
int8_t resolution = encoder_resolutions[i];
uint8_t resolution = encoder_resolutions[i];
#else
int8_t resolution = ENCODER_RESOLUTION;
uint8_t resolution = ENCODER_RESOLUTION;
#endif
#ifdef SPLIT_KEYBOARD
+2 -2
View File
@@ -22,8 +22,8 @@
void encoder_init(void);
bool encoder_read(void);
void encoder_update_kb(int8_t index, bool clockwise);
void encoder_update_user(int8_t index, bool clockwise);
bool encoder_update_kb(uint8_t index, bool clockwise);
bool encoder_update_user(uint8_t index, bool clockwise);
#ifdef SPLIT_KEYBOARD
void encoder_state_raw(uint8_t* slave_state);
+1
View File
@@ -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;
+438 -203
View File
@@ -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
#ifndef LED_DISABLE_AFTER_TIMEOUT
# define LED_DISABLE_AFTER_TIMEOUT 0
#undef LED_MATRIX_CUSTOM_EFFECT_IMPLS
#undef LED_MATRIX_EFFECT
// -----End led effect includes macros-------
// ------------------------------------------
#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 != 1
# 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;
g_any_key_hit = 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
}
return true;
}
void led_matrix_set_suspend_state(bool state) { g_suspend_state = state; }
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
}
// All LEDs off
void led_matrix_all_off(void) { led_matrix_set_index_value_all(0); }
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
// Uniform brightness
void led_matrix_uniform_brightness(void) { led_matrix_set_index_value_all(LED_MATRIX_MAXIMUM_BRIGHTNESS / BACKLIGHT_LEVELS * led_matrix_eeconfig.val); }
#ifdef LED_MATRIX_KEYREACTIVE_ENABLED
uint8_t led[LED_HITS_TO_REMEMBER];
uint8_t led_count = 0;
void led_matrix_custom(void) {}
void led_matrix_task(void) {
if (!led_matrix_eeconfig.enable) {
led_matrix_all_off();
led_matrix_indicators();
return;
# 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);
}
g_tick++;
if (g_any_key_hit < 0xFFFFFFFF) {
g_any_key_hit++;
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--;
}
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]++;
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
#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)
}
static bool led_matrix_none(effect_params_t *params) {
if (!params->init) {
return false;
}
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
// 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;
// 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
}
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++;
// Tell the LED driver to update its state
led_matrix_driver.flush();
// 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();
// 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,156 +404,180 @@ __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);
// clear the key hits
for (int led = 0; led < DRIVER_LED_TOTAL; led++) {
g_key_hit[led] = 255;
#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;
}
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");
eeconfig_init();
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) {
void led_matrix_mode_eeprom_helper(uint8_t mode, bool write_to_eeprom) {
if (!led_matrix_eeconfig.enable) {
return;
}
if (mode < 1) {
led_matrix_eeconfig.mode = 1;
}
eeconfig_update_led_matrix(led_matrix_eeconfig.raw);
}
void led_matrix_step_reverse(void) {
led_matrix_eeconfig.mode--;
if (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;
}
eeconfig_update_led_matrix(led_matrix_eeconfig.raw);
}
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);
}
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_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_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_mode(uint8_t mode, bool eeprom_write) {
led_matrix_eeconfig.mode = mode;
if (eeprom_write) {
eeconfig_update_led_matrix(led_matrix_eeconfig.raw);
led_task_state = STARTING;
if (write_to_eeprom) {
eeconfig_update_led_matrix();
}
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); }
uint8_t led_matrix_get_mode(void) { return led_matrix_eeconfig.mode; }
void led_matrix_set_value_noeeprom(uint8_t val) { led_matrix_eeconfig.val = val; }
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_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 backlight_set(uint8_t val) { led_matrix_set_value(val); }
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_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); }
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_speed(void) { return led_matrix_eeconfig.speed; }
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_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 led_matrix_set_flags(led_flags_t flags) { led_matrix_eeconfig.flags = flags; }
+105 -39
View File
@@ -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_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_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_task(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
@@ -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
+13
View File
@@ -0,0 +1,13 @@
#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
@@ -0,0 +1,10 @@
#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
@@ -0,0 +1,10 @@
#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
@@ -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
@@ -0,0 +1,10 @@
#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
@@ -0,0 +1,10 @@
#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
@@ -0,0 +1,10 @@
#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
@@ -0,0 +1,10 @@
#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
@@ -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"
@@ -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
@@ -0,0 +1,35 @@
#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
@@ -0,0 +1,32 @@
#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
@@ -0,0 +1,12 @@
#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
@@ -0,0 +1,30 @@
#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
@@ -0,0 +1,30 @@
#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
@@ -0,0 +1,10 @@
#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
@@ -0,0 +1,10 @@
#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
+16 -11
View File
@@ -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
@@ -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;
}
@@ -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;
}
@@ -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;
}
@@ -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
@@ -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
@@ -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;
}
+37 -9
View File
@@ -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;
+2 -6
View File
@@ -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;
}
+5
View File
@@ -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
+129 -1
View File
@@ -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))
+13 -7
View File
@@ -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:
@@ -231,14 +242,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
@@ -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);
+27 -2
View File
@@ -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
}
}
+4 -1
View File
@@ -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;
+6 -1
View File
@@ -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
+5
View File
@@ -205,6 +205,11 @@ bool process_rgb(const uint16_t keycode, const keyrecord_t *record) {
case RGB_MODE_RGBTEST:
#if defined(RGBLIGHT_ENABLE) && !defined(RGBLIGHT_DISABLE_KEYCODES) && defined(RGBLIGHT_EFFECT_RGB_TEST)
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;
}
+20 -11
View File
@@ -16,6 +16,7 @@
#include <ctype.h>
#include "quantum.h"
#include "magic.h"
#ifdef BLUETOOTH_ENABLE
# include "outputselect.h"
@@ -236,7 +237,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
@@ -320,6 +321,17 @@ bool process_record_quantum(keyrecord_t *record) {
case OUT_BT:
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
}
}
@@ -345,29 +357,26 @@ 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(ORYX_ENABLE) && defined(DYNAMIC_KEYMAP_ENABLE)
matrix_init_oryx();
#endif
#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
+9 -46
View File
@@ -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
@@ -209,37 +210,8 @@ 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)
#ifdef ENCODER_ENABLE
# include "encoder.h"
#endif
// For tri-layer
@@ -266,15 +238,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);
+431 -462
View File
File diff suppressed because it is too large Load Diff
+42 -19
View File
@@ -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 != 1
# 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; }
-1
View File
@@ -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
+38 -1
View File
@@ -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,7 +134,15 @@ 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 = {
+1 -1
View File
@@ -5,7 +5,7 @@ typedef HSV (*i_f)(HSV hsv, uint8_t i, uint8_t time);
bool effect_runner_i(effect_params_t* params, i_f effect_func) {
RGB_MATRIX_USE_LIMITS(led_min, led_max);
uint8_t time = scale16by8(g_rgb_timer, rgb_matrix_config.speed / 4);
uint8_t time = scale16by8(g_rgb_timer, qadd8(rgb_matrix_config.speed / 4, 1));
for (uint8_t i = led_min; i < led_max; i++) {
RGB_MATRIX_TEST_LED_FLAGS();
RGB rgb = rgb_matrix_hsv_to_rgb(effect_func(rgb_matrix_config.hsv, i, time));
@@ -7,7 +7,7 @@ typedef HSV (*reactive_f)(HSV hsv, uint16_t offset);
bool effect_runner_reactive(effect_params_t* params, reactive_f effect_func) {
RGB_MATRIX_USE_LIMITS(led_min, led_max);
uint16_t max_tick = 65535 / rgb_matrix_config.speed;
uint16_t max_tick = 65535 / qadd8(rgb_matrix_config.speed, 1);
for (uint8_t i = led_min; i < led_max; i++) {
RGB_MATRIX_TEST_LED_FLAGS();
uint16_t tick = max_tick;
@@ -19,7 +19,7 @@ bool effect_runner_reactive(effect_params_t* params, reactive_f effect_func) {
}
}
uint16_t offset = scale16by8(tick, rgb_matrix_config.speed);
uint16_t offset = scale16by8(tick, qadd8(rgb_matrix_config.speed, 1));
RGB rgb = rgb_matrix_hsv_to_rgb(effect_func(rgb_matrix_config.hsv, offset));
rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b);
}
@@ -16,7 +16,7 @@ bool effect_runner_reactive_splash(uint8_t start, effect_params_t* params, react
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], rgb_matrix_config.speed);
uint16_t tick = scale16by8(g_last_hit_tracker.tick[j], qadd8(rgb_matrix_config.speed, 1));
hsv = effect_func(hsv, dx, dy, dist, tick);
}
hsv.v = scale8(hsv.v, rgb_matrix_config.hsv.v);
+9 -8
View File
@@ -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;
+30 -14
View File
@@ -722,23 +722,39 @@ 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;
void rgblight_blink_layer(uint8_t layer, uint16_t 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 +771,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();
@@ -874,7 +890,7 @@ void rgblight_update_sync(rgblight_syncinfo_t *syncinfo, bool write_to_eeprom) {
animation_status.restart = true;
}
# endif /* RGBLIGHT_SPLIT_NO_ANIMATION_SYNC */
# endif /* RGBLIGHT_USE_TIMER */
# endif /* RGBLIGHT_USE_TIMER */
}
#endif /* RGBLIGHT_SPLIT */
@@ -1030,7 +1046,7 @@ void rgblight_task(void) {
}
# ifdef RGBLIGHT_LAYER_BLINK
rgblight_unblink_layers();
rgblight_blink_layer_repeat_helper();
# endif
}
+1
View File
@@ -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
+4 -7
View File
@@ -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;
+24 -46
View File
@@ -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);
+79 -13
View File
@@ -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(); }
@@ -201,30 +240,38 @@ typedef struct _Serial_s2m_buffer_t {
matrix_row_t smatrix[ROWS_PER_HAND];
# ifdef ENCODER_ENABLE
uint8_t encoder_state[NUMBER_OF_ENCODERS];
uint8_t encoder_state[NUMBER_OF_ENCODERS];
# endif
} 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];
# 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;
@@ -316,7 +363,7 @@ bool transport_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[])
// TODO: if MATRIX_COLS > 8 change to unpack()
for (int i = 0; i < ROWS_PER_HAND; ++i) {
slave_matrix[i] = serial_s2m_buffer.smatrix[i];
slave_matrix[i] = serial_s2m_buffer.smatrix[i];
# ifdef SPLIT_TRANSPORT_MIRROR
serial_m2s_buffer.mmatrix[i] = master_matrix[i];
# endif
@@ -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();
# 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;
}
@@ -359,7 +416,7 @@ void transport_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[])
for (int i = 0; i < ROWS_PER_HAND; ++i) {
serial_s2m_buffer.smatrix[i] = slave_matrix[i];
# ifdef SPLIT_TRANSPORT_MIRROR
master_matrix[i] = serial_m2s_buffer.mmatrix[i];
master_matrix[i] = serial_m2s_buffer.mmatrix[i];
# endif
}
# ifdef BACKLIGHT_ENABLE
@@ -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
+32 -6
View File
@@ -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();
}
}
+11
View File
@@ -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);