diff options
| -rw-r--r-- | docs/config_options.md | 4 | ||||
| -rw-r--r-- | docs/feature_rgblight.md | 43 | ||||
| -rw-r--r-- | quantum/rgblight.c | 29 | ||||
| -rw-r--r-- | quantum/rgblight.h | 6 |
4 files changed, 79 insertions, 3 deletions
diff --git a/docs/config_options.md b/docs/config_options.md index 16fea83a3..f76685702 100644 --- a/docs/config_options.md +++ b/docs/config_options.md | |||
| @@ -191,7 +191,9 @@ If you define these options you will enable the associated feature, which may in | |||
| 191 | * `#define RGBLIGHT_ANIMATIONS` | 191 | * `#define RGBLIGHT_ANIMATIONS` |
| 192 | * run RGB animations | 192 | * run RGB animations |
| 193 | * `#define RGBLIGHT_LAYERS` | 193 | * `#define RGBLIGHT_LAYERS` |
| 194 | * Lets you define [lighting layers](feature_rgblight.md) that can be toggled on or off. Great for showing the current keyboard layer or caps lock state. | 194 | * Lets you define [lighting layers](feature_rgblight.md?id=lighting-layers) that can be toggled on or off. Great for showing the current keyboard layer or caps lock state. |
| 195 | * `#define RGBLIGHT_LAYER_BLINK` | ||
| 196 | * Adds ability to [blink](feature_rgblight.md?id=lighting-layer-blink) a lighting layer for a specified number of milliseconds (e.g. to acknowledge an action). | ||
| 195 | * `#define RGBLED_NUM 12` | 197 | * `#define RGBLED_NUM 12` |
| 196 | * number of LEDs | 198 | * number of LEDs |
| 197 | * `#define RGBLIGHT_SPLIT` | 199 | * `#define RGBLIGHT_SPLIT` |
diff --git a/docs/feature_rgblight.md b/docs/feature_rgblight.md index 219cd8317..de19b7419 100644 --- a/docs/feature_rgblight.md +++ b/docs/feature_rgblight.md | |||
| @@ -177,6 +177,8 @@ const uint8_t RGBLED_GRADIENT_RANGES[] PROGMEM = {255, 170, 127, 85, 64}; | |||
| 177 | By including `#define RGBLIGHT_LAYERS` in your `config.h` file you can enable lighting layers. These make | 177 | By including `#define RGBLIGHT_LAYERS` in your `config.h` file you can enable lighting layers. These make |
| 178 | it easy to use your underglow LEDs as status indicators to show which keyboard layer is currently active, or the state of caps lock, all without disrupting any animations. [Here's a video](https://youtu.be/uLGE1epbmdY) showing an example of what you can do. | 178 | it easy to use your underglow LEDs as status indicators to show which keyboard layer is currently active, or the state of caps lock, all without disrupting any animations. [Here's a video](https://youtu.be/uLGE1epbmdY) showing an example of what you can do. |
| 179 | 179 | ||
| 180 | ### Defining Lighting Layers :id=defining-lighting-layers | ||
| 181 | |||
| 180 | To define a layer, we modify `keymap.c` to list out LED ranges and the colors we want to overlay on them using an array of `rgblight_segment_t` using the `RGBLIGHT_LAYER_SEGMENTS` macro. We can define multiple layers and enable/disable them independently: | 182 | To define a layer, we modify `keymap.c` to list out LED ranges and the colors we want to overlay on them using an array of `rgblight_segment_t` using the `RGBLIGHT_LAYER_SEGMENTS` macro. We can define multiple layers and enable/disable them independently: |
| 181 | 183 | ||
| 182 | ```c | 184 | ```c |
| @@ -211,8 +213,12 @@ void keyboard_post_init_user(void) { | |||
| 211 | rgblight_layers = my_rgb_layers; | 213 | rgblight_layers = my_rgb_layers; |
| 212 | } | 214 | } |
| 213 | ``` | 215 | ``` |
| 216 | Note: For split keyboards with two controllers, both sides need to be flashed when updating the contents of rgblight_layers. | ||
| 214 | 217 | ||
| 215 | Finally, we enable and disable the lighting layers whenever the state of the keyboard changes: | 218 | ### Enabling and disabling lighting layers :id=enabling-lighting-layers |
| 219 | |||
| 220 | Everything above just configured the definition of each lighting layer. | ||
| 221 | We can now enable and disable the lighting layers whenever the state of the keyboard changes: | ||
| 216 | 222 | ||
| 217 | ```c | 223 | ```c |
| 218 | layer_state_t layer_state_set_user(layer_state_t state) { | 224 | layer_state_t layer_state_set_user(layer_state_t state) { |
| @@ -228,7 +234,40 @@ bool led_update_user(led_t led_state) { | |||
| 228 | } | 234 | } |
| 229 | ``` | 235 | ``` |
| 230 | 236 | ||
| 231 | Note: For split keyboards with two controllers, both sides need to be flashed when updating the contents of rgblight_layers. | 237 | ### Lighting layer blink :id=lighting-layer-blink |
| 238 | |||
| 239 | By including `#define RGBLIGHT_LAYER_BLINK` in your `config.h` file you can turn a lighting | ||
| 240 | layer on for a specified duration. Once the specified number of milliseconds has elapsed | ||
| 241 | the layer will be turned off. This is useful, e.g., if you want to acknowledge some | ||
| 242 | action (e.g. toggling some setting): | ||
| 243 | |||
| 244 | ```c | ||
| 245 | const rgblight_segment_t PROGMEM _yes_layer[] = RGBLIGHT_LAYER_SEGMENTS( {9, 6, HSV_GREEN} ); | ||
| 246 | const rgblight_segment_t PROGMEM _no_layer[] = RGBLIGHT_LAYER_SEGMENTS( {9, 6, HSV_RED} ); | ||
| 247 | |||
| 248 | const rgblight_segment_t* const PROGMEM _rgb_layers[] = | ||
| 249 | RGBLIGHT_LAYERS_LIST( _yes_layer, _no_layer ); | ||
| 250 | |||
| 251 | void keyboard_post_init_user(void) { | ||
| 252 | rgblight_layers = _rgb_layers; | ||
| 253 | } | ||
| 254 | |||
| 255 | // Note we user post_process_record_user because we want the state | ||
| 256 | // after the flag has been flipped... | ||
| 257 | void post_process_record_user(uint16_t keycode, keyrecord_t *record) { | ||
| 258 | switch (keycode) { | ||
| 259 | case DEBUG: | ||
| 260 | rgblight_blink_layer(debug_enable ? 0 : 1, 500); | ||
| 261 | break; | ||
| 262 | |||
| 263 | case NK_TOGG: | ||
| 264 | case NK_ON: | ||
| 265 | case NK_OFF: | ||
| 266 | rgblight_blink_layer(keymap_config.nkro ? 0 : 1, 500); | ||
| 267 | break; | ||
| 268 | } | ||
| 269 | } | ||
| 270 | ``` | ||
| 232 | 271 | ||
| 233 | ## Functions | 272 | ## Functions |
| 234 | 273 | ||
diff --git a/quantum/rgblight.c b/quantum/rgblight.c index 26cb41a96..33326fa86 100644 --- a/quantum/rgblight.c +++ b/quantum/rgblight.c | |||
| @@ -658,6 +658,31 @@ static void rgblight_layers_write(void) { | |||
| 658 | } | 658 | } |
| 659 | } | 659 | } |
| 660 | } | 660 | } |
| 661 | |||
| 662 | # ifdef RGBLIGHT_LAYER_BLINK | ||
| 663 | uint8_t _blinked_layer_mask = 0; | ||
| 664 | uint16_t _blink_duration = 0; | ||
| 665 | static uint16_t _blink_timer; | ||
| 666 | |||
| 667 | void rgblight_blink_layer(uint8_t layer, uint16_t duration_ms) { | ||
| 668 | rgblight_set_layer_state(layer, true); | ||
| 669 | _blinked_layer_mask |= 1 << layer; | ||
| 670 | _blink_timer = timer_read(); | ||
| 671 | _blink_duration = duration_ms; | ||
| 672 | } | ||
| 673 | |||
| 674 | void rgblight_unblink_layers(void) { | ||
| 675 | if (_blinked_layer_mask != 0 && timer_elapsed(_blink_timer) > _blink_duration) { | ||
| 676 | for (uint8_t layer = 0; layer < RGBLIGHT_MAX_LAYERS; layer++) { | ||
| 677 | if ((_blinked_layer_mask & 1 << layer) != 0) { | ||
| 678 | rgblight_set_layer_state(layer, false); | ||
| 679 | } | ||
| 680 | } | ||
| 681 | _blinked_layer_mask = 0; | ||
| 682 | } | ||
| 683 | } | ||
| 684 | # endif | ||
| 685 | |||
| 661 | #endif | 686 | #endif |
| 662 | 687 | ||
| 663 | __attribute__((weak)) void rgblight_call_driver(LED_TYPE *start_led, uint8_t num_leds) { ws2812_setleds(start_led, num_leds); } | 688 | __attribute__((weak)) void rgblight_call_driver(LED_TYPE *start_led, uint8_t num_leds) { ws2812_setleds(start_led, num_leds); } |
| @@ -909,6 +934,10 @@ void rgblight_task(void) { | |||
| 909 | # endif | 934 | # endif |
| 910 | } | 935 | } |
| 911 | } | 936 | } |
| 937 | |||
| 938 | # ifdef RGBLIGHT_LAYER_BLINK | ||
| 939 | rgblight_unblink_layers(); | ||
| 940 | # endif | ||
| 912 | } | 941 | } |
| 913 | 942 | ||
| 914 | #endif /* RGBLIGHT_USE_TIMER */ | 943 | #endif /* RGBLIGHT_USE_TIMER */ |
diff --git a/quantum/rgblight.h b/quantum/rgblight.h index b1585b158..e06073728 100644 --- a/quantum/rgblight.h +++ b/quantum/rgblight.h | |||
| @@ -192,6 +192,12 @@ bool rgblight_get_layer_state(uint8_t layer); | |||
| 192 | 192 | ||
| 193 | // Point this to an array of rgblight_segment_t arrays in keyboard_post_init_user to use rgblight layers | 193 | // Point this to an array of rgblight_segment_t arrays in keyboard_post_init_user to use rgblight layers |
| 194 | extern const rgblight_segment_t *const *rgblight_layers; | 194 | extern const rgblight_segment_t *const *rgblight_layers; |
| 195 | |||
| 196 | # ifdef RGBLIGHT_LAYER_BLINK | ||
| 197 | # define RGBLIGHT_USE_TIMER | ||
| 198 | void rgblight_blink_layer(uint8_t layer, uint16_t duration_ms); | ||
| 199 | # endif | ||
| 200 | |||
| 195 | # endif | 201 | # endif |
| 196 | 202 | ||
| 197 | extern LED_TYPE led[RGBLED_NUM]; | 203 | extern LED_TYPE led[RGBLED_NUM]; |
