From 2d3fbc5d0ad70309ede5cdeb9cf84380fd69baae Mon Sep 17 00:00:00 2001 From: Chris Lewis Date: Wed, 25 Jul 2018 11:59:44 +1000 Subject: [PATCH 01/14] Draft commit of typing speed RGB control --- quantum/quantum.c | 3 +++ quantum/quantum.h | 2 ++ quantum/rgblight.c | 18 +++++++++++++++--- readme.md | 20 +++++++++++++++++++- 4 files changed, 39 insertions(+), 4 deletions(-) diff --git a/quantum/quantum.c b/quantum/quantum.c index 9c6ed3330e..1a5d992818 100644 --- a/quantum/quantum.c +++ b/quantum/quantum.c @@ -187,12 +187,15 @@ static uint16_t scs_timer[2] = {0, 0}; */ static bool grave_esc_was_shifted = false; +uint8_t typing_speed = 0; bool process_record_quantum(keyrecord_t *record) { /* This gets the keycode from the key pressed */ keypos_t key = record->event.key; uint16_t keycode; + if (typing_speed < 100) typing_speed += 1; + #if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS) /* TODO: Use store_or_get_action() or a similar function. */ if (!disable_action_cache) { diff --git a/quantum/quantum.h b/quantum/quantum.h index 0675a90ac3..35822f9a4f 100644 --- a/quantum/quantum.h +++ b/quantum/quantum.h @@ -55,6 +55,8 @@ #include "send_string_keycodes.h" extern uint32_t default_layer_state; +//Used in rgblight.c to match RGB animation to typing speed +extern uint8_t typing_speed; #ifndef NO_ACTION_LAYER extern uint32_t layer_state; diff --git a/quantum/rgblight.c b/quantum/rgblight.c index aa70cbd9ec..548c84a74e 100644 --- a/quantum/rgblight.c +++ b/quantum/rgblight.c @@ -24,13 +24,15 @@ #include "rgblight.h" #include "debug.h" #include "led_tables.h" +#include "quantum.h" #ifndef RGBLIGHT_LIMIT_VAL #define RGBLIGHT_LIMIT_VAL 255 #endif -#define MIN(a,b) (((a)<(b))?(a):(b)) -#define MAX(a,b) (((a)>(b))?(a):(b)) +//These conflict with a chained include that comes from including quantum.h +// #define MIN(a,b) (((a)<(b))?(a):(b)) +// #define MAX(a,b) (((a)>(b))?(a):(b)) __attribute__ ((weak)) const uint8_t RGBLED_BREATHING_INTERVALS[] PROGMEM = {30, 20, 10, 5}; @@ -628,7 +630,17 @@ void rgblight_effect_rainbow_swirl(uint8_t interval) { static uint16_t last_timer = 0; uint16_t hue; uint8_t i; - if (timer_elapsed(last_timer) < pgm_read_byte(&RGBLED_RAINBOW_SWIRL_INTERVALS[interval / 2])) { + + //Improvement: move this code into rgblight_task() so that the typing_speed can be used across all RGB effects, not just swirl + static uint16_t decay_timer = 0; + if (timer_elapsed(decay_timer) > 250 || decay_timer == 0) { + if (typing_speed > 0) typing_speed -= 1; + //Improvement(?): decay by a greater rate depending on how big typing_speed is, so you can't reach max speed just by outpacing the regular decay + decay_timer = timer_read(); + } + + //Improvement: make the usage of typing speed more easily configurable, either with a pre-processor toggle or with real-time key toggles + if (timer_elapsed(last_timer) < MAX(1, 100 - typing_speed)) { return; } last_timer = timer_read(); diff --git a/readme.md b/readme.md index 859e3ed12f..226ed74add 100644 --- a/readme.md +++ b/readme.md @@ -1,4 +1,22 @@ -# Quantum Mechanical Keyboard Firmware +# Quantum Mechanical Keyboard Firmware - chrislewisdev fork + +## Typing Speed -> RGB Animation Control + +This fork of qmk_firmware contains the code I whipped up to make your keyboard's RGB animation speed match your typing speed. As of writing, this is a "first draft" version, aka the simplest implementation I could think of with the quickest/hackiest code. Beware hard-coding :) + +Regardless, I'm happy to share the code and discuss improvements with anyone who'd like to contribute. I'll do my best to facilitate it in my spare time. + +## Getting Started + +My entire change amounts to several lines in `quantum.h`, `quantum.c` and `rgblight.c`. To see the details it's probably easiest if you look at my first commit to this fork which contains all the changes. + +I've left a couple of "Improvement:" comments around the code to indicate what I think would make it better or more "production"-ready. These could be good places to start for anyone interested in contributing. + +To test it, I've just been using my DZ60 keyboard, building the firmware with `make dz60:default` and flashing with qmk_toolbox. + +Below is the original QMK readme: + +# QMK [![Current Version](https://img.shields.io/github/tag/qmk/qmk_firmware.svg)](https://github.com/qmk/qmk_firmware/tags) [![Build Status](https://travis-ci.org/qmk/qmk_firmware.svg?branch=master)](https://travis-ci.org/qmk/qmk_firmware) From 876cb7a14fee02cb3d59e2f9b133f84118e985d1 Mon Sep 17 00:00:00 2001 From: Chris Lewis Date: Wed, 25 Jul 2018 12:08:13 +1000 Subject: [PATCH 02/14] More information in the readme --- readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/readme.md b/readme.md index 226ed74add..4f23243287 100644 --- a/readme.md +++ b/readme.md @@ -8,11 +8,11 @@ Regardless, I'm happy to share the code and discuss improvements with anyone who ## Getting Started -My entire change amounts to several lines in `quantum.h`, `quantum.c` and `rgblight.c`. To see the details it's probably easiest if you look at my first commit to this fork which contains all the changes. +My entire change amounts to several lines in `quantum.h`, `quantum.c` and `rgblight.c`. To see the details it's probably easiest if you look at [this commit](https://github.com/chrislewisdev/qmk_firmware/commit/2d3fbc5d0ad70309ede5cdeb9cf84380fd69baae) which contains all the changes. I've left a couple of "Improvement:" comments around the code to indicate what I think would make it better or more "production"-ready. These could be good places to start for anyone interested in contributing. -To test it, I've just been using my DZ60 keyboard, building the firmware with `make dz60:default` and flashing with qmk_toolbox. +To test it, I've just been using my DZ60 keyboard, building the firmware with `make dz60:default` and flashing with qmk_toolbox. If you're not familiar with how to do that, it's probably best you consult the [QMK documentation](https://docs.qmk.fm/#/). Below is the original QMK readme: From 5f2b065dad5054b0301ec2fecba47f66818c4fd7 Mon Sep 17 00:00:00 2001 From: Chris Lewis Date: Fri, 27 Jul 2018 00:23:44 +1000 Subject: [PATCH 03/14] Support all RGB animation modes (Fixes #1) * Added support for all RGB light modes to use typing speed Except christmas lights because that is seizure-inducing at high speeds! * Introduced a value range specific to each RGB mode Because some modes are a little too much when running at full speed! --- quantum/quantum.c | 2 +- quantum/quantum.h | 1 + quantum/rgblight.c | 36 ++++++++++++++++++++++-------------- quantum/rgblight.h | 3 +++ 4 files changed, 27 insertions(+), 15 deletions(-) diff --git a/quantum/quantum.c b/quantum/quantum.c index 1a5d992818..30a7beba40 100644 --- a/quantum/quantum.c +++ b/quantum/quantum.c @@ -194,7 +194,7 @@ bool process_record_quantum(keyrecord_t *record) { keypos_t key = record->event.key; uint16_t keycode; - if (typing_speed < 100) typing_speed += 1; + if (typing_speed < TYPING_SPEED_MAX_VALUE) typing_speed += 1; #if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS) /* TODO: Use store_or_get_action() or a similar function. */ diff --git a/quantum/quantum.h b/quantum/quantum.h index 35822f9a4f..1837caddbb 100644 --- a/quantum/quantum.h +++ b/quantum/quantum.h @@ -57,6 +57,7 @@ extern uint32_t default_layer_state; //Used in rgblight.c to match RGB animation to typing speed extern uint8_t typing_speed; +#define TYPING_SPEED_MAX_VALUE 100 #ifndef NO_ACTION_LAYER extern uint32_t layer_state; diff --git a/quantum/rgblight.c b/quantum/rgblight.c index 548c84a74e..fda64855d1 100644 --- a/quantum/rgblight.c +++ b/quantum/rgblight.c @@ -569,8 +569,25 @@ void rgblight_show_solid_color(uint8_t r, uint8_t g, uint8_t b) { rgblight_setrgb(r, g, b); } +void typing_speed_decay_task() { + static uint16_t decay_timer = 0; + + if (timer_elapsed(decay_timer) > 500 || decay_timer == 0) { + if (typing_speed > 0) typing_speed -= 1; + decay_timer = timer_read(); + } +} + +uint8_t typing_speed_matched_interval(uint8_t minValue, uint8_t maxValue) { + return MAX(minValue, maxValue - (maxValue - minValue) * ((float)typing_speed / TYPING_SPEED_MAX_VALUE)); +} + void rgblight_task(void) { + if (rgblight_timer_enabled) { + + typing_speed_decay_task(); + // mode = 1, static light, do nothing here if (rgblight_config.mode >= 2 && rgblight_config.mode <= 5) { // mode = 2 to 5, breathing mode @@ -603,7 +620,7 @@ void rgblight_effect_breathing(uint8_t interval) { static uint16_t last_timer = 0; float val; - if (timer_elapsed(last_timer) < pgm_read_byte(&RGBLED_BREATHING_INTERVALS[interval])) { + if (timer_elapsed(last_timer) < typing_speed_matched_interval(1, 100)) { return; } last_timer = timer_read(); @@ -618,7 +635,7 @@ void rgblight_effect_rainbow_mood(uint8_t interval) { static uint16_t current_hue = 0; static uint16_t last_timer = 0; - if (timer_elapsed(last_timer) < pgm_read_byte(&RGBLED_RAINBOW_MOOD_INTERVALS[interval])) { + if (timer_elapsed(last_timer) < typing_speed_matched_interval(5, 100)) { return; } last_timer = timer_read(); @@ -631,16 +648,7 @@ void rgblight_effect_rainbow_swirl(uint8_t interval) { uint16_t hue; uint8_t i; - //Improvement: move this code into rgblight_task() so that the typing_speed can be used across all RGB effects, not just swirl - static uint16_t decay_timer = 0; - if (timer_elapsed(decay_timer) > 250 || decay_timer == 0) { - if (typing_speed > 0) typing_speed -= 1; - //Improvement(?): decay by a greater rate depending on how big typing_speed is, so you can't reach max speed just by outpacing the regular decay - decay_timer = timer_read(); - } - - //Improvement: make the usage of typing speed more easily configurable, either with a pre-processor toggle or with real-time key toggles - if (timer_elapsed(last_timer) < MAX(1, 100 - typing_speed)) { + if (timer_elapsed(last_timer) < typing_speed_matched_interval(1, 100)) { return; } last_timer = timer_read(); @@ -669,7 +677,7 @@ void rgblight_effect_snake(uint8_t interval) { if (interval % 2) { increment = -1; } - if (timer_elapsed(last_timer) < pgm_read_byte(&RGBLED_SNAKE_INTERVALS[interval / 2])) { + if (timer_elapsed(last_timer) < typing_speed_matched_interval(5, 100)) { return; } last_timer = timer_read(); @@ -700,7 +708,7 @@ void rgblight_effect_snake(uint8_t interval) { } void rgblight_effect_knight(uint8_t interval) { static uint16_t last_timer = 0; - if (timer_elapsed(last_timer) < pgm_read_byte(&RGBLED_KNIGHT_INTERVALS[interval])) { + if (timer_elapsed(last_timer) < typing_speed_matched_interval(5, 100)) { return; } last_timer = timer_read(); diff --git a/quantum/rgblight.h b/quantum/rgblight.h index 0f7b5ffb56..ecc1ff6058 100644 --- a/quantum/rgblight.h +++ b/quantum/rgblight.h @@ -167,4 +167,7 @@ void rgblight_effect_knight(uint8_t interval); void rgblight_effect_christmas(void); void rgblight_effect_rgbtest(void); +void typing_speed_decay_task(void); +uint8_t typing_speed_matched_interval(uint8_t minValue, uint8_t maxValue); + #endif From 676b01312fd9b0b467bc3ac01ba46494b9cd0dbd Mon Sep 17 00:00:00 2001 From: Chris Lewis Date: Fri, 27 Jul 2018 10:06:06 +1000 Subject: [PATCH 04/14] Update readme.md --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 4f23243287..f29e62a983 100644 --- a/readme.md +++ b/readme.md @@ -10,7 +10,7 @@ Regardless, I'm happy to share the code and discuss improvements with anyone who My entire change amounts to several lines in `quantum.h`, `quantum.c` and `rgblight.c`. To see the details it's probably easiest if you look at [this commit](https://github.com/chrislewisdev/qmk_firmware/commit/2d3fbc5d0ad70309ede5cdeb9cf84380fd69baae) which contains all the changes. -I've left a couple of "Improvement:" comments around the code to indicate what I think would make it better or more "production"-ready. These could be good places to start for anyone interested in contributing. +I've created GitHub Issues for the most pressing things that need to be addressed before this could be merged into QMK - if you're interested in helping out, please do take a look! To test it, I've just been using my DZ60 keyboard, building the firmware with `make dz60:default` and flashing with qmk_toolbox. If you're not familiar with how to do that, it's probably best you consult the [QMK documentation](https://docs.qmk.fm/#/). From 7cefccd13e04b7ed68c4ab45be6b8e48be22eebb Mon Sep 17 00:00:00 2001 From: Chris Lewis Date: Fri, 27 Jul 2018 23:48:07 +1000 Subject: [PATCH 05/14] Update readme.md --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index f29e62a983..1c98c795d8 100644 --- a/readme.md +++ b/readme.md @@ -8,7 +8,7 @@ Regardless, I'm happy to share the code and discuss improvements with anyone who ## Getting Started -My entire change amounts to several lines in `quantum.h`, `quantum.c` and `rgblight.c`. To see the details it's probably easiest if you look at [this commit](https://github.com/chrislewisdev/qmk_firmware/commit/2d3fbc5d0ad70309ede5cdeb9cf84380fd69baae) which contains all the changes. +My original change amounts to several lines in `quantum.h`, `quantum.c` and `rgblight.c`. To see the details it's probably easiest if you look at [this commit](https://github.com/chrislewisdev/qmk_firmware/commit/2d3fbc5d0ad70309ede5cdeb9cf84380fd69baae) which contains all the changes. I've created GitHub Issues for the most pressing things that need to be addressed before this could be merged into QMK - if you're interested in helping out, please do take a look! From e783cb06f7f412f8c7fa9aa6acf800b34efb21f3 Mon Sep 17 00:00:00 2001 From: Chris Lewis Date: Sat, 28 Jul 2018 15:54:08 +1000 Subject: [PATCH 06/14] Re-arrange typing_speed definitions (Fixes #5) (#6) * Re-arrange variable definitions to avoid including quantum.h from rgblight.c * Fix a compilation error when trying to run make test:all --- quantum/quantum.c | 5 +++-- quantum/quantum.h | 3 --- quantum/rgblight.c | 7 +++---- quantum/rgblight.h | 4 ++++ 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/quantum/quantum.c b/quantum/quantum.c index 30a7beba40..ff59bc0c41 100644 --- a/quantum/quantum.c +++ b/quantum/quantum.c @@ -187,14 +187,15 @@ static uint16_t scs_timer[2] = {0, 0}; */ static bool grave_esc_was_shifted = false; -uint8_t typing_speed = 0; bool process_record_quantum(keyrecord_t *record) { /* This gets the keycode from the key pressed */ keypos_t key = record->event.key; uint16_t keycode; - if (typing_speed < TYPING_SPEED_MAX_VALUE) typing_speed += 1; + #ifdef RGBLIGHT_ENABLE + if (typing_speed < TYPING_SPEED_MAX_VALUE) typing_speed += 1; + #endif #if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS) /* TODO: Use store_or_get_action() or a similar function. */ diff --git a/quantum/quantum.h b/quantum/quantum.h index 1837caddbb..0675a90ac3 100644 --- a/quantum/quantum.h +++ b/quantum/quantum.h @@ -55,9 +55,6 @@ #include "send_string_keycodes.h" extern uint32_t default_layer_state; -//Used in rgblight.c to match RGB animation to typing speed -extern uint8_t typing_speed; -#define TYPING_SPEED_MAX_VALUE 100 #ifndef NO_ACTION_LAYER extern uint32_t layer_state; diff --git a/quantum/rgblight.c b/quantum/rgblight.c index fda64855d1..88a21d0aff 100644 --- a/quantum/rgblight.c +++ b/quantum/rgblight.c @@ -24,15 +24,13 @@ #include "rgblight.h" #include "debug.h" #include "led_tables.h" -#include "quantum.h" #ifndef RGBLIGHT_LIMIT_VAL #define RGBLIGHT_LIMIT_VAL 255 #endif -//These conflict with a chained include that comes from including quantum.h -// #define MIN(a,b) (((a)<(b))?(a):(b)) -// #define MAX(a,b) (((a)>(b))?(a):(b)) +#define MIN(a,b) (((a)<(b))?(a):(b)) +#define MAX(a,b) (((a)>(b))?(a):(b)) __attribute__ ((weak)) const uint8_t RGBLED_BREATHING_INTERVALS[] PROGMEM = {30, 20, 10, 5}; @@ -569,6 +567,7 @@ void rgblight_show_solid_color(uint8_t r, uint8_t g, uint8_t b) { rgblight_setrgb(r, g, b); } +uint8_t typing_speed = 0; void typing_speed_decay_task() { static uint16_t decay_timer = 0; diff --git a/quantum/rgblight.h b/quantum/rgblight.h index ecc1ff6058..5b95431299 100644 --- a/quantum/rgblight.h +++ b/quantum/rgblight.h @@ -89,6 +89,10 @@ extern const uint8_t RGBLED_SNAKE_INTERVALS[3] PROGMEM; extern const uint8_t RGBLED_KNIGHT_INTERVALS[3] PROGMEM; extern const uint16_t RGBLED_RGBTEST_INTERVALS[1] PROGMEM; +//Used in rgblight.c and quantum.c to match RGB animation to typing speed +extern uint8_t typing_speed; +#define TYPING_SPEED_MAX_VALUE 100 + typedef union { uint32_t raw; struct { From f5025c41664af3789afdf30074b601a1d85bb808 Mon Sep 17 00:00:00 2001 From: Chris Lewis Date: Sat, 28 Jul 2018 16:02:36 +1000 Subject: [PATCH 07/14] Tweaks to the typing speed decay rate --- quantum/quantum.c | 2 +- quantum/rgblight.c | 6 +++++- quantum/rgblight.h | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/quantum/quantum.c b/quantum/quantum.c index ff59bc0c41..9c44c07561 100644 --- a/quantum/quantum.c +++ b/quantum/quantum.c @@ -194,7 +194,7 @@ bool process_record_quantum(keyrecord_t *record) { uint16_t keycode; #ifdef RGBLIGHT_ENABLE - if (typing_speed < TYPING_SPEED_MAX_VALUE) typing_speed += 1; + if (typing_speed < TYPING_SPEED_MAX_VALUE) typing_speed += (TYPING_SPEED_MAX_VALUE / 100); #endif #if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS) diff --git a/quantum/rgblight.c b/quantum/rgblight.c index 88a21d0aff..000d91e9e7 100644 --- a/quantum/rgblight.c +++ b/quantum/rgblight.c @@ -573,6 +573,10 @@ void typing_speed_decay_task() { if (timer_elapsed(decay_timer) > 500 || decay_timer == 0) { if (typing_speed > 0) typing_speed -= 1; + //Decay a little faster at half of max speed + if (typing_speed > TYPING_SPEED_MAX_VALUE / 2) typing_speed -= 1; + //Decay even faster at 3/4 of max speed + if (typing_speed > TYPING_SPEED_MAX_VALUE / 4 * 3) typing_speed -= 3; decay_timer = timer_read(); } } @@ -676,7 +680,7 @@ void rgblight_effect_snake(uint8_t interval) { if (interval % 2) { increment = -1; } - if (timer_elapsed(last_timer) < typing_speed_matched_interval(5, 100)) { + if (timer_elapsed(last_timer) < typing_speed_matched_interval(1, 200)) { return; } last_timer = timer_read(); diff --git a/quantum/rgblight.h b/quantum/rgblight.h index 5b95431299..b3264dff1f 100644 --- a/quantum/rgblight.h +++ b/quantum/rgblight.h @@ -91,7 +91,7 @@ extern const uint16_t RGBLED_RGBTEST_INTERVALS[1] PROGMEM; //Used in rgblight.c and quantum.c to match RGB animation to typing speed extern uint8_t typing_speed; -#define TYPING_SPEED_MAX_VALUE 100 +#define TYPING_SPEED_MAX_VALUE 200 typedef union { uint32_t raw; From 12fcf80d3da5771a8db76f2a07a8eade3d9c2101 Mon Sep 17 00:00:00 2001 From: Chris Lewis Date: Sat, 18 Aug 2018 20:43:39 +1000 Subject: [PATCH 08/14] Renamed to momentum; moved implementation into dedicated files --- common_features.mk | 1 + quantum/momentum.c | 32 ++++++++++++++++++++++++++++++++ quantum/momentum.h | 11 +++++++++++ quantum/quantum.c | 2 +- quantum/rgblight.c | 30 ++++++------------------------ quantum/rgblight.h | 9 ++------- 6 files changed, 53 insertions(+), 32 deletions(-) create mode 100644 quantum/momentum.c create mode 100644 quantum/momentum.h diff --git a/common_features.mk b/common_features.mk index b78f04d2a8..dd21507196 100644 --- a/common_features.mk +++ b/common_features.mk @@ -105,6 +105,7 @@ endif ifeq ($(strip $(RGBLIGHT_ENABLE)), yes) OPT_DEFS += -DRGBLIGHT_ENABLE SRC += $(QUANTUM_DIR)/rgblight.c + SRC += $(QUANTUM_DIR)/momentum.c CIE1931_CURVE = yes LED_BREATHING_TABLE = yes ifeq ($(strip $(RGBLIGHT_CUSTOM_DRIVER)), yes) diff --git a/quantum/momentum.c b/quantum/momentum.c new file mode 100644 index 0000000000..e0fadc991c --- /dev/null +++ b/quantum/momentum.c @@ -0,0 +1,32 @@ +#include "momentum.h" + +#ifndef MIN +#define MIN(a,b) (((a)<(b))?(a):(b)) +#endif +#ifndef MAX +#define MAX(a,b) (((a)>(b))?(a):(b)) +#endif + +#define TYPING_SPEED_MAX_VALUE 200 +uint8_t typing_speed = 0; + +void momentum_accelerate() { + if (typing_speed < TYPING_SPEED_MAX_VALUE) typing_speed += (TYPING_SPEED_MAX_VALUE / 100); +} + +void momentum_decay_task() { + static uint16_t decay_timer = 0; + + if (timer_elapsed(decay_timer) > 500 || decay_timer == 0) { + if (typing_speed > 0) typing_speed -= 1; + //Decay a little faster at half of max speed + if (typing_speed > TYPING_SPEED_MAX_VALUE / 2) typing_speed -= 1; + //Decay even faster at 3/4 of max speed + if (typing_speed > TYPING_SPEED_MAX_VALUE / 4 * 3) typing_speed -= 3; + decay_timer = timer_read(); + } +} + +uint8_t match_momentum(uint8_t minValue, uint8_t maxValue) { + return MAX(minValue, maxValue - (maxValue - minValue) * ((float)typing_speed / TYPING_SPEED_MAX_VALUE)); +} \ No newline at end of file diff --git a/quantum/momentum.h b/quantum/momentum.h new file mode 100644 index 0000000000..7acf139255 --- /dev/null +++ b/quantum/momentum.h @@ -0,0 +1,11 @@ +#ifndef MOMENTUM_H +#define MOMENTUM_H + +#include +#include "timer.h" + +void momentum_accelerate(void); +void momentum_decay_task(void); +uint8_t match_momentum(uint8_t minValue, uint8_t maxValue); + +#endif \ No newline at end of file diff --git a/quantum/quantum.c b/quantum/quantum.c index 9c44c07561..ea2300ebd0 100644 --- a/quantum/quantum.c +++ b/quantum/quantum.c @@ -194,7 +194,7 @@ bool process_record_quantum(keyrecord_t *record) { uint16_t keycode; #ifdef RGBLIGHT_ENABLE - if (typing_speed < TYPING_SPEED_MAX_VALUE) typing_speed += (TYPING_SPEED_MAX_VALUE / 100); + momentum_accelerate(); #endif #if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS) diff --git a/quantum/rgblight.c b/quantum/rgblight.c index 000d91e9e7..022fe21f16 100644 --- a/quantum/rgblight.c +++ b/quantum/rgblight.c @@ -567,29 +567,11 @@ void rgblight_show_solid_color(uint8_t r, uint8_t g, uint8_t b) { rgblight_setrgb(r, g, b); } -uint8_t typing_speed = 0; -void typing_speed_decay_task() { - static uint16_t decay_timer = 0; - - if (timer_elapsed(decay_timer) > 500 || decay_timer == 0) { - if (typing_speed > 0) typing_speed -= 1; - //Decay a little faster at half of max speed - if (typing_speed > TYPING_SPEED_MAX_VALUE / 2) typing_speed -= 1; - //Decay even faster at 3/4 of max speed - if (typing_speed > TYPING_SPEED_MAX_VALUE / 4 * 3) typing_speed -= 3; - decay_timer = timer_read(); - } -} - -uint8_t typing_speed_matched_interval(uint8_t minValue, uint8_t maxValue) { - return MAX(minValue, maxValue - (maxValue - minValue) * ((float)typing_speed / TYPING_SPEED_MAX_VALUE)); -} - void rgblight_task(void) { if (rgblight_timer_enabled) { - typing_speed_decay_task(); + momentum_decay_task(); // mode = 1, static light, do nothing here if (rgblight_config.mode >= 2 && rgblight_config.mode <= 5) { @@ -623,7 +605,7 @@ void rgblight_effect_breathing(uint8_t interval) { static uint16_t last_timer = 0; float val; - if (timer_elapsed(last_timer) < typing_speed_matched_interval(1, 100)) { + if (timer_elapsed(last_timer) < match_momentum(1, 100)) { return; } last_timer = timer_read(); @@ -638,7 +620,7 @@ void rgblight_effect_rainbow_mood(uint8_t interval) { static uint16_t current_hue = 0; static uint16_t last_timer = 0; - if (timer_elapsed(last_timer) < typing_speed_matched_interval(5, 100)) { + if (timer_elapsed(last_timer) < match_momentum(5, 100)) { return; } last_timer = timer_read(); @@ -651,7 +633,7 @@ void rgblight_effect_rainbow_swirl(uint8_t interval) { uint16_t hue; uint8_t i; - if (timer_elapsed(last_timer) < typing_speed_matched_interval(1, 100)) { + if (timer_elapsed(last_timer) < match_momentum(1, 100)) { return; } last_timer = timer_read(); @@ -680,7 +662,7 @@ void rgblight_effect_snake(uint8_t interval) { if (interval % 2) { increment = -1; } - if (timer_elapsed(last_timer) < typing_speed_matched_interval(1, 200)) { + if (timer_elapsed(last_timer) < match_momentum(1, 200)) { return; } last_timer = timer_read(); @@ -711,7 +693,7 @@ void rgblight_effect_snake(uint8_t interval) { } void rgblight_effect_knight(uint8_t interval) { static uint16_t last_timer = 0; - if (timer_elapsed(last_timer) < typing_speed_matched_interval(5, 100)) { + if (timer_elapsed(last_timer) < match_momentum(5, 100)) { return; } last_timer = timer_read(); diff --git a/quantum/rgblight.h b/quantum/rgblight.h index b3264dff1f..67bab7eb57 100644 --- a/quantum/rgblight.h +++ b/quantum/rgblight.h @@ -80,6 +80,8 @@ #include #endif +#include "momentum.h" + extern LED_TYPE led[RGBLED_NUM]; extern const uint8_t RGBLED_BREATHING_INTERVALS[4] PROGMEM; @@ -89,10 +91,6 @@ extern const uint8_t RGBLED_SNAKE_INTERVALS[3] PROGMEM; extern const uint8_t RGBLED_KNIGHT_INTERVALS[3] PROGMEM; extern const uint16_t RGBLED_RGBTEST_INTERVALS[1] PROGMEM; -//Used in rgblight.c and quantum.c to match RGB animation to typing speed -extern uint8_t typing_speed; -#define TYPING_SPEED_MAX_VALUE 200 - typedef union { uint32_t raw; struct { @@ -171,7 +169,4 @@ void rgblight_effect_knight(uint8_t interval); void rgblight_effect_christmas(void); void rgblight_effect_rgbtest(void); -void typing_speed_decay_task(void); -uint8_t typing_speed_matched_interval(uint8_t minValue, uint8_t maxValue); - #endif From 13f7c9e3a1f322ebdd61b6b300a6720bd28153b6 Mon Sep 17 00:00:00 2001 From: Chris Lewis Date: Sat, 18 Aug 2018 21:03:02 +1000 Subject: [PATCH 09/14] Groundwork for toggling momentum on/off (currently always on) --- quantum/momentum.c | 5 +++++ quantum/momentum.h | 3 ++- quantum/quantum.c | 2 +- quantum/rgblight.c | 34 ++++++++++++++++++++++++++++------ 4 files changed, 36 insertions(+), 8 deletions(-) diff --git a/quantum/momentum.c b/quantum/momentum.c index e0fadc991c..8b2d8dc06d 100644 --- a/quantum/momentum.c +++ b/quantum/momentum.c @@ -1,4 +1,5 @@ #include "momentum.h" +#include "timer.h" #ifndef MIN #define MIN(a,b) (((a)<(b))?(a):(b)) @@ -10,6 +11,10 @@ #define TYPING_SPEED_MAX_VALUE 200 uint8_t typing_speed = 0; +bool momentum_enabled() { + return true; +} + void momentum_accelerate() { if (typing_speed < TYPING_SPEED_MAX_VALUE) typing_speed += (TYPING_SPEED_MAX_VALUE / 100); } diff --git a/quantum/momentum.h b/quantum/momentum.h index 7acf139255..d72c043d15 100644 --- a/quantum/momentum.h +++ b/quantum/momentum.h @@ -2,8 +2,9 @@ #define MOMENTUM_H #include -#include "timer.h" +#include +bool momentum_enabled(void); void momentum_accelerate(void); void momentum_decay_task(void); uint8_t match_momentum(uint8_t minValue, uint8_t maxValue); diff --git a/quantum/quantum.c b/quantum/quantum.c index ea2300ebd0..ae308fad2d 100644 --- a/quantum/quantum.c +++ b/quantum/quantum.c @@ -194,7 +194,7 @@ bool process_record_quantum(keyrecord_t *record) { uint16_t keycode; #ifdef RGBLIGHT_ENABLE - momentum_accelerate(); + if (momentum_enabled()) momentum_accelerate(); #endif #if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS) diff --git a/quantum/rgblight.c b/quantum/rgblight.c index 022fe21f16..2c26c807a3 100644 --- a/quantum/rgblight.c +++ b/quantum/rgblight.c @@ -571,7 +571,7 @@ void rgblight_task(void) { if (rgblight_timer_enabled) { - momentum_decay_task(); + if (momentum_enabled()) momentum_decay_task(); // mode = 1, static light, do nothing here if (rgblight_config.mode >= 2 && rgblight_config.mode <= 5) { @@ -605,7 +605,11 @@ void rgblight_effect_breathing(uint8_t interval) { static uint16_t last_timer = 0; float val; - if (timer_elapsed(last_timer) < match_momentum(1, 100)) { + uint8_t interval_time = momentum_enabled() + ? match_momentum(1, 100) + : pgm_read_byte(&RGBLED_RAINBOW_SWIRL_INTERVALS[interval / 2]); + + if (timer_elapsed(last_timer) < interval_time) { return; } last_timer = timer_read(); @@ -620,7 +624,11 @@ void rgblight_effect_rainbow_mood(uint8_t interval) { static uint16_t current_hue = 0; static uint16_t last_timer = 0; - if (timer_elapsed(last_timer) < match_momentum(5, 100)) { + uint8_t interval_time = momentum_enabled() + ? match_momentum(5, 100) + : pgm_read_byte(&RGBLED_RAINBOW_MOOD_INTERVALS[interval]); + + if (timer_elapsed(last_timer) < interval_time) { return; } last_timer = timer_read(); @@ -633,7 +641,11 @@ void rgblight_effect_rainbow_swirl(uint8_t interval) { uint16_t hue; uint8_t i; - if (timer_elapsed(last_timer) < match_momentum(1, 100)) { + uint8_t interval_time = momentum_enabled() + ? match_momentum(1, 100) + : pgm_read_byte(&RGBLED_RAINBOW_SWIRL_INTERVALS[interval / 2]); + + if (timer_elapsed(last_timer) < interval_time) { return; } last_timer = timer_read(); @@ -662,7 +674,12 @@ void rgblight_effect_snake(uint8_t interval) { if (interval % 2) { increment = -1; } - if (timer_elapsed(last_timer) < match_momentum(1, 200)) { + + uint8_t interval_time = momentum_enabled() + ? match_momentum(1, 200) + : pgm_read_byte(&RGBLED_SNAKE_INTERVALS[interval / 2]); + + if (timer_elapsed(last_timer) < interval_time) { return; } last_timer = timer_read(); @@ -693,7 +710,12 @@ void rgblight_effect_snake(uint8_t interval) { } void rgblight_effect_knight(uint8_t interval) { static uint16_t last_timer = 0; - if (timer_elapsed(last_timer) < match_momentum(5, 100)) { + + uint8_t interval_time = momentum_enabled() + ? match_momentum(5, 100) + : pgm_read_byte(&RGBLED_KNIGHT_INTERVALS[interval]); + + if (timer_elapsed(last_timer) < interval_time) { return; } last_timer = timer_read(); From b070efe019ca579a944934ee0bc6ab8dae272541 Mon Sep 17 00:00:00 2001 From: Chris Lewis Date: Sat, 18 Aug 2018 21:58:52 +1000 Subject: [PATCH 10/14] Add EEPROM toggle for momentum-matching --- quantum/momentum.c | 11 ++++++++++- quantum/momentum.h | 1 + quantum/quantum.c | 5 +++++ quantum/quantum_keycodes.h | 3 +++ tmk_core/common/eeconfig.c | 1 + tmk_core/common/eeconfig.h | 2 +- 6 files changed, 21 insertions(+), 2 deletions(-) diff --git a/quantum/momentum.c b/quantum/momentum.c index 8b2d8dc06d..662f71d51c 100644 --- a/quantum/momentum.c +++ b/quantum/momentum.c @@ -1,5 +1,7 @@ #include "momentum.h" #include "timer.h" +#include "eeconfig.h" +#include "eeprom.h" #ifndef MIN #define MIN(a,b) (((a)<(b))?(a):(b)) @@ -12,7 +14,14 @@ uint8_t typing_speed = 0; bool momentum_enabled() { - return true; + return eeprom_read_byte(EECONFIG_MOMENTUM) == 1; +} + +void momentum_toggle() { + if (momentum_enabled()) + eeprom_update_byte(EECONFIG_MOMENTUM, 0); + else + eeprom_update_byte(EECONFIG_MOMENTUM, 1); } void momentum_accelerate() { diff --git a/quantum/momentum.h b/quantum/momentum.h index d72c043d15..1fe4c58aea 100644 --- a/quantum/momentum.h +++ b/quantum/momentum.h @@ -5,6 +5,7 @@ #include bool momentum_enabled(void); +void momentum_toggle(void); void momentum_accelerate(void); void momentum_decay_task(void); uint8_t match_momentum(uint8_t minValue, uint8_t maxValue); diff --git a/quantum/quantum.c b/quantum/quantum.c index ae308fad2d..5301c8bd75 100644 --- a/quantum/quantum.c +++ b/quantum/quantum.c @@ -516,6 +516,11 @@ bool process_record_quantum(keyrecord_t *record) { rgblight_mode(35); } return false; + case MOM_TOG: + if (record->event.pressed) { + momentum_toggle(); + } + return false; #endif // defined(RGBLIGHT_ENABLE) || defined(RGB_MATRIX_ENABLE) #ifdef PROTOCOL_LUFA case OUT_AUTO: diff --git a/quantum/quantum_keycodes.h b/quantum/quantum_keycodes.h index f2cdb8a3bf..2391122d9d 100644 --- a/quantum/quantum_keycodes.h +++ b/quantum/quantum_keycodes.h @@ -425,6 +425,9 @@ enum quantum_keycodes { RGB_MODE_GRADIENT, RGB_MODE_RGBTEST, + //Momentum matching toggle + MOM_TOG, + // Left shift, open paren KC_LSPO, diff --git a/tmk_core/common/eeconfig.c b/tmk_core/common/eeconfig.c index 3e5987ee3b..4d76cc0a69 100644 --- a/tmk_core/common/eeconfig.c +++ b/tmk_core/common/eeconfig.c @@ -22,6 +22,7 @@ void eeconfig_init(void) #endif #if defined(RGBLIGHT_ENABLE) || defined(RGB_MATRIX_ENABLE) eeprom_update_dword(EECONFIG_RGBLIGHT, 0); + eeprom_update_byte(EECONFIG_MOMENTUM, 0); #endif #ifdef STENO_ENABLE eeprom_update_byte(EECONFIG_STENOMODE, 0); diff --git a/tmk_core/common/eeconfig.h b/tmk_core/common/eeconfig.h index 1397a90c79..87cf9b485e 100644 --- a/tmk_core/common/eeconfig.h +++ b/tmk_core/common/eeconfig.h @@ -37,7 +37,7 @@ along with this program. If not, see . #define EECONFIG_STENOMODE (uint8_t *)13 // EEHANDS for two handed boards #define EECONFIG_HANDEDNESS (uint8_t *)14 - +#define EECONFIG_MOMENTUM (uint8_t *)15 /* debug bit */ #define EECONFIG_DEBUG_ENABLE (1<<0) From b444fa38afc6a3ebb5481d17a7abcd00d70ea8a9 Mon Sep 17 00:00:00 2001 From: Chris Lewis Date: Sat, 18 Aug 2018 22:21:16 +1000 Subject: [PATCH 11/14] Moved momentum out of RGBLIGHT_ENABLE toggles so it's more generic --- common_features.mk | 4 ++-- quantum/quantum.c | 10 +++++----- quantum/rgblight.c | 1 + quantum/rgblight.h | 2 -- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/common_features.mk b/common_features.mk index dd21507196..261d4fc25f 100644 --- a/common_features.mk +++ b/common_features.mk @@ -105,7 +105,6 @@ endif ifeq ($(strip $(RGBLIGHT_ENABLE)), yes) OPT_DEFS += -DRGBLIGHT_ENABLE SRC += $(QUANTUM_DIR)/rgblight.c - SRC += $(QUANTUM_DIR)/momentum.c CIE1931_CURVE = yes LED_BREATHING_TABLE = yes ifeq ($(strip $(RGBLIGHT_CUSTOM_DRIVER)), yes) @@ -208,7 +207,8 @@ QUANTUM_SRC:= \ $(QUANTUM_DIR)/quantum.c \ $(QUANTUM_DIR)/keymap_common.c \ $(QUANTUM_DIR)/keycode_config.c \ - $(QUANTUM_DIR)/process_keycode/process_leader.c + $(QUANTUM_DIR)/process_keycode/process_leader.c \ + $(QUANTUM_DIR)/momentum.c ifndef CUSTOM_MATRIX ifeq ($(strip $(SPLIT_KEYBOARD)), yes) diff --git a/quantum/quantum.c b/quantum/quantum.c index 5301c8bd75..64e364a245 100644 --- a/quantum/quantum.c +++ b/quantum/quantum.c @@ -42,6 +42,8 @@ extern backlight_config_t backlight_config; #include "process_midi.h" #endif +#include "momentum.h" + #ifdef AUDIO_ENABLE #ifndef GOODBYE_SONG #define GOODBYE_SONG SONG(GOODBYE_SOUND) @@ -193,9 +195,7 @@ bool process_record_quantum(keyrecord_t *record) { keypos_t key = record->event.key; uint16_t keycode; - #ifdef RGBLIGHT_ENABLE - if (momentum_enabled()) momentum_accelerate(); - #endif + if (momentum_enabled()) momentum_accelerate(); #if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS) /* TODO: Use store_or_get_action() or a similar function. */ @@ -516,13 +516,13 @@ bool process_record_quantum(keyrecord_t *record) { rgblight_mode(35); } return false; + #endif // defined(RGBLIGHT_ENABLE) || defined(RGB_MATRIX_ENABLE) case MOM_TOG: if (record->event.pressed) { momentum_toggle(); } return false; - #endif // defined(RGBLIGHT_ENABLE) || defined(RGB_MATRIX_ENABLE) - #ifdef PROTOCOL_LUFA + #ifdef PROTOCOL_LUFA case OUT_AUTO: if (record->event.pressed) { set_output(OUTPUT_AUTO); diff --git a/quantum/rgblight.c b/quantum/rgblight.c index 2c26c807a3..4f1bb11c6a 100644 --- a/quantum/rgblight.c +++ b/quantum/rgblight.c @@ -24,6 +24,7 @@ #include "rgblight.h" #include "debug.h" #include "led_tables.h" +#include "momentum.h" #ifndef RGBLIGHT_LIMIT_VAL #define RGBLIGHT_LIMIT_VAL 255 diff --git a/quantum/rgblight.h b/quantum/rgblight.h index 67bab7eb57..0f7b5ffb56 100644 --- a/quantum/rgblight.h +++ b/quantum/rgblight.h @@ -80,8 +80,6 @@ #include #endif -#include "momentum.h" - extern LED_TYPE led[RGBLED_NUM]; extern const uint8_t RGBLED_BREATHING_INTERVALS[4] PROGMEM; From e7a39d9c12c126b230740ce7b6bc93e0744764f2 Mon Sep 17 00:00:00 2001 From: Chris Lewis Date: Sat, 18 Aug 2018 22:26:44 +1000 Subject: [PATCH 12/14] Move momentum decay task out of rgblight_task() --- quantum/rgblight.c | 3 --- tmk_core/protocol/lufa/lufa.c | 2 ++ 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/quantum/rgblight.c b/quantum/rgblight.c index 4f1bb11c6a..4136077992 100644 --- a/quantum/rgblight.c +++ b/quantum/rgblight.c @@ -571,9 +571,6 @@ void rgblight_show_solid_color(uint8_t r, uint8_t g, uint8_t b) { void rgblight_task(void) { if (rgblight_timer_enabled) { - - if (momentum_enabled()) momentum_decay_task(); - // mode = 1, static light, do nothing here if (rgblight_config.mode >= 2 && rgblight_config.mode <= 5) { // mode = 2 to 5, breathing mode diff --git a/tmk_core/protocol/lufa/lufa.c b/tmk_core/protocol/lufa/lufa.c index cb918d3dce..b15c7a76c8 100644 --- a/tmk_core/protocol/lufa/lufa.c +++ b/tmk_core/protocol/lufa/lufa.c @@ -1074,6 +1074,8 @@ int main(void) MIDI_Device_USBTask(&USB_MIDI_Interface); #endif + if (momentum_enabled()) momentum_decay_task(); + #if defined(RGBLIGHT_ANIMATIONS) & defined(RGBLIGHT_ENABLE) rgblight_task(); #endif From 7e0ca8df8dc254aaa0e4a784c228d7125ffddf90 Mon Sep 17 00:00:00 2001 From: Chris Lewis Date: Sat, 18 Aug 2018 22:44:59 +1000 Subject: [PATCH 13/14] Fix missing momentum.h in lufa.c --- tmk_core/protocol/lufa/lufa.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tmk_core/protocol/lufa/lufa.c b/tmk_core/protocol/lufa/lufa.c index b15c7a76c8..3bfcc40dd6 100644 --- a/tmk_core/protocol/lufa/lufa.c +++ b/tmk_core/protocol/lufa/lufa.c @@ -54,6 +54,7 @@ #include "quantum.h" #include #include "outputselect.h" +#include "momentum.h" #ifdef NKRO_ENABLE #include "keycode_config.h" From 97b7a6e84c06be988b5145d7fdd8dfc70e5d6d11 Mon Sep 17 00:00:00 2001 From: Chris Lewis Date: Sat, 18 Aug 2018 22:35:59 +1000 Subject: [PATCH 14/14] Experimental LED support (untested) --- quantum/quantum.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/quantum/quantum.c b/quantum/quantum.c index 64e364a245..dda8ea8a99 100644 --- a/quantum/quantum.c +++ b/quantum/quantum.c @@ -1194,7 +1194,10 @@ static inline uint16_t scale_backlight(uint16_t v) { */ ISR(TIMER1_OVF_vect) { - uint16_t interval = (uint16_t) breathing_period * 244 / BREATHING_STEPS; + uint16_t interval = momentum_enabled() + ? match_momentum(1, 10) + : (uint16_t) breathing_period * 244 / BREATHING_STEPS; + // resetting after one period to prevent ugly reset at overflow. breathing_counter = (breathing_counter + 1) % (breathing_period * 244); uint8_t index = breathing_counter / interval % BREATHING_STEPS;