Skip to content

Commit

Permalink
Velocikey: Match RGB animation speed to typing speed (qmk#3754)
Browse files Browse the repository at this point in the history
* Draft commit of typing speed RGB control

* More information in the readme

* Support all RGB animation modes (Fixes qmk#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!

* Update readme.md

* Update readme.md

* Re-arrange typing_speed definitions (Fixes qmk#5) (qmk#6)

* Re-arrange variable definitions to avoid including quantum.h from rgblight.c

* Fix a compilation error when trying to run make test:all

* Tweaks to the typing speed decay rate

* Renamed to momentum; moved implementation into dedicated files

* Groundwork for toggling momentum on/off (currently always on)

* Add EEPROM toggle for momentum-matching

* Moved momentum out of RGBLIGHT_ENABLE toggles so it's more generic

* Move momentum decay task out of rgblight_task()

* Fix missing momentum.h in lufa.c

* Experimental LED support (untested)

* Draft commit of typing speed RGB control

* More information in the readme

* Support all RGB animation modes (Fixes qmk#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!

* Update readme.md

* Update readme.md

* Re-arrange typing_speed definitions (Fixes qmk#5) (qmk#6)

* Re-arrange variable definitions to avoid including quantum.h from rgblight.c

* Fix a compilation error when trying to run make test:all

* Tweaks to the typing speed decay rate

* Renamed to momentum; moved implementation into dedicated files

* Groundwork for toggling momentum on/off (currently always on)

* Add EEPROM toggle for momentum-matching

* Moved momentum out of RGBLIGHT_ENABLE toggles so it's more generic

* Move momentum decay task out of rgblight_task()

* Fix missing momentum.h in lufa.c

* Added documentation

* Renamed feature to velocikey

* Reverted readme to original state

* Correct the readme title

* Updated feature name in the docs

* Update EECONFIG name

* Add compile-time toggles for velocikey

* Update feature documentation

* Revert "Merge branch 'led-support' into master"

This reverts commit e123ff5, reversing
changes made to df111a5.

* Move velocikey EECONFIG definition to depend on VELOCIKEY_ENABLE

* Rename decay_task function to decelerate

* Apply suggestions from code review

Co-Authored-By: chrislewisdev <chris@chrislewisdev.com>

* Re-order eeconfig definitions

* Apply coding conventions

* Apply #ifdef check in lufa.c

* Refactored interval time checks into one functionc

* Small rename

* Fix unused function error for layouts not using all rgb effects

* Only update EEPROM if Velocikey is enabled

* Incorporate code review feedback

* Small adjustment to top-end decay rate

* Add Velocikey documentation to table of contents

* Bring tetris:default keymap size down by disabling audio
  • Loading branch information
chrislewisdev authored and dlafrance committed May 24, 2019
1 parent cadacb4 commit a661c8b
Show file tree
Hide file tree
Showing 11 changed files with 158 additions and 6 deletions.
5 changes: 5 additions & 0 deletions common_features.mk
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,11 @@ ifeq ($(strip $(HD44780_ENABLE)), yes)
OPT_DEFS += -DHD44780_ENABLE
endif

ifeq ($(strip $(VELOCIKEY_ENABLE)), yes)
OPT_DEFS += -DVELOCIKEY_ENABLE
SRC += $(QUANTUM_DIR)/velocikey.c
endif

ifeq ($(strip $(DYNAMIC_KEYMAP_ENABLE)), yes)
OPT_DEFS += -DDYNAMIC_KEYMAP_ENABLE
SRC += $(QUANTUM_DIR)/dynamic_keymap.c
Expand Down
1 change: 1 addition & 0 deletions docs/_summary.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
* [Thermal Printer](feature_thermal_printer.md)
* [Unicode](feature_unicode.md)
* [Userspace](feature_userspace.md)
* [Velocikey](feature_velocikey.md)

* For Makers and Modders
* [Hand Wiring Guide](hand_wire.md)
Expand Down
30 changes: 30 additions & 0 deletions docs/feature_velocikey.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Velocikey

Velocikey is a feature that lets you control the speed of lighting effects (like the Rainbow Swirl effect) with the speed of your typing. The faster you type, the faster the lights will go!

## Usage
For Velocikey to take effect, there are two steps. First, when compiling your keyboard, you'll need to set `VELOCIKEY_ENABLE=yes` in `rules.mk`, e.g.:

```
BOOTMAGIC_ENABLE = no
MOUSEKEY_ENABLE = no
STENO_ENABLE = no
EXTRAKEY_ENABLE = yes
VELOCIKEY_ENABLE = yes
```

Then, while using your keyboard, you need to also turn it on with the VLK_TOG keycode, which toggles the feature on and off.

The following light effects will all be controlled by Velocikey when it is enabled:
- RGB Breathing
- RGB Rainbow Mood
- RGB Rainbow Swirl
- RGB Snake
- RGB Knight

Support for LED breathing effects is planned but not available yet.

As long as Velocikey is enabled, it will control the speed regardless of any other speed setting that your RGB lights are currently on.

## Configuration
Velocikey doesn't currently support any configuration via keyboard settings. If you want to adjust something like the speed increase or decay rate, you would need to edit `velocikey.c` and adjust the values there to achieve the kinds of speeds that you like.
17 changes: 16 additions & 1 deletion quantum/quantum.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ extern backlight_config_t backlight_config;
#include "process_midi.h"
#endif

#ifdef VELOCIKEY_ENABLE
#include "velocikey.h"
#endif

#ifdef HAPTIC_ENABLE
#include "haptic.h"
#endif
Expand Down Expand Up @@ -251,6 +255,10 @@ bool process_record_quantum(keyrecord_t *record) {
// return false;
// }

#ifdef VELOCIKEY_ENABLE
if (velocikey_enabled() && record->event.pressed) { velocikey_accelerate(); }
#endif

#ifdef TAP_DANCE_ENABLE
preprocess_tap_dance(keycode, record);
#endif
Expand Down Expand Up @@ -568,7 +576,14 @@ bool process_record_quantum(keyrecord_t *record) {
#endif
return false;
#endif // defined(RGBLIGHT_ENABLE) || defined(RGB_MATRIX_ENABLE)
#ifdef PROTOCOL_LUFA
#ifdef VELOCIKEY_ENABLE
case VLK_TOG:
if (record->event.pressed) {
velocikey_toggle();
}
return false;
#endif
#ifdef PROTOCOL_LUFA
case OUT_AUTO:
if (record->event.pressed) {
set_output(OUTPUT_AUTO);
Expand Down
3 changes: 3 additions & 0 deletions quantum/quantum_keycodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,9 @@ enum quantum_keycodes {
RGB_MODE_GRADIENT,
RGB_MODE_RGBTEST,

//Momentum matching toggle
VLK_TOG,

// Left shift, open paren
KC_LSPO,

Expand Down
40 changes: 35 additions & 5 deletions quantum/rgblight.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@
#include "rgblight.h"
#include "debug.h"
#include "led_tables.h"
#ifdef VELOCIKEY_ENABLE
#include "velocikey.h"
#endif

#define _RGBM_SINGLE_STATIC(sym) RGBLIGHT_MODE_ ## sym,
#define _RGBM_SINGLE_DYNAMIC(sym)
Expand Down Expand Up @@ -607,6 +610,19 @@ void rgblight_sethsv_at(uint16_t hue, uint8_t sat, uint8_t val, uint8_t index) {
rgblight_setrgb_at(tmp_led.r, tmp_led.g, tmp_led.b, index);
}

#if defined(RGBLIGHT_EFFECT_BREATHING) || defined(RGBLIGHT_EFFECT_RAINBOW_MOOD) || defined(RGBLIGHT_EFFECT_RAINBOW_SWIRL) \
|| defined(RGBLIGHT_EFFECT_SNAKE) || defined(RGBLIGHT_EFFECT_KNIGHT)

static uint8_t get_interval_time(const uint8_t* default_interval_address, uint8_t velocikey_min, uint8_t velocikey_max) {
return
#ifdef VELOCIKEY_ENABLE
velocikey_enabled() ? velocikey_match_speed(velocikey_min, velocikey_max) :
#endif
pgm_read_byte(default_interval_address);
}

#endif

void rgblight_setrgb_range(uint8_t r, uint8_t g, uint8_t b, uint8_t start, uint8_t end) {
if (!rgblight_config.enable || start < 0 || start >= end || end > RGBLED_NUM) { return; }

Expand Down Expand Up @@ -707,6 +723,7 @@ void rgblight_show_solid_color(uint8_t r, uint8_t g, uint8_t b) {
}

void rgblight_task(void) {

if (rgblight_timer_enabled) {
// static light mode, do nothing here
if ( 1 == 0 ) { //dummy
Expand Down Expand Up @@ -778,7 +795,9 @@ 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])) {
uint8_t interval_time = get_interval_time(&RGBLED_RAINBOW_SWIRL_INTERVALS[interval / 2], 1, 100);

if (timer_elapsed(last_timer) < interval_time) {
return;
}
last_timer = timer_read();
Expand All @@ -798,7 +817,9 @@ 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])) {
uint8_t interval_time = get_interval_time(&RGBLED_RAINBOW_MOOD_INTERVALS[interval], 5, 100);

if (timer_elapsed(last_timer) < interval_time) {
return;
}
last_timer = timer_read();
Expand All @@ -820,7 +841,10 @@ 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])) {

uint8_t interval_time = get_interval_time(&RGBLED_RAINBOW_SWIRL_INTERVALS[interval / 2], 1, 100);

if (timer_elapsed(last_timer) < interval_time) {
return;
}
last_timer = timer_read();
Expand Down Expand Up @@ -855,7 +879,10 @@ 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])) {

uint8_t interval_time = get_interval_time(&RGBLED_SNAKE_INTERVALS[interval / 2], 1, 200);

if (timer_elapsed(last_timer) < interval_time) {
return;
}
last_timer = timer_read();
Expand Down Expand Up @@ -892,7 +919,10 @@ const uint8_t RGBLED_KNIGHT_INTERVALS[] PROGMEM = {127, 63, 31};

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])) {

uint8_t interval_time = get_interval_time(&RGBLED_KNIGHT_INTERVALS[interval], 5, 100);

if (timer_elapsed(last_timer) < interval_time) {
return;
}
last_timer = timer_read();
Expand Down
46 changes: 46 additions & 0 deletions quantum/velocikey.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#include "velocikey.h"
#include "timer.h"
#include "eeconfig.h"
#include "eeprom.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;

bool velocikey_enabled(void) {
return eeprom_read_byte(EECONFIG_VELOCIKEY) == 1;
}

void velocikey_toggle(void) {
if (velocikey_enabled())
eeprom_update_byte(EECONFIG_VELOCIKEY, 0);
else
eeprom_update_byte(EECONFIG_VELOCIKEY, 1);
}

void velocikey_accelerate(void) {
if (typing_speed < TYPING_SPEED_MAX_VALUE) typing_speed += (TYPING_SPEED_MAX_VALUE / 100);
}

void velocikey_decelerate(void) {
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 -= 2;
decay_timer = timer_read();
}
}

uint8_t velocikey_match_speed(uint8_t minValue, uint8_t maxValue) {
return MAX(minValue, maxValue - (maxValue - minValue) * ((float)typing_speed / TYPING_SPEED_MAX_VALUE));
}
13 changes: 13 additions & 0 deletions quantum/velocikey.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#ifndef VELOCIKEY_H
#define VELOCIKEY_H

#include <stdint.h>
#include <stdbool.h>

bool velocikey_enabled(void);
void velocikey_toggle(void);
void velocikey_accelerate(void);
void velocikey_decelerate(void);
uint8_t velocikey_match_speed(uint8_t minValue, uint8_t maxValue);

#endif
1 change: 1 addition & 0 deletions tmk_core/common/eeconfig.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ void eeconfig_init_quantum(void) {
eeprom_update_dword(EECONFIG_RGBLIGHT, 0);
eeprom_update_byte(EECONFIG_STENOMODE, 0);
eeprom_update_dword(EECONFIG_HAPTIC, 0);
eeprom_update_byte(EECONFIG_VELOCIKEY, 0);

eeconfig_init_kb();
}
Expand Down
1 change: 1 addition & 0 deletions tmk_core/common/eeconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define EECONFIG_HANDEDNESS (uint8_t *)14
#define EECONFIG_KEYBOARD (uint32_t *)15
#define EECONFIG_USER (uint32_t *)19
#define EECONFIG_VELOCIKEY (uint8_t *)23

#define EECONFIG_HAPTIC (uint32_t*)24

Expand Down
7 changes: 7 additions & 0 deletions tmk_core/common/keyboard.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifdef QWIIC_ENABLE
# include "qwiic.h"
#endif
#ifdef VELOCIKEY_ENABLE
#include "velocikey.h"
#endif

#ifdef MATRIX_HAS_GHOST
extern const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS];
Expand Down Expand Up @@ -336,6 +339,10 @@ void keyboard_task(void)
midi_task();
#endif

#ifdef VELOCIKEY_ENABLE
if (velocikey_enabled()) { velocikey_decelerate(); }
#endif

// update LED
if (led_status != host_keyboard_leds()) {
led_status = host_keyboard_leds();
Expand Down

0 comments on commit a661c8b

Please sign in to comment.