Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to blink lighting layer for a specified duration #8760

Merged
merged 9 commits into from
May 9, 2020
4 changes: 3 additions & 1 deletion docs/config_options.md
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,9 @@ If you define these options you will enable the associated feature, which may in
* `#define RGBLIGHT_ANIMATIONS`
* run RGB animations
* `#define RGBLIGHT_LAYERS`
* 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.
* 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.
* `#define RGBLIGHT_LAYER_BLINK`
* 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).
* `#define RGBLED_NUM 12`
* number of LEDs
* `#define RGBLIGHT_SPLIT`
Expand Down
43 changes: 41 additions & 2 deletions docs/feature_rgblight.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,8 @@ const uint8_t RGBLED_GRADIENT_RANGES[] PROGMEM = {255, 170, 127, 85, 64};
By including `#define RGBLIGHT_LAYERS` in your `config.h` file you can enable lighting layers. These make
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.

### Defining Lighting Layers :id=defining-lighting-layers

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:

```c
Expand Down Expand Up @@ -211,8 +213,12 @@ void keyboard_post_init_user(void) {
rgblight_layers = my_rgb_layers;
}
```
Note: For split keyboards with two controllers, both sides need to be flashed when updating the contents of rgblight_layers.

Finally, we enable and disable the lighting layers whenever the state of the keyboard changes:
### Enabling and disabling lighting layers :id=enabling-lighting-layers

Everything above just configured the definition of each lighting layer.
We can now enable and disable the lighting layers whenever the state of the keyboard changes:

```c
layer_state_t layer_state_set_user(layer_state_t state) {
Expand All @@ -228,7 +234,40 @@ bool led_update_user(led_t led_state) {
}
```

Note: For split keyboards with two controllers, both sides need to be flashed when updating the contents of rgblight_layers.
### Lighting layer blink :id=lighting-layer-blink

By including `#define RGBLIGHT_LAYER_BLINK` in your `config.h` file you can turn a lighting
layer on for a specified duration. Once the specified number of milliseconds has elapsed
the layer will be turned off. This is useful, e.g., if you want to acknowledge some
action (e.g. toggling some setting):

```c
const rgblight_segment_t PROGMEM _yes_layer[] = RGBLIGHT_LAYER_SEGMENTS( {9, 6, HSV_GREEN} );
const rgblight_segment_t PROGMEM _no_layer[] = RGBLIGHT_LAYER_SEGMENTS( {9, 6, HSV_RED} );

const rgblight_segment_t* const PROGMEM _rgb_layers[] =
RGBLIGHT_LAYERS_LIST( _yes_layer, _no_layer );

void keyboard_post_init_user(void) {
rgblight_layers = _rgb_layers;
}

// Note we user post_process_record_user because we want the state
// after the flag has been flipped...
void post_process_record_user(uint16_t keycode, keyrecord_t *record) {
switch (keycode) {
case DEBUG:
rgblight_blink_layer(debug_enable ? 0 : 1, 500);
break;

case NK_TOGG:
case NK_ON:
case NK_OFF:
rgblight_blink_layer(keymap_config.nkro ? 0 : 1, 500);
break;
}
}
```

## Functions

Expand Down
29 changes: 29 additions & 0 deletions quantum/rgblight.c
Original file line number Diff line number Diff line change
Expand Up @@ -662,6 +662,31 @@ static void rgblight_layers_write(void) {
}
}
}

# ifdef RGBLIGHT_LAYER_BLINK
uint8_t _blinked_layer_mask = 0;
uint16_t _blink_duration = 0;
static uint16_t _blink_timer;

void rgblight_blink_layer(uint8_t layer, uint16_t duration_ms) {
rgblight_set_layer_state(layer, true);
_blinked_layer_mask |= 1 << layer;
_blink_timer = timer_read();
_blink_duration = duration_ms;
}

void rgblight_unblink_layers(void) {
if (_blinked_layer_mask != 0 && timer_elapsed(_blink_timer) > _blink_duration) {
for (uint8_t layer = 0; layer < RGBLIGHT_MAX_LAYERS; layer++) {
if ((_blinked_layer_mask & 1 << layer) != 0) {
rgblight_set_layer_state(layer, false);
}
}
_blinked_layer_mask = 0;
}
}
# endif

#endif

#ifndef RGBLIGHT_CUSTOM_DRIVER
Expand Down Expand Up @@ -911,6 +936,10 @@ void rgblight_task(void) {
# endif
}
}

# ifdef RGBLIGHT_LAYER_BLINK
rgblight_unblink_layers();
# endif
}

#endif /* RGBLIGHT_USE_TIMER */
Expand Down
6 changes: 6 additions & 0 deletions quantum/rgblight.h
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,12 @@ bool rgblight_get_layer_state(uint8_t layer);

// Point this to an array of rgblight_segment_t arrays in keyboard_post_init_user to use rgblight layers
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);
# endif

# endif

extern LED_TYPE led[RGBLED_NUM];
Expand Down